Let's say I want to create a fixed cap of 10,000 NFTs. I pre-generate the token_metadata and store it on IPFS. The token_ids are only recorded on the FA2 contract when they're bought.

If I don't want to store any individual token metadata (token_id, ipfs links) on-chain because it would be too expensive (creating 10,000+ big_map entries being the limitation), is there a "standard" so that wallets and marketplaces are able to load the metadata accordingly?

I loaded up my metadata on TzComet and it's complaining about this:

Optional View token_metadata is not there. This means that the contract is likely invalid: it must provide token-specific metadata using a big-map annotated with %token_metadata which was not found by TZComet.

This is how I'm initializing the contract:

class TZColorsFA2(sp.Contract):
    def __init__(self, initial_auction_house_address):
            initial_auction_house_address = initial_auction_house_address, 
            ledger = sp.big_map(tkey=LedgerKey.get_type(), tvalue=sp.TNat), 
            token_metadata = sp.big_map({"": sp.utils.bytes_of_string('ipfs://QmTwyN85GfziB5BGhF2ELogeJRt6CwevZY729bahQqKHiD')}), 
            allowances = sp.big_map(tkey=AllowanceKey.get_type(), tvalue=sp.TBool),
            metadata = sp.big_map({"": sp.utils.bytes_of_string('ipfs://QmYgdJzbJAHvZw4BNb1NXqtFM4GKHaieWaFcLKHazQ78hy')})

I'm guessing there is no standard way to do this...

I suppose, I could go with this approach and not fully implementing the TZIP-012 standard is not a big problem. This is what tzcolors.io did and it doesn't seem like a big deal because their custom smart contract and webpage marketplace knew how to look up the token_id's back to their metadata.

1 Answer 1


Yes, there is no standard way to do that. However, there is a "URI-pattern" approach, which is non-standard, but I believe it will be, eventually.

The idea is to place the string %token_metadata_uri field in the contract storage, where you specify a URI pattern, telling how to build a link to the token metadata for a token with the given token_id.

Let's say, the following parameters are allowed in the pattern:

  • {tokenId} - required;
  • {contract} - optional;
  • {chainId} - optional.

So, URI patterns would be, for example:

  • https://site.com/{tokenId}.json;
  • https://site.com?contract={contract}&token={tokenId} ;
  • https://site.com/{chainId}/metadata/{contract}/{tokenId}.

Looks pretty good and extremely cheap, however there are some cons:

  • data availability is not guaranteed, in contrast with storing on-chain;
  • there is no way to know if metadata of a particular token was updated.

Nevertheless, Ubisoft is already using this approach: https://tzkt.io/KT1TnVQhjxeNvLutGvzwZvYtC7vKRpwPWhc6/storage

  • Thanks for the reply. Hopefully this becomes a standard soon. Right now the metadata storage is a huge limitation when pre-generating a large amount of NFTs. If the individual token metadata is stored under an IPFS folder, the token metadata is guaranteed to be unchanged. The trick would be to make this work when minting more. Maybe, there could be multiple token_metadata_uri(1|2|3|4) that could be tried if the first one doesn't work. That way NFT batches could be minted.
    – JJJ
    Jan 3, 2022 at 0:25
  • 1
    @JJJ or you could simply move everything to a new folder and change the token_metadata_uri. Fallback URIs will do as well, but it doesn't scale (imagine there are 100+ URIs and you have to check most of them to find the working one).
    – Groxan
    Jan 3, 2022 at 21:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.