NFT metadata has many use cases. One of the most well-known use cases is calculating the rarity of collectible NFTs. However, there are many use cases beyond collecting our digital furry friends.
You can use NFT metadata for many other purposes:
To ensure we can cater to all these use cases, Hedera introduced token metadata JSON schemas that try to standardize the structure of token metadata. HIP10 was the first version of such a standard. Now, HIP412 (v2) replaces the HIP10 standard. HIP412 represents the "token metadata JSON schema V2".
So, why do we need the token metadata JSON schema V2, how can you implement it, and what does the token metadata JSON schema look like? Let's get started.
The HIP412 specification provides the second version of our token metadata JSON schema. The token metadata JSON schema V2 provides a standard scheme for non-fungible token metadata on Hedera. This standard aims to provide a common JSON schema for structuring metadata to make it easier for NFT tooling to parse metadata.
For example, NFT explorers want to scrape information about an NFT's attributes to calculate rarity. The token metadata JSON schema V2 defines the "attributes" property and its format to make it easier for NFT tooling to find the correct information about an NFT.
In short, the token metadata JSON schema V2 defines a flexible specification for creating NFTs on Hedera.
It's essential to understand that the token metadata JSON schema V2 requires you to store metadata using a storage solution, centralized or decentralized, such as IPFS or Arweave.
When creating a non-fungible token using the Hedera Token Service, you set the metadata value to the metadata JSON file to define your NFT, wherever it’s stored. This technique allows you to connect the metadata to the token created on the Hedera network. It's not allowed to use the "memo" or "symbol" fields on the NFT.
Here's an excerpt from the "NFT minting" tutorial.
// IPFS content identifiers for which we will create a NFT let CID = "ipfs://QmTzWcVfk88JRqjTpVwHzBeULRTNzHY7mnBSG42CpwHmPa"; // Mint new NFT let mintTx = await new TokenMintTransaction() .setTokenId(tokenId) .setMetadata([Buffer.from(CID)]) .freezeWith(client);
You can find the reference implementation for the token metadata JSON schema V2 in the Hedera Improvements Proposals GitHub repository, via the NFT.Storage gateway link, or IPFS itself (ipfs://bafkreidcsqzr5su356thecwuyzrhsgekfdsqzuyuqxtsu4vh7oc34iv5oy).
The schema defines three required properties:
The image field is required. It can both serve as a preview image or the full-resolution image for your NFT to ensure cross-platform compatibility. The image property will be displayed in wallets and marketplaces by default.
image
Creators are recommended to point to a thumbnail in the image field and put the high-resolution image in the files array with the is_default_file boolean set to indicate that this file represents the default image for the NFT.
files
is_default_file
Here's an example of a full implementation for a collectible NFT.
{ "name": "Example NFT 001", "creator": "Jane Doe, John Doe", "creatorDID": "did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.123", "description": "This describes my NFT", "image": "https://myserver.com/preview-image-nft-001.png", "checksum": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "type": "image/png", "format": "[email protected]", "properties" : { "external_url": "https://nft.com/mycollection/001" }, "files": [ { "uri": "https://myserver.com/high-resolution-nft-001.png", "checksum": "9defbb6402d4bf39f2ea580099c73194647b24a659b6f6b778e3dd71755b8862", "is_default_file": true, "type": "image/png" }, { "uri": "ipfs://yusopwpksaioposjfopiapnnjlsl", "type": "image/png" } ], "attributes": [ { "trait_type": "color", "display_type": "color", "value": "rgb(255,0,0)" }, { "trait_type": "hasPipe", "display_type": "boolean", "value": true }, { "trait_type": "coolness", "display_type": "boost", "value": 10, "max_value": 100 }, { "trait_type": "stamina", "display_type": "percentage", "value": 83 } , { "trait_type": "birth", "display_type": "datetime", "value": 732844800 } ], "localization": { "uri": "ipfs://QmWS1VAdMD353A6SDk9wNyvkT14kyCiZrNDYAad4w1tKqT/{locale}.json", "default": "en", "locales": ["es", "fr"] } }
All other properties are optional, but they are essential to provide more information about your NFT. Here's an overview of the other properties you should look out for.
Want to learn more about the specification? You can click the different URLs to find more information about each property or look up the JSON schema.
You can use the token metadata validator package to verify if your metadata is correctly structured. This code package allows you to validate your metadata against the token metadata JSON schema V2. The package is created using JavaScript and can be installed with a package manager like NPM or Yarn.
Here's a small code example of how to use the package.
const { validator, defaultVersion } = require('@hashgraph/nft-utilities'); const metadata = { name: "My First NFT", attributes: [ { trait_type: "Background", value: "Yellow" } ], creator: "NFT artist", image: "ipfs://bafkreibwci24bt2xtqi23g35gfx63wj555u77lwl2t55ajbfjqomgefxce" }; const issues = validator(JSON.stringify(metadata), defaultVersion);
The metadata specification section has shown you how to create a collectible NFT on Hedera using the token metadata V2 schema. What else can we use the standard for?
Here's a multi-file NFT that includes a video, which is the main file for the NFT, and a PDF document. The PDF document has a metadata object which again adheres to the specification.
{ "name": "Example NFT", "creator": "Jane Doe, John Doe", "creatorDID": "did:hedera:mainnet:7Prd74ry1Uct87nZqL3ny7aR7Cg46JamVbJgk8azVgUm;hedera:mainnet:fid=0.0.123", "description": "This is an example NFT metadata", "image": "https://myserver.com/preview-image-001.png", "checksum": "9defbb6402d4bf39f2ea580099c73194647b24a659b6f6b778e3dd71755b8862", "type": "image/png", "files": [ { "uri": "ipfs://bawlkjaklfjoiaefklankfldanmfoieiajfl", "type": "video/mp4", "is_default_file": true }, { "uri": "ipfs://bawlkjaklfjoiaefklankfldanmfoieiajfl", "type": "application/pdf", "metadata": { "name": "Example second file", "description": "The description is recommended but optional. The image provided is an optional preview", "image": "ipfs://bawlkjaklfjoiaefklankflda1313ieiajfl", "type": "image/jpeg" } } ], "localization": { "uri": "ipfs://QmWS1VAdMD353A6SDk9wNyvkT14kyCiZrNDYAad4w1tKqT/{locale}.json", "default": "en", "locales": ["es", "fr"] } }
It's possible to indefinitely nest files. Here's an example with nested files (level 2 nesting).
The image listed in the files object represents a cover image for the PDF. Further, this object includes metadata which again lists a files array. This files array contains a file of type "application/vnd.ms-powerpoint" (PowerPoint presentation) attached to the PDF. For example, the PowerPoint presentation supplements the PDF.
{ "name": "Example NFT", "image": "ipfs://bafkreibwci24bt2xtqi23g35gfx63wj555u77lwl2t55ajbfjqomgefxce", "type": "image/png", "files": [ { "uri": "ipfs://bawlkjaklfjoiaefklankfldanmfoieiajfl", "type": "application/pdf", "metadata": { "name": "Example second file", "description": "The description is recommended but optional. The image provided is an optional preview", "image": "ipfs://bawlkjaklfjoiaefklankflda1313ieiajfl", "type": "image/jpeg", "files": [ { "uri": "ipfs://QmWS1VAdMD353A6SDk9wNyvkT14kyCiZrNDYAad4w1tKqT", "type": "application/vnd.ms-powerpoint" } ] } } ] }
Here's a basic NFT that defines a creator and description. Besides that, it lists the required properties "image", "type", and "name".
Further, the "properties" property includes additional metadata that the token metadata V2 specification does not specify. You can include any data in the "properties" object. As a best practice, if you define a boolean, start its naming with "is" or "has". For example, "hasProperty" or "isCollectible".
{ "name": "Example NFT", "creator": "John Doe", "description": "This is an example NFT metadata", "image": "ipfs://bafkreibwci24bt2xtqi23g35gfx63wj555u77lwl2t55ajbfjqomgefxce", "type": "image/png", "properties": { "license": "MIT-0", "collection": "Generic Collection Name", "website": "www.johndoe.com", "isCollectible": true } }
The token metadata JSON schema V2 will continue to evolve based on changing market dynamics and community needs. The sole purpose is to provide a "common language" for NFT metadata to make it easier for NFT tooling to interpret NFT metadata.
Do you have suggestions or want to make changes? Go to the Hedera Improvement Proposals GitHub repository where you can submit an issue or create a pull request.