Skip to content

Metadata Declarations

Abstract

This ARC describes a standard for a self-sovereign on-chain project & info declaration. The declaration is an ipfs link to a JSON document attached to a smart contract with multi-wallet verification capabilities that contains information about a project, including project tokens, FAQ, NFT collections, team members, and more.

Motivation

In our current ecosystem we have a number of centralized implementations for parts of these vital pieces of information to be communicated to other relevant parties. All NFT marketplaces implement their own collection listing systems & requirements. Block explorers all take different approaches to sourcing images for ASA’s; The most common being a github repository that the Tinyman team controls & maintains. This ARC aims to standardize the way that projects communicate this information to other parts of our ecosystem.

We can use a smart contract with multi-wallet verification to store this information in a decentralized, self-sovereign & verifiable way by using custom field metadata & IPFS. A chain parser can be used to read the information stored & verify the details against the verified wallets attached to the contract.

Specification

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

This proposal specifies an associated off-chain JSON metadata file, displayed below. This metadata file contains many separate sections and escape hatches to include unique metadata about various businesses & projects. For the purposes of requiring as few files & ipfs uploads as possible the sections are all included within the same file. The file is then added to IPFS and the link saved in a custom field on the smart contract under the key project.

FieldSchemaDescriptionRequired
versionstringThe version of the standard that the metadata is following.true
associatesarray<Associate>An array of objects that represent the associates of the project.false
collectionsarray<Collection>An array of objects that represent the collections of the project.false
tokensarray<Token>An array of objects that represent the tokens of the project.false
faqarray<FAQ>An array of objects that represent the FAQ of the project.false
extrasobjectAn object that represents any extra information that the project wants to include.false
Top Level JSON Example
{
"version": "0.0.2",
"associates": [...],
"collections": [...],
"tokens": [...],
"faq": [...],
"extras": {...}
}

Version

We envision this is an evolving / living standard that allows the community to add new sections & metadata as needed. The version field will be used to determine which version of the standard the metadata is following. This will allow for backwards compatibility & future proofing as the standard changes & grows. At the top level, version is the only required field.

Associates

Associates are a list of wallets & roles that are associated with the project. This can be used to display the team members of a project, or the owners of a collection.

The associates field is an array of objects that contain the following fields:

FieldSchemaDescriptionRequired
addressstringThe algorand wallet address of the associated persontrue
rolestringA short title for the role the associate plays within the project.true

eg:

"associates": [
{
"address": "W5MD3VTDUN3H2FFYJR2NDXGAAV2SJ44XEEDGBWHIZKH6ZZXF44SE7KEPVP",
"role": "Project Founder"
},
...
]

Collections

NFT Collections have no formal standard for how they should be declared. This section aims to standardize the way that collections are declared & categorized. The collections field is an array of objects that contain the following fields:

FieldSchemaDescriptionRequired
namestringThe name of the collectiontrue
networkstringThe blockchain network that the collection is minted on.
Default: algorand
Special: multichain
false
prefixesarray<string>An array of strings that represent the prefixes to match against the unit_name of the NFTs in the collection.false
addressesarray<string>An array of strings that represent the addresses that minted the NFTs in the collection.false
assetsarray<uint64>An array of strings that represent the asset_ids of the NFTs in the collection.false
excluded_assetsarray<uint64>An array of strings that represent the asset_ids of the NFTs in the collection that should be excluded.false
artistsarray<string>An array of strings that represent the addresses of the artists that created the NFTs in the collection.false
banner_imagestringAn IPFS link to an image that represents the collection.
if set banner_id should be unset & vice-versa
false
banner_iduint64An asset_id that represents the collection.false
avatar_imagestringAn IPFS link to an image that represents the collection.
if set avatar_id should be unset & vice-versa
false
avatar_iduint64An asset_id that represents the collection.false
explicitbooleanA boolean that represents whether or not the collection contains explicit content.false
royalty_percentageuint64A uint64 with a value ranging from 0-10000 that represents the royalty percentage that the collection would prefer to take on secondary sales.false
propertiesarray<CollectionProperties>An array of objects that represent traits from an entire collection.false
extrasobjectAn object of key value pairs for any extra information that the project wants to include for the collection.false

eg:

"collections": [
{
"name": "My Collection",
"networks": "algorand",
"prefixes": [
"AKC",
...
],
"addresses": [
"W5MD3VTDUN3H2FFYJR2NDXGAAV2SJ44XEEDGBWHIZKH6ZZXF44SE7KEPVP",
...
],
"assets": [
123456789,
...
],
"excluded_assets": [
123456789,
...
],
"artists": [
"W5MD3VTDUN3H2FFYJR2NDXGAAV2SJ44XEEDGBWHIZKH6ZZXF44SE7KEPVP",
...
],
"banner_image": "ipfs://...",
"avatar": 123456789,
"explicit": false,
"royalty_percentage": "750", // ie: 7.5%
"properties": [
{
"name": "Fur",
"values": [
{
"name": "Red",
"image": "ipfs://...",
"image_integrity": "sha256-...",
"image_mimetype": "image/png",
"animation_url": "ipfs://...",
"animation_url_integrity": "sha256-...",
"animation_url_mimetype": "image/gif",
"extras": {
"key": "value",
...
}
},
...
]
}
...
],
"extras": {
"key": "value",
...
}
},
...
]

Collection Scoping

Not all collections have been consistent with their naming conventions. Some collections are minted across multiple wallets due to prior asa minting limitations. The following fields used together offer great flexibility in creating a group of NFTs to include in a collection. prefixes, addresses, assets, excluded_assets. Combined, these fields allow for maximum flexibility for mints that may have mistakes or exist across wallets & dont all conform to a consistent standard.

prefixes allows for simple grouping of a set of NFTs based on the beginning part of the ASAs unit_name. This is useful for collections that have a consistent naming convention for their NFTs. Every other scoping field modifies this rule.

addresses scope down the collection to only include ASAs minted by the addresses listed in this field. This is useful for projects that mint different collections across multiple wallets that utilize the same prefix.

assets is a direct entry in the collection for NFTs that dont conform to any of the prefix rules.

excluded_assets is a direct exclusion on an NFT that may conform to a prefix but should be excluded from the collection.

banner_image, banner_id, avatar_image, avatar_id are all very self explanatory. They allow for a glancable preview of the collection to display on NFT marketplaces, analytics sites & others. Both banner & avatar field groups should be one or the other, not both. banner_image or banner_id (likely an ASA id from the creator). avatar_image or avatar_id (likely an ASA id from the collection).

explicit is a boolean that indicates whether or not the collection contains explicit content. This is useful for sites that want to filter out explicit content.

properties is an array of objects that represent traits from an entire collection. Many new NFT collections are choosing to use ARC-19 and mint their NFTs as blank slates. This can prevent sniping but also has the adverse affect of obscuring the trait information of a collection. This field allows for a collection to declare its traits, values, image previews of the trait it references and extra metadata.

Collection Properties

FieldSchemaDescriptionRequired
namestringThe name of the propertytrue
valuesarray<CollectionPropertyValue>An array of objects that represent the values of the property.true

Collection Property Values

FieldSchemaDescriptionRequired
namestringThe name of the valuetrue
imagestringAn IPFS link to an image that represents the value.false
image_integritystringA sha256 hash of the image that represents the value.false
image_mimetypestringThe mimetype of the image that represents the value.false
animation_urlstringAn IPFS link to an animation that represents the value.false
animation_url_integritystringA sha256 hash of the animation that represents the value.false
animation_url_mimetypestringThe mimetype of the animation that represents the value.false
extrasobjectAn object of key value pairs for any extra information that the project wants to include for the property value.false

Tokens

Tokens are a list of assets that are associated with the project. This can be used to verify the tokens of a project and for others to easily source images to represent the token on their own platforms.

FieldSchemaDescriptionRequired
asset_iduint64The asset_id of the tokentrue
imagestringAn IPFS link to an image that represents the token.false
image_integritystringA sha256 hash of the image that represents the token.false
image_mimetypestringThe mimetype of the image that represents the token.false

eg:

"tokens": [
{
"asset_id": 123456789,
"image": "ipfs://...",
"image_integrity": "sha256-...",
"image_mimetype": "image/png",
}
...
]

FAQ

Frequently Asked Questions for the project to address the common questions people have about their project and help inform the community.

FieldSchemaDescriptionRequired
qstringThe questiontrue
astringThe answertrue

eg:

"faq": [
{
"q": "What is XYZ Collection?",
"a": "XYZ Collection is a premiere NFT project that..."
},
...
]

Extras

Custom Metadata for extending & customizing the declaration for your own use cases. This object can be found at several levels throughout the specification, The top level, within collections & within collection property value objects.

FieldSchemaDescriptionRequired
keystringThe key of the extra informationtrue
valuestringThe value of the extra informationtrue

eg:

"extras": {
"key": "value",
...
}

Contract Providers

Custom metadata needs to be verifiable and many projects use many wallets as a means of separating concerns. Providers are smart contracts that have the capability of verifying multiple wallets & thus provide evidence to parsers of the authenticity of such data. Providers that support this standard will be listed on the ARC compatibility matrices site.

Rationale

See the motivation section above for the general rationale.

Security Considerations

None

Copyright and related rights waived via CCO.