Skip to main content

Metadata

On this page, we dive into the intricacies of how NFT metadata can be managed on Immutable.

We cover topics like royalties, the significance of metadata, defining off-chain metadata in ERC721 (NFT) and ERC1155 (SFT) contracts, serving metadata, updating the indexer for new and existing assets (NFTs, SFTs & collections), and verifying the accuracy of indexed metadata.


Immutable’s metadata strategy is tailored specifically for Web3 gaming assets, which differ significantly from traditional NFTs. Our advanced services support the dynamic, fluid nature of in-game assets.

caution

All ERC721 and ERC1155 collections should have their metadata stored using the baseURI/token_id format.

See here for more information how to implement.

What is Metadata?

Metadata defines the characteristics of ERC721 (non-fungible assets NFTs), ERC1155 (semi-fungible assets SFTs) and gaming collections on the blockchain. On Immutable, this data can be accessed via our Blockchain Data APIs.

blockchain minting api asset relationships

Metadata in Web3 Gaming

  • On-Chain Metadata: Stored directly on the blockchain, ensuring permanence and security. Ideal for immutable attributes but incurs gas fees for updates. Not recommended for Web3 gaming assets that have metadata that changes often.
  • Off-Chain Metadata: Stored outside the blockchain, offering flexibility for updates and richer content. Recommended for attributes that may change frequently or require more extensive storage (e.g. images, movies, etc).

Best Practices

  • Minimize On-Chain Metadata: Off-chain storage allows for more frequent updates and cost-effective storage. For tasks like game rebalancing, which necessitate frequent metadata updates, storing such data on-chain can prove to be a costly endeavor for game studios. By leveraging off-chain storage for non-essential attributes, game developers can strike a balance between security and efficiency, enhancing the overall Web3 gaming experience.
  • Ensure Off-Chain Metadata is Indexed: Immutable indexes both on and off-chain metadata for collections, however Immutable's Blockchain Data API only indexes off-chain metadata for NFTs and SFTs. All on-chain metadata for gaming assets should be duplicate to off-chain metadata to ensure it is indexed and shared with Immutable's ecosystem.
  • Metadata Storage: Metadata can be hosted on various platforms such as your game backend, AWS S3, InterPlanetary File System (IPFS), or other data hosting solutions. Choose a solution that meets your application's performance requirements. IPFS is not recommended for Web3 gaming due to performance limitations.
  • Subgraphs: If your application requires the use of subgraphs, IPFS is recommended for this purpose.

How Should Collections Reference Where Their Metadata is Stored?

An in-game asset's off-chain metadata is represented on-chain by a baseURI, which points to the location where the off-chain metadata is stored (i.e., the URL where the data can be accessed).

This URI is defined in the token’s smart contract during deployment and determines the off-chain metadata root URL for all assets minted by that collection.

When using Immutable's preset contracts, the token's external metadata URL is constructed by concatenating the following attributes:

[baseURI]/[token_ID]

  • The baseURI is specified in a collection's smart contract at the time of deployment. In standard collection implementations, all assets belonging to a collection will share the same baseURI.
  • The token_ID is generated during the minting process, and when appended to the baseURI, it provides the unique location of an asset's metadata.

For example:

  • baseURI = https://peach-dear-wildfowl-698.mypinata.cloud/ipfs/QmVhfy6QYWBzwUZfDSJGvScLScaWKHEyUKBax8AmYqd4Sr/nft-metadata/
  • token_ID = 1

Token 1's metadata would be located at https://peach-dear-wildfowl-698.mypinata.cloud/ipfs/QmVhfy6QYWBzwUZfDSJGvScLScaWKHEyUKBax8AmYqd4Sr/nft-metadata/1.

If you are using preset ERC721 or ERC1155 contracts, ensure you define baseURI when configuring the deploy.ts file before deploying your smart contract.

For guidelines on how to format metadata, see this guide. To get started or for testing purposes, you can fork our sample metadata repository.

A step-by-step guide to preparing metadata for an asset can be found in the contract deployment and minting tutorial.

danger

If you are using your own ERC721 or ERC1155 contract, Immutable strongly suggest conforming to the [baseURI]/[token_ID] convention. If no baseURI field is defined, our Blockchain Data API will attempt to call the tokenURI() method, which incurs additional gas costs during minting as you will need to update the tokenURI field.

If your game is implementing the tokenURI method you must not define a baseURI field on your contract.

Viewing an Asset's Metadata

The metadata of NFTs, SFTs, or collections can be explored through the NFTs or Collections endpoints of the Blockchain Data API. These functions will return the metadata in JSON format.

Verifying Metadata Indexing

To verify if metadata has been indexed correctly, query the NFTs or Collections endpoints of the Blockchain Data API and examine the last_metadata_synced_at parameter in the response:

  • If this value is null, the metadata has not yet been refreshed.
  • If this value is not null but no metadata is present, then there was an error with the metadata refresh.

What is a metadata_id?

Every minted asset is assigned two key identifiers:

  1. token_id: A unique identifier for each asset within a specific collection, distinguishing one asset from another.

  2. metadata_id: A unique identifier for the metadata associated with one or more assets within the same collection. This ID is automatically generated by Immutable.

metadata_id for ERC721

For ERC721 assets, NFTs that share identical metadata (often referred to as stacked assets) will have the same metadata_id in a collection. This process is managed automatically by Immutable's Blockchain Data API. For example, if two cards in a collection have identical attributes, they will each have a unique token_id but share the same metadata_id.

If one of these cards undergoes an upgrade (e.g., through crafting), it will be assigned a new metadata_id, accessible via the NFT endpoint. If the card is the only asset with these new attributes, it will receive a unique metadata_id. If other assets in the collection share the same updated attributes, they will be grouped under the same metadata_id.

metadata_id for ERC1155

For ERC1155 assets, which inherently stack by having token_ids with quantities greater than 1, there is typically a 1:1 relationship between metadata_id and token_id within a collection. However, this 1:1 relationship is not enforced by the system.

For example, a Fire Sword might be represented by token_id=231, and the total number of Fire Swords in the game would be determined by the quantity assigned to token_id=231.

note

Game studios do not set metadata_id themselves, they are generated by Immutable and can be identified through the NFT endpoint.

Changing an Asset or a Collection's Metadata

If metadata is changed post-mint, collection owners should POST a metadata refresh to submit the assets new metadata to the Blockchain Data API service to ensure members of Immutable's ecosystem are aware of the updates.

See our guide on metadata refresh.

caution

To ensure that marketplaces, aggregators, and other third-party entities remain aware of the current state of your games assets, which inherently impact the value of the associated gaming asset, it is imperative to initiate a metadata refresh call when an asset's metadata changes.

Support for IERC721Metadata and ERC1155 metadata standard

We strongly recommend implementing baseURI as described above to ensure we can index your metadata as fast as possible. If you are porting existing contracts from other chains you might use the OpenZeppelin ERC721 Metadata extension or the metadata functionality described in the ERC1155 standard. If you cannot add a baseURI to your contract we will fetch uri information via onchain calls to the respective functions. To ensure this is the case the contract must not have a baseURI set.