您的第一个 NFT
注意:以下教程正在进行中。 此外,Aptos(非同质化)代币规范尚未正式确定。
- 名称,资产的名称,在集合中必须是唯一的
- 描述,资产的描述
- URL,一个指向关于资产的更多信息的链外非描述指针可以是媒体,如图像或视频或更多元数据
- 供应量,这个 NFT 的单位总数,许多 NFT 只有一个,而那些有多个的被称为版本
此外,大多数 NFT 是具有共同属性(例如主题、创建者或最小合约)的集合或一组 NFT 的一部分。每个集合都有一组相似的属性:
- 名称,集合的名称,在创建者的帐户中必须是唯一的
- 描述,资产的描述
- URL,一个指向关于资产的更多信息的链外非描述指针可以是媒体,如图像或视频或更多元数据
Aptos Token 被定义为:
域 | 类型 | 描述 |
---|---|---|
id | GUID:ID | 代币的全局唯一标识符也可用于识别创建者 |
name | ASCII::String | 代币的名称,在集合中必须是唯一的 |
collection | GUID:ID | 包含此代币的集合的全局唯一标识符 |
balance | u64 | 与供应相关的此代币的当前存储量, 1 <= balance <= supply |
Aptos TokenData 被定义为:
域 | 类型 | 描述 |
---|---|---|
id | GUID:ID | 代币的全局唯一标识符也可用于识别创建者 |
description | ASCII::String | 代币描述信息 |
name | ASCII::String | 代币的名称,在集合中必须是唯一的 |
supply | u64 | 此 Token 的总版本数 |
uri | ASCII::String | 附加信息/媒体的 URL |
metadata | TokenType | 一个通用的、可选的用户定义结构,用于包含有关此代币链上的附加信息 |
Token 是使用 Move 属性
store
定义的,这意味着它们可以保存到全局存储中。Token 不能被隐式丢弃,必须被销毁以确保总余额等于供应。Token 不能被复制。也就是说,由于缺少复制操作,除了创建者之外,任何人都无法更改总余额或供应量。请注意,当前的 API 没有公开发布创建代币的能力。Token 可以通过其 id 或 TokenType、集合名称和 Token 名称的元组来唯一标识。TokenData 具有
copy
属性,支持简单的代币余额拆分。每当余额大于 1 的个人向另一个人提供其余额的一部分少于其总余额时,就会发生代币拆分。交易代币的用户请注意,两个代币可以共享相同的 TokenData,因为 Aptos 标准不会尝试识别代币是否复制了另一个代币的属性。重复前面所说的,代币可以通过其 id 或 TokenType 、集合名称和代币名称来唯一标识。创建者可以更改 TokenType、集合名称或代币名称集中的任何值,以创建相似但不完全相同的代币。Aptos 定义了一组按其唯一 ID 分组在一起的集合:
struct Collections<TokenType: copy + drop + store> has key {
collections: Table<ASCII::String, Collection>,
}
struct TokenMetadata<TokenType: store> has key {
metadata: Table<ID, TokenType>,
}
由于 Collections 具有属性键,因此它直接存储到创建者帐户。 需要注意的是,如果没有 Collections 的概念,而 Collection 具有 key 属性,则 Aptos 帐户只能有一个集合,而通常情况并非如此。 可以按名称在集合集中查找集合,因此强制使用唯一的集合名称。
Token 和 TokenData 结构在其内容中是固定的。 资源 TokenMetadata 使创建者能够存储额外的 Token 数据。 表中的数据存储为 Token 的唯一 ID。 由于 script 函数不能支持结构或泛型的限制,使用它是可选的并且需要定制化 API。
每个集合都有以下字段:
域 | 类型 | 描述 |
---|---|---|
tokens | Table<ASCII::String, TokenMetadata<TokenType>> | 跟踪与此集合关联的所有Token |
claimed_tokens | Table<ASCII::String, address> | 跟踪 supply == 1 的 Token 的存储地址 |
description | ASCII::String | 集合描述 |
name | ASCII::String | 此集合的名称在指定 TokenType 的创建者帐户中必须是唯一的。 |
uri | ASCII::String | 附加信息/媒体的 URL |
count | u64 | 此集合跟踪的不同 Token 总数 |
maximum | Option<u64> | 可在此集合中铸造的可选 Token 的最大数量 |
集合不是用于累积 Token 的存储,因此它不包含 Token,而是包含 TokenData:
域 | 类型 | 描述 |
---|---|---|
id | GUID:ID | 此 Token 的全球唯一标识符也可用于识别创建者 |
data | TokenData | 关于此代币的附加数据,这是代币的供应量 > 1 |
为了获取和存储 Token,用户必须拥有一个 TokenType 库:
struct Gallery has key {
gallery: Table<ID, Token>,
}
与 Collections 一样,它作为资源存储在 Aptos 帐户上。
- 创建新 Token 需要编写 Move 代码
- 用于创建新标记的脚本函数必须定制化,因为 Move 不支持模板类型或结构作为输入参数
- 脚本函数上的模板类型为编写脚本函数增加了额外的难度
本教程将引导您完成:
- 创建自己的 Token 集合
- 我们最喜欢的猫的 Token
- 并将该 Token 给其他人。
请从下面的代码仓库中 clone 最新代码!
本教程以您的第一个事务为基础,作为此示例的库。 以下教程包含可以在下面完整下载的示例代码:
Python
Rust
Typescript
Aptos Token 使创作者能够创建有限或无限的收藏。 许多 NFT 具有有限的性质,创造者只打算永远创造一定数量,这会导致稀缺性。 而其他代币可能具有无限的性质,例如,用于实用程序的集合可能会随着时间的推移出现新的代币。 SimpleToken 集合可以通过使用适当的脚本函数以任一行为实例化:
有限,即不能超过最大数量的代币可以铸造:
public(script) fun create_finite_collection_script(
account: signer,
description: vector<u8>,
name: vector<u8>,
uri: vector<u8>,
maximum: u64,
)
无限制,即可以添加到集合中的 Token 数量没有限制:
public(script) fun create_unlimited_collection_script(
account: signer,
description: vector<u8>,
name: vector<u8>,
uri: vector<u8>,
)
这些脚本函数可以通过 REST API 调用。 下面演示了如何调用 ,如下所示:
Python
def create_collection(self, account: Account, description: str, name: str, uri: str):
"""Creates a new collection within the specified account"""
payload = {
"type": "script_function_payload",
"function": f"0x1::Token::create_unlimited_collection_script",
"type_arguments": [],
"arguments": [
description.encode("utf-8").hex(),
name.encode("utf-8").hex(),
uri.encode("utf-8").hex(),
]
}
self.submit_transaction_helper(account, payload)
可以在集合创建后创建 Token。 为此,Token 必须指定与先前创建的集合名称相同的 collection_name。 创建 SimpleToken 的 Move 脚本函数是:
public(script) fun create_token_script(
account: signer,
collection_name: vector<u8>,
description: vector<u8>,
name: vector<u8>,
supply: u64,
uri: vector<u8>,
)
这些脚本函数可以通过 REST API 调用。 下面演示了如何调用 ,如下所示:
Python
def create_token(
self,
account: Account,
collection_name: str,
description: str,
name: str,
supply: int,
uri: str,
):
payload = {
"type": "script_function_payload",
"function": f"0x1::Token::create_token_script",
"type_arguments": [],
"arguments": [
collection_name.encode("utf-8").hex(),
description.encode("utf-8").hex(),
name.encode("utf-8").hex(),
str(supply),
uri.encode("utf-8").hex(),
]
}
self.submit_transaction_helper(account, payload)
在 Aptos 和 Move 中,每个代币都占据空间并拥有所有权。 因此,代币转移不是单方面的,需要类似于公告板的两个阶段过程。 发送者必须首先注册一个 Token 可供接收者声明,然后接收者必须声明这个 Token。 这已在名为
TokenTransfer
的概念验证 Move 模块中实现。 SimpleToken 提供了一些包装函数来支持转账到另一个帐户、声明该转账或停止该转账。