TON 离线签名全方位实战:从脚手架到链上广播

·

关键词:TON 钱包、离线签名、Solana Web3.js、Node.js 开发环境、TON RPC、golang tonutils-go、助记词派生

本文基于真实踩坑经历,示范如何在 Ubuntu 20.04 上完成 TON 离线签名链上广播的端到端流程,并穿插 Solana-Wallet 共研思路,帮助开发者、创业者与投资者快速落地 Web3 产品。


一、脚手架:5 分钟搭好 TypeScript+Jest 环境

本地快速启项目不必依赖大型脚手架。以下脚本可以一键生成纯净可运行的 TypeScript 项目,已含 Jest 单元测试。

chmod +x scaffold.sh
./scaffold.sh ton-offline-demo

scaffold.sh 核心步骤:

#!/bin/bash
set -exu
dir=$1
mkdir $dir && cd $dir
npm init -y
npm i -D typescript @types/node jest ts-jest @types/jest
npx tsc --init
npx ts-jest config:init
echo 'export const sum = (a: number, b: number): number => a + b;' > src/index.ts
mkdir tests
echo "
import { sum } from '../src';
test('1+2=3', () => { expect(sum(1, 2)).toBe(3); });
" > tests/example.test.ts
jq '.scripts += {"build":"tsc","test":"jest"}' package.json > tmp.json && mv tmp.json package.json

运行单元测试:

npm run test -- tests/example.test.ts

常见问题(Node 20 编译 nan 失败)
👉 一键升级/降级 Node 版本的终极方案


二、开发依赖:Solana 与 TON 共用同一个 repo

把 TON 与 Solana 的钱包工具放在同一仓库,方便横向对比 ed25519 派生差异:

npm i @solana/web3.js @solana/spl-token ed25519-hd-key bs58 tonweb tonweb-mnemonic bip39

三、助记词→私钥→TON 地址

TON 官方钱包多用 24 词 BIP-39,核心流程:

  1. 生成助记词
  2. 种子通过 bip39.mnemonicToSeedSync 产出 64 字节
  3. 以 BIP-44 Path m/44'/607'/0'/0'/0' 派生私钥
  4. 用 TonWeb 的 WalletClass.all.v3R2 计算地址

代码片段梳理:

import { derivePath } from 'ed25519-hd-key';
import TonWeb from 'tonweb';
const tonweb = new TonWeb();

export async function createTonAddress(seedHex: string, index: number){
  const path = `m/44'/607'/0'/0'/${index}'`;
  const key  = derivePath(path, seedHex);
  const publicKey = key.key; // Buffer
  const WalletClass = tonweb.wallet.all.v3R2;
  const wallet = new WalletClass(tonweb.provider, { publicKey });
  const addr = await wallet.getAddress(); // Promise<string>
  return addr.toString(true, true, true);
}

Jest 检测:

jest tests/ton.test.ts -t 'get ton addr'
FAQ
Q1:为什么 getAddress() 需要 await
A:TonWeb 内部使用 Promise<Address> 封装,即使计算纯 CPU 密集型也保持统一异步接口。

四、离线签名:不触网即可获得 boc 与 txHash

原理:把交易体转成 Cell → BOC → Base64,无需联网即可拿到「签名后的转账包」与「交易哈希」。

const keyPair = TonWeb.utils.nacl.sign.keyPair.fromSecretKey(
  TonWeb.utils.hexToBytes(privateKey)
);
const { secretKey, publicKey } = keyPair;

const wallet = new TonWeb.wallet.all.v3R2(tonweb.provider, { publicKey });
const seqno  = 7; // 可离线手动指定
const amount = TonWeb.utils.toNano('0.001');
const memo   = '8701657';

const transfer = wallet.methods.transfer({
  secretKey,
  toAddress: 'EQD5vcDeRhwaLgAvralVC7sJXI-fc2aNcMUXqcx-BQ-OWnOZ',
  amount,
  seqno,
  payload: memo,
  sendMode: 3,
});

const txdata = await transfer.getQuery();
const boc    = await txdata.toBoc();
const txhash = await txdata.hash();

const offlineSignedTx = {
  boc: TonWeb.utils.bytesToBase64(boc),
  txhash: TonWeb.utils.bytesToBase64(txhash),
};

console.log('离线已签名:', offlineSignedTx);

拿到 boc 后,可用 curl 直接 POST 到任意 TON RPC 节点完成广播,也可交给前端通过网页广播。


五、向链上广播的三种姿势

  1. TonWeb RPC
    最方便,但 RPC 偶尔 429;需自己轮询状态。
  2. Rust/C++ 方案
    TON 官方 tonlib 必须用 clang-16 编译,libsecp256k1 缺失是常见问题,新手不建议入坑。
  3. Go tonutils-go
    👉 用 Go 编写离线钱包,一行代码即可广播交易

Go 的极简示例(已适配 mainnet):

client := liteclient.NewConnectionPool()
cfg, _ := liteclient.GetConfigFromUrl(ctx, "https://ton.org/global-config.json")
client.AddConnectionsFromConfig(ctx, cfg)
api := ton.NewAPIClient(client)

hexStr := "YOUR_64_byte_PRIVATE_KEY"
bytes, _ := hex.DecodeString(hexStr)
w, _ := wallet.FromPrivateKey(api, bytes, wallet.V4R2)

addr := address.MustParseAddr("EQD5vcDeRhwaLgAvralVC7sJXI-fc2aNcMUXqcx-BQ-OWnOZ")
msg := w.BuildTransfer(addr, tlb.MustFromTON("0.001"), false, "8701657")
ext, _ := w.BuildExternalMessage(msg)
client.SendMessage(ctx, ext)

FAQ

Q2:VS Code 修改代码后测试未生效?
A:TypeScript 需 npm run build 手动转译,再运行 jest。可开启 --watch 实时监听。

Q3:okx 充值 TON 的 memo 会变?
A:每次刷新充值页面,交易所都会 生成新的唯一 memo 并标记到 UID,旨在防重复、便对账。如果你是量化机器人,请先 GET /deposit/addr 接口再循环刷新。

Q4:Rust 编译 segfault?
A:TON 要求 clang-16 + lld-16,Ubuntu 需额外安装 llvm-16-devlibsecp256k1-dev

Q5:官方 24 词助记词与 12 词区别有多大?
A:24 词熵 256 bits,更安全;12 词熵 128 bits,够用。一般交易所钱包生成时默认 24 词。

Q6:如何在浏览器里广播离线 boc
A:向 https://toncenter.com/api/v2/sendBoc 发送 POST {boc} 即可,或用社区开源的 TON API SDK 封装的 client.sendFile(boc)


总结

从脚手架、助记词派生,到离线签名、再到区块链广播,TON 钱包开发已完全可跑通。希望本文的踩坑笔记能为你省下 5–7 小时调试时间,助力团队把产品 First-Launch 周期压缩到 48 小时内

👉 立即体验 5 分钟极速上链 DEMO