@@ -155,16 +155,20 @@ The `user token` represents an NFT (non-fungible token).
155155
156156##### Pattern
157157
158- The ` user token ` and ` reference NFT ` MUST have an identical name, preceded by the ` asset_name_label ` prefix.
158+ The ` user token ` and ` reference NFT ` MUST have an identical name (heretofore entitled ` asset_name ` ) , preceded by the ` asset_name_label ` prefix.
159159
160160Example:\
161161` user token ` : ` (222)Test123 ` \
162162` reference NFT ` : ` (100)Test123 `
163163
164164##### Metadata
165165
166- This is a low-level representation of the metadata, following closely the structure of CIP-0025. All UTF-8 encoded keys
167- and values need to be converted into their respective byte's representation when creating the datum on-chain.
166+ This is either:
167+
168+ 1 . A low-level direct representation of the metadata, following closely the structure of CIP-0025
169+ 2 . A 721-ERC-style token mapping exactly matching the structure of CIP-0025
170+
171+ All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain.
168172
169173```
170174files_details =
@@ -188,6 +192,26 @@ metadata =
188192 ; ... Additional properties are allowed
189193 }
190194
195+ metadata_map =
196+ {
197+ __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict
198+
199+ "721":
200+ {
201+ ; As many of the below as needed based on which reference tokens are added
202+ "<policy_id>":
203+ {
204+ "<asset_name_1>" : metadata,
205+ ; ...
206+ "<asset_name_n>" : metadata,
207+ }
208+ }
209+ }
210+
211+ metadata_field =
212+ metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
213+ / metadata_map ; Multi-metadata is now supported as in CIP-0025
214+
191215; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
192216; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
193217; Data URLs (on-chain data) must comply to RFC2397.
@@ -198,12 +222,12 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8
198222; and needs to be at least Unit/Void: #6.121([])
199223extra = plutus_data
200224
201- datum = #6.121([metadata , version, extra])
225+ datum = #6.121([metadata_field , version, extra])
202226
203- version = 1 / 2 / 3
227+ version = 1 / 2 / 3 / 4
204228```
205229
206- Example datum as JSON:
230+ Example datum as JSON (direct metadata) :
207231
208232``` json
209233{
@@ -236,6 +260,45 @@ Example datum as JSON:
236260}
237261```
238262
263+ Example datum as JSON (721-style):
264+
265+ ``` json
266+ {
267+ "constructor" : 0 ,
268+ "fields" : [
269+ {
270+ "map" : [
271+ {
272+ "k" : { "bytes" : " 373231" },
273+ "v" : {
274+ "map" : [
275+ {
276+ "k" : { "bytes" : " 5370616365427564204131" },
277+ "v" : {
278+ "map" : [
279+ {
280+ "k" : { "bytes" : " 6E616D65" },
281+ "v" : { "bytes" : " 5370616365427564" }
282+ },
283+ {
284+ "k" : { "bytes" : " 696D616765" },
285+ "v" : { "bytes" : " 697066733A2F2F74657374" }
286+ }
287+ ]
288+ }
289+ }
290+ ]
291+ }
292+ }
293+ ]
294+ },
295+ {
296+ "int" : 4
297+ }
298+ ]
299+ }
300+ ```
301+
239302##### Retrieve metadata as 3rd party
240303
241304A third party has the following NFT ` d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(222)TestToken ` they want
@@ -244,7 +307,9 @@ to lookup. The steps are
2443071 . Construct ` reference NFT ` from ` user token ` : ` d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken `
2453082 . Look up ` reference NFT ` and find the output it's locked in.
2463093 . Get the datum from the output and lookup metadata by going into the first field of constructor 0.
247- 4 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
310+ 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)
311+ 5 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
312+ 6 . For multi-map style metadata, return only the JSON values inside the matching path: ` 721 ` ->>` policy_id ` ->>` asset_name `
248313
249314##### Retrieve metadata from a Plutus validator
250315
@@ -274,17 +339,20 @@ The `user token` is an FT (fungible token).
274339
275340##### Pattern
276341
277- The ` user token ` and ` reference NFT ` MUST have an identical name, preceded by the ` asset_name_label ` prefix.
342+ The ` user token ` and ` reference NFT ` MUST have an identical name (heretofore called ` asset_name ` ) , preceded by the ` asset_name_label ` prefix.
278343
279344Example:\
280345` user token ` : ` (333)Test123 ` \
281346` reference NFT ` : ` (100)Test123 `
282347
283348##### Metadata
284349
285- This is a low-level representation of the metadata, following closely the structure of the Cardano foundation off-chain
286- metadata registry. All UTF-8 encoded keys and values need to be converted into their respective byte's representation
287- when creating the datum on-chain.
350+ This is either:
351+
352+ 1 . A low-level direct representation of the metadata, following closely the structure of the Cardano foundation off-chain metadata registry
353+ 2 . A 721-ERC-style token mapping exactly matching the structure of CIP-0025
354+
355+ All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain.
288356
289357```
290358; Explanation here: https://developers.cardano.org/docs/native-tokens/token-registry/cardano-token-registry/
@@ -304,6 +372,26 @@ metadata =
304372 ; ... Additional properties are allowed
305373 }
306374
375+ metadata_map =
376+ {
377+ __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict
378+
379+ "721":
380+ {
381+ ; As many of the below as needed based on which reference tokens are added
382+ "<policy_id>":
383+ {
384+ "<asset_name_1>" : metadata,
385+ ; ...
386+ "<asset_name_n>" : metadata,
387+ }
388+ }
389+ }
390+
391+ metadata_field =
392+ metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
393+ / metadata_map ; Multi-metadata is now supported as in CIP-0025
394+
307395; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
308396; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
309397; Data URLs (on-chain data) must comply to RFC2397.
@@ -314,9 +402,9 @@ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8
314402; and needs to be at least Unit/Void: #6.121([])
315403extra = plutus_data
316404
317- datum = #6.121([metadata , version, extra])
405+ datum = #6.121([metadata_field , version, extra])
318406
319- version = 1 / 2 / 3
407+ version = 1 / 2 / 3 / 4
320408```
321409
322410Example datum as JSON:
@@ -360,7 +448,9 @@ to lookup. The steps are
3604481 . Construct ` reference NFT ` from ` user token ` : ` d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken `
3614492 . Look up ` reference NFT ` and find the output it's locked in.
3624503 . Get the datum from the output and lookup metadata by going into the first field of constructor 0.
363- 4 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
451+ 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)
452+ 5 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
453+ 6 . For multi-map style metadata, return only the JSON values inside the matching path: ` 721 ` ->>` policy_id ` ->>` asset_name `
364454
365455##### Retrieve metadata from a Plutus validator
366456
@@ -403,9 +493,12 @@ Example:\
403493
404494##### Metadata
405495
406- This is a low-level representation of the metadata, following closely the structure of CIP-0025 with the optional
407- decimals field added. All UTF-8 encoded keys and values need to be converted into their respective byte's representation
408- when creating the datum on-chain.
496+ This is either:
497+
498+ 1 . A low-level direct representation of the metadata, following closely the structure of CIP-0025 with the optional decimals field added
499+ 2 . A 721-ERC-style token mapping exactly matching the structure of CIP-0025
500+
501+ All UTF-8 encoded keys and values need to be converted into their respective byte's representation when creating the datum on-chain.
409502
410503```
411504files_details =
@@ -430,19 +523,39 @@ metadata =
430523 ; ... Additional properties are allowed
431524 }
432525
526+ metadata_map =
527+ {
528+ __RESERVE_KEYWORD_721_V4__ : bool, ; Long name to avoid conflict
529+
530+ "721":
531+ {
532+ ; As many of the below as needed based on which reference tokens are added
533+ "<policy_id>":
534+ {
535+ "<asset_name_1>" : metadata,
536+ ; ...
537+ "<asset_name_n>" : metadata,
538+ }
539+ }
540+ }
541+
542+ metadata_field =
543+ metadata ; For backwards-compatibility in v4 onward, a map itself is valid metadata
544+ / metadata_map ; Multi-metadata is now supported as in CIP-0025
545+
433546; A valid Uniform Resource Identifier (URI) as a UTF-8 encoded bytestring.
434547; The URI scheme must be one of `https` (HTTP), `ipfs` (IPFS), `ar` (Arweave) or `data` (on-chain).
435548; Data URLs (on-chain data) must comply to RFC2397.
436- uri = bounded_bytes ; UTF-8
549+ uri = bounded_bytes / [ * bounded_bytes ] ; UTF-8
437550
438551; Custom user defined plutus data.
439552; Setting data is optional, but the field is required
440553; and needs to be at least Unit/Void: #6.121([])
441554extra = plutus_data
442555
443- datum = #6.121([metadata , version, extra])
556+ datum = #6.121([metadata_field , version, extra])
444557
445- version = 3
558+ version = 3 / 4
446559```
447560
448561Example datum as JSON:
@@ -502,7 +615,9 @@ to lookup. The steps are
5026151 . Construct ` reference NFT ` from ` user token ` : ` d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc.(100)TestToken `
5036162 . Look up ` reference NFT ` and find the output it's locked in.
5046173 . Get the datum from the output and lookup metadata by going into the first field of constructor 0.
505- 4 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
618+ 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)
619+ 5 . Convert to JSON and encode all string entries to UTF-8 if possible, otherwise leave them in hex.
620+ 6 . For multi-map style metadata, return only the JSON values inside the matching path: ` 721 ` ->>` policy_id ` ->>` asset_name `
506621
507622##### Retrieve metadata from a Plutus validator
508623
@@ -551,7 +666,8 @@ version of these tokens from any point in time with the following format:
5516661. [6d897eb](https://github.com/cardano-foundation/CIPs/tree/6d897eb60805a58a3e54821fe61284d5c5903764/CIP-XXXX)
5526672. [45fa23b](https://github.com/cardano-foundation/CIPs/tree/45fa23b60806367a3e52231e552c4d7654237678/CIP-XXXX)
5536683. [bfc6fde](https://github.com/cardano-foundation/CIPs/tree/bfc6fde340280d8b51f5a7131b57f4cc6cc5f260/CIP-XXXX)
554- 4. **Current**
669+ 4. [YYYYYYY](https://github.com/cardano-foundation/CIPs/tree/abcdefabcdefabcdefabcdefabcdefabcdefabcd/CIP-XXXX)
670+ 5. **Next Editor**
555671```
556672
557673Each 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
578694
579695- Added [ * bounded_bytes] support to the image and src tags on the metadata
580696
697+ #### version 4
698+
699+ - Add backwards-compatible support for multi-asset 721-ERC-style metadata mappings
700+
581701## Rationale: how does this CIP achieve its goals?
582702
583703Without separation of ` reference NFT ` and ` user token ` you lose all flexibility and moving the ` user token ` would be
0 commit comments