> For the complete documentation index, see [llms.txt](https://gushi10546.gitbook.io/aptos-kai-fa-zhe-wen-dang/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gushi10546.gitbook.io/aptos-kai-fa-zhe-wen-dang/kai-fa-zhe-jiao-cheng/di-yi-ge-dai-bi.md).

# 第一个代币

本教程介绍了如何编译、部署和铸造 *Moon Coin* 代币。

## 第 1 步：选择 SDK

* [官方 Aptos Typescript SDK](https://aptos.dev/sdks/typescript-sdk)
* [官方 Aptos Python SDK](https://aptos.dev/sdks/python-sdk)
* [官方 Aptos Rust SDK](https://aptos.dev/sdks/rust-sdk)

## 第 2 步：获取 CLI

[从 Git 安装 CLI](https://aptos.dev/cli-tools/aptos-cli-tool/install-aptos-cli)

## 第 3 步：运行示例

克隆 `aptos-core`：

```bash
git clone <https://github.com/aptos-labs/aptos-core.git>
```

### 第 3.1 步：SDK 特定示例

* Typescript

  导航至 Typescript SDK 目录：

  ```bash
  cd ~/aptos-core/ecosystem/typescript/sdk
  ```

  安装必要的依赖项

  ```bash
  yarn
  ```

  运行 `your_coin` 示例：

  ```bash
  yarn your_coin ~/aptos-core/aptos-move/move-examples/moon_coin
  ```
* Python

  导航至 Python SDK 目录：

  ```bash
  cd ~/aptos-core/ecosystem/python/sdk
  ```

  安装必要的依赖项

  ```bash
  curl -sSL <https://install.python-poetry.org> | python3
  poetry update
  ```

  运行 `your_coin` 示例：

  ```bash
  poetry run python -m examples.your-coin ~/aptos-core/aptos-move/move-examples/moon_coin
  ```
* Rust

  待发布

### 第 3.2 步：构建包

进行到一半时，demo 会暂停并显示以下输出：

```
=== Addresses ===
Alice: 0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7ba
Bob: 0xc8421fa4a99153f955e50f1de2a6acff2f3fd0bb33aa17ba1f5b32b699f6c825

Update the package with Alice's address, compile, and press enter.
```

此时，打开另一个终端并将目录更改为 *MoonCoin* 包的目录

```bash
cd ~/aptos-core/aptos-move/move-examples/moon_coin
```

现在使用 CLI 构建包：

```
aptos move compile --named-addresses MoonCoin=0x5e603a89cf690d7134cf2f24fdb16ba90c4f5686333721c12e835fb6c76bc7ba --save-metadata
```

`--named-addresses` 是一个必须转译的地址映射表，让编译后的软件包能够存储到 Alice 的帐户中。注意 `MoonCoin` 是如何被设置为上面显示的 Alice 地址的。另外，为了发布软件包，还需要 `--save-metadata`。

### 第 3.3 步：完成示例

返回前面的提示，按回车键，现在软件包已经准备好发布了。

应用程序将完成，显示：

```
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

  ```tsx
  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

  ```python
  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)
  ```
* Rust

  待发布

### 第 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>)` 是一个简单的 代币管理框架，由用户直接管理代币。它为铸造和销毁提供了便捷的包装。

```rust
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。在本教程中，这就是 `CoinStore<MoonCoin>`

#### 第 4.3.1 步：初始化代币

一旦代币类型发布到区块链上，发布该代币的实体可以初始化代币：

```rust
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` 才能使用代币：

```rust
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>` 结构。它将在代币跟踪供应时更新。

```rust
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 不会发出转账事件，而是利用提款和存款事件。
