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 of 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:
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
:
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: Providing 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 an assets. To easily automate this process, parties can do the following:
Exchange defines a trait with all of the required data;
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, such as
named
andtech.trait.wallet.square_icon
, in metadata - with this other wallets & services will be able to handle the on-chain entity;Implement parsing of metadata and required traits 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 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 must 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, for example with a file containing a movie.
Last updated