Token metadata
The link between on-chain and off-chain data
Smart contracts need only store the minimum amount of data to identify the owner of a token. "External" properties are typically stored off-chain.
Sometimes these data are stored on regular cloud services. However, for better coherence and decentralisation, many projects store the token metadata on a decentralised service called IPFS. Other decentralised storage solutions include Filecoin and Arweave.
IPFS works with content-addressable URI, which means that the URI of an object is the signature (hash) of its content. This allows us to create a strong link between the on-chain information and the off-chain metadata. tzip-12 and tzip-21 allow this by adding a token_metadata
map, where the empty string key will point to a byte-encoded string representing the metadata URI (see the doc for more details)
The steps to publish metadata on IPFS are as follows
Prepare the content
A NFT usually has a media representation (image, video...). We'll use a simple PNG image here, one of a zombie, the other of a brain. Don't ask me why.
The media file can be published on IPFS, which means made available on at least a node on the network. To achieve this, either you can have an IPFS node running, or you can use pinning services such as:
When the file will be published, you will get a content identifier (CID) in return. This is used to construct the URI to access the content.
We'll use the following two images for our dApp:
If your browser cannot open these links, replace ipfs://
with https://ipfs.io/ipfs/
to use a gateway.
JSON
Now that we have our images, we can prepare the rest of the metadata. Following the token metadata standard, we end up with the following format:
These two files are also published to IPFS. We get these two URI for our metadata:
Contract encoding
According to the standard, the two metadata URI must be set as a bytes sequence representing the URI string in the smart contract. This gives us:
Zombie:
697066733a2f2f516d546d65517a55754b37716d467337795466563254434c5a416852466d716d714a793536636b6b7a666a586939
Brainz:
697066733a2f2f516d53445733794257756e7977624c544c78723835784843464d6d747a5372365a55565138433375346161314d65
To generate the byte sequence from a string, we can use this Node.js one-liner:
These two byte-strings are the values set in the `set_token_metadata` contract call, as we saw earlier.
Last updated