Traits

Intro

The metadata trait is a specification of how particular information about an on-chain entity must be provided in metadata document. Strict specification for the presentation of data allows interoperability of apps within the ecosystem.

This document provides the insight on how to use the metadata and traits. We will go down up and start with the technical implementation.

JSON Schema

JSON Schema is the widely adopted standard of defining structure of JSON documents. Essentially you can define a JSON doc in the format of JSON Schema which specifies what information conforming JSON docs must contain. Then you can validate any JSON doc if it conforms to the specification in JSON Schema format.

There are many implementations of JSON Schema that allows to validate the provided JSON document with the specification in JSON Schema format.

JSON Schema and traits

Any trait is a JSON schema document that specifies what information must be provided in metadata file. If a metadata file conforms to a particular trait - then any off-chain app in the ecosystem can use information specified by this trait.

We have the public registry of traits: GitHub. It allows companies to share information about various traits.

Metadata and traits

Let's consider an example of metadata document of NFT token from previous section:

{
    "metadata_id": "2300-15980",
    "title": "Metadata of NFT item Long Sword",
    "description": "...",
    "traits": {
        "named": {
            "name": "Long Sword"
        },
        "tech.trait.wallet.square_icon": {
            "image_uri": "https://github.com/traittech/traits-registry/blob/main/examples/trait-logo-150.svg"
        },
        ...
    }
}

This metadata contains property traits -> named, where named is the ID of the trait. This particular ID is the common trait located in the public registry of traits: GitHub. Let's consider the trait named:

{
    "$id": "https://github.com/traittech/traits-registry/traits/named/trait.json",
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "title": "Name of an on-chain entity",
    "description": "This trait provides the name of an on-chain entity.",
    "type": "object",
    "properties": {
      "name": {
        "description": "The name of the object.",
        "type": "string",
        "minLength": 1,
        "maxLength": 32
      }
    },
    "required": [ "name" ],
    "additionalProperties": false
}

This trait specifies that the JSON document, which conforms to the trait, provides the string property name with the length 1..32 symbols. As a result any on-chain entity annotated with metadata that conforms to the trait named can be properly displayed to the users.

Also the NFT metadata contains property traits -> tech.trait.wallet.square_icon, where tech.trait.wallet.square_icon is the ID of application-specific trait. It's definition is also located in the public registry of traits: GitHub. As described in the definition, this trait provides a logo for the on-chain entity displayed by the TRAIT wallet - metadata must contain a URI to the image file with logo.

You can find more examples of metadata files here: GitHub.

Metadata and on-chain entities

Metadata is a JSON file that contains information about an on-chain entity (such as NFT or Fungible token). It can be hosted on game studio' server, Amazon S3 or any other publicly-accessible storage.

On-chain entities store a URI to the metadata file. This link is stored on the blockchain.

The one possible approach to annotate on-chain entities with metadata is to create a dedicated metadata file for each minted on-chain entity. This way you can make absolute unique NFTs with unique attributes and visuals.

Another approach is to have a single metadata file for a number of on-chain entities. I.e. a number of NFTs store the same URI to metadata file. This way you can create a required number of NFTs with identical stats. But these NFTs are still independent tokens and can be owned by different players.

Metadata and off-chain apps

Metadata file can contain any number and any combination of traits. Any info needed for proper handling of an on-chain entity by an off-chain app can be included into metadata.

Examples

Example: Provide data to an exchange

Let's say we have NFTs that we want to list on an exchange. Usually, every exchange has its own requirements for the data provided for the listed NFTs. To easily automate this process, parties can do the following:

  • Exchange defines a trait with all of the required data: text description, visuals etc;

  • Creator of the NFT Collection adds this trait to the metadata of all NFTs from the collection;

  • When NFTs are deposited to the exchange - backend service of the exchange fetches & parses metadata, gets all needed information;

This allows to transfer all the necessary data to the exchange service automatically and with the minimal effort.

Example: Cross-play

Let's assume that two games are going to share the same game items. For example, two RPG games are going to share a set of armour and swords. So that the players of both games will be able to use the same game items. And players will be able to transfer items from their account in Game A to their account in Game B.

Both games will need to share the media assets (such as 3D models and textures). Additionally, both games will need to share the parameters of assets such as damage inflicted by a sword or level of protection provided by a set of armour.

Need to say that the balance system of two games can be very different and particular stats of game items can be different in two games. And also some information needs to be added to the on-chain NFTs and tokens to be displayed to the players in wallets, exchanges and other services.

Keeping all of these things in sync can be challenging and time consuming. Traits provide a solution to this challenge:

  • Define a number of traits for different aspects in form of JSON Schema: com.game-a.item_attributes, com.game-a.3d_assets, com.game-b.item_attributes, com.game-b.3d_assets, etc.;

  • Implement defined traits in NFT metadata;

  • Also implement a number of common traits in metadata, such as named and tech.trait.wallet.square_icon;

  • Implement parsing of metadata in both games;

The described concept allows game assets to be shared between the games with minimal or no direct integration between the games. And it provides a clear path for future updates of the items (such as issuing new kinds of items or rebalancing).

Common traits

Common traits are used by the most parties of the ecosystem and represent basic data about on-chain entities such as fungible tokens, NFTs and NFT collections, and AppAgents. These standards are described in the form of JSON schema which you can find here. Following the ecosystem's growth, more common traits will be added.

App-specific traits

Any application can define it's own trait and use it to exchange data between services and apps. Such a trait can precisely follow the app's requirements.

App Traits shall be stored in a Git repo in the form of a JSON schema and distributed between all interested parties. If you believe that your trait will be used by a decent percent of the TRAIT community, you can make a PR to the registry.

ID of app-specific trait must follow reverse domain name notation to avoid conflicts with other apps & traits: wiki.

Validation of metadata

After an app fetches a metadata file it shall perform validation of the file before further use. Validation can be performed by existing validators, implemented in various programming languages: link. The overall logic of validation contains several steps:

  • first the app needs to validate the overall structure of metadata defined here: GitHub;

  • after that the app shall check existence of required traits. This can be done simply by checking that the property traits contains required sub-properties - IDs of needed traits;

  • Each trait subsection of JSON metadata shall be validated with the corresponding JSON Schema. Definitions of traits can be found in trait registry or embedded into the app.

After these steps the app can be sure that all required info is provided and can handle the on-chain entity properly. If validation fails for any reason - then app shall process this as a error case depending on the context.

Important to say that the TRAIT blockchain does not provide any guarantee about existence and content of any metadata file. The TRAIT blockchain only provides a mean to distribute the URL to JSON metadata files between all interested parties.

Size of metadata file

Any JSON metadata file shall not exceed 32k bytes. Larger metadata may not be supported by all applications in the ecosystem and may lead to a poor user experience.

When an app fetches a JSON metadata file - it shall control the amount of fetched data. A malicious party can intentionally link an on-chain entity with some big file to disrupt the apps.

Quick References

  • Public registry of traits: GitHub

Last updated