在 TON 区块链生态中,开发者常常面临一个核心问题:如何确认一笔交易是否成功执行?此外,通过 TonClient 发送交易后返回的 Boc 数据有何作用?如何从中提取关键信息?本文将从交易结构、消息构建、结果确认等角度,系统性地解答这些问题,助你深入理解 TON 的交易机制。
TON 交易的基本概念
TON 区块链采用基于消息的异步模型,每一笔交易都包含三个核心组成部分:
- 初始入站消息:用于触发智能合约执行的起始消息,可包含特定调用方法。
- 合约状态变更:消息触发的操作可能导致合约存储状态更新(可选)。
- 生成的出站消息:合约执行后可能向其他参与者发送新消息(可选)。
简单来说,发起一笔 TON 转账交易,实质是向目标钱包合约发送一条消息,合约根据消息内容执行相应操作。
构建交易消息
在使用 TonConnect 发送交易前,需先构建有效的交易消息。以下以 JavaScript 版本的 TonConnect SDK 为例,说明如何定义交易参数:
基础转账消息结构
export declare interface SendTransactionRequest {
validUntil: number; // 交易有效期(Unix 时间戳)
network?: CHAIN; // 网络类型:主网或测试网
from?: string; // 发送方地址(格式为 "地址")
messages: {
address: string; // 接收方地址
amount: string; // 转账金额(单位:nanoTon)
stateInit?: string; // 合约初始化数据(可选)
payload?: string; // 交易附加数据(可选)
}[];
}
示例:简单转账
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 600, // 有效期 10 分钟
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F",
amount: "20000000", // 0.02 TON
},
],
};
添加交易注释
若需为转账添加注释,需构建特定负载数据(Payload),并将其编码为 Base64 格式:
import { beginCell } from "@ton/ton";
const body = beginCell()
.storeUint(0, 32) // 写入 32 位零值标识文本注释
.storeStringTail("Hello, TON!") // 写入注释内容
.endCell();
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 600,
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F",
amount: "20000000",
payload: body.toBoc().toString("base64"), // 添加注释负载
},
],
};
获取与解析交易结果
发送交易后,如何确认其已上链并获取最终结果?以下是关键步骤与代码实现。
发送交易并获取 Boc
使用 TonConnect 发送交易后,将返回一个包含 boc
字段的响应对象:
const [tonConnectUi] = useTonConnectUI();
const result = await tonConnectUi.sendTransaction(transaction);
// result.boc 为已签名的交易 Boc 数据
该 boc
是触发交易的初始内容,将被广播到 TON 网络进行验证与执行。
监听交易确认状态
通过 TonClient 查询交易状态,比对链上交易哈希与发送的 Boc 哈希,可确认交易是否成功:
const waitForTransaction = async (options, client) => {
const { hash, refetchInterval = 1000, refetchLimit, address } = options;
return new Promise((resolve) => {
let refetches = 0;
const walletAddress = Address.parse(address);
const interval = setInterval(async () => {
refetches += 1;
console.log("等待交易确认...");
const state = await client.getContractState(walletAddress);
if (!state || !state.lastTransaction) {
clearInterval(interval);
resolve(null);
return;
}
const { lt: lastLt, hash: lastHash } = state.lastTransaction;
const lastTx = await client.getTransaction(walletAddress, lastLt, lastHash);
if (lastTx && lastTx.inMessage) {
const msgCell = beginCell().store(storeMessage(lastTx.inMessage)).endCell();
const inMsgHash = msgCell.hash().toString("base64");
if (inMsgHash === hash) {
clearInterval(interval);
resolve(lastTx);
}
}
if (refetchLimit && refetches >= refetchLimit) {
clearInterval(interval);
resolve(null);
}
}, refetchInterval);
});
};
该方法通过定期查询合约最新交易,比对入站消息哈希是否匹配,从而确认交易完成。此外,也可使用 getTransactions
方法监听链上交易变化。
常见问题
1. 什么是 Boc?它在 TON 交易中起什么作用?
Boc(Bag of Cells)是 TON 区块链中数据的序列化格式,用于表示消息、交易和状态等信息。发送交易后返回的 Boc 是已签名的交易内容,包含所有必要参数,用于网络验证与执行。
2. 如何判断一笔 TON 交易是否成功?
可通过比对发送交易的 Boc 哈希与链上最新交易的入站消息哈希是否一致来判断。若一致,则交易已确认;若长时间未匹配,可能因网络拥堵或手续费不足导致失败。
3. 交易注释(Payload)是否必须?如何正确添加?
注释非必填,但常用于标识转账用途。添加时需构建特定 Cell 结构,包含 32 位零值标识和文本内容,并编码为 Base64 格式作为 Payload 传入。
4. TonClient 在交易流程中扮演什么角色?
TonClient 是 TON 区块链的客户端工具,用于与网络交互,包括发送交易、查询状态、获取交易详情等。它是开发者监控和确认交易的核心接口。
5. TON 与以太坊在交易处理上有何主要区别?
TON 采用异步消息模型,交易无需等待区块确认即可继续操作;而以太坊为同步模型,需等待区块最终性。此外,TON 的消息传递机制支持更复杂的跨合约交互。
6. 交易长时间未确认可能有哪些原因?
常见原因包括网络拥堵、Gas 费用不足、交易参数错误(如地址格式无效)、或节点同步延迟。建议检查交易参数并适当提高 Gas 限额。
总结
TON 作为基于消息的异步区块链,其交易机制与以太坊等同步模型区块链有显著差异。理解消息构建、Boc 数据处理及交易状态监控方法,是构建高效 DApp 的关键。通过合理使用 TonClient 和 TonConnect,开发者可有效追踪交易结果,提升应用可靠性。