TON 开发实战手账:地址、钱包、Jetton/ NFT 与 DEX 一站式指南

·

想在 The Open Network 上高效开发,却常被地址转换、Jetton 钱包查找、NFT 批量铸造或 DeDust 交换难住?这篇实战手账将常见场景拆成小段代码与可复用思路,助你快速起跑。

1. TON 地址:两种格式一次看懂

关键词:TON 地址、用户友好地址、原始地址、地址验证

1.1 格式速查

TON 用两套编码标记同一个合约:

1.2 一键互转

import { Address } from "@ton/core";

// 字符串 → Address 对象
const addr = Address.parse('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');

// Address 对象 → 用户友好 / 原始
console.log(addr.toString());        // 用户友好
console.log(addr.toRawString());     // 原始

1.3 判断地址是否有效

const TonWeb = require("tonweb");
console.log(TonWeb.utils.Address.isValid('EQ…'));

FAQ:地址

Q1:地址第一个字母为什么有时是 E、U、k、0?
A:前 6 bit 表示 flag。E=主网可弹回,U=主网不可弹回,k=测试网可弹回,0=测试网不可弹回。

Q2:在浏览器地址栏复制时 +、/ 会出错?
A:把 urlSafe=true 即可把 +// 换成 - _

Q3:合约部署后地址会变吗?
A:不会,地址 = 工作链+状态哈希,部署后哈希不变,地址即终身不变。


2. 标准钱包:转帐 + 留言一步到位

关键词:TON 钱包、部署合约、消息序列

2.1 发送 TON 并留言

import { TonClient, WalletContractV4, internal, mnemonicToPrivateKey } from "@ton/ton";

const client = new TonClient({ endpoint: "https://testnet.toncenter.com/api/v2/jsonRPC" });
const mnemonics = "word1 word2 ...".split(" ");
const keyPair = await mnemonicToPrivateKey(mnemonics);
const wallet = client.open(WalletContractV4.create({ workchain: 0, publicKey: keyPair.publicKey }));

await wallet.sendTransfer({
  seqno: await wallet.getSeqno(),
  secretKey: keyPair.secretKey,
  messages: [internal({
    to: "UQ…目标地址…",
    value: "100000000",          // 0.1 TON,单位 nanoton
    body: "Hello, TON!"
  })]
});

2.2 带长注释?用蛇形 Cell

当文字 > 1023 bit,需拆成多个 cell:writeStringTail 分段写入、readStringTail 递归读出。代码示例已在原文贴出,直接复用即可。


3. Jetton(代币)实战

关键词:Jetton 钱包地址、TEP-74、转账注释

3.1 离线计算用户 Jetton 钱包地址

省去实时 getWalletAddress 调用,三步搞定:

  1. 通过 get_jetton_data 拿钱包代码 cell。
  2. storeStateInit 拼装 (code, data)
  3. 用状态哈希生成新地址。
    👉 跟随完整示例重现实验室场景

3.2 构造带注释的 Jetton 转账

import { beginCell, toNano } from "@ton/core";

const forwardPayload = beginCell()
  .storeUint(0, 32)                              // 0 opcode 表示注释
  .storeStringTail("早餐咖啡钱 ☕")
  .endCell();

const messageBody = beginCell()
  .storeUint(0x0f8a7ea5, 32)                    // jetton transfer opcode
  .storeUint(0, 64)                             // query_id
  .storeCoins(toNano(5))                        // 5 Jetton(单位最小可分割)
  .storeAddress(destinationAddress)
  .storeAddress(responseAddress)
  .storeBit(0)                                  // 无自定义 payload
  .storeCoins(toNano("0.03"))                   // 转发给接收方的 TON
  .storeBit(1)
  .storeRef(forwardPayload)
  .endCell();

FAQ:Jetton

Q1:为什么同样转出 5 个币,主网测试网显示数量不同?
A:转账使用“不可分割最小单位”,UI 端按 decimals 显示。若 decimals=9,则 5×10⁹;decimals=6 则 5×10⁶。

Q2:手续费如何估算?
A:transfer + forward 费用 = 0.05 TON 左右,合约若需存储再加 0.01-0.02 TON。


4. NFT 高效开发

关键词:NFT、批量部署、更换所有者、更改合集元数据

4.1 一交易最多造 100-130 枚

受计算费 1 TON 限制,无需多笔交易:

4.2 更换合集所有者

只需 3 步:opcode→3、query_id→0、新地址写入 cell,0.05 TON 即可。

4.3 更新合集内容及版税

合集存储结构:[collectionMetaCell, nftCommonMetaCell]
若只改 NFT 前缀,保留旧 royaltyCell 即可;发送 opcode→4 完成。


5. 在 DeDust DEX 完成第一笔闪兑

关键词:DeDust、Pool、Vault、forwardPayload

  1. 找地址factory.getVault(native)factory.getPool(VOLATILE, [TON, JETTON])
  2. 检查状态await pool.getReadinessStatus() === READY
  3. T➡️J

    • nativeVault 发送 swap 消息并携带 5 TON
    • gasAmount=0.25 TON 防卡住
  4. J➡️T

    • 向对应 jettonVault 转账 jetton,附带 forwardPayload
      createSwapPayload({ poolAddress })

详细 SDK 初始化代码已在原文提供。👉 即可查看 DeDust 官方 TL-B 模式细节


6. 消息解析:一眼识别转账类型

关键词:解析交易、外部消息、opcode、TON Connect

6.1 通用步骤

  1. client.getTransactions(addr, {limit:10})
  2. inMessage.body.loadUint(32) 取 opcode

    • 0:附带文本
    • 0x7362d09c:Jetton 转账通知
    • 0x05138d91:NFT 转账通知
  3. 校验收款地址,防止伪造

6.2 定位 TON Connect 交易

因 TON Connect 只返回 BOC,需:


7. 小结与下一步

已覆盖 TON 地址、钱包转账、Jetton、NFT、DEX 交换、消息解析 六大高频场景。建议即刻动手:

愿你在 The Open Network 的星辰大海乘风破浪!