How to implement attributes property in TON NFT on-chain metadata

I’m building an NFT project on the TON blockchain and need to store all metadata directly on the blockchain rather than using external storage. This is important because I’m planning to have a public minting feature. I’ve figured out how to handle most of the metadata fields within the smart contract, but I’m struggling with implementing the attributes section properly.

Here’s my current approach that isn’t working correctly:

cell trait_data = begin_cell().store_int(0,8).store_slice("{\"trait_type\":\"background\",\"value\":\"blue\"}").end_cell();

nft_metadata~udict_set_ref(256, "attributes"H, trait_data);

Can anyone show me the correct way to structure the attributes field for TON NFT metadata when building it inside the contract code?

hmm interesting approaches from both of you! i’m curious about one thing though - are you handling dynamic attributes at all? like what if you want to generate different trait combinations during minting?

i’ve been experimenting with a similar setup and found that hardcoding the json strings works for static collections, but gets tricky when you need conditional logic. have you tried building the attributes programmatically based on some randomness or input parameters?

also @LiamDragon22 - just wondering, are you planning to have the attributes affect any game mechanics or just display purposes? because that might change how you want to structure the data storage. sometimes it’s worth storing traits as separate fields too if you need to query them later in contract calls.

btw, one small thing i noticed - make sure your json is properly escaped when you’re concatenating strings in func. i had some weird parsing issues on the frontend when quotes weren’t handled right :sweat_smile:

Your problem is you’re storing a single trait as a string instead of creating a proper JSON array for multiple attributes. TON NFT metadata needs the attributes field as a serialized JSON array.

I hit this same issue last year building my own TON NFT collection. Here’s what worked for me - build the complete attributes array as a JSON string first, then store it:

slice attributes_json = "{\"attributes\":[{\"trait_type\":\"background\",\"value\":\"blue\"},{\"trait_type\":\"rarity\",\"value\":\"common\"}]}"; cell attributes_cell = begin_cell().store_slice(attributes_json).end_cell(); nft_metadata~udict_set_ref(256, "attributes"H, attributes_cell);

The key is building the full JSON structure with the attributes array wrapper. Also escape your quotes properly in the JSON strings. This approach worked reliably for me across multiple mainnet contract deployments.

you don’t need the outer wrapper for attributes - just store the array directly. try cell attrs = begin_cell().store_slice("[{\"trait_type\":\"bg\",\"value\":\"blue\"}]").end_cell(); then set it normally. works fine without the extra json wrapping