AVATA 平台 NFT 元数据规范
一、什么是元数据Metadata?
在文昌链上,每一个具体的资产可以由以下元素描述:
- 资产类别:原生NFT/MT模块的Denom,或者EVM智能合约中的合约地址
- 资产ID:同一资产类别中的每个资产都具有唯一标识,即资产ID(NFT ID)
- 链上数据(Data):用于定义资产的业务属性,以及相关描述性数据,例如发行相关信息、实物映射关系、跨链相关信息等等
- 链外资源(URI):通常以url链接的形式,用于指向链下更为复杂的内容,例如图片、音频、模型、属性等
其中资产类别和资产ID组成了该资产在链上的唯一标识符号,而链上数据和链外资源组成了一个资产的元数据,赋予数字资产丰富的多维度属性。
建立通用的元数据规范有利于资产发行方快速规范进行对接完成资产发行,也便于不同的应用可以正确的提取这些属性并轻松的在前端进行展示,从而赋能更多生态场景。
二、推荐的元数据实施方式
在文昌链上,我们建议通过「链上数据(Data)」定义资产的业务属性以及相关描述;通过「链外资源(URI)」指定该NFT的“实质内容”,例如图片、音频、模型、属性等。
关于「链外资源(URI)」,目前主流的技术方案是将元数据以JSON的形式通过中心化或去中心化的方式存储,生成url并在上链过程中指定到资产数据结构的特定字段
文昌链支持多种不同协议的数字资产:原生NFT、MT,每种协议的链上数据结构稍有不同,如下列举了各种协议中的操作方法:
I 【底层链API接入】(原SDK接入方式):
NFT 和 MT
文昌链SDK中提供了以下方法去查询指定的NFT和MT:
iris query nft token <denom-id> <token-id> // 查询nft
iris query mt token <denom-id> <mt-id> // 查询 mt
在返回的数据结构中,我们可以在 nft.uri 和 mt.data.uri 中找到元数据JSON文件的url:
// 原生NFT数据结构
{
"sender": "",
"recipient": "",
"denom": "",
"id": "",
"uri": "http://example.com/example.json", // 此处为元数据JSON文件的储存位置
"data": "",
"name": "",
"uri_hash": "",
"denom_name": "",
"nft_name": ""
},
// 原生MT数据结构
{
"id": "",
"denom_id": "",
"amount": "",
"data": {
"uri":"http://example.com/example.json" // 此处为元数据JSON文件的储存位置
},
"sender": "",
"recipient": "",
"denom_name": ""
}
关于元数据哈希值,建议直接对 JSON 文件本身执行 SHA256 Hash 计算,方法如下:
// http://example.com/example.json 为元数据JSON文件的储存位置
response,err := client.Get("http://example.com/example.json")
if err != nil {
return
}
// 读取文件二进制数据
resultBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return
}
// 使用 sha-256 计算摘要
hashBytes := sha256.Sum256(resultBytes)
// 生成 hash 字符串
uriHash := hex.EncodeToString(hashBytes[:])
fmt.Println(uriHash)
II 【 AVATA多链跨链分布式应用服务平台】
AVATA为应用方提供与底层区块链交互的开放API,通过AVATA的API可以发行上述四种协议的数字资产。调用AVATA API接口发行数字资产时,可以分别在uri 和 data.uri 中指定元数据。
// 发行文昌链原生NFT,入参时在uri中指定元数据JSON文件的url
{
"name": "string",
"uri": "http://example.com/example.json", // 此处为元数据JSON文件的储存位置
"uri_hash": "string",
"data": "string",
"recipient": "string",
"tag": {
"key1": "string",
"key2": "string",
"key3": "string"
},
"operation_id": "string"
}
// 发行文昌链原生MT,入参时在data.uri中指定元数据JSON文件的url
{
"data": {
"uri":"http://example.com/example.json" // 此处为元数据JSON文件的储存位置
},
"amount": 1,
"recipient": "string",
"tag": {
"key1": "string",
"key2": "string",
"key3": "string"
},
"operation_id": "string"
}
三、资产元数据规范建议
我们推荐使用的元数据结构符合ERC-721官方元数据标准,该标准在当前主流的NFT项目和应用中得到了广泛的认可和使用。
以下是一个NFT元数据示例:
{
"description": "Friendly Creature that enjoys long swims in the ocean.",
"external_url": "https://oss.bianjie.ai/20220914010854282a92892.html",
"image": "http://example.com/example.png",
"name": "Dave Starbelly",
"attributes": [ ... ],
}
以下是该元数据结构的具体字段和使用说明:
{
"name": "", // NFT名称
"description": "", // NFT的文字介绍,值为String格式,发行方可以根据前端应用的需求来定义字符串格式和解析方式,比如支持Markdown语法等;
"description_url":[], // NFT介绍的网络素材,值为图片url数组,可以使用海报或长图以便在应用端展示对NFT的图文介绍;
"external_url": "", // 外部链接,值为网页的url,可以允许跳转到指定的外部页面,可用于指向发行方的原生应用或跳转到指定的NFT应用场景web页面;
"image": "", // NFT图片,值为图片的url
"animation_url":"", // 多媒体素材,值为素材的url,如视频、音频、3D模型、HTML(可允许使用 JavaScript 画布、WebGL 等构建丰富的体验和交互式 NFT)
"background_color":"", // NFT卡片背景色
"attributes": [ // NFT的属性集合,项目方可以根据业务属性自定义该NFT的属性分类以及取值
// 默认的String类型属性
{
"trait_type": "Base",
"value": "Starfish"
},
// 默认的number类型属性
{
"trait_type": "level",
"value": "5"
},
// 指定为Boost样式的number类型属性,可以与默认的number类型进行不同的前端展示
{
"display_type": "boost_number",
"trait_type": "Aqua Power",
"value": 40
},
// 指定为Boost样式的百分比number类型属性,可以与默认的number类型进行不同的前端展示
{
"display_type": "boost_percentage",
"trait_type": "Stamina Increase",
"value": 10
},
// 指定数值样式的number类型属性,可以与默认的number类型进行不同的前端展示
// max_value为可选项,赋值则指定该属性的最大值
{
"display_type": "number",
"trait_type": "排名",
"value": 1,
"max_value": 30
},
// 日期类型属性
{
"display_type": "date",
"trait_type": "birthday",
"value": 1546360800
}
]
}
四、关于资产类别元数据的建议
资产类别,又称为Class,同一类别的数字资产可以被收藏在同一个集合中,后者被很多应用称为“Collection”或者“系列”。资产类别也需要使用到元数据,用于方便展示数字资产集合的信息,如名称,封面,介绍,外链等。
在文昌链原生NFT和MT中,其Class可以通过Denom去定义,发行NFT或MT之前,需要先创建Denom。文昌链SDK中可使用如下方法:
irita tx nft issue <denom-id> --schema=<schema-content or path/to/schema.json> --mint-restricted=<mint-restricted> --update-restricted=<update-restricted>
其中schema.json就是Class的元数据。
如果您自己需要在文昌链上部署ERC-721和ERC-1155智能合约来发行NFT,您也可以在合约中添加如下方法返回一个合约级的元数据作为Class结构:
contract MyCollectible is ERC721 {
function contractURI() public view returns (string memory) {
return "https://metadata-url.com/my-metadata";
}
}
或者使用AVATA 的如下API来创建 NFT 和 MT:
/*
发行文昌链原生 NFT
接口:https://apis.avata.bianjie.ai/v1beta1/nft/classes,入参时在uri中指定元数据JSON文件的url
*/
{
"name": "string",
"class_id": "string",
"symbol": "string",
"description": "string",
"uri": "http://example.com/example.json", // 此处为Class元数据JSON文件的储存位置
"uri_hash": "string",
"data": "string",
"owner": "string",
"tag": {
"key1": "string",
"key2": "string",
"key3": "string"
},
"operation_id": "string"
}
/*
发行文昌链原生 MT
接口:https://apis.avata.bianjie.ai/v1beta1/mt/classes
入参时在data.uri中指定元数据JSON文件的url
*/
{
"name": "string",
"owner": "string",
"data": {
"uri": "http://example.com/example.json", // 此处为Class元数据JSON文件的储存位置
},
"tag": {
"key1": "string",
"key2": "string",
"key3": "string"
},
"operation_id": "string"
}
以上的Class 元数据JSON均可以以下面的标准来定义,这样可以更好的适应更多NFT应用。
{
"name": "", // NFT Class的名称,值为String类型
"description": "", // NFT Class的文字描述,值为String类型
"image": "", // NFT Class的图片,值为图片的url
"external_url": "", // NFT Class的外部链接,值为网页的url
}