跳转到内容

Aptos代币标准(旧版)

NFT是一种存储在区块链上的非同质化代币,它唯一地定义了资产的归属权.NFT最初在EIP-721中定义,后来在EIP-1155中进行了扩展.NFT通常通过以下属性定义:

  • name:资产名称.在同一个集合内必须唯一.
  • description:资产描述.
  • uri:指向链外数据的URL链接,用于获取资产更多信息.这些资产可以是图片,视频等媒体文件或更多元数据.
  • supply:该NFT的总供应量.许多NFT只有一个供应量,而拥有多个供应量的则被称为”版本”.

此外,大多数NFT都属于某个集合(collection),即具有共同属性(如主题,创建者或最小合约单位)的一组NFT.每个集合都有类似的属性集:

  • name:集合名称.在创建者账户内必须唯一.
  • description:集合描述.
  • uri:指向链外数据的URL链接,用于获取集合更多信息.
  • supply:该集合当前的NFT总数.
  • maximum:该集合允许的最大NFT数量.若maximum设为0,则不跟踪供应量.

Aptos代币标准基于以下原则开发:

  • 互操作性:通过标准实现提升生态系统项目间的互操作性.由于Move是静态语言且不支持动态分发,这一原则尤为重要.
  • 流动性:通过在同一合约中定义NFT,同质化(非小数)和半同质化代币,实现最大流动性.这些不同类型的代币可以相同方式存储,转移和交易,从而更容易在各类市场,交易所和其他交易方式间实现互操作.
  • 丰富的链上属性:支持自定义链上代币属性.用户可以定义自己的属性并存储在链上,这有可能消除对链外元数据的依赖.
  • 降低开销:减少从同质化代币创建大量NFT的成本.例如,通过重用某些同质化代币的链上元数据,降低相似代币的开销.

Aptos代币标准使用PropertyMap模块来存储代币的链上属性.PropertyMap将字符串键映射到链上的属性值,该值以二进制规范序列化(BCS)格式及其类型存储.当前PropertyMap仅支持原始类型(bool, u8, u64, u128, address和String).诸如Aptos Names等应用程序会定义特定于应用的属性,这些属性由应用程序智能合约读写.

您可以将属性添加到TokenData中的default_properties.此处定义的属性默认由所有代币共享.

default_properties字段是一个带有类型信息的键值存储.它利用PropertyMap模块,该模块包含将不同原始类型序列化和反序列化为属性值的函数.

您也可以使用代币本身定义的token_properties进行链上定制.可以为该特定代币的某个属性创建定制值,从而允许代币拥有与其默认值不同的属性值.

请注意,链上存储自定义代币属性存在限制:每个代币最多1000个属性,且字段名称限制为128个字符.

同质化代币共享相同的默认属性值.但这些属性值会随时间演变而变得互不相同.为了支持此类代币属性的演变,Aptos代币标准提供了property_version字段.其工作原理如下:

  • 在代币创建(铸造)期间,所有代币初始时property_version设为0,这些代币可以堆叠在一起作为同质化代币.
  • 当创建者变更代币的默认属性时,被变更的代币将被分配一个唯一的property_version以创建新的token_id,从而与其他同质化代币区分.这个唯一的token_id允许代币拥有自己的属性值,且该代币的所有进一步变更不会再次改变property_version.此时该代币本质上已成为NFT.

为了使可变性对创建者和所有者都明确可见,Aptos代币标准在集合级别和代币级别都提供了mutability_config来控制哪些字段是可变的.这里的”可配置”意味着创建者可以在创建时将该字段配置为可变或不可变.

请遵循以下标准以确保您的NFT能在各类钱包中正确显示.

您应该将元数据存储在如Irys这样的链上数据解决方案中的JSON文件里,并在代币或集合的uri字段中提供该JSON文件的URL.我们建议开发者按照ERC-1155链下数据模式来格式化JSON文件.

{
"image": "https://gateway.irys.xyz/QH3rksVhbFg5L9vvjGzb4POUibCEG-TGPInmofp-O-o",
"animation_url": "https://gateway.irys.xyz/QH3rksVhbFg5L9vvjHzb4POUibCEG-TGPInmofp-O-o",
"external_url": "https://petra.app/",
"attributes": [
{
"trait_type": "web",
"value": "yes"
},
{
"trait_type": "mobile",
"value": "yes"
},
{
"trait_type": "extension",
"value": "yes"
}
],
"properties": {
"files": [
{
"uri": "https://gateway.irys.xyz/QH3rksVhbFg5L9vvjGzb4POUibCEG-ENXUnmofp-O-o",
"type": "image/png"
},
{
"uri": "https://gateway.irys.xyz/QH3rksVhbFg5L9vvjGzb4POUibCEG-UENCnmofp-O-o",
"type": "unknown",
"cdn": true
},
{
"uri": "https://gateway.irys.xyz/QH3rksVhbFg5L9vvjGzb4POUibCEG-DJHUUnmofp-O-o",
"type": "video/mp4"
}
],
"category": "video"
}
}
  • image: 图像资源的URL.可使用?ext={文件扩展名}查询参数提供文件类型信息
  • animation_url: 资产多媒体附件的URL.可使用相同的file_extension查询参数提供文件类型
  • external_url: 用户也可查看图像的外部网站URL
  • attributes: 对象数组,每个对象应包含trait_typevalue字段.value可以是字符串或数字
  • properties.files: 对象数组,每个对象应包含作为资产组成部分的文件URI和类型.类型应与文件扩展名匹配.该数组还应包含imageanimation_url字段中指定的文件,以及与资产相关的任何其他文件.可使用?ext={文件扩展名}查询参数提供文件类型信息
  • properties.category: 支持的类别包括:
    • image - PNG, GIF, JPG
    • video - MP4, MOV
    • audio - MP3, FLAC, WAV
    • vr - 3D模型;GLB, GLTF
    • html - HTML页面;HTML页面中的脚本和相对路径也受支持

您还可以通过在文件对象中使用cdn标志将文件托管在CDN上以提供更快的加载速度.当文件存在时,这应该是钱包读取媒体文件(video, audio, vr)的主要位置.如果文件不再可用,钱包可以回退使用animation_url加载文件.

{
"properties": {
"files": [
{
"uri": "https://watch.videodelivery.net/52a52c4a261c88f19d267931426c9be6",
"type": "unknown",
"cdn": true
}
]
}
}

以下流程图展示了代币数据在Aptos中的流转过程.

Signed Transaction Flow Signed Transaction Flow

如上图所示,与代币相关的数据同时存储在创建者账户和所有者账户中.

以下表格描述了结构体级别的字段.完整列表请参阅Aptos代币框架.

字段描述
Collections维护一个名为collection_data的表格,将集合名称映射到CollectionData.同时存储该创建者创建的所有TokenData.
CollectionData存储集合元数据.supply表示当前集合中已创建的代币数量,maximum是该集合中代币数量的上限.
CollectionMutabilityConfig指定哪些字段是可变的.
TokenData作为存储代币元数据的主要结构体.Properties字段允许用户添加未在代币数据中定义的自定义属性.用户可以根据TokenData铸造更多代币,这些代币共享相同的TokenData.
TokenMutabilityConfig控制哪些字段是可变的.
TokenDataId用于表示和查询链上TokenData的ID.该ID主要包含三个字段:创建者地址,集合名称和代币名称.
Royalty指定计算版税的分母和分子,并包含用于存放版税的收款人账户地址.
PropertyValue包含属性的值和类型.
字段描述
TokenStore存储该地址所拥有代币的主要结构体.它将 TokenId 映射到实际代币.
Token数量字段表示代币的个数.
TokenIdTokenDataId 指向该代币的元数据.property_version 表示该代币的属性相对于 TokenDatadefault_properties 发生了变异的版本.

更详细描述请参阅 Aptos代币框架.

每个Aptos代币都属于一个集合.开发者首先需要通过 create_collection_script 创建一个集合,然后创建属于该集合的代币 create_token_script.为了实现并行的 TokenDataToken 创建,开发者可以创建无限量的集合和 TokenData,其中集合和 TokenDatamaximum 都设置为 0.通过这种设置,代币合约不会跟踪代币类型(TokenData 数量)和每个代币类型中的代币供应量.因此,TokenData 和代币可以并行创建.

Aptos还对输入大小实施简单验证并防止重复:

  • 代币名称 - 在每个集合内唯一
  • 集合名称 - 在每个账户内唯一
  • 代币和集合名称长度 - 小于128个字符
  • URI长度 - 小于512个字符
  • 属性映射 - 最多可容纳1000个属性,每个键应小于128个字符

我们的标准支持可变性设计,其核心原则是:

所有可变字段必须在代币创建时明确指定.这样当代币所有者从创建者处获取代币时,可以清楚知晓哪些字段是可变的.我们的合约使用CollectionMutabilityConfig来检查集合级别的字段可变性,同时使用TokenMutabilityConfig来检查TokenData字段的可变性.

关于属性可变性,我们提供两种机制:

  • 存储在TokenData中的default_properties,由属于该TokenData的所有代币共享
  • 存储在代币本身的token_properties

要修改default_properties,开发者可以在TokenMutabilityConfig设为true时使用mutate_tokendata_property进行变更.

警告:除非绝对必要,否则应将TokenMutabilityConfig字段设为false.允许修改default_properties会赋予创建者过大权限——他们甚至可以在代币创建后修改可燃烧配置,从而获得销毁代币的权力.

对于代币中存储的token_properties,我们的标准通过在default_properties中设置TOKEN_PROPERTY_MUTABLE属性来控制可变性.当创建者在初始化TokenData时将TOKEN_PROPERTY_MUTABLE设为true时,才能修改token_properties.需注意:如果mutate_tokendata_property被启用,创建者仍可通过覆写default_properties中的设置来间接修改token_properties.

我们提供burnburn_by_creator函数,分别供代币所有者和创建者销毁代币.这两个函数的执行权限同样受代币创建时的配置约束,确保双方都明确销毁权限.只有当default_properties中的BURNABLE_BY_OWNER属性为true时允许所有者销毁,而BURNABLE_BY_CREATORtrue时允许创建者销毁.当某个TokenData下的所有代币都被销毁后,该TokenData会从创建者账户移除.同理,如果集合中所有TokenData都被移除,对应的CollectionData也将从创建者账户删除.

我们提供三种不同的代币转移模式:

为防止用户收到不想要的NFT,接收方必须首先接收转移要约,然后主动确认接受,代币才会存入其存储地址.这是默认的转移行为,例如:

  1. 当Alice想向Bob发送NFT时,她需要先向Bob发出转移要约,此时NFT仍保留在Alice账户
  2. 只有当Bob确认接收后,NFT才会从Alice账户转移到Bob的代币存储中

如果用户希望直接接收 NFT 转账,跳过初始的报价和申领步骤,可以调用 opt_in_direct_transfer 来允许他人直接将 NFT 转入该用户的代币存储库.选择启用直接转账后,用户可以调用 transfer 直接转账代币.例如,一旦 Bob 选择启用,Alice 或任何人都可以直接将代币发送到 Bob 的代币存储库.

发送方和接收方可以共同签署一笔转账交易,直接将代币从发送方转移到接收方 direct_transfer_script.例如,当 Alice 和 Bob 都签署了转账交易后,代币将直接从 Alice 的账户转移到 Bob 的账户.