TON 交易智能体实战:读余额、拿硬报价、非托管构建 swap
基于 MCP 的 TON 交易智能体:AI 如何读取余额、获取硬报价并以非托管方式构建 swap——get_balance、get_swap_quote、build_swap_tx 全流程。
每个 TON 交易智能体都绕不开的第一个问题
你让 AI 智能体“等价格回落时把 50 USDT 换成 GRAM”——它却发出了一笔 50,000 USDT 的交易。原因是 TON 上的 USDT decimals = 6(50 USDT = 50,000,000 raw 单位),而智能体默认按九个零的普通 Jetton 来算——金额直接放大了 1000 倍。1000 倍的误差,真金白银,交易不可逆。镜像版的错误也是同一个根源:智能体看到余额里的原始数字 1000000000,信誓旦旦地汇报“您有十亿 USDT”,实际上只有 1000。
这不是编出来吓唬人的故事,而是每个把 LLM 通过裸 RPC 直连 TON DeFi 的人都会踩的那些坑:decimals 搞混、不知道 Jetton 钱包地址就读不了 Jetton 余额、私钥顺着上下文泄漏出去。下文讲的就是如何搭一个TON 交易智能体(trading agent TON):读余额、拿硬报价、构建 swap,全程不碰你的私钥。工具是 TONNode——面向 TON 的 hosted MCP 服务器。
什么是 TON 交易智能体,它为什么需要 MCP
交易智能体就是一个 LLM(Claude、Cursor、Codex 或任何别的 MCP 客户端),能按用户指令读取链上状态并准备交易:“看看我的 USDT 余额”“500 USDT 能换多少 GRAM”“把 swap 构建出来”。模型本身是看不到区块链的——它需要工具。
这正是 MCP(Model Context Protocol) 干的事:一套让智能体调用外部工具的标准。与其教模型手搓 ADNL 请求、解析 BOC cell,不如直接给它一组类型化的函数:“查余额”“拿报价”“构建交易”。TONNode 作为这类工具的提供方接入,给智能体正好 16 个函数来操作 TON 网络:读取、swap、跨链、生成钱包。
交易智能体只需要其中五个,而且这五个在免费套餐里全都能用:
读取 (get_balance, get_jetton_balance)
-> 确认 decimals (get_jetton_info)
-> 报价 (get_swap_quote)
-> 构建 swap (build_swap_tx)
-> 钱包通过 TonConnect 签名
最后一步有个关键细节:签名的是用户的钱包,不是服务器。TONNode 返回的是未签名消息——为什么这一点是原则问题,文末细说。
第 1 步:智能体读取余额(get_balance、get_jetton_balance)
要 swap,先得知道手里有什么。两个工具:
get_balance—— 地址上的 GRAM 余额。GRAM 就是 2026 年 6 月改名后的 Toncoin;网络本身仍然叫 TON。get_jetton_balance—— Jetton 余额:USDT、NOT 或任何别的代币。妙处在于 Jetton 钱包地址是链上推算出来的。你只传所有者地址和 Jetton 的 master 地址,TONNode 自己推导出 Jetton 钱包地址并读取余额。不需要提前知道这个地址,也不用把它另外保存在什么地方。
给智能体的提示词就长这样:
查一下钱包 UQAbc...xyz 的余额:
上面有多少 GRAM,多少 USDT?
模型在底层调 get_balance 拿原生余额、调 get_jetton_balance 拿 USDT。只有一个麻烦:返回的还不是“人类可读”的金额,而是 raw 单位。重头戏从这里开始。关于如何一次调用拿到 USDT 余额、不用折腾 Jetton 钱包地址,另有一篇专门拆解:/blog/usdt-balance-ton-one-call。
decimals 决定一切:get_jetton_info,以及为什么 USDT = 6
TON 上的余额和金额都以 raw 单位存储——不带小数部分的整数。要得到人类可读的金额,得把原始数除以 10^decimals。坑就埋在这里:不同 Jetton 的 decimals 各不相同。
- USDT 是
decimals = 6。也就是1 USDT = 1,000,000raw 单位。 - TON 上绝大多数 Jetton 是
decimals = 9(GRAM 也是)。也就是1 个代币 = 1,000,000,000raw 单位。
把 6 和 9 搞混,金额就恰好错 1000 倍——正是文章开头那个“十亿 USDT”。对交易智能体来说这不是小细节,而是信任的根基:连数量级都会搞错的智能体,是不能放手让它去构建交易的。
所以管道里必须插入 get_jetton_info——它返回 Jetton 的元数据:名称、符号、发行量,以及最关键的 decimals。智能体内部的正确逻辑:
raw = get_jetton_balance(...) // 例如 1000000000
decimals = get_jetton_info(...) // USDT → 6
human = raw / 10 ** decimals // 1000000000 / 1e6 = 1000 USDT
同样的 raw 在 decimals = 9 下只等于 1 个代币——天壤之别。不要把 decimals 硬编码进提示词,也别让模型“凭记忆脑补”:换个新 Jetton 它就会错。让它每次都从 get_jetton_info 现取、现算。这个坑为什么真的让人赔钱,详见:/blog/jetton-decimals-ton。
第 2 步:通过 Omniston 拿硬报价(get_swap_quote)
余额读完、单位换算正确——现在智能体需要价格。DeFi 里“凭感觉估个价”行不通:流动性分散在多个 DEX 上,汇率随时在动,智能体必须依据实时报价,而不是猜测。
get_swap_quote 通过 Omniston 协议给出 GRAM ⇄ Jetton swap 的硬报价。Omniston 一次性聚合了 TON 上两个最大的 DEX(STON.fi 和 DeDust)的流动性。智能体不用自己去轮询池子、比价、算滑点:Omniston 直接从合并后的流动性里返回最优路由。
给我一个报价:现在 50 USDT 能换多少 GRAM?
模型带着金额 50000000(就是上一步那种 raw 单位)调用 get_swap_quote,拿回具体数字:进多少、出多少、走哪条路由、滑点多大。这是决策点:如果智能体带着条件(“只有汇率优于 X 才 swap”),它就拿报价对比阈值,要么继续,要么等下一轮。重要:报价还不是成交。没有任何资金移动,没有任何签名。这是纯粹的读市场。
第 3 步:构建未签名 swap(build_swap_tx),在钱包里签名
用户看到报价,说“行,换”。智能体调用 build_swap_tx,拿到一笔未签名的 swap 交易,直接可用于 TonConnect。
请注意“未签名”这个词。服务器组装出正确的消息——接收方地址、payload、金额、路由参数——然后原样返回。接下来消息进入用户自己的钱包(Tonkeeper、MyTonWallet,任何兼容 TonConnect 的钱包),用户看到自己到底在签什么,自己确认。落笔签名的是用户自己的私钥——它待在用户的钱包里,而不是服务器上。
get_balance / get_jetton_balance → 读取手里有什么
↓
get_jetton_info → 确认 decimals,换算
↓
get_swap_quote (Omniston) → 硬报价
↓
build_swap_tx → 未签名交易
↓
用户钱包 (TonConnect) → 签名并发送
每一步都是一次独立、显式的工具调用。智能体不会拿你的钱“自作主张地多做一步”:它只负责准备,决定和签名都留给人。非托管 swap 的完整场景,从报价到签名逐步拆解在这里:/blog/agent-swap-ton-noncustodial。
非托管:为什么服务器永远不持有智能体的密钥
这不是营销话术,而是一条架构边界。TONNode 的 swap、跨链和钱包生成工具严格非托管:
- 服务器从不签名任何交易。
- 服务器从不保存私钥和资金。
- 它对外返回的一切都是未签名的 TonConnect 消息。
为什么这对交易智能体尤其重要?因为智能体天生就在跟钱打交道,也天生可能出错——理解错需求、搞错金额、陷入死循环。如果私钥放在服务器上并由它自行签名,智能体的一次失误就意味着资金在你不知情的情况下没了。而在非托管架构里,最后一道防线是你自己:你的钱包不确认,任何交易都发不出去。
对比一下 TON Foundation 官方的 @ton/mcp——那是一个托管型智能体钱包:它持有 operator 密钥并自行签名(split-key 方案:operator 密钥在智能体手里,owner 密钥在用户手里)。它有自己的长处——无需人工参与的自主支出、NFT 和 DNS 操作、Foundation 官方身份。但信任模型不同:那里的智能体是真的能动资金的。TONNode 有意选择了相反的边界:服务器什么都不签。两种思路的完整对比:/blog/custodial-vs-noncustodial-mcp。
如何接入:5 分钟上手
好消息:搭起这条交易管道不用花钱。但别把两条免费路径搞混——它们的工具集不一样。
本地公共配置提供完整的读取工具集(8 个工具:get_masterchain_info、get_balance、get_account_state、get_transactions、run_get_method、get_jetton_balance、parse_address、get_jetton_info)。通过 npx 安装,无需密钥:
{
"mcpServers": {
"ton": {
"command": "npx",
"args": ["-y", "@tonnode/mcp"]
}
}
}
@tonnode/mcp 包是开源的(MIT),发布在 npm 和 GitHub(tonnode/mcp)上,走 TON 原生 ADNL 协议,智能体和网络之间没有任何 HTTP 中间层。把配置贴进 Claude Desktop、Cursor 或任何 MCP 客户端——智能体立刻就能读余额、调 get_jetton_info。
而报价本身——get_swap_quote 和 build_swap_tx——属于 SWAP 组,走 hosted 端点。关键在于:免费的 Hobby 密钥就能用上全部 16 个工具,包括报价和 swap 构建。也就是说整条交易管道(读取 → 报价 → swap)都可以免费搭起来——但走的是 hosted 的 Hobby 密钥,不是本地公共配置。hosted 端点的配置:
{
"mcpServers": {
"ton": {
"type": "http",
"url": "https://mcp.tonnode.io/mcp",
"headers": { "Authorization": "Bearer tn_live_…" }
}
}
}
TONNode 正好有 16 个工具,所有套餐都开放全部 16 个——你付费买的只是吞吐量,不是功能:
- Hobby —— 永久免费,60 请求/分钟,无需绑卡。
- Pro —— $29/月,300 请求/分钟。
- Scale —— $199/月,1200 请求/分钟。
起步和跑通交易管道,免费的 Hobby 密钥绰绰有余:每分钟 60 个请求,足够智能体做很多次连续调用。不用绑卡,登录后立刻发放密钥。
领取免费 Hobby 密钥(60 req/min,无需绑卡):tonnode.io/dashboard?plan=hobby
16 个工具完整列表:tonnode.io/mcp · 价格:tonnode.io/pricing
把这五个工具串成管道——get_balance、get_jetton_balance、get_jetton_info、get_swap_quote、build_swap_tx——盯住 decimals,把签名交给钱包。这样你得到的交易智能体,会老老实实读余额、拿硬报价、按真实金额准备 swap,而且一秒钟都没有接触过任何人的私钥。TON 上的交易智能体,本来就该这么工作。