Aptos客户端签名交易后服务端提交与托管转账验证方法咨询
解决方案:后端提交已签名APT交易并验证转账目标
一、正确提交已签名交易到Aptos链
你之前用AptosClient.submitTransaction()失败,核心原因大概率是没传够完整的交易数据——只传签名缓冲区是不够的,必须结合原始交易信息、公钥一起构造合法的已签名交易对象。
步骤1:客户端需传递的完整数据
客户端签名后,要把以下三组数据一起发给后端:
rawTransactionBytes:原始交易的base64序列化数据(包含转账金额、发送方、托管账户地址、链ID等核心信息)signatureBytes:钱包签名后的base64缓冲区publicKeyBytes:用户钱包公钥的base64字符串
步骤2:后端构造已签名交易并提交
以TypeScript SDK为例,完整代码逻辑如下:
import { AptosClient, RawTransaction, SignedTransaction, Ed25519PublicKey, Ed25519Signature } from "@aptos-labs/ts-sdk"; // 初始化客户端(测试网换测试节点地址) const client = new AptosClient("https://fullnode.mainnet.aptoslabs.com"); // 从请求体获取客户端传来的数据 const { rawTransactionBytes, signatureBytes, publicKeyBytes } = req.body; // 反序列化原始交易 const rawTransaction = RawTransaction.deserialize(Buffer.from(rawTransactionBytes, "base64")); // 构造公钥与签名对象 const publicKey = new Ed25519PublicKey(Buffer.from(publicKeyBytes, "base64")); const signature = new Ed25519Signature(Buffer.from(signatureBytes, "base64")); // 组装合法的已签名交易 const signedTransaction = new SignedTransaction({ rawTransaction, publicKey, signature, }); // 提交交易到链上 const transactionHash = await client.submitTransaction(signedTransaction);
其他语言SDK(如Python)逻辑一致,核心是必须完整构造包含原始交易、公钥、签名的已签名交易结构,不能只传签名。
二、验证交易是否转入托管账户
提交交易后,需等待链上确认,再从交易详情中验证核心信息:
步骤1:等待交易确认
用交易哈希轮询查询状态,直到交易变为committed状态:
async function waitForTxCommit(client: AptosClient, txHash: string) { let tx = await client.getTransactionByHash(txHash); while (tx.status !== "committed") { await new Promise(resolve => setTimeout(resolve, 1000)); tx = await client.getTransactionByHash(txHash); } return tx; } const confirmedTx = await waitForTxCommit(client, transactionHash);
步骤2:验证交易核心信息
从确认后的交易中提取payload,验证是否为APT转账且接收方是托管账户:
const YOUR_CUSTODY_ACCOUNT = "0x..."; // 替换为你的托管账户地址 // 检查是否是合法的转账交易 if (confirmedTx.payload.type !== "entry_function_payload") { throw new Error("无效的交易类型"); } if (confirmedTx.payload.function !== "0x1::coin::transfer") { throw new Error("交易并非APT代币转账"); } // 提取并验证接收方与金额 const [recipient, amount] = confirmedTx.payload.arguments; if (recipient !== YOUR_CUSTODY_ACCOUNT) { throw new Error("交易未转入托管账户"); } // 可选:验证转账金额符合业务要求(1APT = 1e8 octas) if (BigInt(amount) < BigInt("100000000")) { throw new Error("转账金额未达最低要求"); }
额外安全验证:匹配交易发送方与当前用户
为避免恶意提交他人的签名交易,要验证交易发起地址是否为当前请求积分的用户:
const userWalletAddr = req.user.walletAddress; // 假设你已获取用户钱包地址 if (rawTransaction.sender !== userWalletAddr) { throw new Error("交易发送方与当前用户不匹配"); }
三、常见问题排查
- 提交交易失败:检查
rawTransaction序列化/反序列化是否正确,公钥与签名是否匹配,链ID是否和当前网络一致(主网链ID=1,测试网=2)。 - 交易确认超时:检查节点地址是否正确,网络是否连通,或交易是否因gas不足被拒绝。
内容的提问来源于stack exchange,提问作者johames
相关产品推荐
相关产品推荐

