TEP Metadata Roadmap
This page records the planned metadata parsing work for Phase 2 wrappers.
Implementation is tracked in TODO.md; this document keeps standards and
scope visible before parser code lands.
Standards
- TEP-64 defines token and NFT metadata content layouts, including off-chain URI content and on-chain dictionary content.
- TEP-74 defines jetton contract interfaces whose wrappers need metadata from jetton master data.
- TEP-62 defines NFT item and collection interfaces whose wrappers need collection and item metadata.
The parser should use upstream TON and official TEP behavior as protocol truth. SDKs such as pytoniq, pytoniq-core, tonutils-go, tongo, and STON.fi ton-rs are comparison references only.
Initial Parser Shape
The first metadata layer should be common and raw-preserving:
- Decode snake-cell byte strings.
- Decode chunked content dictionaries.
- Distinguish on-chain content, off-chain URI content, and unsupported content.
- Preserve raw cells and unknown keys so future TEP extensions do not become lossy decode failures.
- Surface malformed content as structured errors with enough context for users to inspect the original cell.
src/metadata.rs implements this common layer as parse_tep64_content:
- top-level
0x01is decoded as off-chain URI content using snake bytes; - top-level
0x00is decoded as on-chainHashmapE 256 ^Cellcontent keyed by SHA-256 field-name hashes; - on-chain values with in-value
0x00decode as snake bytes; - on-chain values with in-value
0x01decode as chunkedHashmapE 32 ^Cellcontent and concatenate chunks in ascending chunk-index order; - unsupported top-level tags and unknown dictionary keys preserve the raw cell;
- malformed on-chain field values are preserved as field diagnostics instead of dropping the entire dictionary.
The recognized key set currently covers common TEP-64 fields used by jettons and
NFTs: uri, name, description, image, image_data, symbol,
decimals, amount_style, render_type, content_url, and video.
Jetton and NFT wrappers should build on that common layer instead of duplicating metadata parsing.
Jetton Metadata
src/jetton.rs implements typed metadata support for TEP-74-compatible jetton
masters. The wrapper decodes the official get_jetton_data() stack layout:
total_supplyas a non-negative integer;mintableas-1for true and0for false;admin_addressas a standard internal address oraddr_none;jetton_contentas a TEP-64 content cell;jetton_wallet_codeas the returned wallet code cell.
JettonMasterData::metadata() maps the parsed TEP-64 content into
JettonMetadata fields for uri, name, description, image,
image_data, symbol, decimals, and amount_style. Unknown keys,
unsupported jetton-adjacent keys, raw content, and field-level malformed value
diagnostics remain inspectable. Off-chain JSON fetching is not implemented in
this layer; off-chain content only fills the discovered URI.
Required fixture coverage:
- Off-chain URI content: covered by deterministic unit tests.
- On-chain dictionary content: covered by deterministic unit tests.
- Unknown-key preservation: covered by deterministic unit tests.
- Malformed field diagnostics and top-level malformed content rejection: covered by deterministic unit tests.
The Contract helper jetton_master_data_latest() runs get_jetton_data at
the provider’s latest masterchain block and decodes successful stacks.
jetton_metadata_latest() returns the mapped metadata. Mock-provider tests
cover method-id routing, latest-block lookup, provider errors, and non-zero
exit code propagation.
Jetton Message Bodies
src/jetton/payload.rs implements typed TEP-74 message-body builders and
decoders for:
transfer#0f8a7ea5;burn#595f07bc;internal_transfer#178d4519;transfer_notification#7362d09c;excesses#d53276db.
The builders preserve message addresses as TL-B MsgAddress, encode jetton
amounts and forwarded Toncoin values as VarUInteger 16 through Grams, and
support both inline and referenced forward_payload branches. Custom payloads
are encoded as Maybe ^Cell, matching the standard message body shape.
Deterministic unit tests cover roundtrips, opcode rejection, empty excess
payloads, custom payload references, and inline versus referenced forward
payloads.
NFT Metadata
src/nft.rs implements typed metadata support for TEP-62-compatible NFT
collections and items. The wrapper decodes the official get-method stack
layouts:
get_collection_data()returnsnext_item_index,collection_content, andowner_address;get_nft_data()returnsinit?,index,collection_address,owner_address, andindividual_content;get_nft_content(index, individual_content)returns a full TEP-64 content cell for a collection-backed item.
NftCollectionData::metadata() maps collection content into NftMetadata.
Standalone item metadata is supported by nft_item_metadata_latest() when
collection_address is addr_none; collection-backed item metadata should be
resolved by running nft_full_item_metadata_latest(&item_data) on the
collection contract so merge behavior remains contract-defined.
Address stack entries accept addr_none as None and standard internal
addresses as Some(Address). External addresses, variable-length internal
addresses, anycast, trailing data, and malformed cells are structured decode
errors.
NftMetadata maps uri, name, description, image, image_data,
render_type, content_url, and video. Unknown keys and known but
NFT-unmapped jetton fields such as symbol, decimals, and amount_style
remain raw-preserved. Malformed known field values become field diagnostics
instead of invalidating the whole metadata object.
Required fixture coverage:
- Collection metadata: covered by deterministic unit tests.
- Item metadata: covered by deterministic unit tests.
- Individual-content merge behavior through
get_nft_content: covered by deterministic mock-provider tests. - Unknown-key preservation: covered by deterministic unit tests.
- Malformed content rejection and malformed field diagnostics: covered by deterministic unit tests.
NFT Message Bodies
src/nft/payload.rs implements typed TEP-62 and TEP-66 message-body builders
and decoders for:
transfer#5fcc3d14;ownership_assigned#05138d91;excesses#d53276db;get_static_data#2fcb26a2;report_static_data#8b771735;get_royalty_params#693d3950;report_royalty_params#a8cb00ad.
The transfer and ownership helpers share the same ForwardPayload branch type
as jettons. report_static_data encodes the NFT index as uint256 and accepts
addr_none for standalone items. report_royalty_params preserves the TEP-66
uint16 numerator and denominator fields. Deterministic tests cover each
message shape, query-only payloads, addr_none, forward payload branches, and
opcode rejection.
Current Limits
The common parser, jetton metadata mapper, and NFT metadata mapper do not fetch
off-chain JSON or merge semi-chain content locally. Jetton wallet-data
get-method helpers, jetton master get_wallet_address, NFT
get_nft_address_by_index, SBT extensions, indexer API integration, and full
wallet-send convenience flows remain out of scope for the current wrapper
layer.
Sources
- Official TON token metadata documentation for TEP-64 content markers, snake encoding, chunked encoding, and common jetton/NFT metadata keys: https://docs.ton.org/standard/tokens/metadata.
- Official TON jetton interface documentation for
get_jetton_data()stack fields,mintable-1/0semantics, and TEP-74 message bodies: https://docs.ton.org/standard/tokens/jettons/api. - Official TON NFT interface documentation for
get_collection_data(),get_nft_data(),get_nft_content()stack fields, and TEP-62/TEP-66 message bodies: https://docs.ton.org/standard/tokens/nft/api. - Official TON NFT reference documentation for contract-defined full item content composition: https://docs.ton.org/standard/tokens/nft/nft-reference.