ERC-721 Collection Metadata Extension

------------------------------------------  DRAFT ----------------------------------------

ERC-721 Collection metadata Extension 

This standardizes on a new collectionUri that supports metadata at the collection level.  Collection metadata includes general descriptive information as well as detailed definition of NFT asset level traits held in the tokenUri metadata storage.   Applications can leverage this collection metadata to discover collection wide NFT trait metadata.


This specification provides a basic collectionUri standard, similar to ERC721CollectionMetadata, to be extended within real world NFT contract implementations.  


This specification also defines a metadata schema to the off-chain data.  This schema supports basic descriptive information and collection wide trait metadata.


ERC-721 Collection Metadata is used by ERC-721 Catalog Extension and ERC-721 Product Extension to create a standard for Web3.0 Commerce.  These standards support catalog categories, NFT categorization, search, filtering, and detailed Product Asset NFT trait discovery and display. 


Authors Richard Pedersen (@rpedersen)

Created 2023-05-15

Requires EIP-721, EIP-165, ERC721CollectionMetadata


Github project


Table of Contents



Abstract




Motivation

Current solutions, like OpenSea, centralize the management of this NFT collection level metadata and force applications to build on their propriety API's.  This standard allows applications to directly retrieve both collection wide metadata from Ethereum contracts and referenced off-chain metadata.

Projects like Decentraland Marketplace (https://market.decentraland.org), manage this information within their centralized solutions to support their ecommerce marketplaces.   NFT projects that leverage this Collection Metadata standard will make their solutions consumable by third party applications.

Solutions like Web3.0 Commerce Product Asset Service (PAS) leverage this standard.  PAS dynamically discovers blockchain ERC-721 collections (products) and presents those assets to standard Web2.0 storefronts via a GraphQL Service API.  This is an example of a Web3.0 Composable Commerce Component Service.


Specification


interface IERC721CollectionMetadata {

   

    // returns a URI with details about this collection

    // the collectionUri **MUST** be immutable (e.g., ipfs:// and not http://)

    // the collectionUri **MUST** be content addressable (e.g., ipfs:// and not http://)

    function setCollectionUri(string memory collectionUri) external;


    function getCollectionUri() external view returns (string memory);

}




Collection Metadata Schema referenced by collectionUri

{

    "$schema": "http://json-schema.org/draft-07/schema#",

    "title": "Metadata Schema",

    "type": "object",

    "version": "0.0.1",

    "properties": {

        "name": {

            "type": "string",

            "description": "Identifies the asset to which this token represents."

        },

        "description": {

            "type": "string",

            "description": "Description of the asset to which this token represents."

        },

        "image": {

            "type": "string",

            "description": "Header image for product"

        },

        "attributeTypes": {

            "type": "array",

            "items": {

                "type": "object",

                "properties": {

                    "name": {

                        "type": "string",

                        "description": "Name of trait."

                    },

                    "display_name": {

                        "type": "string",

                        "description": "Display name of trait."

                    },

                    "struct_type": {

                        "type": "string",

                        "description": "scalar, list, range, location, point, ..."

                    },

                    "scalar_type": {

                        "type": "string",

                        "description": "string, integer, boolean, number, ..."

                    },

                    "min": {

                        "type": [

                            "string",

                            "integer",

                            "number",

                            "boolean"

                        ],

                        "description": "min for trait."

                    },

                    "max": {

                        "type": [

                            "string",

                            "integer",

                            "number",

                            "boolean"

                        ],

                        "description": "min for trait."

                    },

                    "list": {

                        "type": "array",

                        "items": {

                            "type": [

                                "string",

                                "integer",

                                "number",

                                "boolean"

                            ],

                            "description": "list values"

                        }

                    }


                }

            },

            "required": [

                "name",

                "description"

            ]

        }

    },

    "required": [

        "name",

        "image",

        "description"

    ]

}



Example Collection metadata (Decentraland example)


{

    "name": "Decentraland",

    "description": "....",

    "image": "https://....",

    "attributeTypes": [

        {

            "name": "type",

            "display_name": "type",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "parcel",

                "estate"

            ]

        },

        {

            "name": "status",

            "display_name": "status",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "buy",

                "rent"

            ]

        },

        {

            "name": "x",

            "display_name": "x",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "y",

            "display_name": "y",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "adjacent-to-road",

            "display_name": "adjacent to road",

            "struct_type": "scalar",

            "scalar_type": "boolean"

        },

        {

            "name": "near-a-district",

            "display_name": "near a district",

            "struct_type": "scalar",

            "scalar_type": "boolean"

        },

        {

            "name": "distance-to-road",

            "display_name": "distance to road",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "max": 10

        },

        {

            "name": "distance-to-district",

            "display_name": "distance to district",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "max": 10

        }

    ]

}




Rationale

Many NFT projects maintain collection level metadata disconnected from their on-chain NFT's.   This current tokenUri approach to NFT metadata forces solutions to retain a bunch of information in centralized data sources like OpenSea does. Third parties must access this centralized data via OpenSea specific API's.   The inclusion of collection level metadata that adhere to a standard schema allows third party application to discover and implicitly understand NFT trait data.

An example of this is the metaverses Decentraland where they represent land with X/Y Cartesian Coordinates and Type of parcel or estate.  They also include distance values from a road or district.  The current blockchain implementation requires 3rd party applications to read all 100k plus land NFT's to get a complete understanding of metadata attributes.  There is currently no way to learn what type of scalar value or data structure these traits represent.

This collection metadata standard includes an AttributeTypes section that defines each Attribute within the tokenUri metadata.  The AttributeType defines the Attribute data structure and scalar type.  It also defines the limits and candidate values for these Attributes.


 "attributeTypes": [

{

            "name": "x",

            "display_name": "x",

            "struct_type": "scalar",

            "scalar_type": "integer",

            "min": -200,

            "max": 200

        },

        {

            "name": "type",

            "display_name": "type",

            "struct_type": "list",

            "scalar_type": "string",

            "list": [

                "parcel",

                "estate"

            ]

        }

]


This standard leverages principles from: