Все статьи
7 мин чтения

Как собрать торгового агента на TON: читать, котировать, свапать

Торговый агент TON на MCP: как агент читает балансы, берёт котировку и собирает своп некастодиально — get_balance, get_swap_quote, build_swap_tx.

торговый агент TONtrading agent TONMCPсвоп TONнекастодиальностьOmniston

Проблема, с которой начинается любой торговый агент на TON

Вы просите ИИ-агента «свапнуть 50 USDT в GRAM, когда цена просядет» — а он отправляет транзакцию на 50 000 USDT вместо 50. Потому что у USDT в TON decimals = 6 (50 USDT = 50 000 000 raw-единиц), а агент по умолчанию посчитал как для обычного жетона с девятью нулями — и заложил в сумму в 1000 раз больше. Ошибка в 1000 раз, реальные деньги, необратимая транзакция. Тот же корень у зеркальной ошибки: агент видит на балансе сырое 1000000000 и уверенно рапортует «у вас миллиард USDT», хотя там 1000.

Это не выдуманные страшилки, а ровно те грабли, на которые наступает каждый, кто подключает LLM к DeFi на TON напрямую через сырые RPC: перепутанные decimals, невозможность прочитать баланс жетона без адреса джеттон-кошелька, утёкший через контекст приватный ключ. Ниже — как собрать торговый агент на TON (trading agent TON), который читает балансы, берёт твёрдую котировку и собирает своп, ни разу не прикоснувшись к вашим ключам. Инструмент — TONNode, hosted MCP-сервер для TON.

Что такое торговый агент на TON и зачем ему MCP

Торговый агент — это LLM (Claude, Cursor, Codex или любой другой MCP-клиент), которая по запросу пользователя умеет читать состояние сети и готовить сделки: «покажи мой баланс USDT», «сколько GRAM я получу за 500 USDT», «собери своп». Сама по себе модель блокчейн не видит — ей нужны инструменты.

Именно это и делает MCP (Model Context Protocol) — стандарт, по которому агенты вызывают внешние инструменты. Вместо того чтобы учить модель сочинять сырые ADNL-запросы и парсить BOC-ячейки, вы отдаёте ей набор типизированных функций: «дай баланс», «дай котировку», «собери транзакцию». TONNode подключается как источник таких инструментов и даёт агенту ровно 16 функций для работы с сетью: чтение, свап, кроссчейн, генерация кошелька.

Торговому агенту из них нужны пять, и все пять доступны даже на бесплатном тарифе:

читать (get_balance, get_jetton_balance)
   -> уточнить decimals (get_jetton_info)
      -> котировать (get_swap_quote)
         -> собрать своп (build_swap_tx)
            -> кошелёк подписывает через TonConnect

Ключевая деталь последнего шага: подписывает кошелёк пользователя, а не сервер. TONNode возвращает неподписанные сообщения — почему это принципиально, разберём в конце.

Шаг 1: агент читает балансы (get_balance, get_jetton_balance)

Прежде чем что-то свапать, агент должен понять, чем он располагает. Два инструмента:

  • get_balance — баланс GRAM на адресе. GRAM — это переименованный в июне 2026 Toncoin; сама сеть по-прежнему называется TON.
  • get_jetton_balance — баланс жетона: USDT, NOT, любого другого. Магия здесь в том, что джеттон-кошелёк вычисляется он-чейн. Вы передаёте адрес владельца и мастер-адрес жетона, а TONNode сам выводит адрес джеттон-кошелька и читает его баланс. Не нужно заранее знать этот адрес и где-то его хранить.

Промпт агенту выглядит буквально так:

Проверь баланс кошелька UQAbc...xyz:
сколько на нём GRAM и сколько USDT?

Под капотом модель вызывает get_balance для нативного баланса и get_jetton_balance для USDT. Одна беда: то, что вернётся, — это ещё не «человеческие» суммы, а сырые единицы. И вот тут начинается самое важное. Про то, как получить баланс USDT одним вызовом без плясок с адресами джеттон-кошелька, есть отдельный разбор: /blog/usdt-balance-ton-one-call.

decimals решают всё: get_jetton_info и почему USDT = 6

Балансы и суммы в TON хранятся в raw-единицах — целых числах без дробной части. Чтобы получить человекочитаемую сумму, сырое число нужно поделить на 10^decimals. И вот засада: у разных жетонов разное число decimals.

  • У USDT decimals = 6. То есть 1 USDT = 1 000 000 raw-единиц.
  • У большинства жетонов в TON decimals = 9 (как у GRAM). То есть 1 жетон = 1 000 000 000 raw-единиц.

Перепутать 6 и 9 — это ошибиться в сумме ровно в 1000 раз. Тот самый «миллиард USDT» из начала статьи. Для торгового агента это не косметика, а корень доверия: если он путает порядки, ему нельзя давать собирать сделки.

Поэтому в конвейер встраивается get_jetton_info — он отдаёт метаданные жетона: имя, символ, эмиссию и — самое важное — 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 в промпте и не давайте модели «додумывать» их по памяти: на новом жетоне она ошибётся. Пусть тянет из get_jetton_info каждый раз и пересчитывает по факту. Подробно про эту ловушку и почему она стоит людям денег: /blog/jetton-decimals-ton.

Шаг 2: твёрдая котировка через Omniston (get_swap_quote)

Балансы прочитаны и пересчитаны в правильных единицах — теперь агенту нужна цена. В DeFi «примерная цена из головы» не работает: ликвидность размазана по нескольким DEX, курс двигается, и агент должен опираться на актуальную котировку, а не на догадку.

get_swap_quote даёт твёрдую котировку на своп GRAM ⇄ жетон через протокол Omniston, который агрегирует ликвидность сразу двух крупнейших DEX TON — STON.fi и DeDust. Агенту не нужно самому опрашивать пулы, сравнивать цены и считать проскальзывание: Omniston возвращает лучший маршрут из объединённой ликвидности.

Дай котировку: сколько GRAM я получу за 50 USDT прямо сейчас?

Модель вызывает get_swap_quote с суммой 50000000 (те самые raw-единицы из прошлого шага) и получает конкретные числа: сколько на входе, сколько на выходе, по какому маршруту, с каким проскальзыванием. Это точка принятия решения: если у агента есть условие («свапай только если курс лучше X»), он сравнивает котировку с порогом и либо идёт дальше, либо ждёт следующей итерации. Важно: котировка — это ещё не сделка. Никакие средства не двигаются, ничего не подписывается. Это чистое чтение рынка.

Шаг 3: сборка неподписанного свопа (build_swap_tx) и подпись в кошельке

Пользователь увидел котировку и говорит «да, свапаем». Агент вызывает build_swap_tx и получает неподписанную транзакцию свопа, готовую для TonConnect.

Подчеркну слово «неподписанную». Сервер собирает корректное сообщение — адрес получателя, payload, сумму, параметры маршрута — и возвращает его как есть. Дальше сообщение уходит в кошелёк пользователя (Tonkeeper, MyTonWallet, любой TonConnect-совместимый), пользователь видит, что именно подписывает, и подтверждает сам. Подпись ставит приватный ключ пользователя, который живёт в его кошельке, а не на сервере.

get_balance / get_jetton_balance   →  прочитать, что есть
        ↓
get_jetton_info                     →  уточнить decimals, пересчитать
        ↓
get_swap_quote (Omniston)           →  твёрдая котировка
        ↓
build_swap_tx                       →  неподписанная транзакция
        ↓
кошелёк пользователя (TonConnect)   →  подпись и отправка

Каждый шаг — отдельный явный вызов инструмента. Агент ничего не «доделывает по своему усмотрению» с деньгами: он готовит, а решение и подпись остаются за человеком. Полный сценарий некастодиального свапа, от котировки до подписи, разобран по шагам здесь: /blog/agent-swap-ton-noncustodial.

Некастодиальность: почему сервер никогда не держит ключи агента

Это не маркетинговая формулировка, а архитектурная граница. У TONNode инструменты свапа, кроссчейна и генерации кошелька строго некастодиальны:

  • Сервер никогда не подписывает транзакции.
  • Сервер никогда не хранит приватные ключи и средства.
  • Всё, что он отдаёт наружу, — это неподписанные TonConnect-сообщения.

Почему это важно именно для торгового агента? Потому что агент по определению работает с деньгами и по определению может ошибиться — не так понять запрос, перепутать сумму, зациклиться. Если бы ключи лежали на сервере и он подписывал сам, ошибка агента означала бы утрату средств без вашего ведома. В некастодиальной схеме последний рубеж — вы: ни одна транзакция не уходит, пока её не подтвердил ваш кошелёк.

Сравните с официальным @ton/mcp от TON Foundation — это кастодиальный агент-кошелёк: он держит 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 — open source (MIT), лежит на npm и GitHub (tonnode/mcp), работает по нативному ADNL-протоколу TON без HTTP-прослоек между агентом и сетью. Вставили конфиг в Claude Desktop, Cursor или любой MCP-клиент — и агент уже умеет читать балансы и дёргать get_jetton_info.

А вот сами котировки — get_swap_quote и build_swap_tx — относятся к группе СВАП и идут через hosted-эндпоинт. Ключевой момент: на бесплатном ключе Hobby доступны все 16 инструментов, включая котировку и сборку свопа. То есть весь торговый конвейер (чтение → котировка → своп) собирается бесплатно — но именно через 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 под контролем и отдавайте подпись кошельку. Так у вас получится торговый агент, который честно читает балансы, берёт твёрдую котировку и готовит своп на реальные суммы, ни на секунду не получив доступа к чужим ключам. Именно так и должен работать торговый агент на TON.

Дайте вашему агенту доступ к TON

16 MCP-инструментов: чтение, некастодиальные свапы, кроссчейн и кошельки. Бесплатный тариф — 60 запр/мин, карта не нужна.