-
Notifications
You must be signed in to change notification settings - Fork 445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ERC: NFT Metadata Extension like JSON-LD #417
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
--- | ||
eip: 7280 | ||
title: NFT Metadata Extension like JSON-LD | ||
description: Let NFT metadata have a feature equivalent to JSON-LD to be semantic. | ||
author: Yohei Nishikubo (@yoheinishikubo) | ||
discussions-to: https://ethereum-magicians.org/t/eip-7280-nft-metadata-extension-like-json-ld/14935 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2023-07-04 | ||
requires: 721, 1155, 3525 | ||
--- | ||
|
||
## Abstract | ||
|
||
This proposal expands the metadata format for Non-Fungible Tokens ([ERC-721](./eip-721.md), [ERC-1155](./eip-1155.md), [ERC-3525](./eip-3525.md), and others), adding support for linked data like JSON-LD format. The additional data is stored under the linked_data key in the metadata JSON. | ||
|
||
## Motivation | ||
|
||
The existing metadata format for Non-Fungible Tokens is limited and doesn't support the inclusion of structured and semantically meaningful data. By integrating JSON-LD (Linked Data), we can enhance the richness and interoperability of the metadata associated with NFTs. | ||
|
||
This allows for complex metadata structures that can link to external schemas and data, improving the contextual relevance and usability of NFTs across various applications. | ||
|
||
## Specification | ||
|
||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. | ||
|
||
The JSON-LD based metadata is stored under a new `linked_data` key in the metadata JSON. The `linked_data` key is an array of objects, where each object contains two keys: `schema` and `data`. | ||
|
||
| name | compliance level | type | description | | ||
| ------ | ---------------- | ------ | ------------------------------ | | ||
| schema | MUST | object | The schema of the linked data. | | ||
| data | MUST | object | The data of the linked data. | | ||
|
||
### Schema | ||
|
||
| name | compliance level | type | description | | ||
| ----------- | ---------------- | ------ | ------------------------------ | | ||
| uri | MUST | string | The URI of the schema. | | ||
| name | MUST | string | The name of the schema. | | ||
| description | OPTIONAL | string | The description of the schema. | | ||
|
||
### Data | ||
|
||
| name | compliance level | type | description | | ||
| ----------- | ---------------- | ------ | --------------------------------------------------------- | | ||
| uri | MUST | string | The URI of the data. | | ||
| lang | OPTIONAL | string | The language of the data. IETF language tag like `en-US`. | | ||
| name | OPTIONAL | string | The name of the data. | | ||
| description | OPTIONAL | string | The description of the data. | | ||
|
||
## Rationale | ||
|
||
For providing typical webpage for an NFT, it's much simple to include JSON-LD in HTML header tag with this extension. Just looking for JSON-LD compliant value's uri from `linked_data` array, fetch it and embed its content in HTML header tag. | ||
This means the minter of NFT can control the appearance in the search result of Google, for example. | ||
In more common case for interoperability, the NFT metadata can include any schema and data with this extension. This means the NFT metadata can be used as a data source for any application. With the schema, the implementation is much easier. | ||
|
||
## Backwards Compatibility | ||
|
||
The proposed expansion to the NFT metadata format is backward compatible with existing implementations. NFTs that do not include the `linked_data` key will continue to function as before, and existing applications consuming NFT metadata will not be affected. | ||
|
||
## Reference Implementation | ||
|
||
Here is an example metadata JSON demonstrating the new linked_data structure: | ||
|
||
```json | ||
{ | ||
"name": "NFT Name", | ||
"description": "This NFT represents...", | ||
"image": "https://example.org/images/nft.png", | ||
"linked_data": [ | ||
{ | ||
"schema": { | ||
"name": "VideoObject", | ||
"uri": "https://example.org/schemas/VideoObject.json" | ||
}, | ||
"data": { | ||
"uri": "https://example.org/data/video1.json" | ||
} | ||
}, | ||
{ | ||
"schema": { | ||
"name": "MusicRecording", | ||
"uri": "https://example.org/schemas/MusicRecording.json" | ||
}, | ||
"data": { | ||
"uri": "https://example.org/data/music1.json" | ||
} | ||
}, | ||
{ | ||
"schema": { | ||
"name": "GoogleTravelImpactModel", | ||
"uri": "https://example.org/schemas/GoogleTravelImpactModel.json" | ||
}, | ||
"data": { | ||
"uri": "https://example.org/data/gtim1.json" | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
In the example above, the NFT metadata contains three linked data objects, each with a different schema and data: | ||
First one. VideoObject data can be used as JSON-LD in HTML header tag and realize rich snippet in Google search result. | ||
Second one. MusicRecording data is based on a schema from `schema.org`. However this one cannot realize rich snippet. | ||
Third one. GoogleTravelImpactModel data is a dedicated schema for Google Travel Impact Model. | ||
The most important point is that any schema and data can be included with this standard like above. | ||
|
||
### Sample files | ||
|
||
- [VideoObject.json](../assets/eip-7280/samples/schemas/VideoObject.json) | ||
- [MusicRecording.json](../assets/eip-7280/samples/schemas/MusicRecording.json) | ||
- [GoogleTravelImpactModel.json](../assets/eip-7280/samples/schemas/GoogleTravelImpactModel.json) | ||
- [video1.json](../assets/eip-7280/samples/data/video1.json) | ||
- [music1.json](../assets/eip-7280/samples/data/music1.json) | ||
- [gtim1.json](../assets/eip-7280/samples/data/gtim1.json) | ||
|
||
## Security Considerations | ||
|
||
The proposed expansion does not introduce any additional security considerations beyond those already associated with NFTs and linked data. Implementations should adhere to best practices for secure handling and validation of metadata from external sources. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
{ | ||
"flightEmissions": [ | ||
{ | ||
"flight": { | ||
"origin": "ZRH", | ||
"destination": "CDG", | ||
"operatingCarrierCode": "AF", | ||
"flightNumber": 1115, | ||
"departureDate": { | ||
"year": 2024, | ||
"month": 6, | ||
"day": 1 | ||
} | ||
}, | ||
"emissionsGramsPerPax": { | ||
"first": 92137, | ||
"business": 92137, | ||
"premiumEconomy": 61425, | ||
"economy": 61425 | ||
} | ||
}, | ||
{ | ||
"flight": { | ||
"origin": "CDG", | ||
"destination": "BOS", | ||
"operatingCarrierCode": "AF", | ||
"flightNumber": 334, | ||
"departureDate": { | ||
"year": 2024, | ||
"month": 6 | ||
"day": 1 | ||
} | ||
}, | ||
"emissionsGramsPerPax": { | ||
"first": 1384120, | ||
"business": 1107296, | ||
"premiumEconomy": 415236, | ||
"economy": 276824 | ||
} | ||
}, | ||
{ | ||
"flight": { | ||
"origin": "ZRH", | ||
"destination": "BOS", | ||
"operatingCarrierCode": "LX", | ||
"flightNumber": 52, | ||
"departureDate": { | ||
"year": 2024, | ||
"month": 5, | ||
"day": 1 | ||
} | ||
}, | ||
"emissionsGramsPerPax": { | ||
"first": 1887615, | ||
"business": 1510092, | ||
"premiumEconomy": 566284, | ||
"economy": 377523 | ||
} | ||
} | ||
], | ||
"modelVersion": { | ||
"major": 1, | ||
"minor": 7, | ||
"patch": 0, | ||
"dated": "20230817" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
{ | ||
"@context": "https://schema.org/", | ||
"@type": "MusicRecording", | ||
"name": "Cupid", | ||
"byArtist": { | ||
"@type": "MusicGroup", | ||
"name": "Fifty Fifty", | ||
"memberOf": [ | ||
{ | ||
"@type": "Person", | ||
"name": "Aran" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Keena" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Saena" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Sio" | ||
} | ||
] | ||
}, | ||
"datePublished": "2023-02-24", | ||
"inLanguage": "Korean", | ||
"producer": { | ||
"@type": "Person", | ||
"name": "Siahn" | ||
}, | ||
"recordLabel": { | ||
"@type": "Organization", | ||
"name": "Attrakt", | ||
"foundingDate": "2021", | ||
"location": { | ||
"@type": "Country", | ||
"name": "South Korea" | ||
} | ||
}, | ||
"recordingOf": { | ||
"@type": "MusicComposition", | ||
"composer": [ | ||
{ | ||
"@type": "Person", | ||
"name": "Adam von Mentzer" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Mac Felländer-Tsai" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Louise Udin" | ||
} | ||
], | ||
"lyricist": [ | ||
{ | ||
"@type": "Person", | ||
"name": "Keena" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Ahin" | ||
} | ||
], | ||
"musicArrangement": [ | ||
{ | ||
"@type": "Person", | ||
"name": "Adam von Mentzer" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Mac Felländer-Tsai" | ||
}, | ||
{ | ||
"@type": "Person", | ||
"name": "Louise Udin" | ||
} | ||
], | ||
"timeRequired": "PT3M", | ||
"inLanguage": "Korean", | ||
"description": "Its lyrics describe a young woman's unrequited crush and her feeling dumb for falling in love. In the song's chorus, the group sings, 'I gave a second chance to Cupid/I believed you, I'm so stupid/Let me show you, my secret love, is it real?/Cupid is so dumb.' The group harmonizes on the song, while the latter half of the song includes a key change and a rap verse performed by Keena. The instrumental features synths and guitars." | ||
}, | ||
"duration": "PT3M", | ||
"genre": "K-pop, Disco-pop, Synth-pop, Bubblegum", | ||
"inAlbum": { | ||
"@type": "MusicAlbum", | ||
"name": "The Beginning: Cupid", | ||
"datePublished": "2023-02-24" | ||
}, | ||
"position": "1", | ||
"description": "\"Cupid\" is a single by South Korean girl group Fifty Fifty, released on February 24, 2023. The song achieved significant international success, charting in numerous countries including the United States." | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"@context": "http://schema.org", | ||
"@type": "VideoObject", | ||
"name": "FIFTY FIFTY (피프티피프티) - 'Cupid' Official MV", | ||
"description": "The video is a song lyrics expressing feelings of loneliness and longing for love. The speaker questions why they are feeling lonely and desires to be held and loved. They mention giving Cupid a second chance and feeling foolish for believing in love. The speaker practices love in their dreams and wants someone to share their feelings with. They express their willingness to wait and not give up on love. The text ends with the speaker calling themselves a fool for love and giving Cupid another chance despite feeling stupid. The text suggests that Cupid is not intelligent and is giving the reader one final opportunity.", | ||
"thumbnailUrl": "https://i.ytimg.com/vi/Qc7_zRjH808/maxresdefault.jpg", | ||
"uploadDate": "2023-02-23T13:00:10Z", | ||
"duration": "PT3M23S", | ||
"contentUrl": "https://www.youtube.com/watch?v=Qc7_zRjH808", | ||
"embedUrl": "https://www.youtube.com/embed/Qc7_zRjH808", | ||
"interactionStatistic": { | ||
"@type": "InteractionCounter", | ||
"userInteractionCount": "100219440" | ||
}, | ||
"commentCount": "76810", | ||
"regionsAllowed": "Worldwide" | ||
} |
91 changes: 91 additions & 0 deletions
91
assets/erc-7280/samples/schemas/GoogleTravelImpactModel.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-07/schema#", | ||
"type": "object", | ||
"properties": { | ||
"flightEmissions": { | ||
"type": "array", | ||
"items": { | ||
"type": "object", | ||
"properties": { | ||
"flight": { | ||
"type": "object", | ||
"properties": { | ||
"origin": { | ||
"type": "string" | ||
}, | ||
"destination": { | ||
"type": "string" | ||
}, | ||
"operatingCarrierCode": { | ||
"type": "string" | ||
}, | ||
"flightNumber": { | ||
"type": "integer" | ||
}, | ||
"departureDate": { | ||
"type": "object", | ||
"properties": { | ||
"year": { | ||
"type": "integer" | ||
}, | ||
"month": { | ||
"type": "integer" | ||
}, | ||
"day": { | ||
"type": "integer" | ||
} | ||
}, | ||
"required": ["year", "month", "day"] | ||
} | ||
}, | ||
"required": [ | ||
"origin", | ||
"destination", | ||
"operatingCarrierCode", | ||
"flightNumber", | ||
"departureDate" | ||
] | ||
}, | ||
"emissionsGramsPerPax": { | ||
"type": "object", | ||
"properties": { | ||
"first": { | ||
"type": "integer" | ||
}, | ||
"business": { | ||
"type": "integer" | ||
}, | ||
"premiumEconomy": { | ||
"type": "integer" | ||
}, | ||
"economy": { | ||
"type": "integer" | ||
} | ||
}, | ||
"required": ["first", "business", "premiumEconomy", "economy"] | ||
} | ||
}, | ||
"required": ["flight", "emissionsGramsPerPax"] | ||
} | ||
}, | ||
"modelVersion": { | ||
"type": "object", | ||
"properties": { | ||
"major": { | ||
"type": "integer" | ||
}, | ||
"minor": { | ||
"type": "integer" | ||
}, | ||
"patch": { | ||
"type": "integer" | ||
}, | ||
"dated": { | ||
"type": "string" | ||
} | ||
}, | ||
"required": ["major", "minor", "patch", "dated"] | ||
} | ||
}, | ||
"required": ["flightEmissions", "modelVersion"] | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to use something like JSON Schema to specify these requirements. That's up to you though.