本文作者:木头[1]
创建 node 项目
package.json
依赖包
"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
提供生成地址的方法
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
输出:
=== 地址 ===
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/