Reading of NFD metadata

Every NFD is a distinct instance of an Algorand Smart Contract. It has a distinct Application ID, and because it is a contract account, it can also independently hold and control its own assets.

Every NFD is created using a fixed amount of global state keys, storing only 'internal' properties (i.*) in global state. Starting in version 2.x(+) of the NFD contracts, all user-defined and verified properties are stored in box storage. Prior to 2.x, all properties were stored in global state.

All NFD data is stored with prefixed keys, where the 2 character prefix defines the type and permission level on the key.

Property Types

The 3 different types are:

  • "i." - Internal

    • Internal properties can ONLY be set by the contract itself as part of creation, and various state changes - minting, reservations / claiming, offering up for sale, etc.

    • These are all stored in global state.

  • "u." - User-Defined

    • User defined properties can only be set by the Owner.

    • NFDomains can clear u. fields as part of putting up an NFD for sale (as part of clearing all metadata), or when a property is verified [moving from u. to v. - which is deleting the u.xxx value and moving to its corresponding v.xx value].

  • "v." - Verified

    • Verified properties can currently only be set by NFDomains.

    • In the future, as Off-chain/On-Chain Oracle contracts become available that provide equivalent (and trustable) services, then NFD contracts will hopefully be able to allow specific oracles to set specific verified properties.

Internal, and Verified properties will often be camelCase.

All user-defined properties will always be lowercase (at least as set in transactions provided by the API/UI). The contracts themselves don't care - users own their data - but differing from conventions may cause problems in integrations.

Property Schema

In the majority of cases, properties are simply 'bit buckets' - often just string values. Some values (only internal properties) are stored natively as integers (in Algorand 64-bit Big-Endian format - compatible with itob / btoi TEAL operations). Some are packed Algorand 32-byte PKs (not including the checksum).

Aside from some specific internal properties, properties will have special suffixes to denote different encodings.

Encoding Suffix hints

  • .a - This represents an Algorand Account address. The value will be the 32-byte public-key of the account. The Algorand SDK EncodeAddress method can be used to convert to an Algorand account.

    • An example would be i.owner.a - the owner of the NFD.

  • .#.as - this represents a 'set' of Algorand addresses. There will be up to 3 per value packed together.

    • An example would be v.caAlgo.0.as - this would represent the first (up to 10 - 0 through 9) of a set of packed algorand addresses . This particularly property contains the 'verified' linked 'Crypto Address' Algo addresses. v.caAlgo.0.as would contain 1, 2, or 3 addresses. If there were more, then v.caAlgo.1.as would be present with addresses 4+ (up to #6) and so on. The user linking 10 addresses would create calls to the update_field method, setting v.caAlgo.0.as, v.caAlgo.1.as, v.caAlgo.2.as, and v.caAlgo.3.as to fit all 10 addresses. If the user removed 9 leaving just 1, then the API wouold generate calls to remove all but v.caAlgo.0.as - setting it to just the 1 address.

  • _## - This represents a value that's been extended across keys. The boxes used for properties are constrained to 1988 bytes (allowing for 60 char key name), with larger values spread across keys.

    • An example would be a long u.metadata field (perhaps 3K characters). It would be stored as u.bio_00 with (8+1988 bytes [u.bio_00 being 8 bytes] and then 1988 bytes of the first part of its value). u.bio_01 would then contain the remaining 1084 bytes of the 3K valuen. In this 3072 byte example, 1988 chars in 00, and 1084 in 01.

    • On update, the NFDomains API will create update_field transactions to remove any excess fields if the value is shortened, and also the extra fields when the value is longer. During reading, all of these extended values are concatenated together and returned via the API as a single field, stripping off the suffix. ie, just u.bio in this example.

Last updated