Skip to content
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

Proposal for initial best practices for ICRC7 metadata #76

Open
skilesare opened this issue Apr 26, 2024 · 5 comments
Open

Proposal for initial best practices for ICRC7 metadata #76

skilesare opened this issue Apr 26, 2024 · 5 comments

Comments

@skilesare
Copy link
Contributor

To provide a standardized approach to handling metadata for NFTs within the Internet Computer ecosystem, the ICRCX metadata standard has been designed. This standard facilitates multiple methods for specifying and verifying metadata, accommodating diverse NFT use cases and ensuring interoperability with existing standards. Below is a comprehensive description of the ICRCX metadata standard's specifications:

ICRCX Metadata Standard Specification

Metadata Retrieval Methods

The ICRCX standard supports several methods for associating metadata with NFTs. Each method caters to different storage preferences and application requirements:

  1. URI-based Metadata (IcrcX:metadata:uri):

    • Description: Metadata is hosted externally and accessible via a specified URI. The URI points to a JSON file containing the metadata.
    • Structure: #Text containing the URI.
  2. Embedded JSON Metadata (icrcX:metadata:json):

    • Description: Metadata is directly embedded within the NFT as a JSON string.
    • Structure: #Text containing JSON data.
  3. Direct Value Metadata (icrcX:metadata:value):

    • Description: Metadata is provided directly as a map within the NFT, using the Value type to support complex structures.
    • Structure: Value type, typically a map containing key-value pairs.
  4. Image Only Metadata (icrcX:metadata:image):

    • Description: Only an image URL is provided as the NFT's metadata.
    • Structure: #Text containing the image URL.
    • or `Array[#Text(url),#Text(mimetype)]
  5. Canister-based Metadata (icrcX:metadata:canister):

    • Description: Metadata is fetched from a specified Internet Computer canister.
    • Structure: Array containing #Text(canisterID) and #Text(path) and an optional #Text(path) format which shuld be json or candid.
    • This type is important because IC based smart contracts can pull these resources via http_request without an http outcall.

Optional Verification via Hash

To ensure the integrity and authenticity of the metadata, especially when it is stored externally, a hash can optionally be provided:

  • Metadata Hash (icrcX:metadata:hash):
    • Description: Accompanies any of the metadata retrieval methods to provide a verifiable hash of the metadata content.
    • Structure: #Blob containing the hash value.

Standard Items for icrcX:metadata:value

When using the direct value method for metadata (icrcX:metadata:value), the following standard items are recommended within the metadata map:

  • icrcX:name: Text — Name of the NFT.
  • icrcX:description: Text — Description of the NFT.
  • icrcX:image: Text — URL or data URL pointing to an image representing the NFT.
  • icrcX:preview: Text — URL or data URL pointing to a thumbnail image of the NFT.
  • icrcX:experience: Text — URL or data URL pointing to a dapp for interacting with the NFT.
  • icrcX:attributes: Array of Maps — Each attribute is a map containing properties like trait type, value, and display type.

JSON Format Compliance

When metadata is represented in JSON format (either embedded or via URI), it should adhere to widely accepted standards such as those established for ERC-721 or ERC-1155:

  • The JSON structure should generally omit the "icrcX:" prefix used in direct value maps.
  • An optional field, icrcX:metadata:format, may be used to specify the metadata standard or version being followed (e.g., "erc721", "enjin", "opensea").

Summary

This standardized approach ensures flexibility in how metadata is stored and accessed while promoting consistency in its structure and verification. It supports both on-chain and off-chain storage strategies, caters to different levels of complexity in metadata content, and facilitates interoperability with existing blockchain ecosystems through compliance with popular standards like ERC-721 and ERC-1155.

@skilesare
Copy link
Contributor Author

Updated in response to the 20240521 Working Group meeting:

To provide a standardized approach to handling metadata for NFTs within the Internet Computer ecosystem, the ICRC-76 metadata standard has been designed. This standard facilitates a bi-modal for specifying and verifying metadata, accommodating diverse NFT use cases, and ensuring interoperability with existing standards. The initial standards are purposely simple and MAY be extended through additional ICRC Extensions to target specific systems, standards, and protocols. Below is a comprehensive description of the ICRC-76 metadata standard's specifications:

ICRC-76 Metadata Standard Specification

Metadata Retrieval Methods

The ICRCX standard supports two methods for associating metadata with NFTs. Each method caters to different storage preferences and application requirements:

  1. URI-based Metadata (IcrcX:metadata:uri):

    • Description: Metadata is hosted externally and accessible via a specified URI. The URI points to either a JSON file containing the metadata or, alternately, a data URI as specified in RFC 2397.
    • Structure:
      • #Text containing the URI.
    • Limits: Response from the Internet Computer are currently limited to 2MB in size. Any data of significant files may need to be held off-chain or at an IC-URI(described later).
    • Examples
      • Text Data: #Text(data:text/plain,Hello%20World)
      • IPFS: #Text(ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi/dir/file.json)
      • JSON Data: #Text("data:application/json,{'name':'example','value':'data'}")
      • Image Data: #Text("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...")
      • IC-URI: #Text(icdata://2222s-4iaaa-aaaaf-ax2uq-cai/item/64/data.json) - An IC canister can retrieve this data in a trusted manner using http_request without having to resort to http-outcalls.
      • URL: #Text("https://foo.com/id/64/data.json") - When a URL is encountered, the metadata should be loaded from this URL.
  2. Direct Value Metadata (icrcX:metadata:value):

    • Description: Metadata is provided directly as a map within the NFT, using the Value type to support complex structures.
    • Structure: Value type, typically a map containing key-value pairs.
    • Off-chain nodes: Text values that correspond to an internet addressable URI, IC-URI, or IPFS locations should be followed to retrieve additional metadata.

//todo: Some outstanding questions on what to do about data in metadata that is Text, a URI, but NOT supposed to be traversed and included in the metadata. (Choice one is to have a specific tag in a map for this type of data ie icrc76:no_follow or two to have a tag for followable links ie icrc76:metadata:follow).

IC-URI specification

Locations that hold data on the IC that are both addressable from the IC and from https can use the IC-URI specification as follows:

ic-http://{canister_id}/{path}?[__icrc76hash={hash}&__icrc76mime={mimetype} where

  • The query string parameter __icrc76hash is optional but should match the hash of the retrieved file if present.
  • The query string parameter __icrc76mime is optional and should have no effect but to tell the retrieving program how to treat the data.
  • The data should be accessible via an IC HTTP gateway and via a call the the indicated canister's http_request method.

Optional Verification via Hash

To ensure the integrity and authenticity of the metadata, especially when it is stored externally, a hash can optionally be provided:

  • Metadata Hash (icrcX:metadata:hash):

    • Description: Accompanies any data URL that needs that does not support a query string parameter of __icrc76hash.
    • Structure: #Blob containing the sha256 hash value.
  • Query String Paramater (__icrc76hash):

    • Description: Appended to URLs that can be retrieved. Tells the server the expected has so that it can be matched server side if desired.
    • Structure: `?__icrc76hash={sha256 hash} in hex representation

Standard Items for icrcX:metadata:value and/or JSON structure.

ICRC-76 does not specifically specify these structures but encourages the extension of ICRC-76 via other ICRC proposals that will allow for standardization of data useful for parsing and interoperating with other systems.

Examples:

  • A standard that matches the OpenSea Standard for NFTs.
  • A standard that matches the Enjin Standard for NFTs.
  • A custom standard that extends basic NFT standards with features usually only available to the Internet Computer Blockchain.

Summary

This standardized approach ensures flexibility in how metadata is stored and accessed while promoting consistency in its structure and verification. It supports both on-chain and off-chain storage strategies, caters to different levels of complexity in metadata content, and facilitates interoperability with existing blockchain ecosystems through compliance with popular standards like ERC-721 and ERC-1155.

@dietersommer
Copy link
Collaborator

This is already in a great shape, please find some comments in the forum to further improve it.

@sea-snake
Copy link
Contributor

sea-snake commented Jul 2, 2024

External metadata

ICRC-3 extension that defines a value that is a record that points to external json metadata:

Map {
   icrc123_url: Text; // Path to external json
   hash?: '8o3vfuaowrgva' // Optional SHA-256 hash of external json UTF-8 string
   path?: 'a.c.[2].d' // Optional path to json value within above json
}

Standardized urls for http assets on the IC

The following url format:

ic-http://{canister_id}/{path}

Details like mime etc are not included since main purpose is to have urls that point to IC http urls without relying on a gateway in the url.

@skilesare
Copy link
Contributor Author

skilesare commented Jul 5, 2024

Updated in response to the 20240602 Working Group meeting:

To provide a standardized approach to handling metadata for NFTs within the Internet Computer ecosystem, the ICRC-76 metadata standard has been designed. This standard facilitates specifying and verifying metadata, accommodating diverse NFT use cases, and ensuring interoperability with existing standards. The initial standards are purposely simple and MAY be extended through additional ICRC Extensions to target specific systems, standards, and protocols. Below is a comprehensive description of the ICRC-76 metadata standard's specifications:

ICRC-76 Metadata Standard Specification

Metadata Retrieval Methods

The ICRC-76 standard supports three methods for associating metadata with NFTs. Each method caters to different storage preferences and application requirements:

  1. Value based metadata
  • Description: Metadata is hosted in the NFT as a tree of Value based variants.
  • Structure:
    • The key used to specify ICRC-76 metadata is icrc76:metadata.

    • The Value used for Value based metadata should be a Map and that map may contain unbounded vec {Text;Value;} pairs provided the whole does not exceed the maximum return value for an Internet Computer query(currently 2MB).

    • The top-level Map MUST not be an ICRC-61 map(see 3.).

    • Uses standard Value types as defined in ICRC-3.

    • Descendent Map nodes that conform to ICRC-61 should be followed by the client and the Map replaced with the remote file as described in ICRC-61.

    • Examples

      • Pure Value
         [("icrc76:metadata", #Map([
             ("id","#Text("item-1"),  
             ("preview", #Text("https://foo.bar.com/images/preview/item-1")
           ])
         )]
      
    • Value with ICRC-61 Replace

         [("icrc76:metadata", #Map([
             ("id","#Text("item-1"),  
             ("preview", ("file", #Map[
                ("icrc61_url", #Text("https://foo.bar/data.json"),
                ("icrc61_hash, #Text("UNhYo7NpAQ61sEpPbHXH4B5C4tLwF87qNaAg17Qn8Jw=")),
              ]))
           ])
         )]
      

      Rendered as:

         [("icrc76:metadata", #Map([
             ("id","#Text("item-1"),  
             ("preview", #Text("data:application/json;charset=utf-8;base64,ew0KICAiZm9vIjoiYmFyIiwNCiAgImZpenoiOiJidXp6Ig0KfQ==)"))
           ])
         )]
      
  1. DataURI based metadata
  • Description: Metadata is hosted in the NFT as a data URI as specified in RFC 2397.

  • Example:

      [
        ("icrc76:metadata", #Text("data:image/json;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...")
      ]
    
  1. External based metadata
  • Description: Metadat is hosted outside the nft in a remote location
  • Structure:
  • The key used to specify ICRC-76 metadata is icrc76:metadata.
  • The Value used for Value based metadata should be an ICRC-61 standard Map that points to a valid external resource.
  • Example:
    • External
        [("icrc76:metadata",  #Map[
               ("icrc61_url", #Text("https://foo.bar/data.json"),
               ("icrc61_hash, #Text("UNhYo7NpAQ61sEpPbHXH4B5C4tLwF87qNaAg17Qn8Jw=")),
        )]
    
    Rendered as:
       [("icrc76:metadata", #Text("data:application/json;charset=utf-8;base64,ew0KICAiZm9vIjoiYmFyIiwNCiAgImZpenoiOiJidXp6Ig0KfQ==)"))
       )]
    

Standard Items for icrc76:metadata keys and/or JSON structure.

ICRC-76 does not specifically specify these structures but encourages the extension of ICRC-76 via other ICRC proposals that will allow for standardization of data useful for parsing and interoperating with other systems.

Examples:

  • A standard that matches the OpenSea Standard for NFTs.
  • A standard that matches the Enjin Standard for NFTs.
  • A custom standard that extends basic NFT standards with features usually only available to the Internet Computer Blockchain.

Summary

This standardized approach ensures flexibility in how metadata is stored and accessed while promoting consistency in its structure and verification. It supports both on-chain and off-chain storage strategies, caters to different levels of complexity in metadata content, and facilitates interoperability with existing blockchain ecosystems through compliance with popular standards like ERC-721 and ERC-1155.

@sea-snake
Copy link
Contributor

sea-snake commented Jul 8, 2024

Didn't get around to define the whole OpenSea inspired spec in full detail yet but here's the current definition of the
spec. The spec mentions ICRC-99 as number, this is just a placeholder.

The main goal was to be OpenSea compatible (support same feature set) but allow for multiple assets with various data
types with various purposes. Where asset purposes and attribute display types can be standardized in ICRC extensions.


External metadata entry point

The following metadata property MUST be defined in the root of the token metadata if we want to return external
off-chain metadata.

Property ICRC-3 Type Description
icrc99:external_metadata variant { Map } Contains below external metadata properties.

External JSON metadata properties

Property Optional ICRC-3 Type Description
url No variant { Text } URL that returns the metadata in JSON format (protocol is not limited to HTTP)
sha256_hash Yes variant { Blob } SHA-256 hash of HTTP response body bytes returned from above url.

On-chain metadata entry point

The following metadata property MUST be defined in the root of the token metadata if we want to return on-chain
metadata.

Property ICRC-3 Type Description
icrc99:metadata variant { Map } Contains below on-chain metadata properties.

Metadata properties

Property Optional ICRC-3 Type JSON Type Description
external_url Yes variant { Text } string URL that allows the user to view the item on your site.
name Yes variant { Text } string Plain text.
description Yes variant { Text } string Markdown.
assets Yes variant { Array = vec variant { Map } } object[] List of assets ordered by priority descending.
attributes Yes variant { Array = vec variant { Map } } object[] List of attributes ordered by priority descending.

Asset properties

Property Optional ICRC-3 Type JSON Type Description
url No variant { Text } string URL that returns the asset e.g. a PNG image (protocol is not limited to HTTP).
mime No variant { Text } string Mime type as defined in RFC 6838.
sha256_hash Yes variant { Blob } string (base64) SHA-256 hash of HTTP response body bytes returned from above url.
purpose Yes variant { Text } string Indicate purpose of asset.

Purpose values

Below list of purpose values are part of the ICRC-99 standard, this list could be extended by other standards.
Purpose values can define additional properties in the asset.

Value Description
icrc99:image Original size image that is shown on e.g. item details page. Additional optional width and height properties define the dimensions in number of pixels.
icrc99:preview Small image meant as preview within e.g. a list of items. Additional optional width and height properties define the dimensions in number of pixels.

Attribute properties

Property Optional ICRC-3 Type JSON Type Description
value No variant { Text; Nat; Int } string | number Value of the trait.
trait_type No variant { Text } string Name of the trait.
display_type Yes variant { Text } string Indicate how attribute should be displayed.

Display type values

Below list of display types are part of the ICRC-99 standard, this list could be extended by other standards.
Display types can define additional properties in the attribute.

Value Description
icrc99:property Shows attribute as property with e.g. rarity, this is the default display type.
icrc99:date Shows attribute as date, expects epoch timestamp number in milliseconds.
icrc99:time Shows attribute as date with time, expects epoch timestamp number in milliseconds.
icrc99:rank Shows attribute as progress rank e.g. 4 of 10, expects number and additional max_value property with a number.
icrc99:stat Show attribute as stat e.g. 1 out of 2, expects number and additional max_value property with a number.
icrc99:boost Shows attribute as boost e.g. +10, expects number and optional additional min_value and max_value properties. Numbers can be either positive or negative.
icrc99:boost_percentage Same as icrc99:boost but shows values with %.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants