-
Notifications
You must be signed in to change notification settings - Fork 375
CIP-0068 | Support multi-asset metadata a la CIP-0025 #1112
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -155,16 +155,20 @@ The `user token` represents an NFT (non-fungible token). | |
|
|
||
| ##### Pattern | ||
|
|
||
| The `user token` and `reference NFT` MUST have an identical name, preceded by the `asset_name_label` prefix. | ||
| The `user token` and `reference NFT` MUST have an identical name (heretofore entitled `asset_name`), preceded by the `asset_name_label` prefix. | ||
|
|
||
| Example:\ | ||
| `user token`: `(222)Test123`\ | ||
| `reference NFT`: `(100)Test123` | ||
|
|
||
| ##### Metadata | ||
|
|
||
| This is a low-level representation of the metadata, following closely the structure of CIP-0025. All UTF-8 encoded keys | ||
| and values need to be converted into their respective byte's representation when creating the datum on-chain. | ||
| This is either: | ||
|
|
||
| 1. A low-level direct representation of the metadata, following closely the structure of CIP-0025 | ||
| 2. A 721-ERC-style token mapping exactly matching the structure of CIP-0025 | ||
|
|
||
| All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. | ||
|
|
||
| ``` | ||
| files_details = | ||
|
|
@@ -188,6 +192,26 @@ metadata = | |
| ; ... Additional properties are allowed | ||
| } | ||
|
|
||
| metadata_map = | ||
| { | ||
| __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict | ||
|
|
||
| "721": | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the point of having |
||
| { | ||
| ; As many of the below as needed based on which reference tokens are added | ||
| "<policy_id>": | ||
| { | ||
| "<asset_name_1>" : metadata, | ||
| ; ... | ||
| "<asset_name_n>" : metadata, | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not some valid CDDL. It looks like you are confusing CDDL with JSON. Overall we should avoid talking about JSON as metadata and datum are CBOR encoded and CBOR -> JSON is not directly bijective. This only leads to confusion. Note that JSON in CIP68 is only discussed in examples and even this is slightly questionable in my opinion. |
||
| metadata_field = | ||
| metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata | ||
| / metadata_map ; Multi-metadata is now supported as in CIP-0025 | ||
|
|
||
| ; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring. | ||
| ; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain). | ||
| ; Data URLs (on-chain data) must comply to RFC2397. | ||
|
|
@@ -198,12 +222,12 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8 | |
| ; and needs to be at least Unit/Void: #6.121([]) | ||
| extra = plutus_data | ||
|
|
||
| datum = #6.121([metadata, version, extra]) | ||
| datum = #6.121([metadata_field, version, extra]) | ||
|
|
||
| version = 1 / 2 / 3 | ||
| version = 1 / 2 / 3 / 4 | ||
| ``` | ||
|
|
||
| Example datum as JSON: | ||
| Example datum as JSON (direct metadata): | ||
|
|
||
| ```json | ||
| { | ||
|
|
@@ -236,6 +260,45 @@ Example datum as JSON: | |
| } | ||
| ``` | ||
|
|
||
| Example datum as JSON (721-style): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again what "721-style" means? |
||
|
|
||
| ```json | ||
| { | ||
| "constructor": 0, | ||
| "fields": [ | ||
| { | ||
| "map": [ | ||
| { | ||
| "k": { "bytes": "373231" }, | ||
| "v": { | ||
| "map": [ | ||
| { | ||
| "k": { "bytes": "5370616365427564204131" }, | ||
| "v": { | ||
| "map": [ | ||
| { | ||
| "k": { "bytes": "6E616D65" }, | ||
| "v": { "bytes": "5370616365427564" } | ||
| }, | ||
| { | ||
| "k": { "bytes": "696D616765" }, | ||
| "v": { "bytes": "697066733A2F2F74657374" } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "int": 4 | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| ##### Retrieve metadata as 3rd party | ||
|
|
||
| A third party has the following NFT `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken` they want | ||
|
|
@@ -244,7 +307,9 @@ to lookup. The steps are | |
| 1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` | ||
| 2. Look up `reference NFT` and find the output it's locked in. | ||
| 3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. | ||
| 4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false) | ||
| 5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name` | ||
|
|
||
| ##### Retrieve metadata from a Plutus validator | ||
|
|
||
|
|
@@ -274,17 +339,20 @@ The `user token` is an FT (fungible token). | |
|
|
||
| ##### Pattern | ||
|
|
||
| The `user token` and `reference NFT` MUST have an identical name, preceded by the `asset_name_label` prefix. | ||
| The `user token` and `reference NFT` MUST have an identical name (heretofore called `asset_name`), preceded by the `asset_name_label` prefix. | ||
|
|
||
| Example:\ | ||
| `user token`: `(333)Test123`\ | ||
| `reference NFT`: `(100)Test123` | ||
|
|
||
| ##### Metadata | ||
|
|
||
| This is a low-level representation of the metadata, following closely the structure of the Cardano foundation off-chain | ||
| metadata registry. All UTF-8 encoded keys and values need to be converted into their respective byte's representation | ||
| when creating the datum on-chain. | ||
| This is either: | ||
|
|
||
| 1. A low-level direct representation of the metadata, following closely the structure of the Cardano foundation off-chain metadata registry | ||
| 2. A 721-ERC-style token mapping exactly matching the structure of CIP-0025 | ||
|
|
||
| All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. | ||
|
|
||
| ``` | ||
| ; Explanation here: https://developers.cardano.org/docs/native-tokens/token-registry/cardano-token-registry/ | ||
|
|
@@ -304,6 +372,26 @@ metadata = | |
| ; ... Additional properties are allowed | ||
| } | ||
|
|
||
| metadata_map = | ||
| { | ||
| __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict | ||
|
|
||
| "721": | ||
| { | ||
| ; As many of the below as needed based on which reference tokens are added | ||
| "<policy_id>": | ||
| { | ||
| "<asset_name_1>" : metadata, | ||
| ; ... | ||
| "<asset_name_n>" : metadata, | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again not valid CDDL |
||
| metadata_field = | ||
| metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata | ||
| / metadata_map ; Multi-metadata is now supported as in CIP-0025 | ||
|
|
||
| ; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring. | ||
| ; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain). | ||
| ; Data URLs (on-chain data) must comply to RFC2397. | ||
|
|
@@ -314,9 +402,9 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8 | |
| ; and needs to be at least Unit/Void: #6.121([]) | ||
| extra = plutus_data | ||
|
|
||
| datum = #6.121([metadata, version, extra]) | ||
| datum = #6.121([metadata_field, version, extra]) | ||
|
|
||
| version = 1 / 2 / 3 | ||
| version = 1 / 2 / 3 / 4 | ||
| ``` | ||
|
|
||
| Example datum as JSON: | ||
|
|
@@ -360,7 +448,9 @@ to lookup. The steps are | |
| 1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` | ||
| 2. Look up `reference NFT` and find the output it's locked in. | ||
| 3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. | ||
| 4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false) | ||
| 5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name` | ||
|
|
||
| ##### Retrieve metadata from a Plutus validator | ||
|
|
||
|
|
@@ -403,9 +493,12 @@ Example:\ | |
|
|
||
| ##### Metadata | ||
|
|
||
| This is a low-level representation of the metadata, following closely the structure of CIP-0025 with the optional | ||
| decimals field added. All UTF-8 encoded keys and values need to be converted into their respective byte's representation | ||
| when creating the datum on-chain. | ||
| This is either: | ||
|
|
||
| 1. A low-level direct representation of the metadata, following closely the structure of CIP-0025 with the optional decimals field added | ||
| 2. A 721-ERC-style token mapping exactly matching the structure of CIP-0025 | ||
|
|
||
| All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain. | ||
|
|
||
| ``` | ||
| files_details = | ||
|
|
@@ -430,19 +523,39 @@ metadata = | |
| ; ... Additional properties are allowed | ||
| } | ||
|
|
||
| metadata_map = | ||
| { | ||
| __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict | ||
|
|
||
| "721": | ||
| { | ||
| ; As many of the below as needed based on which reference tokens are added | ||
| "<policy_id>": | ||
| { | ||
| "<asset_name_1>" : metadata, | ||
| ; ... | ||
| "<asset_name_n>" : metadata, | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again not valid CDDL |
||
| metadata_field = | ||
| metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata | ||
| / metadata_map ; Multi-metadata is now supported as in CIP-0025 | ||
|
|
||
| ; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring. | ||
| ; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain). | ||
| ; Data URLs (on-chain data) must comply to RFC2397. | ||
| uri = bounded_bytes ; UTF-8 | ||
| uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8 | ||
|
|
||
| ; Custom user defined plutus data. | ||
| ; Setting data is optional, but the field is required | ||
| ; and needs to be at least Unit/Void: #6.121([]) | ||
| extra = plutus_data | ||
|
|
||
| datum = #6.121([metadata, version, extra]) | ||
| datum = #6.121([metadata_field, version, extra]) | ||
|
|
||
| version = 3 | ||
| version = 3 / 4 | ||
| ``` | ||
|
|
||
| Example datum as JSON: | ||
|
|
@@ -502,7 +615,9 @@ to lookup. The steps are | |
| 1. Construct `reference NFT` from `user token`: `d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken` | ||
| 2. Look up `reference NFT` and find the output it's locked in. | ||
| 3. Get the datum from the output and lookup metadata by going into the first field of constructor 0. | ||
| 4. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 4. Determine whether this is a direct metadata or the CIP-0025 map style using the `__RESERVE_KEYWORD_721_V4__` map value (if present, default false) | ||
| 5. Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex. | ||
| 6. For multi-map style metadata, return only the JSON values inside the matching path: `721`->>`policy_id`->>`asset_name` | ||
|
|
||
| ##### Retrieve metadata from a Plutus validator | ||
|
|
||
|
|
@@ -551,7 +666,8 @@ version of these tokens from any point in time with the following format: | |
| 1. [6d897eb](https://github.com/cardano-foundation/CIPs/tree/6d897eb60805a58a3e54821fe61284d5c5903764/CIP-XXXX) | ||
| 2. [45fa23b](https://github.com/cardano-foundation/CIPs/tree/45fa23b60806367a3e52231e552c4d7654237678/CIP-XXXX) | ||
| 3. [bfc6fde](https://github.com/cardano-foundation/CIPs/tree/bfc6fde340280d8b51f5a7131b57f4cc6cc5f260/CIP-XXXX) | ||
| 4. **Current** | ||
| 4. [YYYYYYY](https://github.com/cardano-foundation/CIPs/tree/abcdefabcdefabcdefabcdefabcdefabcdefabcd/CIP-XXXX) | ||
| 5. **Next Editor** | ||
| ``` | ||
|
|
||
| Each time a new version is introduced the previous version's link MUST be updated to match the last commit corresponding | ||
|
|
@@ -578,6 +694,10 @@ versions of the affected tokens. `asset_name_labels` **MUST** only be marked obs | |
|
|
||
| - Added [* bounded_bytes] support to the image and src tags on the metadata | ||
|
|
||
| #### version 4 | ||
|
|
||
| - Add backwards-compatible support for multi-asset 721-ERC-style metadata mappings | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Backwards-compatible" with what exactly? |
||
|
|
||
| ## Rationale: how does this CIP achieve its goals? | ||
|
|
||
| Without separation of `reference NFT` and `user token` you lose all flexibility and moving the `user token` would be | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
This is confusing. Why referencing 721-ERC-style here? What does this mean? This is an Ethereum standard and it is not referenced anywhere. The only link with CIP25 is the 721 metadata label.
Also "mapping exactly matching the structure of CIP-0025" is also confusing. I think you are only talking about the
policy_id -> asset_namemapping? The rest is different (222/333/444, bytes instead of strings, etc.). Also only CIP25v2 use bytes as keys in the mapping.Note that "following closely the structure of CIP-0025" was about the individual asset metadata (name, image, files, etc.). Whereas you seem to talk about its encapsulation in
policy_id -> asset_namemaps.