TON 非托管 Swap:AI 智能体如何不碰私钥兑换代币
AI 智能体如何在 TON 上完成非托管代币 Swap:通过 Omniston 调用 get_swap_quote 与 build_swap_tx,服务器不签名、不保管私钥,签名始终在用户钱包。
谁持有私钥——AI 智能体在 TON 上非托管 Swap 代币的核心问题
设想一下:你让 AI 智能体盯着行情,等 USDT 价格回落时用 GRAM 补仓。智能体分析市场、找准时机、备好交易——而这时才浮出一个大家往往想得太晚的问题:要让智能体真正完成 swap,必须有人用私钥给交易签名。这把私钥在谁手里?
如果答案是“智能体所依赖的那个服务”——那你就把支配自己资金的权力交给了别人的代码。一次 prompt 注入、一次日志泄露,智能体签下的就不再是你以为的那笔交易。问题的关键从来不是“怎么调 DEX”,而是如何让智能体负责组装交易,同时把签名严格留在用户自己的钱包里。下面我们就来拆解,AI 智能体如何在 TON 上非托管地 swap 代币。
Swap 的两个部分:计算是安全的,签名不是
DEX 上的 swap 由两个性质截然不同的部分组成。第一部分是纯计算、安全的:查询汇率、计算滑点、组装交易体。第二部分是不可逆、危险的:用私钥给交易体签名并广播上链。分岔就在这里:
- 托管模式。 智能体(或它背后的服务器)持有私钥并自行签名。很方便——智能体可以完全自主行动。但签名私钥就摆在 LLM 旁边,而 LLM 是非确定性的,可能被不可信文本(jetton 描述、其他工具的返回结果、用户消息)说服。TON Foundation 官方的
@ton/mcp就是这种架构:它是一个持有 operator 私钥的智能体钱包,转账和 swap 都由它自己签名(split-key 方案:operator 私钥在智能体手里,owner 私钥在用户手里)。这套模式是行得通的,也有自己的长处——自主支出、支持 NFT 和 DNS、官方包的身份。但它本质上是对私钥持有者的信任。 - 非托管模式。 服务器只负责组装交易,并以未签名的形式返回。签名由用户钱包通过 TonConnect 完成。服务器从头到尾看不到、也不保存私钥。
对一个 7×24 运转的交易智能体来说,第二种模式消除了最大的风险:哪怕基础设施被攻破,最坏的结果也只是一份未签名的交易草稿——你反正还要手动或按自己钱包的策略去确认它。关于这个分岔的详细分析,见 TONNode 与官方 @ton/mcp 的诚实对比。
TONNode 的非托管模式:服务器只返回未签名交易
TONNode 是一个面向 TON 的 hosted MCP 服务器。MCP(Model Context Protocol)是 AI 智能体(Claude、Cursor、ChatGPT/Codex 以及任何 MCP 客户端)调用外部工具的标准协议。TONNode 为智能体提供了 16 个操作 TON 的工具,其中 swap、跨链和钱包生成工具是严格非托管的。
核心不变量:服务器绝不签名,绝不保管资金和私钥。 对 swap 来说,这意味着最终工具返回的不是一笔“已执行的交易”,而是一条未签名的 TonConnect 消息——一个等待签名的对象。服务器手里没有签名,因此它在物理上不可能在签名之后偷换收款方。
TONNode 的 swap 恰好就是两个工具:
get_swap_quote——硬报价,build_swap_tx——可直接交给 TonConnect 的未签名交易。
两者都走 Omniston 协议,它同时聚合 STON.fi 和 DeDust 的流动性——报价会在两个 DEX 上同时计算,你拿到的是其中更优的那个。Swap 以 GRAM⇄jetton 交易对进行。GRAM 是 Toncoin 的新名字(2026 年 6 月更名);网络本身仍叫 TON。也就是说,报价里的“GRAM”就是这条链的原生币。
get_swap_quote:通过 Omniston(STON.fi + DeDust)获取硬报价
第一步是搞清楚你实际能拿到多少。get_swap_quote 返回硬报价:预期到账数量和汇率。由于底层的 Omniston 会同时向 STON.fi 和 DeDust 询价,智能体不需要自己遍历各个池子逐一比较——它看到的已经是聚合后的结果。
获取 100 USDT → GRAM 的 swap 报价。
使用 get_swap_quote,展示预期到账数量和汇率。
有一个细节经常导致报价算错:报价使用的是 raw 单位(代币最小不可分割的份额),而不是“人类可读”的数字。所以在计算 jetton 的 swap 数量之前,必须先知道它的 decimals。
get_jetton_info:为什么 swap 前必须查 decimals(USDT = 6)
有一个典型错误会直接把 swap 搞砸:智能体拿到“100 USDT”,就把 100 填进数量字段。但链上的 jetton 根本没有“100”这个概念——只有 raw 单位。一个代币等于多少 raw 单位由 decimals 参数决定,数量按 数量 × 10^decimals 计算。
- TON 上的 USDT
decimals = 6→ 100 USDT 就是100 × 10^6 = 100 000 000raw 单位。 - 绝大多数 jetton
decimals = 9→ 100 个代币就是100 000 000 000raw 单位。
如果天真地按 GRAM 的习惯给“100 USDT”补上九个零,你请求的 swap 金额就会是本意的 1000 倍。在这里错上三个数量级实在太容易了。所以 get_jetton_info 是必经步骤:它返回 jetton 的名称、符号、decimals 和发行量。
Swap 之前先用 get_jetton_info 查询输入 jetton 的 decimals,
然后再计算 raw 单位的数量。
这个话题在通过 MCP 把 AI 智能体接入 TON一文中有更深入的展开。
辅助工具:parse_address 和 get_jetton_balance
在组装交易之前,还有两个值得先调用的辅助工具:
parse_address——离线校验和转换地址(EQ/UQ/raw)。在动手组装任何东西之前,它能以极低的成本挡住 jetton 地址或收款地址里的手误。get_jetton_balance——按钱包的主地址查询 jetton 余额。查询余额所需的 jetton-wallet 地址由工具在链上自行推导,所以要传的是主地址,而不是 jetton-wallet 地址。常见错误就是塞进 jetton-wallet 地址——不必,给主地址就行。
build_swap_tx:交给 TonConnect 的未签名消息
拿到报价、把数量换算成正确的 raw 单位之后,build_swap_tx 负责组装交易本身。非托管的精髓就在这里:工具返回的是一条未签名的 TonConnect 消息。 它不是已发出的交易,而是一份草稿:合约地址、金额、payload。服务器把“信封”递给了你,但没有封口——封印(签名)由你的钱包来盖。
接下来这条消息进入兼容 TonConnect 的钱包(Tonkeeper 等),用户能看到自己到底在签什么,然后确认。私钥在任何一步都不会离开钱包,也不会到达 TONNode 的服务器。
用 build_swap_tx 按最新报价组装 swap 交易。
返回未签名的 TonConnect 消息——我会在钱包里签名。
完整流程:从报价到钱包签名
jetton swap 的典型顺序是这样的:
parse_address——校验并规范化 jetton 地址和收款地址(离线)。get_jetton_info——查询decimals(USDT 是 6,多数是 9)、名称、符号。get_jetton_balance——确认余额充足(用主地址,不是 jetton-wallet 地址)。get_swap_quote——通过 Omniston(STON.fi + DeDust)拿到硬报价。build_swap_tx——组装未签名的 TonConnect 交易。- 用户钱包通过 TonConnect 签名——签名发生在用户一侧。
在 prompt 层面,对智能体说起来非常自然:
我想把 50 GRAM 换成 USDT。
先用 parse_address 校验 USDT 的 jetton 地址,
用 get_jetton_info 查它的 decimals,
用 get_jetton_balance 检查余额,
再用 get_swap_quote 拿报价,并用 build_swap_tx 组装交易。
不要发送交易——把未签名的 TonConnect 消息返回给我。
智能体会自己把这段话拆成一串工具调用,最终你拿到一份交易草稿,由你在自己的钱包里签名。注意:最后一步不是 TONNode 的工具。签名由钱包完成,非托管的边界正是划在这里。如果你在搭建一个完整的交易智能体,可以看看TON 上交易的延迟剖析——那篇文章把这套流程嵌进了决策循环。至于 TON 之外的交易,TONNode 提供了基于原子化 HTLC 托管合约的五个非托管跨链工具。
如何把 swap 工具接入 Claude、Cursor 或 ChatGPT
Swap 工具在所有套餐上都可用,包括免费的 Hobby(60 请求/分钟)——Hobby 就是一把 hosted key。你付费买的只是吞吐量,16 个工具的集合在所有 key 上完全一致。
本地免费——只读场景。 @tonnode/mcp 是开源包(MIT),通过 TON 原生的 ADNL 协议直连、不经过任何 HTTP 中间层,一条命令即可启动。公共配置提供完整的只读工具集:
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@tonnode/mcp"]
}
}
}
Hosted 端点——swap 及其余全部工具。 用自己的 key(免费的 Hobby 就够了),获得有保障的吞吐量和全部 16 个工具,包括 get_swap_quote 和 build_swap_tx:
{
"mcpServers": {
"ton": {
"type": "http",
"url": "https://mcp.tonnode.io/mcp",
"headers": { "Authorization": "Bearer tn_live_…" }
}
}
}
把这段配置放进你 MCP 客户端的设置里——Claude Desktop、Cursor、ChatGPT/Codex 或任何兼容 MCP 的智能体都行。接入 hosted key 之后,get_swap_quote 和 build_swap_tx 会自动出现在智能体的工具列表里。tn_live_… key 登录后即刻发放,无需绑卡。
要点回顾
- TONNode 的 swap 就是两个工具:
get_swap_quote(硬报价)和build_swap_tx(交给 TonConnect 的未签名交易)。 - 两者都走 Omniston——STON.fi 和 DeDust 的流动性聚合器。
- 签名永远在用户手里。 服务器不保管、不签名任何私钥——这与托管式的官方
@ton/mcp不同。 - Swap jetton 之前先用
get_jetton_info查decimals(USDT = 6,多数 = 9),否则 raw 单位的数量会算错。 - Swap 工具在任何 hosted key 上都可用,包括免费的 Hobby。
对智能体来说,TON 上的非托管 swap 是一种角色分离的纪律:服务器负责计算和组装,钱包负责签名。在 TONNode 里,这就是 Omniston 之上的两个工具,外加保证 decimals 正确的 get_jetton_info——没有任何一把私钥离开用户。
最简单的起点是一把免费 key。 无需绑卡领取 Hobby key,几分钟内接好 swap 工具:tonnode.io/dashboard?plan=hobby。想先浏览完整的工具集?看看工具页面。