7.MOVE从入门到实战-Aptos测试网发起一笔交易

2022-11-07 11:12:54 浏览数 (1)

本文作者:木头[1]

创建 node 项目

package.json依赖包

代码语言:javascript复制
"dependencies": {
  "@types/node": "^17.0.21",
  "aptos": "^1.3.7",
  "cross-fetch": "^3.1.5",
  "fmt": "^2.0.0",
  "js-sha3": "^0.8.0",
  "prettier": "^2.7.1",
  "tweetnacl": "^1.0.3"
},
"devDependencies": {
  "ts-node": "^10.9.1",
  "typescript": "^4.7.4"
}

创建帐户

引入Aptos提供生成地址的方法

代码语言:javascript复制
import { AptosAccount, TxnBuilderTypes, BCS, MaybeHexString } from "aptos";
const account = new AptosAccount();
console.log(`地址: ${account.address()} 私钥种子: ${Buffer.from(account.signingKey.secretKey).toString("hex").slice(0, 64)}`);

水龙头领取代币

在发起交易之前先领取一下测试代币作手续费

代码语言:javascript复制
//aptos测试节点URL  REST API地址
export const NODE_URL = "https://fullnode.devnet.aptoslabs.com";
//aptos水龙头URL
export const FAUCET_URL = "https://faucet.devnet.aptoslabs.com";

//Aptos客户端 水龙头客户端方法
import { AptosClient, FaucetClient } from "aptos";

//创建水龙头客户端
const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);

//领取2万个测试代币
await faucetClient.fundAccount(account.address(), 20000);

查询余额

接口:getAccountResource()[2]

代码语言:javascript复制
//创建ptos客户端
const client = new AptosClient(NODE_URL);

export async function accountBalance(accountAddress: MaybeHexString): Promise<number | null> {
  const resource = await client.getAccountResource(accountAddress, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
  if (resource == null) {
    return null;
  }
  return parseInt((resource.data as any)["coin"]["value"]);
}

发起交易

将给定数量的代币金额从给定的帐户转移到收件人的帐户地址。接口:TxnBuilderTypes.TypeTagStruct()[3]

TxnBuilderTypes.ScriptFunction.natural()[4]

代码语言:javascript复制
async function transfer(accountFrom: AptosAccount, recipient: MaybeHexString, amount: number): Promise<string> {
  //类型标记结构
  const token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString("0x1::aptos_coin::AptosCoin"));

  //事务负载脚本函数
  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      "0x1::coin",
      "transfer",
      [token],
      [BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(recipient)), BCS.bcsSerializeUint64(amount)],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  //原始事务处理
  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000)   10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  //生成BCS事务
  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  //提交已签名的BCS事务
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

完整 ts 代码

代码语言:javascript复制
//节点URL  REST API地址
export const NODE_URL = "https://fullnode.devnet.aptoslabs.com";
//水龙头URL
export const FAUCET_URL = "https://faucet.devnet.aptoslabs.com";

//生成账号接口
import { AptosAccount, TxnBuilderTypes, BCS, MaybeHexString } from "aptos";

//Aptos客户端 水龙头客户端
import { AptosClient, FaucetClient } from "aptos";

//创建节点客户端
const client = new AptosClient(NODE_URL);
const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);


//Helper方法返回与帐户关联的硬币余额
export async function accountBalance(accountAddress: MaybeHexString): Promise<number | null> {
  const resource = await client.getAccountResource(accountAddress, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
  if (resource == null) {
    return null;
  }

  return parseInt((resource.data as any)["coin"]["value"]);
}

/**
 * 将给定的硬币金额从给定的帐户从转移到收件人的帐户地址。
 */
async function transfer(accountFrom: AptosAccount, recipient: MaybeHexString, amount: number): Promise<string> {
  //类型标记结构
  const token = new TxnBuilderTypes.TypeTagStruct(TxnBuilderTypes.StructTag.fromString("0x1::aptos_coin::AptosCoin"));

  //事务负载脚本函数
  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      "0x1::coin",
      "transfer",
      [token],
      [BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(recipient)), BCS.bcsSerializeUint64(amount)],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  //原始事务处理
  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000)   10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  //生成BCS事务
  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  //提交已签名的BCS事务
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}


async function main() {
  //创建两个账户,A和B,并为A而不是B提供资金
  const a = new AptosAccount();
  const b = new AptosAccount();

  console.log("n=== 地址 ===");
  console.log(
    `A: ${a.address()} Key: ${Buffer.from(a.signingKey.secretKey).toString("hex").slice(0, 64)}`,
  );
  console.log(`B: ${b.address()} Key: ${Buffer.from(b.signingKey.secretKey).toString("hex").slice(0, 64)}`);

  //水龙头领取代币
  await faucetClient.fundAccount(a.address(), 20000);
  await faucetClient.fundAccount(b.address(), 0);

  console.log("n=== 初始余额 ===");
  console.log(`A: ${await accountBalance(a.address())}`);
  console.log(`B: ${await accountBalance(b.address())}`);

  // A 转账给 B 1000个硬币
  const txHash = await transfer(a, b.address(), 1000);
  await client.waitForTransaction(txHash);

  console.log("n=== 账户余额 ===");
  console.log(`A: ${await accountBalance(a.address())}`);
  console.log(`B: ${await accountBalance(b.address())}`);

}

if (require.main === module) {
  main();
}

运行程序

执行命令:$ node --loader ts-node/esm transaction.ts输出:

代码语言:javascript复制
=== 地址 ===
A: 0xacc02f55737a690e3c452bd84fa6adee1b26bdcecc2938f522b931f6bd1062c2 Key: ae299733eddfb2fbac2cb926f81d24aecc7532c5baae228aa5964e2a87fd5b80
B: 0xeeb6b0446439df55bbbc22c0dbd9415dfe9994a21137a9e3c4f1e23007f7d709 Key: 69a9f4e7ed37252569a07aca4f763dcbe93c10203fe5773a0fd6551f7104fdb9

=== 初始余额 ===
A: 20000
B: 0

=== 账户余额 ===
A: 18996
B: 1000

区块浏览器

https://explorer.devnet.aptos.dev/[5]

参考资料

[1]

木头: https://learnblockchain.cn/people/3015

[2]

getAccountResource(): https://aptos-labs.github.io/ts-sdk-doc/classes/AptosClient.html#getAccountResource

[3]

TxnBuilderTypes.TypeTagStruct(): https://aptos-labs.github.io/ts-sdk-doc/classes/TxnBuilderTypes.TypeTagStruct.html

[4]

TxnBuilderTypes.ScriptFunction.natural(): https://aptos-labs.github.io/ts-sdk-doc/classes/TxnBuilderTypes.ScriptFunction.html

[5]

https://explorer.devnet.aptos.dev/: https://explorer.devnet.aptos.dev/

0 人点赞