diff --git a/CIP-0010/registry.json b/CIP-0010/registry.json index 7a1a85b0b..56927b7fa 100644 --- a/CIP-0010/registry.json +++ b/CIP-0010/registry.json @@ -33,7 +33,11 @@ }, { "transaction_metadatum_label": 839, - "description": "Agora - Proposal creation metadata" + "description": "Agora - Proposal creation metadata" + }, + { + "transaction_metadatum_label": 867, + "description": "CIP-0088 - Token Policy Registration Standard" }, { "transaction_metadatum_label": 888, diff --git a/CIP-0088/CIPs/0025/CIP25_v1.cddl b/CIP-0088/CIPs/0025/CIP25_v1.cddl new file mode 100644 index 000000000..54c640245 --- /dev/null +++ b/CIP-0088/CIPs/0025/CIP25_v1.cddl @@ -0,0 +1,7 @@ +; CIP-0025: Token Metadata Standard +; Version: 1 + +cip25-details = { + ? 0 : uint, ; version + 1 : token-project-details ; [CIP-0025 Token Project Details](../common/token-project-details.cddl) +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0025/CIP25_v1.json b/CIP-0088/CIPs/0025/CIP25_v1.json new file mode 100644 index 000000000..45f4bc3c4 --- /dev/null +++ b/CIP-0088/CIPs/0025/CIP25_v1.json @@ -0,0 +1,40 @@ +{ + "25": { + "0": 1, + "1": { + "0": "SpaceBudz", + "1": [ + "10,000 SpaceBudz are out there.", + "Where will your SpaceBudz take you?" + ], + "2": [ + "https://", + "static.spacebudz.io", + "/images/logo.png" + ], + "3": [ + "https://", + "static.spacebudz.io", + "/images/banner.jpg" + ], + "4": 0, + "5": [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + "6": "SpaceBudz" + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0025/CIP25_v1.schema.json b/CIP-0088/CIPs/0025/CIP25_v1.schema.json new file mode 100644 index 000000000..695f72a34 --- /dev/null +++ b/CIP-0088/CIPs/0025/CIP25_v1.schema.json @@ -0,0 +1,30 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/CIPs/0025/CIP25_v1.schema.json", + "title": "CIP-25: Token Project Details", + "description": "Additional context for token policy declaring support for CIP-25 token metadata standards", + "type": "object", + "properties": { + "25": { + "type": "object", + "properties": { + "0": { + "type": "integer", + "title": "Version", + "description": "The version of the standard in use", + "minimum": 1 + }, + "1": { + "title": "Project Details", + "description": "Describe top-level details about the Token Project", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/token-project-details_v1.schema.json" + } + }, + "required": [ + "1" + ] + } + }, + "required": [ + "25" + ] +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0025/README.md b/CIP-0088/CIPs/0025/README.md new file mode 100644 index 000000000..bde83c007 --- /dev/null +++ b/CIP-0088/CIPs/0025/README.md @@ -0,0 +1,81 @@ +# CIP-88 Extension: CIP-0025 | Token Project Information + +`Version: 1` + +## Top-Level Fields + +Both CIP-25 and CIP-68 are specifications describing a standard for storing and retrieving token metadata from the +chain. To this end, we have given them the same data structure although each will utilize their own numerical index in +the feature set and CIP-Specific details section of the registration. + +These sections may be separated in the future if the respective CIPs diverge in terms of the data or information that +may be useful to provide about one format or the other in the future. + +| index | name | type | required | notes | +|-------|--------------------------|------------------|----------|-------------------------------------------------------------------------------------------------------------| +| 0 | Version | Unsigned Integer | No | Default: 1, which version of this specification is in use | +| 1 | Token Collection Details | Object | Yes | Provide additional context about this "Collection" for consumption by marketplaces, explorers, and wallets. | + +The information registered here is helpful to aggregator services and marketplaces, it applies equally to both CIP-25 +and CIP-68 metadata standards. A project utilizing one or the other should reference this documentation and include the +relevant information under index #6, prefixed by the number of the CIP (25 or 68) depending upon the metadata format. + +## Token Collection Details Fields + +| index | name | type | required | +|-------|---------------------|----------|----------| +| 0 | Collection Name | String | Yes | +| 1 | Description | Array | No | +| 2 | Project Image | UriArray | No | +| 3 | Project Banner | UriArray | No | +| 4 | NSFW Flag | 0 or 1 | No | +| 5 | Social Media | Array | No | +| 6 | Project/Artist Name | String | No | + +For details on what these fields represent and how they should be structured in the metadata, please refer to +[Token Project Details](../common/Token-Project-Details_v1.md) + +## CIP-25 Example + +```cbor +{ + 25: { + 0: 1, + 1: { + 0: "Cool NFT Project", + 1: [ + "This is a description of my project", + "longer than 64 characters so broken up into a string array" + ], + 2: [ + "https://", + "static.coolnftproject.io", + "/images/icon.png" + ], + 3: [ + "https://", + "static.coolnftproject.io", + "/images/banner1.jpg" + ], + 4: 0, + 5: [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + 6: "Virtua Metaverse" + } + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/0026/CIP26_v1.cddl b/CIP-0088/CIPs/0026/CIP26_v1.cddl new file mode 100644 index 000000000..bdced0fee --- /dev/null +++ b/CIP-0088/CIPs/0026/CIP26_v1.cddl @@ -0,0 +1,39 @@ +; CIP-0026: Fungible Token Registration Standard +; Version: 1 + +string = text .size (0..64) + +; A uri should consist of a scheme and one or more path strings describing the path to the resource +; The first entry should contain the URI "Scheme" (e.g. "https://", "ftp://", "ar://", "ipfs://") +; One or more subsequent entries should describe the path of the URI + +uri.scheme = text .size (5..64) +uri.path = text .size (1..64) +uri = { + uri.scheme, + + uri.path +} + +policy_id = bytes .size(28) +asset_name = bytes .size (0..32) + +token-asset = { + policy_id, + asset_name +} + +fungible-details = { + 0 : token-asset, ; asset identifier + 1 : string, ; token name + 2 : [* string], ; description + ? 3 : string, ; token ticker + ? 4 : uint, ; token decimals + ? 5 : uri, ; uri of token website + ? 6 : uri, ; uri of token image + ? 7 : token-asset ; beacon token identifier +} + +cip26-details = { + ? 0 : uint, ; version + 1 : [+ fungible-details] ; CIP-0026 Fungible Token Registration(s) +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0026/CIP26_v1.json b/CIP-0088/CIPs/0026/CIP26_v1.json new file mode 100644 index 000000000..53b3fcf9f --- /dev/null +++ b/CIP-0088/CIPs/0026/CIP26_v1.json @@ -0,0 +1,35 @@ +{ + "26": { + "0": 1, + "1": [ + { + "0": [ + "d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0", + "7370616365636f696e73" + ], + "1": "spacecoins", + "2": "SPACE", + "3": [ + "the OG Cardano community token", + "-", + "whatever you do, your did it!", + "", + "Learn more at https://spacecoins.io!" + ], + "4": 0, + "5": [ + "https://", + "spacecoins.io" + ], + "6": [ + "ipfs://", + "bafkreib3e5u4am2btduu5s76rdznmqgmmrd4l6xf2vpi4vzldxe25fqapy" + ], + "7": [ + "d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0", + "" + ] + } + ] + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0026/CIP26_v1.schema.json b/CIP-0088/CIPs/0026/CIP26_v1.schema.json new file mode 100644 index 000000000..52fc9c78a --- /dev/null +++ b/CIP-0088/CIPs/0026/CIP26_v1.schema.json @@ -0,0 +1,118 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/CIPs/0026/CIP26_v1.schema.json", + "title": "CIP-26: Fungible Token", + "description": "Additional context for a policy declaring support for fungible token standards", + "type": "object", + "properties": { + "26": { + "type": "object", + "properties": { + "0": { + "type": "integer", + "title": "Version", + "description": "The version of the standard in use", + "minimum": 1 + }, + "1": { + "type": "array", + "minItems": 1, + "items": { + "title": "Fungible Token Details", + "description": "Describes details about a particular fungible token under this policy", + "type": "object", + "properties": { + "0": { + "title": "Subject", + "description": "The hex-encoded Policy ID and Asset ID of the token", + "$ref": "#/$defs/tokenAsset" + }, + "1": { + "title": "Name", + "description": "The full display name of the token", + "type": "string", + "example": "spacecoins" + }, + "2": { + "title": "Symbol/Ticker", + "description": "The ticker or listing symbol for the token", + "type": "string", + "example": "SPACE" + }, + "3": { + "title": "Description", + "description": "A short description for the token", + "type": "array", + "items": { + "type": "string", + "maxLength": 64 + }, + "example": [ + "The OG Cardano Community Token","- whatever you do, your did it!" + ] + }, + "4": { + "title": "Decimals", + "description": "How many decimal places this token should be rendered with", + "type": "integer", + "example": 0, + "default": 0 + }, + "5": { + "title": "URL", + "description": "A URL to the project's web page", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json" + }, + "6": { + "title": "Logo", + "description": "A URI to the token's logo", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json" + }, + "7": { + "title": "Reference Token", + "description": "A reference to a 'Beacon Token' that can provide additional context via inline datum to smart contracts", + "$ref": "#/$defs/tokenAsset" + } + }, + "required": [ + "0", + "1", + "2" + ] + } + } + }, + "required": [ + "1" + ] + } + }, + "required": [ + "26" + ], + "$defs": { + "tokenAsset": { + "title": "Token Asset", + "description": "The hex-encoded Policy ID and hex-encoded Asset ID of the token", + "type": "array", + "minItems": 2, + "maxItems": 2, + "items": [ + { + "title": "Policy ID", + "description": "The hex-encoded Policy ID of the token", + "type": "string", + "maxLength": 56, + "minLength": 56 + }, + { + "title": "Asset ID", + "description": "The hex-encoded Asset ID of the token", + "type": "string", + "minLength": 0, + "maxLength": 64 + } + ], + "additionalItems": false + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0026/README.md b/CIP-0088/CIPs/0026/README.md new file mode 100644 index 000000000..8bb41646d --- /dev/null +++ b/CIP-0088/CIPs/0026/README.md @@ -0,0 +1,188 @@ +# CIP-88 Extension: CIP-0026 | Fungible Tokens / Monetary Policy + +`Version: 1` + +## Top-Level Fields + +| index | name | type | required | notes | +|-------|-----------------|------------------------|----------|-------------------------------------------------------------------------------------------| +| 0 | Version | Unsigned Integer | No | Default: 1, which version of this specification is in use | +| 1 | Fungible Tokens | Array\ | No | An array of one or more fungible token registration objects covered by this registration. | + +See [CIP26_v1.cddl](./CIP26_v1.cddl) for a full CBOR CDDL spec, [CIP26_v1.json](./CIP26_v1.json) as an example, and +[CIP26_v1.schema.json](./CIP26_v1.schema.json) for schema documentation. This information can replace the information +currently housed in the [Cardano Token Registry](https://github.com/cardano-foundation/cardano-token-registry) and is +based on the format currently used in those registrations along with a few additional fields. + +Because it is possible that multiple fungible tokens could be minted under a single Policy ID, the format for CIP-26 +tokens is slightly different. Here we include an array of fungible token details inside an array to enable multiple +tokens under the same policy to be registered in a single transaction. + +**Example:** + +```cbor +{ + 867: { + 0: 1, + 1: { + 6: { + 26: { + 0: 1, + 1: [ + [...Fungible Token 1 Details...], + [...Fungible Token 2 Details...] + ] + } + } + }, + 2: [...] + } +} +``` + +## Fungible Token Details Fields + +| index | name | type | required | +|-------|--------------------------------------|---------------------------------------|----------| +| 0 | [Subject](#0--subject) | [Token Identifier](#token-identifier) | Yes | +| 1 | [Token Name](#1--token-name) | String | Yes | +| 2 | [Description](#2--description) | Array | Yes | +| 3 | [Token Ticker](#3--token-ticker) | String | No | +| 4 | [Token Decimals](#4--token-decimals) | Unsigned Integer | No | +| 5 | [Token Website](#5--token-website) | [URI Array](#uri-array) | No | +| 6 | [Token Image](#6--token-image) | [URI Array](#uri-array) | No | +| 7 | [Beacon Token](#7--beacon-token) | [Token Identifier](#token-identifier) | No | + +### Field Notes + +#### 0: Subject + +***Type: [Token Identifier](#token-identifier) | Required: Yes*** + +A Token Identifier identifying the specific token being registered. + +**Example:** `[h'd894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0',h'7370616365636f696e73']` + +#### 1: Token Name + +***Type: String | Required: Yes*** + +This is the full "display name" of the token. + +**Example:** `"spacecoins"` + +#### 2: Description + +***Type: Array | Required: Yes*** + +A plain-text description for the token. This should be an array of zero or more strings. + +**Example:** `[ +"the OG Cardano community token", +"-", +"whatever you do, your did it!", +"", +"Learn more at https://spacecoins.io!" +]` + +#### 3: Token Ticker + +***Type: String | Required: No | Default: [Token Name](#1--token-name)*** + +A short "ticker" identifier for the token. Usually 1 to 5 characters. + +**Example:** `"SPACE"` + +#### 4: Token Decimals + +***Type: Unsigned Integer | Required: No | Default: 0*** + +How many decimal places this token should be treated as having to create a "whole unit". Default is 0 (no decimals). +Lovelace has 6 decimal places (1.000001) + +**Example:** `6` + +#### 5: Token Website + +**Type: [URI Array](#uri-array) | Required: No | default: Null** + +A valid [URI Array](#uri-array) object describing the URI to the token website. + +**Example:** `["https://","www.spacecoins.io"]` + +#### 6: Token Image + +**Type: [URI Array](#uri-array) | Required: No | Default: Null** + +A valid [URI Array](#uri-array) describing the URI to a thumbnail image to be used for the token. Recommended 64px by +64px resolution, transparent background PNG file. + +**Example:** `["ipfs://","bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly"]` + +#### 7: Beacon Token + +**Type: [Token Identifier](#token-identifier) | Required: No | Default: Null** + +A valid [Token Identifier](#token-identifier) to be used as a _"beacon token"_ for the project. Purposes and format +TBD. This token could be used as a reference input in smart contracts and provide context and data via inline datum. + +#### Token Identifier + +A token identifier is an array that MUST contain two entries. The first entry MUST be the byte-encoded Policy ID. The +second entry MUST be the byte-encoded Asset ID. + +**Example:** `[h'',h'']` + +#### URI Array + +A URI Array ([Schema Definition](../common/uri-array.schema.json)) is an array of two or more strings that can be +concatenated to create a valid URI. The first entry of the URI Array must define the _URI +scheme_ (`https://, ar://, ipfs://, etc`) and subsequent entries define the path and any arguments that may be required +(`www.spacecoins.io`). + +**Example:** +`["https://", "www.spacecoins.io"]`, `["ar://", "abc123"]`, `["ipfs://", "bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly"]` + +## CIP-26 Example + +```cbor +{ + 26: { + 0: 1, + 1: [ + { + 0: [ + h'd894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0', + h'7370616365636f696e73' + ], + 1: "spacecoins", + 2: [ + "the OG Cardano community token", + "-", + "whatever you do, your did it!", + "", + "Learn more at https://spacecoins.io!" + ], + 3: "SPACE", + 4: 0, + 5: ["https://","spacecoins.io"], + 6: [ + "ipfs://", + "bafkreib3e5u4am2btduu5s76rdznmqgmmrd4l6xf2vpi4vzldxe25fqapy" + ], + 7: [ + [ + "ipfs://", + "bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly" + ], + "3507afe1daf05498d764dce55e8ba41e4acecd5bf42606ac2b8b7dc2eb0c305e" + ], + 8: [ + h'd894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0', + h'7370616365636f696e74' + ] + } + ] + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/0027/CIP27_v1.cddl b/CIP-0088/CIPs/0027/CIP27_v1.cddl new file mode 100644 index 000000000..788eae0cd --- /dev/null +++ b/CIP-0088/CIPs/0027/CIP27_v1.cddl @@ -0,0 +1,15 @@ +; CIP-0027: NFT Royalty Standard +; Version: 1 + +address = [+ string] ; The address to receive royalties in BECH32 format +string = text .size (0..64) + +royalty-details = { + 1 : string ; Rate as floating point string ("0.000001" .. "1.000000") + 2 : address ; Royalty receipt address +} + +cip27-details = { + ? 0 : string, ; Version + 1 : royalty-details ; Royalty detail information +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0027/CIP27_v1.json b/CIP-0088/CIPs/0027/CIP27_v1.json new file mode 100644 index 000000000..819880acc --- /dev/null +++ b/CIP-0088/CIPs/0027/CIP27_v1.json @@ -0,0 +1,12 @@ +{ + "27": { + "0": 1, + "1": { + "0": "0.05", + "1": [ + "addr_test1qqp7uedmne8vjzue66hknx87jspg56qhkm4gp6ahyw7kaahevmtcux", + "lpy25nqhaljc70094vfu8q4knqyv6668cvwhsq64gt89" + ] + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0027/CIP27_v1.schema.json b/CIP-0088/CIPs/0027/CIP27_v1.schema.json new file mode 100644 index 000000000..362bb5679 --- /dev/null +++ b/CIP-0088/CIPs/0027/CIP27_v1.schema.json @@ -0,0 +1,50 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/CIPs/0027/CIP27_v1.schema.json", + "title": "CIP-27: Token Royalty Details", + "description": "Additional context for token policy declaring support for CIP-27 royalty standards", + "type": "object", + "properties": { + "27": { + "type": "object", + "properties": { + "0": { + "type": "integer", + "title": "Version", + "description": "The version of the standard in use", + "minimum": 1 + }, + "1": { + "title": "Royalty Details", + "description": "Describe top-level details about the Token Project", + "type": "object", + "properties": { + "0": { + "type": "string", + "title": "Royalty Rate", + "description": "Rate of royalties to charge as represented by a floating point number between 1.000000 and 0.000000" + }, + "1": { + "type": "array", + "title": "Recipient Address", + "description": "The recipient address to receive royalties in BECH32 format.", + "items": { + "type": "string", + "maxLength": 64 + } + } + }, + "required": [ + "0", + "1" + ] + } + }, + "required": [ + "1" + ] + } + }, + "required": [ + "27" + ] +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0027/README.md b/CIP-0088/CIPs/0027/README.md new file mode 100644 index 000000000..df9ce6335 --- /dev/null +++ b/CIP-0088/CIPs/0027/README.md @@ -0,0 +1,55 @@ +# CIP-88 Extension: CIP-0027 | Cardano Token Royalty Information + +`Version: 1` + +## Top Level Fields + +| index | name | type | required | notes | +|-------|-----------------|--------|----------|----------------------------------------------------------------| +| 0 | Version | UInt | No | Default: 1, which version of this specification is in use | +| 1 | Royalty Details | Object | Yes | An object detailing the project royalties as defined in CIP-27 | + +## Royalty Details Fields + +| index | name | type | required | +|-------|-------------------|-------------------|----------| +| 0 | Rate | String | Yes | +| 1 | Recipient Address | Array | Yes | + +### Field Notes + +#### 0: Rate + +***Type: String | Required: Yes*** + +This should be a floating point number between 0.000000 - 1.000000 representing the rate of royalties requested + +**Example:** `"0.05"` + +#### 1: Recipient Address + +***Type: Array | Required: Yes*** + +This should be an array containing a single Cardano Shelley-era address in BECH32 format to receive royalties + +**Example:** `[ +"addr_test1qqp7uedmne8vjzue66hknx87jspg56qhkm4gp6ahyw7kaahevmtcux", +"lpy25nqhaljc70094vfu8q4knqyv6668cvwhsq64gt89" +]` + +## CIP-27 Example + +```cbor +{ + 27: { + 0: 1, + 1: { + 0: "0.05", + 1: [ + "addr_test1qqp7uedmne8vjzue66hknx87jspg56qhkm4gp6ahyw7kaahevmtcux", + "lpy25nqhaljc70094vfu8q4knqyv6668cvwhsq64gt89" + ] + } + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/0048/CIP48_v1.cddl b/CIP-0088/CIPs/0048/CIP48_v1.cddl new file mode 100644 index 000000000..95f2553c7 --- /dev/null +++ b/CIP-0088/CIPs/0048/CIP48_v1.cddl @@ -0,0 +1,23 @@ +; CIP-0048: Metadata References Standard +; Version: 1 + +string = text .size (0..64) + +reference-payload = { + 0 : "content" / "pointer" ; Payload Type: Is the payload a direct content replacement or a pointer + 1 : +} + +reference = { + 0 : string, ; reference name (case sensitive) + 1 : reference-payload ; The payload of the reference +} + +reference-details = { + 1 : [+ reference] +} + +cip48-details = { + ? 0 : uint, ; version + 1 : reference-details ; CIP-0068 NFT Project Details +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0048/README.md b/CIP-0088/CIPs/0048/README.md new file mode 100644 index 000000000..f12870067 --- /dev/null +++ b/CIP-0088/CIPs/0048/README.md @@ -0,0 +1,50 @@ +# CIP-88 Extension: CIP-48 | Metadata References Standard + +`Version: 1` + +CIP-48 has been proposed to extend on-chain metadata formats to support "references" which could be: + +1. Shared/Repeated pieces of content +2. Pointers or References to other on-chain information + +CIP-88 could help support the definition and standardization of the reference definitions at a top-level, allowing +references declared within individual token metadata to be easily identified and replaced. + +## Top Level Fields + +| index | name | type | required | notes | +|-------|-------------------|--------|----------|------------------------------------------------------------| +| 0 | Version | UInt | No | Default "1", which version of this specification is in use | +| 1 | Reference Details | Object | Yes | An object detailing CIP-48 references in use | + +## Reference Details Fields + +| index | name | type | required | notes | +|-------|------------|-------------------|----------|------------------------| +| 1 | References | Array\ | No | An array of References | + + +## Reference Fields + +| index | name | type | required | notes | +|-------|---------|--------|----------|-----------------------------------------------------------------------------------------------------------------------| +| 0 | Name | String | Yes | A case sensitive path identifier for this reference | +| 1 | Type | Enum | Yes | An enum of accepted types of references which may include direct payloads or pointers to other sources of information | +| 2 | Payload | Object | Yes | A "Reference Payload" object containing the information to be substituted in place of the reference | + +**TODO: Expand Support for CIP-48** + +## CIP-48 Example + +```cbor +{ + 48: { + 0: 1, + 1: { + 0: '', + 1: '', + 2: {} + } + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/0060/CIP60_v1.cddl b/CIP-0088/CIPs/0060/CIP60_v1.cddl new file mode 100644 index 000000000..e828a9475 --- /dev/null +++ b/CIP-0088/CIPs/0060/CIP60_v1.cddl @@ -0,0 +1,13 @@ +; CIP-0060: Music Token Metadata Standard +; Version: 1 + +string = text .size (0..64) + +music-token-details = { + ; TBD +} + +cip60-details = { + ? 0 : uint ; version + 1 : music-token-details ; CIP-0060 Music NFT Details +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0060/README.md b/CIP-0088/CIPs/0060/README.md new file mode 100644 index 000000000..3b8e670ee --- /dev/null +++ b/CIP-0088/CIPs/0060/README.md @@ -0,0 +1,5 @@ +# CIP-88 Extension: CIP-60 | Music Token Metadata Standard + +`Version: 1` + +**TODO: Expand Support for CIP-60** \ No newline at end of file diff --git a/CIP-0088/CIPs/0068/CIP68_v1.cddl b/CIP-0088/CIPs/0068/CIP68_v1.cddl new file mode 100644 index 000000000..152a08f13 --- /dev/null +++ b/CIP-0088/CIPs/0068/CIP68_v1.cddl @@ -0,0 +1,7 @@ +; CIP-0068: Token Metadata Standard +; Version: 1 + +cip68-details = { + ? 0 : uint, ; version + 1 : token-project-details ; [CIP-0068 Token Project Details](../common/token-project-details.cddl) +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0068/CIP68_v1.json b/CIP-0088/CIPs/0068/CIP68_v1.json new file mode 100644 index 000000000..6489287df --- /dev/null +++ b/CIP-0088/CIPs/0068/CIP68_v1.json @@ -0,0 +1,40 @@ +{ + "68": { + "0": 1, + "1": { + "0": "SpaceBudz", + "1": [ + "10,000 SpaceBudz are out there.", + "Where will your SpaceBudz take you?" + ], + "2": [ + "https://", + "static.spacebudz.io", + "/images/logo.png" + ], + "3": [ + "https://", + "static.spacebudz.io", + "/images/banner.jpg" + ], + "4": 0, + "5": [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + "6": "SpaceBudz" + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0068/CIP68_v1.schema.json b/CIP-0088/CIPs/0068/CIP68_v1.schema.json new file mode 100644 index 000000000..f2f4108dc --- /dev/null +++ b/CIP-0088/CIPs/0068/CIP68_v1.schema.json @@ -0,0 +1,30 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/CIPs/0068/CIP68_v1.schema.json", + "title": "CIP-68: Token Project Details", + "description": "Additional context for token policy declaring support for CIP-68 token metadata standards", + "type": "object", + "properties": { + "68": { + "type": "object", + "properties": { + "0": { + "type": "integer", + "title": "Version", + "description": "The version of the standard in use", + "minimum": 1 + }, + "1": { + "title": "Project Details", + "description": "Describe top-level details about the Token Project", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/token-project-details_v1.schema.json" + } + }, + "required": [ + "1" + ] + } + }, + "required": [ + "68" + ] +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0068/README.md b/CIP-0088/CIPs/0068/README.md new file mode 100644 index 000000000..39684ad7c --- /dev/null +++ b/CIP-0088/CIPs/0068/README.md @@ -0,0 +1,81 @@ +# CIP-88 Extension: CIP-0066 | Datum Token Project Information + +`Version: 1` + +## Top-Level Fields + +Both CIP-25 and CIP-68 are specifications describing a standard for storing and retrieving token metadata from the +chain. To this end, we have given them the same data structure although each will utilize their own numerical index in +the feature set and CIP-Specific details section of the registration. + +These sections may be separated in the future if the respective CIPs diverge in terms of the data or information that +may be useful to provide about one format or the other in the future. + +| index | name | type | required | notes | +|-------|--------------------------|------------------|----------|-------------------------------------------------------------------------------------------------------------| +| 0 | Version | Unsigned Integer | No | Default: 1, which version of this specification is in use | +| 1 | Token Collection Details | Object | Yes | Provide additional context about this "Collection" for consumption by marketplaces, explorers, and wallets. | + +The information registered here is helpful to aggregator services and marketplaces, it applies equally to both CIP-25 +and CIP-68 metadata standards. A project utilizing one or the other should reference this documentation and include the +relevant information under index #6, prefixed by the number of the CIP (25 or 68) depending upon the metadata format. + +## Token Collection Details Fields + +| index | name | type | required | +|-------|---------------------|----------|----------| +| 0 | Collection Name | String | Yes | +| 1 | Description | Array | No | +| 2 | Project Image | UriArray | No | +| 3 | Project Banner | UriArray | No | +| 4 | NSFW Flag | 0 or 1 | No | +| 5 | Social Media | Array | No | +| 6 | Project/Artist Name | String | No | + +For details on what these fields represent and how they should be structured in the metadata, please refer to +[Token Project Details](../common/Token-Project-Details_v1.md) + +## CIP-68 Example + +```cbor +{ + 68: { + 0: 1, + 1: { + 0: "SpaceBudz v2", + 1: [ + "This is a description of my project", + "longer than 64 characters so broken up into a string array" + ], + 2: [ + "https://", + "static.coolnftproject.io", + "/images/icon.png" + ], + 3: [ + "https://", + "static.coolnftproject.io", + "/images/banner1.jpg" + ], + 4: 0, + 5: [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + 6: "SpaceBudz" + } + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/0086/CIP86_v1.cddl b/CIP-0088/CIPs/0086/CIP86_v1.cddl new file mode 100644 index 000000000..0e6975a06 --- /dev/null +++ b/CIP-0088/CIPs/0086/CIP86_v1.cddl @@ -0,0 +1,10 @@ +; CIP-86: Token Metadata Update Oracles Standard +; Version: 1 + +address = bytes + +cip86-details = { + ? 0: uint, ; version + 1: address ; main address (an address capable of providing a new address to be used for updates per CIP-0086) + 2: address ; update address (the address to monitor for metadata updates per CIP-0086) +} \ No newline at end of file diff --git a/CIP-0088/CIPs/0086/README.md b/CIP-0088/CIPs/0086/README.md new file mode 100644 index 000000000..eab53fb88 --- /dev/null +++ b/CIP-0088/CIPs/0086/README.md @@ -0,0 +1,87 @@ +# CIP-88 Extension: CIP-0086 | Token Metadata Update Oracles + +`Version: 1` + +## Top Level Fields + +| index | name | type | required | +|-------|----------------|---------------------|----------| +| 0 | version | Unsigned Integer | No | +| 1 | main address | [Address](#address) | Yes | +| 2 | update address | [Address](#address) | Yes | + +### Field Notes + +#### 0: Version + +***Type: Unsigned Integer | Required: No | Default: 1*** + +The version of this standard being used + +#### 1: Main Address + +***Type: [Address](#address) | Required: Yes*** + +An address capable of providing a new address to be used for updates +per [CIP-0086](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0086). + +#### 2: Update Address + +***Type: [Address](#address) | Required: Yes*** + +The address to monitor for metadata updates +per [CIP-0086](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0086). + +## Address + +**Type: Array\** + +An address should be represented in the metadata (JSON) as an array of strings using the hex-encoded address value. + +In CBOR, the Address should be represented as a byte-encoded string. + +### Examples + +#### Enterprise Address + +**JSON** +```json +{ + "1": ["613d4d8113505bc64686c7baf802b4ce14c9e203f8a3cd4377babfb3a3"] +} +``` + +**CBOR** +```cbor +{ + 1: h'613d4d8113505bc64686c7baf802b4ce14c9e203f8a3cd4377babfb3a3' +} +``` + +#### Staking Address + +**JSON** +```json +{ + "1": ["01640020a2dafc5f336104f78afe924637c06f269b207ed44782a105f0", "8910cb650afd1bd6cf3fc1480887bfe5d211a0770d0d3fd70fc8e6b9"] +} +``` + +**CBOR** +```cbor +{ + 1: h'01640020a2dafc5f336104f78afe924637c06f269b207ed44782a105f08910cb650afd1bd6cf3fc1480887bfe5d211a0770d0d3fd70fc8e6b9' +} +``` + +## CIP-86 Example + +```cbor +{ + 86: { + 0: 1, ; Version + 1: h'613d4d8113505bc64686c7baf802b4ce14c9e203f8a3cd4377babfb3a3', ; Main Address + 2: h'01640020a2dafc5f336104f78afe924637c06f269b207ed44782a105f08910cb650afd1bd6cf3fc1480887bfe5d211a0770d0d3fd70fc8e6b9' ; Update Address + } +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/README.md b/CIP-0088/CIPs/README.md new file mode 100644 index 000000000..9467373c1 --- /dev/null +++ b/CIP-0088/CIPs/README.md @@ -0,0 +1,32 @@ +# CIP-0088: CIP-Specific Details + +This document describes the format and standards to be used when adding a CIP-specific extension to CIP-88. + +## Why CIP-Specific Extensions? + +The CIP-88 Standard was developed to be future-proof and extensible from the beginning and is the primary rationale for +including CIP-Specific fields and information in a separately versioned and documented format to allow individual +components of the standard to expand and develop at their own pace while keeping the core functionality of the standard +unchanged. + +The hope is that this method will provide for ultimate flexibility while making it easy for downstream integrators to +provide functionality for the pieces of information that they choose to explicitly accept. + +## Documentation Format + +Each CIP-Specific Extension to CIP-88 MUST include a readme documentation of the specified fields as well as a CBOR +CDDL file describing the on-ledger format of the metadata. A JSON example and schema document SHOULD also be included. + +CIP-Specific Extensions to CIP-88 SHOULD only be added after the referenced CIP has achieved `Active` status following +community review and CIP-88 Extensions MUST be added as separate pull requests to further undergo community review and +feedback prior to acceptance as part of the CIP-88 standard. + +CIP-Specific Extensions documentation MUST be placed within a zero-prefixed directory with the CIP numerical ID within +this directory. + +All documents SHOULD follow the format and naming examples found in the [Templates](./template) directory. + + + + + diff --git a/CIP-0088/CIPs/common/CIP88_Master_v1.cddl b/CIP-0088/CIPs/common/CIP88_Master_v1.cddl new file mode 100644 index 000000000..b59b07551 --- /dev/null +++ b/CIP-0088/CIPs/common/CIP88_Master_v1.cddl @@ -0,0 +1,88 @@ +; CIP-0088 Cardano Registration Certificates +; Version: 1 + +; Definitions +string = text .size (0..64) + +; A token-asset is a reference to a specific token + +policy-id = bytes .size (28) ; Policy ID bytes +asset-id = bytes .size (0..32) ; Asset ID bytes + +token-asset = { + policy-id, + asset-id +} + +; A uri should consist of a scheme and one or more path strings describing the path to the resource +; The first entry should contain the URI "Scheme" (e.g. "https://", "ftp://", "ar://", "ipfs://") +; One or more subsequent entries should describe the path of the URI + +uri.scheme = text .size (5..64) +uri.path = text .size (1..64) +uri = { + uri.scheme, + + uri.path +} + +; CIP Details +; +; CIP-Specific details should each be documented in their own versioned file for historic compatibility and future-proofing +; against changes to the specification. Wherever possible, future specs should honor previous fields and be only additive +; where possible. Previously used numeric indexes should never be repurposed. + +cip-details = { + ? 25 : cip25-details, ; ./cip/CIP-25_v1.cddl + ? 26 : cip26-details, ; ./cip/CIP-26_v1.cddl + ? 27 : cip27-details, ; ./cip/CIP-27_v1.cddl + ? 48 : cip48-details, ; ./cip/CIP-48_v1.cddl + ? 60 : cip60-details, ; ./cip/CIP-60_v1.cddl + ? 68 : cip68-details ; ./cip/CIP-68_v1.cddl + ? 86 : cip86-details ; ./cip/CIP-86_v1.cddl +} + +; Registration Scopes +; +; Each registration should begin with a scope declaring the type of object being registered + +token-scope = { + 0, ; scope identifier + bytes .size (28), ; Token Policy ID + [+ bytes .size (1..64)] ; Token Policy Hex +} + +; Validation Methods +; 0 = Ed25519 Key Signature +; 1 = "Beacon" or Reference Token Mint (CIP-27 "Nameless" Token) + +validation.method = uint; +validation.context = string; + +validation-details = { + validation.method, + * validation.context +} + +scope-details = { + 1 : token-scope ; Registration scope + 2 : [* uint], ; Feature Set + 3 : validation-details, ; Signature Method + 4 : uint, ; Nonce + ? 5 : uri, ; Oracle URI + ? 6 : cip-details ; CIP-specific details +} + +witness = { + bytes .size (32), ; Public Key + bytes .size (64) ; Signature +} + +witnesses = [+ witness] + +cip88-registration = { + ? 0 : uint, ; version + 1 : scope-details, + ? 2 : witnesses +} + +metadata = { 867 : uint => cip88-registration } \ No newline at end of file diff --git a/CIP-0088/CIPs/common/README.md b/CIP-0088/CIPs/common/README.md new file mode 100644 index 000000000..4200863fd --- /dev/null +++ b/CIP-0088/CIPs/common/README.md @@ -0,0 +1,21 @@ +# CIP-88: Common Properties + +We use this common directory to declare some definitions that are shared across multiple points of the standard to +decrease redundant declarations and hopefully minify errors. + +## CIP-88 Master CDDL Specification + +The master, top-level CIP-88 CDDL specification is declared in [CIP-88 Master CDDL](./CIP88_Master_v1.cddl). + +## URI Array Schema + +CIP-88 defines a "URI Array" as a well-formed array that can be used to declare URIs in metadata in a standardized way +that is easy to reconstruct when the length of a URI may exceed the string length available to on-chain metadata objects. + +View [URI Array Schema](./uri-array.schema.json) for details. + +## Token Project Details Schema + +CIP-25 and CIP-68 share commonality in that both represent token project "collections" that have many frequent/recurring +definitions that must be shared with explorers and marketplaces. We declare a common and shared structure for this +"collection data" that is documented further at [Token Project Details v1](./Token-Project-Details_v1.md). \ No newline at end of file diff --git a/CIP-0088/CIPs/common/Token-Project-Details_v1.md b/CIP-0088/CIPs/common/Token-Project-Details_v1.md new file mode 100644 index 000000000..400f71153 --- /dev/null +++ b/CIP-0088/CIPs/common/Token-Project-Details_v1.md @@ -0,0 +1,215 @@ +# CIP-88: NFT Project Details Specification + +`Version: 1` + +The Token Project Details specification attempts to provide top-level information about Token Projects for consumption +by wallets, blockchain explorers, and marketplaces to help avoid the hassle of project creators and maintainers needing +to notify and update all potential consumers about the details (name, description, etc) of their project. + +It is broken out as a CIP-88 "Common" element as it is shared by at least CIP-25 and CIP-68 projects and potentially +other standards in the future. + +***NFT Project Details Fields*** + +| Index | Name | Type | Required | +|-------|-----------------------------------------------|--------|----------| +| 0 | [Collection Name](#0--Collection-Name) | String | Yes | +| 1 | [Description](#1--Description) | Array | No | +| 2 | [Project Image](#2--Project-Image) | URI | No | +| 3 | [Project Banner](#3--Project-Banner) | URI | No | +| 4 | [NSFW Flag](#4--NSFW-Flag) | 0 or 1 | No | +| 5 | [Social Media](#5--Social-Media) | Array | No | +| 6 | [Project/Artist Name](#6--ProjectArtist-Name) | String | No | + +**CBOR CDDL Specification** + +A dedicated CDDL file can be found at: [token-project-details_v1.cddl](./token-project-details_v1.cddl) + +```cbor +; Token Project Details CDDL +; Version: 1 + +string = text .size (0..64) + +; A uri should consist of a scheme and one or more path strings describing the path to the resource +; The first entry should contain the URI "Scheme" (e.g. "https://", "ftp://", "ar://", "ipfs://") +; One or more subsequent entries should describe the path of the URI + +uri.scheme = text .size (5..64) +uri.path = text .size (1..64) +uri = { + uri.scheme, + + uri.path +} + +; NFT Project Details +; +; Provide top-level information about NFT projects that can be useful to marketplaces and explorers + +social-media-uri = { + string, ; social media channel name + uri ; social media URI +} + +token-project-details = { + 0 : string, ; Collection Name + ? 1 : [* string], ; Description + ? 2 : uri, ; Project Image + ? 3 : uri, ; Project Banner + ? 4 : 0 / 1, ; NSFW Flag (1 = true, 0 = false) + ? 5 : [* social-media-uri], ; Project social media + ? 6 : string ; Project/Artist Name +} +``` + +## Field Notes + +### 0: Collection Name + +***Type: String | Required: Yes*** + +The "Collection" name that applies specifically to the tokens minted under this policy. + +**Example:** `"SpaceBudz"` + +### 1: Description + +***Type: Array | Required: No*** + +An array of strings containing a brief "description" of this project + +**Example:** `["10,000 SpaceBudz are out there.","Where will your SpaceBudz take you?"]` + +### 2: Project Image + +***Type: URI | Required: No*** + +An array of strings describing a URI to a "profile image" that may be used for this project. + +**Example:** `["ipfs://", ""]` + +### 3: Project Banner + +***Type: URI | Required: No*** + +An array of strings describing a URI to a "banner image" that may be used for this project. + +**Example:** `["ar://",""]` + +### 4: NSFW Flag + +***Type: 0 or 1 | Required: No | Default: 0*** + +"Not Safe for Work" flag. Do the assets within this project contain sensitive material that may not be suitable for all +audiences and should potentially be obfuscated or hidden. 0 = no sensitive content, "Safe for Work"; 1 = sensitive +content, "Not Safe for Work" + +**Example:** `0` + +### 5: Social Media + +***Type: Array | Required: No*** + +An array of zero or more [social media handles](#social-media-handle) for the project. Each entry of the array should be +itself an array. The first entry should be a string containing the "name" of the social media platform. The second entry +should be an array describing the URI to the social media site. + +### 6: Project/Artist Name + +***Type: String | Required: No*** + +#### Social Media Handle + +***Type: Array | Required: No*** + +A social media handle must be an array consisting of two entries. The first entry should be the string social media +platform identifier (i.e. `Twitter, Discord, etc`) while the second entry must be a _URI +Array_ ([Schema Definition](./uri-array.schema.json)) consisting of two or more elements. The first element of the URI +array MUST contain the URI Scheme as a string, while one or more subsequent string entries represent the URI path. + +**Specification (CBOR)** + +```cbor +social-media-title = text .size (1..64) +uri.scheme = text .size (5..64) +uri.path = text .size (1..64) + +social-media-handle = { + social-media-title, ; Name of the social media platform (for labelling purposes) + { ; URI Definition + uri.scheme, ; URI Scheme (i.e. https://, ar://, ipfs://, ftp://) + + uri.path ; One or more strings describing the path to the resource + } +} +``` + +**Example:** + +```cbor +[ + [ + "Twitter", + [ + "https://", + "twitter.com" + ] + ], + [ + "Discord", + [ + "https://", + "discord.gg/", + "buffybot" + ] + ] +] +``` + +### 6: Project/Artist Name + +***Type: String | Required: No*** + +If this policy is part of a larger project or series from a specific artist or project, this field can be used to +contain that name. + +**Example:** `"Alessandro Konrad"` + +## Complete Example + +```cbor +{ + 0: "Cool NFT Project", + 1: [ + "This is a description of my project", + "longer than 64 characters so broken up into a string array" + ], + 2: [ + "https://", + "static.coolnftproject.io", + "/images/icon.png" + ], + 3: [ + "https://", + "static.coolnftproject.io", + "/images/banner1.jpg" + ], + 4: 0, + 5: [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + 6: "Virtua Metaverse" +} +``` \ No newline at end of file diff --git a/CIP-0088/CIPs/common/token-project-details_v1.cddl b/CIP-0088/CIPs/common/token-project-details_v1.cddl new file mode 100644 index 000000000..f05de5668 --- /dev/null +++ b/CIP-0088/CIPs/common/token-project-details_v1.cddl @@ -0,0 +1,34 @@ +; Token Project Details CDDL +; Version: 1 + +string = text .size (0..64) + +; A uri should consist of a scheme and one or more path strings describing the path to the resource +; The first entry should contain the URI "Scheme" (e.g. "https://", "ftp://", "ar://", "ipfs://") +; One or more subsequent entries should describe the path of the URI + +uri.scheme = text .size (5..64) +uri.path = text .size (1..64) +uri = { + uri.scheme, + + uri.path +} + +; NFT Project Details +; +; Provide top-level information about NFT projects that can be useful to marketplaces and explorers + +social-media-uri = { + string, ; social media channel name + uri ; social media URI +} + +token-project-details = { + 0 : string, ; Collection Name + ? 1 : [* string], ; Description + ? 2 : uri, ; Project Image + ? 3 : uri, ; Project Banner + ? 4 : 0 / 1, ; NSFW Flag (1 = true, 0 = false) + ? 5 : [* social-media-uri], ; Project social media + ? 6 : string ; Project/Artist Name +} \ No newline at end of file diff --git a/CIP-0088/CIPs/common/token-project-details_v1.schema.json b/CIP-0088/CIPs/common/token-project-details_v1.schema.json new file mode 100644 index 000000000..73ea62eb1 --- /dev/null +++ b/CIP-0088/CIPs/common/token-project-details_v1.schema.json @@ -0,0 +1,86 @@ +{ + "title": "Project Details", + "description": "Describe top-level details about the NFT Project", + "type": "object", + "properties": { + "0": { + "title": "Policy Name", + "description": "The collection name for NFTs minted under this policy", + "type": "string", + "maxLength": 64 + }, + "1": { + "title": "Policy Description", + "description": "Description for the NFT project", + "type": "array", + "items": { + "type": "string", + "maxLength": 64 + } + }, + "2": { + "title": "Project Image", + "description": "Project icon image URI", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json" + }, + "3": { + "title": "Project Banner Image", + "description": "Project banner image URI", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json" + }, + "4": { + "title": "Not Safe for Work Flag", + "description": "Flag whether the NFTs in the policy contain sensitive content that may not be suitable for all audiences", + "type": "integer", + "enum": [ + 0, + 1 + ] + }, + "5": { + "title": "Social Media URIs", + "description": "An object containing links to social media profiles for the project", + "type": "array", + "items": { + "title": "Project Social Network URI", + "$ref": "#/$defs/socialMediaUri" + } + }, + "6": { + "title": "Project Name", + "description": "The name of the project creating this collection", + "type": "string", + "maxLength": 64 + } + }, + "required": [ + "0" + ], + "$defs": { + "socialMediaUri": { + "title": "Social Media URI", + "type": "array", + "minItems": 2, + "items": [ + { + "title": "Social Network Name", + "description": "The name of the social network", + "type": "string", + "minLength": 1, + "maxLength": 64, + "examples": [ + "Twitter", + "X", + "Discord", + "Website" + ] + }, + { + "title": "Social Network Link", + "description": "A URI Array pointing to the social network resource", + "$ref": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json" + } + ] + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/common/uri-array.schema.json b/CIP-0088/CIPs/common/uri-array.schema.json new file mode 100644 index 000000000..35f095679 --- /dev/null +++ b/CIP-0088/CIPs/common/uri-array.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/common/uri-array.schema.json", + "title": "URI Array", + "$comment": "Because Cardano has a 64-character per string limit in on-chain JSON. Long strings should be broken up into an array of string parts. Particularly helpful for URIs that point to a resource on the internet is breaking URIs by scheme and path. This allows explorers to quickly and easily identify the type of resource before proceeding.", + "type": "array", + "minItems": 2, + "items": [ + { + "title": "URI Scheme", + "description": "The protocol schema definition", + "type": "string", + "examples": [ + "https://", + "ar://", + "ipfs://" + ], + "minLength": 4, + "maxLength": 64 + }, + { + "title": "URI Path", + "description": "One or more strings (64-character limit) to compose the URI", + "type": "string", + "minLength": 1, + "maxLength": 64, + "examples": [ + "faucet.spacecoins.io", + "bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly", + "WRi9jboeKx1fbjcvO5q0kshaMmdaYgDnYlMEy-loZeY" + ] + } + ], + "additionalItems": { + "title": "Path (Cont.)", + "type": "string", + "minLength": 1, + "maxLength": 64 + }, + "examples": [ + [ + "ar://", + "WRi9jboeKx1fbjcvO5q0kshaMmdaYgDnYlMEy-loZeY" + ], + [ + "https://", + "spacecoins.io" + ], + [ + "ipfs://", + "bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly" + ] + ] +} \ No newline at end of file diff --git a/CIP-0088/CIPs/template/CIPXXXX_v1.cddl b/CIP-0088/CIPs/template/CIPXXXX_v1.cddl new file mode 100644 index 000000000..9852de745 --- /dev/null +++ b/CIP-0088/CIPs/template/CIPXXXX_v1.cddl @@ -0,0 +1,21 @@ +; CIP-XXXX: CIP-Descriptor +; Version: 1 + +; Define any common or reusable pieces such as strings, URIs, etc + +string = text .size (0..64) + +; Define any nested objects before the top-level object + +details-object = { + 0 : string ; Something + ? 1 : uint ; Foo + ? 2 : [+ string] ; Stuff +} + +; Define the top-level CIP object + +cip-xxxx-details = { + ? 0 : uint ; optional version number + ? 1 : details-object ; optional details object +} \ No newline at end of file diff --git a/CIP-0088/CIPs/template/CIPXXXX_v1.json b/CIP-0088/CIPs/template/CIPXXXX_v1.json new file mode 100644 index 000000000..ec9cf2f40 --- /dev/null +++ b/CIP-0088/CIPs/template/CIPXXXX_v1.json @@ -0,0 +1,13 @@ +{ + "XXXX": { + "0": 1, + "1": { + "0": "Blah!", + "1": 492, + "2": [ + "Thing #1", + "Thing #2" + ] + } + } +} \ No newline at end of file diff --git a/CIP-0088/CIPs/template/CIPXXXX_v1.schema.json b/CIP-0088/CIPs/template/CIPXXXX_v1.schema.json new file mode 100644 index 000000000..2b9a7cb16 --- /dev/null +++ b/CIP-0088/CIPs/template/CIPXXXX_v1.schema.json @@ -0,0 +1,51 @@ +{ + "$id": "https://raw.githubusercontent.com/cardano-foundation/CIPs/main/CIP-0088/CIPs/XXXX/CIPXXXX_v1.schema.json", + "title": "CIP-XXXX: CIP-Descriptor", + "description": "Describe what we're declaring in this JSON object here...", + "type": "object", + "properties": { + "XXXX": { + "type": "object", + "properties": { + "0": { + "title": "Version", + "description": "The version of this standard being used", + "type": "integer", + "minimum": 1 + }, + "1": { + "type": "object", + "title": "CIP-XXXX Details", + "description": "What's going on here?", + "properties": { + "0": { + "type": "string", + "maxLength": 64, + "title": "Something", + "description": "Probably nothing" + }, + "1": { + "type": "integer", + "title": "Foo", + "description": "Number of Bars" + }, + "2": { + "type": "array", + "title": "Stuff", + "description": "Array of things", + "items": { + "type": "string", + "maxLength": 64, + "title": "Stuff Item", + "description": "Stuff can be things but are all things stuff?" + } + } + }, + "required": ["0"] + } + }, + "required": ["1"] + } + }, + "required": ["XXXX"] +} \ No newline at end of file diff --git a/CIP-0088/CIPs/template/README.md b/CIP-0088/CIPs/template/README.md new file mode 100644 index 000000000..1af201a9d --- /dev/null +++ b/CIP-0088/CIPs/template/README.md @@ -0,0 +1,71 @@ +# CIP-88 Extension: CIP-XXXX | CIP-Descriptor + +`Version: 1` + +## Top-Level Fields + +| index | name | type | required | notes | +|-------|-------------------|--------|----------|-----------------------------------------------------------| +| 0 | Version | UInt | No | Default: 1, which version of this specification is in use | +| 1 | Details Object #1 | Object | No | An object describing the CIP-Specific fields | + +**Note: The Details Object can and SHOULD be renamed to match the needs of the CIP in question. +Additional indices and detail structures may be added at the top level of a CIP-Specific Extension. +Please remove this line prior to publication.** + +## Details Object #1 Fields + +| index | name | type | required | notes | +|-------|-----------|--------|----------|-----------------------------------| +| 0 | Something | String | Yes | This is a note about Something... | +| 1 | Foo | UInt | No | The number of bars | +| 2 | Stuff | Array | No | Can contain things | + +### Field Notes + +#### 0: Something + +***Type: String | Required: Yes*** + +Describe what something is and what it does here... + +**Example:** `"Things"` + +#### 1: Foo + +***Type: Unsigned Integer | Required: No | Default: 0*** + +Describe the Foo field and what it's for here... + +**Example:** `7` + +#### 2: Stuff + +***Type: Array | Required: No | Default: Null*** + +Use a table and/or prose to describe the contents of the Stuff array here... + +**Example:** `[ +'Thing #1', +'Thing #2' +]` + +## CIP-XXXX Example + +```cbor +{ + XXXX: { ; CIP-Specific Identifier + 0: 1, ; version + 1: { ; details object #1 + 0: 'Blah!' ; Something + 1: 492 ; Foo + 2: [ ; Stuff + 'Thing #1', ; Things... + 'Thing #2' ; More things... + ] + } + } +} +``` + + diff --git a/CIP-0088/README.md b/CIP-0088/README.md new file mode 100644 index 000000000..bcf967b05 --- /dev/null +++ b/CIP-0088/README.md @@ -0,0 +1,567 @@ +--- +CIP: 88 +Title: Token Policy Registration +Category: Tokens +Status: Proposed +Authors: +- Adam Dean +Implementors: [] +Discussions: +- https://github.com/cardano-foundation/cips/pull/467 +Created: 2023-02-27 +License: CC-BY-4.0 +--- + +## Abstract + +Currently, token projects (NFT or FT) have no mechanism to register the intent, details, or feature set of their minting +policy on-chain. This CIP will aim to create a method that is backwards compatible and enable projects to declare, and +update over time, the supported feature set and metadata details pertaining to their tokens. + +This CIP will aim to make use of a hybrid (on and off-chain) information schema to enable maximum flexibility and +adaptability as new and novel use cases for native assets expand and grow over time. + +## Motivation: Why is this CIP necessary? + +This CIP was borne out of a distaste for the lack of on-chain token policy intent registration that has been cited as +both a centralization and security concern at various points over the preceding two years of native asset history on +Cardano. + +***Example 1: The Cardano Token Registry*** + +Many Fungible Token (FT) projects require special treatment of their native assets such as decimal places for proper +display and formatting, project information, and token logo. As it stands, these projects must currently register via a +GitHub repository ([Cardano Token Registry](https://github.com/cardano-foundation/cardano-token-registry)) in order to +have their token properly appear in wallets. This GitHub repository is currently managed by the Cardano Foundation (CF). +While there is no reason to believe that the CF would take any malicious or nefarious action, forcing token projects to +register in this fashion introduces a point of centralization, _potential_ gate keeping, and ultimately reliance on the +interaction of a 3rd party (the human at CF responsible for merging pull requests) in order for projects to register, or +update, their information. + +***Note:*** The original intent of the *CIP-26 Cardano Token Registry* was never to have a sole provider or +controller of the repository. However, time has shown that there is little interest from the community or various +service providers to contribute or participate in this or alternative solutions. + +This CIP attempts to provide a decentralized solution to this problem. + +***Example 2: Token Metadata Insecurity*** + +One of the stated rationales for [CIP-68](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0068) was that the +"original" Cardano NFT Metadata Standard ([CIP-25](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0025)) was +insecure in some example use cases. This is due to the link between the transactional metadata and the minting of native +assets. For example, a smart contract that cannot/does not validate against transaction metadata (i.e. Liquidity Pool +tokens) could have a malicious user inject CIP-25 metadata into the transaction, potentially inserting illicit, illegal, +or otherwise nefarious metadata information tied to the tokens which may be picked up and displayed to end users +unwittingly by explorers and wallets. + +***Example 3: De-duplication of Data*** + +Similar to **Example 1** above, when it comes to Non-Fungible Token (NFT) projects +currently operating on the chain there is usually a desire to provide some level of information that pertains to all +tokens under the given policy. Examples include project/collection names, social media handles, and miscellaneous +project registration information. At current, this is generally solved by adding "static" fields in the metadata of +every token. By moving this project-specific information a layer higher, not only do we achieve a path to dynamism +but also reduce ledger bloat size by de-duplicating data. + +Similarly, there are currently multiple marketplaces and decentralized exchanges (DEXes) in operation in the Cardano +ecosystem. At current, most DEXes pull information from the _Cardano Token Registry_ but there is no similar function +for NFT projects. As such, much information must be manually provided to individual marketplaces by the token projects +creating an undue burden on the project creators to provide a largely static amount of information via different web +forms and authentication schemes rather than simply publishing this information to the blockchain directly. + +### CPS-0001: Metadata Discoverability and Trust + +[CPS-0001](https://github.com/cardano-foundation/CIPs/pull/371) presents a problem of metadata discoverability and +trust. +This CIP attempts to address and solve several of the issues proposed in CPS-0001 but is most likely not a "complete" +solution and is rather narrowed (for the time being) to the scope of token projects although with some refinement to +the schema could potentially be expanded to support additional scopes. + +#### Discoverability + +The primary purpose of this CIP is to enhance discoverability of token projects utilizing and parsing only the +information contained on-chain. In the first version of this CIP we address the discoverability of top-level information +related to "Token Projects" such as NFT and FT projects needing to provide social media handles, human-friendly names, +etc. + +The goal of both minimizing redundant data stored on-chain and enhancing discoverability of projects for platforms +like DExes and NFT Marketplaces is specifically referenced in Example #3 above. + +Note that while some external chain indexing and validation will ultimately be required, there is no off-chain, +centralized or decentralized trusted repository of additional information required (although aspects of the metadata +provided may rely on off-chain storage solutions). + +#### Correctness + +This CIP aims to ensure metadata "correctness" on two different fronts. + +1. **Actual Data Correctness** + - This CIP utilizes a strongly-typed, numerically indexed data structure that should minimize common errors and + omissions observed in less strictly-typed standards. Parsers of the data presented within the scope of this + standard should ignore any non-specified or non-conforming data. +2. **Data Provenance** + - Specifically in the context of correctness via proving provenance of the metadata, this CIP aims to address + correctness via the same data witness standards utilized by CIP-26 although with a slightly modified data + structure. + Currently existing solutions for things like NFT Project verification standards rely on trust methods such as + publishing a special message on your website, send us a DM from your Twitter account, and other less secure means + of validating provenance of the data. + +#### Trust + +As mentioned in the *Data Provenance* note on Data Correctness above, this CIP minimizes the trust required by relying +on a verifiable witness signature versus currently existing solutions which largely rely on off-chain trust mechanisms +for proof of provenance. Therefore, we increase trust in the data by describing a relatively simple means of data +validation while decreasing the need for trust outside the scope of the on-chain metadata. + +## Specification + +Where applicable the 0 (zero) index of all specification documents is reserved for an optional integer version +identifier to enable future extensions to this and CIP-specific sub-standards. + +A numeric-indexed structure is used to support required and optional fields in a format that is compatible with both +CBOR and JSON transport formats with minimal changes to the data structure and to minimize the possibility of +misspelling or capitalization issues. + +### Modification and Extension of This Standard + +This standard is likely to need frequent extension and modification, particularly relating to +[CIP-Specific Information](#6-cip-specific-information). Any group or individual wishing to extend or modify this +standard MUST comply to the following criteria: + +- [ ] New CIPs SHOULD achieve the `Active` status prior to being included and documented in this directory after + undergoing the + regular community feedback and review process. +- [ ] Any change or modification to `required` fields in the root standard or a CIP's specific details MUST be written + as a new `version`, MUST increment the version number by `1`, and MUST include new, versioned documentation for + the CIP while leaving previous version documentation intact for backwards compatibility. +- [ ] Submissions for addition to this CIP MUST be made via a separate, dedicated pull request against this repository + so that the format and documentation pertaining to CIP-88 specifically can undergo community review and feedback + prior to inclusion here. +- [ ] Whenever possible, extensions to this CIP SHOULD attempt to introduce new indices and object definitions without + changing or modifying existing data structures to enable new functionality and existing implementations to operate + until newer standards can be adopted and enhance functionality rather than change it. +- [ ] New CIP submissions MUST follow the same paradigms and documentation examples as those found within the + [CIPs](./CIPs) directory including: + - [ ] a README.md document describing the fields, values, and rationale + - [ ] a CBOR CDDL specification file + - [ ] a JSON format schema file (_optional_) + - [ ] a JSON example file showing all defined fields (_optional_) + +### Registration Metadata Format + +`Version: 1` + +| Index | Name | Type | Required | Notes | +|-------|------------------------------------------------------|-------|----------|--------------------------------------------------------------| +| 0 | Version | UInt | Yes | | +| 1 | [Registration Payload](#registration-payload-object) | Map | Yes | Object describing and providing details for the token policy | +| 2 | [Registration Witness](#registration-witness-array) | Array | Yes | Array of witness signatures used to validate the payload | + +### Registration Payload Object + +The Token Registration Payload Object (TRPO) consists of 4 required fields and optional additional fields to +provide context and information. The top-level metadata label of **867** has been chosen for the purposes of this +standard. + +#### Fields + +| Index | Name | Type | Required | Notes/Examples | +|-------|---------------------------------------------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1 | Scope | Array | Yes | An array defining the scope of this registration (for greater compatibility with CPS-0001). The first entry should be an unsigned integer value identifying the type of scope while the second entry addresses the specific scope of registration | +| 2 | Feature Set | Array | Yes | An array of unsigned integers specifying none or more CIP standards utilized by the tokens of this project. Should reference the assigned CIP number. | +| 3 | Validation Method | Array | Yes | How should this payload be validated. | +| 4 | Nonce | UInt | Yes | A simple cache-busting nonce. Recommend to use the blockchain slot height at the time of submission. Only the highest observed nonce value should be honored by explorers. | +| 5 | Oracle URI | Array | No | Reserved for future use, URI to an informational oracle API for this policy | +| 6 | [CIP Details](#6--cip-specific-information) | Object | No | If one or more of the CIPs addressed in the Feature Set have additionally defined metadata, it may be added here | + +The following fields are required in all token registration submissions. + +##### 1. Scope + +Currently, this CIP concerns itself with the scope of *Tokens* with relation to CPS-0001 as described in the Motivation +section. However, the specification is left flexible to encapsulate additional scopes and contexts (Stake Pools, dApps, +etc.) should the specification become adopted and the community desire to expand the scope of this CIP. + +**Scopes** + +| ID | Scope | Format | +|-----|---------------|------------------------------------| +| 0 | Native Script | `[0, h'policyID', [h'policyHex']]` | + +0. **Native Scripts**: Native scripts should be specified as an array with the first entry indicating the type (Native +Script), the second entry indicating the script hash (Policy ID) and the third entry consisting of an array with one or +more 64-byte strings constituting the hex-encoded CBOR representation of the Native Script itself. In this way, CIP-88 +registration may be submitted on-chain prior to any tokens being minted and can be used by validators to confirm the +legitimacy of the certificate without any secondary information source. + +**Example:** + +`[0, h'3668b628d7bd0cbdc4b7a60fe9bd327b56a1902e89fd01251a34c8be', h'8200581c4bdb4c5017cdcb50c001af21d2488ed2e741df55b252dd3ab2482050']` + +#### 2. Feature Set + +The _Feature Set_ is a simple array of unsigned integer values representing the CIP standards that should be applied to +the subject scope. + +**Example:** + +`[25, 27]` + +#### 3. Validation Method + +In order to minimize issues relating to capitalization and misspellings, we should use a well-defined map of integer +values for validation methods that will be utilized by third party observers and processors to authenticate the payload. +The validation method entry should always be provided as an array with the first element being an unsigned integer +representing the method and additional entries providing additional context to the validation as required. + +***Proposed Validation Methods*** + +| ID | Type | Format | Notes | +|-----|------------------------|-------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 0 | Ed25519 Key Signature | `[0]` | The most basic and simplistic approach to signing and validation. In this case the Registration Witness object could contain one or more pubkey + signed witness objects. The payload to be signed should be the hex-encoded CBOR representation of the Registration Payload object. | +| 1 | Beacon/Reference Token | `[1, [h'',h'']]` | Similar to the approach utilized by [CIP-27](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0027). We could attach this metadata during a mint transaction for a specially formatted token under the policy ID in question. CIP-27 uses a "nameless" token that has an empty "Asset ID" for example. This may be a validation method that lends itself better to supporting token projects that are minted via Smart Contract. | + +**Examples:** + +`[0]`, +`[1, [h'',h'']]` + +#### 4. Nonce + +The nonce value is utilized to prevent a replay attack vector. The nonce value should be an unsigned integer value that +is always at least one greater than the previously registered value. + +**Example:** + +`12345` + +#### 5. Data Oracle URI + +To be utilized and expanded upon in a separate CIP, this should be a valid URI pointing to a source of additional, +potentially dynamic information relating to the project and/or the tokens minted under it. + +**Example:** + +`[ +"https://", +"oracle.mytokenproject.io/" +]` + +#### 6. CIP-Specific Information + +This entry, if present, should be a CIP ID indexed object containing additional information pertaining to that CIP. +When and where possible the CIP-Specific registration should follow the CBOR-like declaration syntax to ensure that +the content is well-formed and easily parseable. + +| CIP | Name | Version | Status | CDDL | Rationale | +|-----|-------------------------------|---------|--------|------------------------------------------|---------------------| +| 25 | Token Metadata | 1 | Active | [CIP25_v1.cddl](CIPs/0025/CIP25_v1.cddl) | [CIP-25](CIPs/0025) | +| 26 | Fungible Token Information | 1 | Active | [CIP26_v1.cddl](CIPs/0026/CIP26_v1.cddl) | [CIP-26](CIPs/0026) | +| 27 | Token Royalties | 1 | Active | [CIP27_v1.cddl](CIPs/0027/CIP27_v1.cddl) | [CIP-27](CIPs/0027) | +| 48 | Metadata References | 1 | Draft | [CIP48_v1.cddl](CIPs/0048/CIP48_v1.cddl) | [CIP-48](CIPs/0048) | +| 60 | Music Token Metadata | 1 | Draft | [CIP60_v1.cddl](CIPs/0060/CIP60_v1.cddl) | [CIP-60](CIPs/0060) | +| 68 | Datum Token Metadata | 1 | Active | [CIP68_v1.cddl](CIPs/0068/CIP68_v1.cddl) | [CIP-68](CIPs/0068) | +| 86 | Token Metadata Update Oracles | 1 | Active | [CIP86_v1.cddl](CIPs/0086/CIP86_v1.cddl) | [CIP-86](CIPs/0086) | + +***Note: CIP-0068 Tokens*** + +Due to a lack of clarity in the original language of CIP-0068, standards for fungible, non-fungible, and "rich" fungible +tokens have been added to the core standard. To accommodate for this, projects should use the CIP-68 data when using the +`222` (NFT) or `444` (RFT) tokens for top-level project information. Projects utilizing the `333` (FT) style tokens +should utilize the CIP-26 data structure to provide fungible token context. + +***Beacon Token Registration*** + +Where applicable to a specific CIP, the CIP-specific registration may refer to a "beacon token". This is standardized +in this CIP as a two-element array consisting of the hex-encoded policy ID and asset ID of the token to be used as a +beacon token for the purposes of smart contract interactions. e.g. `[ +h'', +h'' +]` + +**Multiple Feature Set Example (CBOR):** + +```cbor +{ + 25: { + 0: 1, + 1: { + 0: "Cool NFT Project", + 1: [ + "This is a description of my project", + "longer than 64 characters so broken up into a string array" + ], + 2: [ + "https://", + "static.coolnftproject.io", + "/images/icon.png" + ], + 3: [ + "https://", + "static.coolnftproject.io", + "/images/banner1.jpg" + ], + 4: 0, + 5: [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + 6: "Virtua Metaverse" + } + }, + 27: { + 0: 1, + 1: { + 1: "0.05", + 2: [ + "addr_test1qqp7uedmne8vjzue66hknx87jspg56qhkm4gp6ahyw7kaahevmtcux", + "lpy25nqhaljc70094vfu8q4knqyv6668cvwhsq64gt89" + ] + } + } +} +``` + +### Registration Witness Array + +#### (Native Scripts) + +The Witness Array included in the on-chain metadata should consist of an array of arrays with two elements, the public +key of the signing key and the signed key witness. If a script requires multiple signatures, enough signatures to meet +the criteria of the script should be included and required for proper validation of an updated token registration. + +The signing payload should be the hex-encoded Token Registration Payload Object. + +**Example** + +```cbor +[ + [ + h'02b76ae694ce6549d4a20dce308bc7af7fa5a00c7d82b70001e044e596a35deb', + h'23d0614301b0d554def300388c2e36b702a66e85432940f703a5ba93bfb1659a0717962b40d87523c507ebe24efbb12a2024bb8b14441785a93af00276a32e08' + ], + [ + h'26bacc7b88e2b40701387c521cd0c50d5c0cfa4c6c6d7f0901395757', + h'secondSignatureByteString' + ] +] +``` + +### Example NFT Token Registration Metadata + +Below is a complete example of the hypothetical metadata payload for an NFT project registering their policy on-chain. + +```cbor +{ + 867: { + 0: 1, + 1: { + 1: [ + 0, + h'3668b628d7bd0cbdc4b7a60fe9bd327b56a1902e89fd01251a34c8be', + h'8200581c4bdb4c5017cdcb50c001af21d2488ed2e741df55b252dd3ab2482050' + ], + 2: [ + 25, + 27 + ], + 3: [0], + 4: 12345, + 5: [ + "https://", + "oracle.mycoolnftproject.io/" + ], + 6: { + 25: { + 0: 1, + 1: { + 0: "Cool NFT Project", + 1: [ + "This is a description of my project", + "longer than 64 characters so broken up into a string array" + ], + 2: [ + "https://", + "static.coolnftproject.io", + "/images/icon.png" + ], + 3: [ + "https://", + "static.coolnftproject.io", + "/images/banner1.jpg" + ], + 4: 0, + 5: [ + [ + "twitter", + [ + "https://", + "twitter.com/spacebudzNFT" + ] + ], + [ + "discord", + [ + "https://", + "discord.gg/spacebudz" + ] + ] + ], + 6: "Virtua Metaverse" + } + }, + 27: { + 0: 1, + 1: { + 1: "0.05", + 2: [ + "addr_test1qqp7uedmne8vjzue66hknx87jspg56qhkm4gp6ahyw7kaahevmtcux", + "lpy25nqhaljc70094vfu8q4knqyv6668cvwhsq64gt89" + ] + } + } + } + }, + 2: [ + [ + h'02b76ae694ce6549d4a20dce308bc7af7fa5a00c7d82b70001e044e596a35deb', + h'23d0614301b0d554def300388c2e36b702a66e85432940f703a5ba93bfb1659a0717962b40d87523c507ebe24efbb12a2024bb8b14441785a93af00276a32e08' + ], + [ + h'26bacc7b88e2b40701387c521cd0c50d5c0cfa4c6c6d7f0901395757', + h'secondWitnessByteString' + ] + ] + } +} +``` + +### Example Fungible Token Registration Metadata + +```cbor +{ + 867: { + 0: 1, + 1: { + 1: [ + 0, + h'3668b628d7bd0cbdc4b7a60fe9bd327b56a1902e89fd01251a34c8be', + h'8200581c4bdb4c5017cdcb50c001af21d2488ed2e741df55b252dd3ab2482050' + ], + 2: [ + 26 + ], + 3: [0], + 4: 12345, + 5: [ + "https://", + "oracle.tokenproject.io/" + ], + 6: { + 26: { + 0: 1, + 1: [ + { + 0: [ + h"d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0", + h"7370616365636f696e73" + ], + 1: "spacecoins", + 2: [ + "the OG Cardano community token", + "-", + "whatever you do, your did it!", + "", + "Learn more at https://spacecoins.io!" + ], + 3: "SPACE", + 4: 0, + 5: [ + "https://", + "spacecoins.io" + ], + 6: [ + "ipfs://", + "bafkreib3e5u4am2btduu5s76rdznmqgmmrd4l6xf2vpi4vzldxe25fqapy" + ], + 7: [ + [ + "ipfs://", + "bafkreibva6x6dwxqksmnozg44vpixja6jlhm2w7ueydkyk4lpxbowdbqly" + ], + "3507afe1daf05498d764dce55e8ba41e4acecd5bf42606ac2b8b7dc2eb0c305e" + ], + 8: [ + h"d894897411707efa755a76deb66d26dfd50593f2e70863e1661e98a0", + h"7370616365636f696e74" + ] + } + ] + } + } + }, + 2: [ + [ + h'02b76ae694ce6549d4a20dce308bc7af7fa5a00c7d82b70001e044e596a35deb', + h'23d0614301b0d554def300388c2e36b702a66e85432940f703a5ba93bfb1659a0717962b40d87523c507ebe24efbb12a2024bb8b14441785a93af00276a32e08' + ] + ] + } +} +``` + +## Rationale: how does this CIP achieve its goals? + +For this specification, I have drawn inspiration from +[CIP-36: Catalyst/Voltaire Registration Metadata Format](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0036) +which succinctly and canonically publishes data to the main chain (L1) via a metadata transaction and without any +required modification or customization to the underlying ledger. + +By leveraging the existing signing keys present in native asset scripts from the beginning of the Mary Era on Cardano we +can enable all projects to update and provide additional, verified information about their project in a canonical, +verifiable, and on-chain way while also providing for additional off-chain information. + +This makes this CIP backwards compatible with all existing standards (CIP-25, 26, 27, 68, etc) while also providing the +flexibility for future-proofing and adding additional context and information in the future as additional use cases, +utility, and standards evolve. + +## Path to Active + +### Acceptance Criteria + +- [X] This CIP should receive feedback, criticism, and refinement from: CIP Editors and the community of people involved + with token projects (both NFT and FT) to review any weaknesses or areas of improvement. +- [ ] Guidelines and examples of publication of data as well as discovery and validation should be included as part of + criteria for acceptance. +- [X] Specifications should be updated to be written in both JSON Schema and CBOR CDDL format for maximum compatibility. +- [ ] Implementation and use demonstrated by the community: Token Projects, Blockchain Explorers, Wallets, + Marketplaces/DEXes. + +#### TO-DO ACCEPTANCE ACTIONS #### + +- [ ] Publish instructions and tooling for publication and verification of certificates +- [ ] Develop standard for validation of Smart Contract minted tokens + +### Implementation Plan + +1. Publish open source tooling and instructions related to the publication and verification of data utilizing this + standard. +2. Achieve "buy in" from existing community actors and implementors such as: blockchain explorers, token marketplaces, + decentralized exchanges, wallets. + +## Copyright + +This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). \ No newline at end of file