本教程介绍了如何编译、部署和铸造 Moon Coin 代币。
第 1 步:选择 SDK
第 2 步:获取 CLI
从 Git 安装 CLI
第 3 步:运行示例
克隆 aptos-core
:
Copy git clone <https://github.com/aptos-labs/aptos-core.git>
第 3.1 步:SDK 特定示例
Typescript
导航至 Typescript SDK 目录:
Copy cd ~/aptos-core/ecosystem/typescript/sdk
安装必要的依赖项
运行 your_coin
示例:
Copy yarn your_coin ~/aptos-core/aptos-move/move-examples/moon_coin
Python
导航至 Python SDK 目录:
Copy cd ~/aptos-core/ecosystem/python/sdk
安装必要的依赖项
Copy curl -sSL <https://install.python-poetry.org> | python3
poetry update
运行 your_coin
示例:
Copy poetry run python -m examples.your-coin ~/aptos-core/aptos-move/move-examples/moon_coin
第 3.2 步:构建包
进行到一半时,demo 会暂停并显示以下输出:
Copy === Addresses ===
Alice: 0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7ba
Bob: 0xc8421fa4a99153f955e50f1de2a6acff2f3fd0bb33aa17ba1f5b32b699f6c825
Update the package with Alice's address, compile, and press enter.
此时,打开另一个终端并将目录更改为 MoonCoin 包的目录
Copy cd ~/aptos-core/aptos-move/move-examples/moon_coin
现在使用 CLI 构建包:
Copy aptos move compile --named-addresses MoonCoin=0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7ba --save-metadata
--named-addresses
是一个必须转译的地址映射表,让编译后的软件包能够存储到 Alice 的帐户中。注意 MoonCoin
是如何被设置为上面显示的 Alice 地址的。另外,为了发布软件包,还需要 --save-metadata
。
第 3.3 步:完成示例
返回前面的提示,按回车键,现在软件包已经准备好发布了。
应用程序将完成,显示:
Copy Publishing MoonCoin package.
Bob registers the newly created coin so he can receive it from Alice.
Bob's initial MoonCoin balance: 0.
Alice mints Bob some of the new coin.
Bob's updated MoonCoin balance: 100.
第 4 步:深入了解 MoonCoin
第 4.1 步:构建和发布 MoonCoin 包
Move 软件或合约实际上是一组被称为包的模块。在部署或升级一个新的软件包时,必须用 --save-metadata
来调用编译器,以便发布该软件包。在 MoonCoin 的案例中,以下输出文件是至关重要的:
build/Examples/package-metadata.bcs
——与软件包相关的元数据
build/Examples/bytecode_modules/moon_coin.mv
—— moon_coin.move
模块的字节码
这些都由示例读取并发布到区块链上:
Typescript
Copy const modulePath = process.argv[2];
const packageMetadata = fs.readFileSync(path.join(modulePath, "build", "Examples", "package-metadata.bcs"));
const moduleData = fs.readFileSync(path.join(modulePath, "build", "Examples", "bytecode_modules", "moon_coin.mv"));
console.log("Publishing MoonCoin package.");
let txnHash = await client.publishPackage(alice, new HexString(packageMetadata.toString("hex")).toUint8Array(), [
new TxnBuilderTypes.Module(new HexString(moduleData.toString("hex")).toUint8Array()),
]);
await client.waitForTransaction(txnHash, { checkSuccess: true });
Python
Copy moon_coin_path = sys.argv[1]
module_path = os.path.join(
moon_coin_path, "build", "Examples", "bytecode_modules", "moon_coin.mv"
)
with open(module_path, "rb") as f:
module = f.read()
metadata_path = os.path.join(
moon_coin_path, "build", "Examples", "package-metadata.bcs"
)
with open(metadata_path, "rb") as f:
metadata = f.read()
print("\\nPublishing MoonCoin package.")
txn_hash = rest_client.publish_package(alice, metadata, [module])
rest_client.wait_for_transaction(txn_hash)
第 4.2 步:了解 MoonCoin 模块
MoonCoin 模块定义了 MoonCoin 结构,即不同的代币类型。此外,它还包含一个叫做 init_module
的函数。 init_module
在模块发布时被调用。在这种情况下,MoonCoin 将MoonCoin
币种初始化为 ManagedCoin
,该币种由帐户所有者维护。[ManagedCoin](<https://github.com/aptos-labs/aptos-core/blob/f81ccb01f00227f9c0f36856fead4879f185a9f6/aptos-move/framework/aptos-framework/sources/managed_coin.move#L1>)
是一个简单的 代币管理框架,由用户直接管理代币。它为铸造和销毁提供了便捷的包装。
Copy module MoonCoin::moon_coin {
struct MoonCoin {}
fun init_module(sender: &signer) {
aptos_framework::managed_coin::initialize<MoonCoin>(
sender,
b"Moon Coin",
b"MOON",
6,
false,
);
}
}
第 4.3 步:了解代币
代币有几个基本要素:
冻结——阻止一个帐户在 CoinStore 中储存代币
注册——在一个帐户上创建一个用于存储代币的 CoinStore 资源
创建一个新代币的实体也有铸造、销毁和冻结代币的能力。
为了转移、提取或存入代币,必须有一个为特定代币注册的 CoinStore。在本教程中,这就是 CoinStore<MoonCoin>
第 4.3.1 步:初始化代币
一旦代币类型发布到区块链上,发布该代币的实体可以初始化代币:
Copy public fun initialize<CoinType>(
account: &signer,
name: string::String,
symbol: string::String,
decimals: u8,
monitor_supply: bool,
): (BurnCapability<CoinType>, FreezeCapability<CoinType>, MintCapability<CoinType>) {
let account_addr = signer::address_of(account);
assert!(
coin_address<CoinType>() == account_addr,
error::invalid_argument(ECOIN_INFO_ADDRESS_MISMATCH),
);
assert!(
!exists<CoinInfo<CoinType>>(account_addr),
error::already_exists(ECOIN_INFO_ALREADY_PUBLISHED),
);
let coin_info = CoinInfo<CoinType> {
name,
symbol,
decimals,
supply: if (monitor_supply) { option::some(optional_aggregator::new(MAX_U128, false)) } else { option::none() },
};
move_to(account, coin_info);
(BurnCapability<CoinType>{ }, FreezeCapability<CoinType>{ }, MintCapability<CoinType>{ })
}
这样可以确保这种代币类型之前未被初始化过,注意检查以确保初始化的调用者确实发布了这个模块,并且他们的帐户上没有存储 CoinInfo
。如果这两个条件都符合,那么就会存储一个 CoinInfo
,调用者就会获得销毁、冻结和铸造的能力。
MoonCoin 软件包发布时自动调用这个函数。
第 4.3.2 步:注册代币
实体必须在他们的帐户上为代币注册一个 CoinStore
才能使用代币:
Copy public fun register<CoinType>(account: &signer) {
let account_addr = signer::address_of(account);
assert!(
!is_account_registered<CoinType>(account_addr),
error::already_exists(ECOIN_STORE_ALREADY_PUBLISHED),
);
account::register_coin<CoinType>(account_addr);
let coin_store = CoinStore<CoinType> {
coin: Coin { value: 0 },
frozen: false,
deposit_events: account::new_event_handle<DepositEvent>(account),
withdraw_events: account::new_event_handle<WithdrawEvent>(account),
};
move_to(account, coin_store);
}
由于这是一个 public fun
而不是一个 public entry fun
,代币需要提供注册方式,或者用户可以构建 Move 脚本来调用该功能。
MoonCoin 使用 ManagedCoin
,它提供了一个入口函数封装器:managed_coin::register
第 4.3.3 步:铸造代币
铸造代币需要初始化时产生的铸造能力。它接受该功能和数量并返回一个包含代币数量的 Coin<T>
结构。它将在代币跟踪供应时更新。
Copy public fun mint<CoinType>(
amount: u64,
_cap: &MintCapability<CoinType>,
): Coin<CoinType> acquires CoinInfo {
if (amount == 0) {
return zero<CoinType>()
};
let maybe_supply = &mut borrow_global_mut<CoinInfo<CoinType>>(coin_address<CoinType>()).supply;
if (option::is_some(maybe_supply)) {
let supply = option::borrow_mut(maybe_supply);
optional_aggregator::add(supply, (amount as u128));
};
Coin<CoinType> { value: amount }
}
ManagedCoin
通过提供一个入口函数 managed_coin::mint
让这个过程变得更容易。
第 4.3.4 步:转移代币
Aptos 提供了几个构建块来支持转移:
coin::deposit<CoinType>
允许任何实体将代币存入已经调用 coin::register<CoinType>
的帐户
coin::withdraw<CoinType>
允许任何实体从其帐户中提取代币金额
coin::transfer<CoinType>
利用提款和存款来执行端到端的转账
Aptos 不会发出转账事件,而是利用提款和存款事件。