Skip to main content

你的第一笔交易

本教程介绍如何生成交易并将其提交到 Aptos 区块链,并验证这些提交的交易。本教程中使用的transfer-coin示例是使用 Aptos SDK 构建的。

第 1 步:选择一个 SDK

从以下列表中安装您喜欢的 SDK:


第 2 步:运行示例

克隆 aptos-core 存储库:

git clone https://github.com/aptos-labs/aptos-core.git

切换到 Typescript SDK 示例目录:

cd ~/aptos-core/ecosystem/typescript/sdk/examples/typescript

安装依赖:

yarn install

运行 transfer_coin 示例:

yarn run transfer_coin

第 3 步:了解输出

执行上述命令后会出现与以下非常相似的输出:

=== Addresses ===
Alice: 0x0baec07bfc42f8018ea304ddc307a359c1c6ab20fbce598065b6cb19acff7043
Bob: 0xc98ceafadaa32e50d06d181842406dbbf518b6586ab67cfa2b736aaddeb7c74f

=== Initial Balances ===
Alice: 20000
Bob: 0

=== Intermediate Balances ===
Alice: 18996
Bob: 1000

=== Final Balances ===
Alice: 17992
Bob: 2000

上面的输出演示了 transfer-coin 示例执行了以下步骤:

  • 初始化 REST 和水龙头客户端。
  • 创建两个帐户:Alice 和 Bob。
    • 通过水龙头为 Alice 的账户提供资金和创建。
    • 从水龙头创建 Bob 的帐户。
  • 从 Alice 向 Bob 转移 1000 枚 coin。
  • Alice 为进行转账支付的 4 枚 gas coin。
  • 从 Alice 向 Bob 转移 1000 枚 coin。
  • Alice 支付的额外 4 枚 gas 用于进行转账。

接下来,请参阅下面用于完成上述步骤的 SDK 功能的演练。

第 4 步:深入 SDK

transfer-coin 示例代码使用辅助函数与 REST API 进行交互。 本节回顾每个调用并深入了解功能。

查看完整代码

有关完整代码,请参阅 Typescript transfer-coin 您按照以下步骤操作。


步骤 4.1:初始化客户端

第一步,transfer-coin示例初始化 REST 和水龙头客户端。

  • REST 客户端与 REST API 交互,以及
  • 水龙头客户端与 devnet Faucet 服务交互以创建和注资帐户。
const client = new AptosClient(NODE_URL);
const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);

使用 API 客户端,我们可以创建一个 CoinClient,我们将其用于常见的 coin 操作,例如转账和检查余额。

const coinClient = new CoinClient(client); 

common.ts 初始化 URL 值,如下所示:

export const NODE_URL = process.env.APTOS_NODE_URL || "https://fullnode.devnet.aptoslabs.com";
export const FAUCET_URL = process.env.APTOS_FAUCET_URL || "https://faucet.devnet.aptoslabs.com";
tip

默认情况下,这两个服务的 URL 都指向 Aptos devnet 服务。 但是,可以使用以下环境变量配置它们:

  • APTOS_NODE_URL
  • APTOS_FAUCET_URL

步骤 4.2:创建本地帐户

下一步是在本地创建两个帐户。 Accounts 代表链上和链下状态。 链下状态由地址和用于验证所有权的公钥、私钥对组成。 此步骤演示如何生成该链下状态。

const alice = new AptosAccount();
const bob = new AptosAccount();

步骤 4.3:创建区块链账户

在 Aptos 中,每个帐户都必须具有链上表示,以支持接收代币和 coin 以及与其他 dApp 进行交互。 账户代表了存储资产的媒介,因此必须明确创建。 此示例利用 Faucet 创建和资助 Alice 的帐户,并且只创建 Bob 的帐户:

await faucetClient.fundAccount(alice.address(), 100_000_000);
await faucetClient.fundAccount(bob.address(), 0);

步骤 4.4:阅读余额

在此步骤中,SDK 将单个调用转换为查询资源并从该资源读取字段的过程。

console.log(`Alice: ${await coinClient.checkBalance(alice)}`);
console.log(`Bob: ${await coinClient.checkBalance(bob)}`);

SDK 中的 CoinClient 中的 checkBalance 函数查询了 AptosCoin 的 CoinStore 资源并读取当前存储的值:

async checkBalance(
account: AptosAccount,
extraArgs?: {
// The coin type to use, defaults to 0x1::aptos_coin::AptosCoin
coinType?: string;
},
): Promise<bigint> {
const coinType = extraArgs?.coinType ?? APTOS_COIN;
const typeTag = `0x1::coin::CoinStore<${coinType}>`;
const resources = await this.aptosClient.getAccountResources(account.address());
const accountResource = resources.find((r) => r.type === typeTag);
return BigInt((accountResource!.data as any).coin.value);
}

步骤 4.5:转移

与上一步一样,这是另一个辅助步骤,用于构建将 coin 从 Alice 转移到 Bob 的交易。 对于正确生成的交易,API 将返回一个交易哈希,可用于后续步骤检查交易状态。 Aptos 区块链确实在提交时执行了一些验证检查,如果其中任何一个失败,用户将收到一个错误。 这些验证包括交易签名、未使用的序列号以及将交易提交到适当的链。

let txnHash = await coinClient.transfer(alice, bob, 1_000, { gasUnitPrice: BigInt(100) }); 

transfer 函数生成一个交易参数,并让客户端签名、发送和等待它:

async transfer(
from: AptosAccount,
to: AptosAccount,
amount: number | bigint,
extraArgs?: OptionalTransactionArgs & {
// The coin type to use, defaults to 0x1::aptos_coin::AptosCoin
coinType?: string;
},
): Promise<string> {
const coinTypeToTransfer = extraArgs?.coinType ?? APTOS_COIN;
const payload = this.transactionBuilder.buildTransactionPayload(
"0x1::coin::transfer",
[coinTypeToTransfer],
[to.address(), amount],
);
return this.aptosClient.generateSignSubmitTransaction(from, payload, extraArgs);
}

在客户端中,generateSignSubmitTransaction 正在执行此操作:

const rawTransaction = await this.generateRawTransaction(sender.address(), payload, extraArgs);
const bcsTxn = AptosClient.generateBCSTransaction(sender, rawTransaction);
const pendingTransaction = await this.submitSignedBCSTransaction(bcsTxn);
return pendingTransaction.hash;

将以上内容分解为几部分:

  1. transfer内部是Coin Move合约中的EntryFunction,即 Move 中可直接调用的入口函数。
  2. Move函数存储在coin合约上:0x1::coin
  3. 因为Coin合约可以被其他币使用,所以转账时必须明确指定要转账的币种。 如果未使用 coinType 指定,则默认为 0x1::aptos_coin::AptosCoin

步骤 4.6:等待交易成功

在 Typescript 中,只需调用 coinClient.transfer 就足以等待交易完成。 一旦处理(成功或不成功),该函数将返回 API 返回的 Transaction,如果处理时间超过超时,则抛出错误。

如果您希望在事务未成功提交时将其抛出,则可以在调用 transfer 时将 checkSuccess 设置为 true:

await client.waitForTransaction(txnHash);