NFT spec

When Asteroid Protocol initially launched, there was no way to create collections or to combine specific inscriptions/NFTs into groups. This changed with the launch of NFT collections on March 28, 2024. NFT collections use the following specification:

Specification requirements

  • Easy to identify which collection any given NFT belongs to

  • Possible to find all NFTs that belong to a given collection

  • Collection metadata such as its name, description, and image

  • NFT metadata such as name, description, image, and traits

  • Open collection - not all collection NFTs have to be known/minted when creating a collection

  • Backwards compatible with existing inscriptions

NFTs in Asteroid Context

Asteroid protocol already supports arbitrary data inscription with an option to specify a parent and metadata like name, description and mime type (media type of inscribed content)

Let’s define Generic inscription transaction specification to see all the details of what’s available.

Generic Inscription transaction

Inscription transaction MUST specify Inscription operation, optionally CAN provide Inscription data, and optionally CAN require Inscription fee to be paid

Example inscription operation:

urn:{metaprotocol}:{chain-id}@{version};{operation}${param}={value},{param}={value}

KeyDescriptionExample

metaprotocol

A protocol identifier

inscription

chain-id

The chain ID for the Cosmos Hub

cosmoshub-4

version

The current version

v1

operation

A protocol operation

inscribe

param(s)

Operation params

h=hash


Inscription data:

KeyDescriptionExample

Parent

Link to the parent

An account address, collection address

Metadata

Inscription metadata

{ “name": "asteroid", "description": "asteroid", "mime": "image/png" }

Content

Base64 encoded data content

Image, Audio, Text file


Inscription fee:

KeyDescription

Receiver

Fee receiver account address

Denom

Token denomination

Amount

Token amount

IBC Channel

Optional IBC channel

Create a new Inscription transaction

Inscription operation:

urn:inscription:{chain-id}@v1;inscribe$h={hash}

KeyValueDescription

chain-id

cosmoshub-4

The chain ID for the Cosmos Hub

version

v1

The current version

operation

inscribe

Inscribe new content


Params:

ParamDescriptionRestrictions

h

The hash of the content being inscribed

Must be SHA-256(base64(JSON metadata) + base64(content))


Inscription data:

KeyValueDescription

Parent

An account address

Link to the parent

Metadata

Inscription metadata

Content

Image, Audio, Text file

The actual base64 encoded content


Metadata:

KeyDescriptionRestrictions

Name

Inscription name

Description

Inscription description

Mime

The media type of inscribed content

Explicit content

Explicit content flag (currently not in spec, but I would propose to add it so it could be checked when uploading the image and creating the inscribe transaction)

true/false

Attributes

List of Inscription traits (see below)

Inscriptions also support custom "attributes” which can be displayed alongside your artwork. This allows for unique features including rarity traits for collections.

To generate attributes, include them as an array within your metadata:

...
{
"attributes": [
    {
      "trait_type": "Base",
      "value": "Starfish"
    },
    {
      "trait_type": "Eyes",
      "value": "Big"
    },
    {
      "trait_type": "Mouth",
      "value": "Surprised"
    },
    {
      "trait_type": "Level",
      "value": 5
    },
    {
      "trait_type": "Stamina",
      "value": 1.4
    },
    {
      "trait_type": "Personality",
      "value": "Sad"
    },
    {
      "display_type": "boost_number",
      "trait_type": "Aqua Power",
      "value": 40
    },
    {
      "display_type": "boost_percentage",
      "trait_type": "Stamina Increase",
      "value": 10
    },
    {
      "display_type": "number",
      "trait_type": "Generation",
      "value": 2
    }
  ]
}

Here trait_type is the name of the trait, value is the value of the trait, and display_type is an optional field indicating how you would like it to be displayed. For string traits, you don't have to worry about display_type.

Collections

Collections enable NFTs to be grouped together and for that information to be verified on-chain. Additionally, it makes it easier to manage these collections by allocating data for them on-chain

To group NFTs, we must first create a Collection NFT whose purpose is to store any metadata related to that collection. A collection is itself, an NFT.

Inscription data / Metadata:

KeyDescriptionRestrictions

Symbol

Collection symbol (i.e. BAYC could be the symbol for Bored Ape Yacht Club)

Must be unique

Name

Collection name

Must be unique

Description

Collection description

Mime

The media type of the inscribed collection logo

Explicit content

Explicit content flag

Royalty percentage

Optional royalty. Defaults to creator address or user can specify an overriding payment address. Enforcement happens on marketplace level (marketplaces should honor the creator’s intent).

Payment address

Optional royalty payment address

Minter

Optional minter address, when minter is different from the creator (for example when minting is done by off-chain service)

Twitter

Optional Twitter URL

Discord

Optional Discord URL

Website

Optional Website URL

Telegram

Optional Telegram URL

Associating and Verifying Collection NFTs

To associate NFT with collection we set NFT Inscription data / Parent to Collection transaction hash

Indexer must verify if NFT is a valid part of the collection since anyone can set the Inscription data / Parent and pretend their NFT to be part of any collection

NFT is a valid part of the Collection when one of the following conditions is true:

  • Inscribed by the Collection owner

  • Contains signature signed with Collection minter private key (details TBD)

Backwards compatibility and Migration of existing inscriptions

  • All new inscriptions will be inscribed with V2 version

  • There would be a new operation to perform migration (migrate)

  • Migration operation is allowed only once

  • We support v1, migration is optional

  • Anyone could migrate their inscription to v2 and change parent to collection or/and add additional metadata like traits

Updates

  1. Add a way to do mass migrations (i.e. how can I update traits for 100 pre-existing NFTs?)

  2. Updating traits on legacy NFTs can only be done once via migration. Only the creator can do it.

  3. Add to front-end a checkbox that says: “I own the rights to publish this image.”

  4. This model would support packs (a collection would have pack subcollections). “Opening the pack” would be at the moment of minting. Or we could explore having the packs on-chain.

Rarity score

Rarity score for a trait = 1 / number of NFTs with the trait value / total number of nfts in the collection Rarity score for a nft = sum of rarity scores of all of its trait value

Math representation:

Last updated