关键词: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-demoscaffold.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 bip39ed25519-hd-key>= 1.3 时,接口并不接受Uint8Array,需使用Buffer或key.key。- Solana Web3.js 源码几乎只用
interface,体现 组合优于继承 的思维,极易复用改造。
三、助记词→私钥→TON 地址
TON 官方钱包多用 24 词 BIP-39,核心流程:
- 生成助记词
- 种子通过
bip39.mnemonicToSeedSync产出 64 字节 - 以 BIP-44 Path
m/44'/607'/0'/0'/0'派生私钥 - 用 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 节点完成广播,也可交给前端通过网页广播。
五、向链上广播的三种姿势
- TonWeb RPC
最方便,但 RPC 偶尔 429;需自己轮询状态。 - Rust/C++ 方案
TON 官方 tonlib 必须用 clang-16 编译,libsecp256k1缺失是常见问题,新手不建议入坑。 - 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-dev 及 libsecp256k1-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 小时内。