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

EQ, UQ и raw: форматы адресов TON и почему депозит «отскакивает»

EQ, UQ и raw: форматы адресов TON, bounceable против non-bounceable и почему первый депозит на новый кошелёк отскакивает отправителю.

TONадреса TONbounceableEQ UQ rawparse_addressдепозит

Разработчик генерирует свежий кошелёк, копирует адрес, кидает туда первые 5 GRAM на газ — и через минуту монеты возвращаются на отправляющий кошелёк. Баланс нового адреса: ноль. Никакой ошибки, никакого «reverted», транзакция прошла успешно. Просто деньги… отскочили. В чатах TON это классика: «отправил на свой же адрес — не дошло». И почти всегда причина одна — перепутанные форматы адреса и флаг bounceable.

Разберём по фактам, что такое форматы адресов TON — EQ, UQ и raw, чем отличается bounceable от non-bounceable, и почему первый депозит на новый кошелёк уходит обратно отправителю. А заодно покажу, как проверить всё это одним вызовом инструмента из ИИ-агента, не поднимая ни SDK, ни ноду.

Три формата адреса TON: raw, EQ и UQ — в чём разница

У любого адреса в TON под капотом лежит одно и то же: номер воркчейна плюс 256-битный хэш стейт-инита контракта. Это и есть raw-формат:

0:83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8

Слева от двоеточия — воркчейн (обычно 0 — базовый, -1 — мастерчейн), справа — 256-битный хэш в hex. Формат честный и однозначный, но у него нет контрольной суммы: опечатался в одном символе — получил другой валидный на вид адрес. Именно raw обычно ждут get-методы контрактов и низкоуровневые инструменты, а людям его почти не показывают.

Второе представление — user-friendly: те самые 48 символов base64url, которые вы видите в кошельках и эксплорерах:

EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N     (bounceable)
UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBI     (non-bounceable)

В нём зашита та же пара «воркчейн + хэш», плюс байт флагов и CRC16-контрольная сумма на конце. CRC ловит опечатки: битый адрес просто не пройдёт валидацию ещё до отправки. И именно из этого байта флагов рождаются префиксы EQ и UQ.

Ключевое, что стоит усвоить сразу:

  • raw и user-friendly — это два способа записать один и тот же адрес.
  • EQ и UQ — это два варианта одного user-friendly адреса, различающиеся ровно одним флагом.

То есть EQ… и UQ… для одного кошелька указывают на один и тот же raw-хэш, один и тот же контракт, один и тот же баланс. Это не два разных кошелька и не два разных счёта. Разница — только в одном бите намерения отправителя.

Bounceable (EQ) против non-bounceable (UQ): что значит флаг

Тот самый байт флагов внутри user-friendly адреса и определяет префикс:

Флаг Тег Префикс (mainnet) Префикс (testnet)
bounceable 0x11 EQ kQ
non-bounceable 0x51 UQ 0Q

Для тестнета к тегу добавляется 0x80 — отсюда экзотические kQ и 0Q. Но нас интересует смысл флага, а не арифметика тегов.

Bounceable (EQ) означает буквально: «если на принимающей стороне что-то пойдёт не так — верни монеты мне обратно». Это защита для смарт-контрактов. Если вы шлёте деньги контракту, который должен их обработать, а он падает с ошибкой, ещё не задеплоен или газа не хватило, — вы не хотите, чтобы монеты просто зависли в пустоте. Bounce-механизм вернёт их отправителю за вычетом комиссии.

Non-bounceable (UQ) означает противоположное: «доставь и оставь, что бы там ни было». Никакого возврата — монеты просто ложатся на адрес.

Для повседневных переводов между людьми разница незаметна — до одного конкретного случая.

Почему первый депозит на неразвёрнутый кошелёк «отскакивает»

Вот та самая ловушка. В TON адрес кошелька существует до того, как контракт кошелька реально задеплоен в блокчейн. Адрес — это детерминированный хэш от кода контракта и начальных данных (публичного ключа), поэтому вы знаете его сразу после генерации мнемоники, полностью офлайн. Но пока по адресу не прошла первая транзакция, аккаунт находится в состоянии uninit (неинициализированный): адрес есть, кода контракта на нём — нет.

Теперь смотрите, что происходит с bounceable-переводом:

  1. Вы шлёте на этот uninit-адрес перевод в формате EQ (bounceable).
  2. Сеть пытается доставить монеты и «вызвать» принимающий контракт. Принимать их некому — контракта на адресе нет.
  3. Срабатывает bounce: раз доставить не удалось, монеты возвращаются отправителю за вычетом комиссии.

Итог — тот самый «отскок». Транзакция прошла успешно, но баланс нового кошелька остался нулевым, а деньги вернулись туда, откуда пришли. Никто ничего не украл, сеть отработала ровно как задумано — просто вы использовали bounceable-формат там, где не должны были.

А если тот же перевод отправить в формате UQ (non-bounceable)?

  1. Сеть пытается доставить монеты на uninit-адрес.
  2. Bounce отключён флагом — возвращать не нужно.
  3. Монеты остаются на адресе, даже несмотря на то что контракт ещё не развёрнут.

Кошелёк пополнен. Позже, когда вы отправите с него первую исходящую транзакцию, вместе с ней задеплоится код контракта — и аккаунт станет active. С этого момента он спокойно принимает любые переводы, включая bounceable. Правило UQ критично только для самого первого пополнения ещё не развёрнутого кошелька.

Хорошая новость: экосистема постепенно закрывает эту дыру за пользователя. Кошельки v5r1 и ряд клиентов по умолчанию показывают адрес именно в non-bounceable (UQ) виде — как раз чтобы новичок не потерял первый депозит. Но как только вы работаете с адресами программно — из бэкенда, из скрипта, из ИИ-агента — ответственность за флаг снова на вас.

Как правильно слать первый перевод: UQ вместо EQ

Практическое правило умещается в одну строчку:

Первый депозит на новый (uninit) кошелёк — всегда на UQ. Дальше можно как угодно.

Развёрнутая логика для любого сервиса, который отправляет пользователю средства:

  • Адрес получателя в состоянии uninit → шлите на UQ (non-bounceable).
  • Адрес active → можно на EQ (bounceable).
  • Отправляете на смарт-контракт (DEX, джеттон-минтер, эскроу) → EQ, чтобы при ошибке деньги вернулись.

Проблема в том, что «на глаз» EQ от UQ отличается одним символом префикса, а состояние uninit/active по адресу вообще не видно. Обе проверки нужно делать программно. И вот тут не обязательно тащить в проект @ton/ton, поднимать провайдера и парсить ячейки — оба вопроса закрываются двумя инструментами MCP-сервера, которые ИИ-агент дёргает сам.

Если тема генерации и первого пополнения кошелька для вас свежая — есть отдельный разбор в гайде про создание TON-кошелька.

parse_address: конвертация и проверка адресов офлайн одним вызовом

parse_address — это офлайн-инструмент из TONNode, hosted MCP-сервера для TON. Он раскодирует адрес, пересчитывает форматы и проверяет CRC16, не обращаясь к сети: ему не нужны ни нода, ни ключ — это чистая математика над строкой, поэтому мгновенно и без расхода лимитов.

Что он умеет:

  • сконвертировать EQ ⇄ UQ ⇄ raw в любую сторону;
  • проверить валидность адреса (сойдётся ли контрольная сумма);
  • показать флаг bounceable и номер воркчейна.

MCP (Model Context Protocol) — стандарт, по которому ИИ-агенты (Claude, Cursor, ChatGPT/Codex и любой MCP-клиент) вызывают инструменты. Подключается MCP-сервер одной записью в конфиг клиента. Локальный бесплатный вариант с полным набором инструментов чтения:

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Дальше агенту достаточно обычного промпта:

Возьми адрес EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N и покажи его в non-bounceable (UQ) и raw форматах. Проверь, что контрольная сумма валидна.

Агент вызовет parse_address и вернёт UQ-версию того же кошелька, raw-хэш и статус валидности. Никакого ручного base64url-жонглирования и риска опечататься в 48 символах.

get_account_state: как понять, развёрнут ли кошелёк, до отправки

Форматом дело не заканчивается — надо ещё узнать, в каком состоянии адрес: active или uninit. Это уже он-чейн вопрос, и на него отвечает get_account_state. Инструмент возвращает статус аккаунта, флаги и данные о последней транзакции.

Логика перед отправкой первого перевода:

  • get_account_state вернул uninit → адрес ещё не задеплоен → шлём на UQ.
  • вернул active → кошелёк развёрнут → можно спокойно слать на EQ.

Промпт агенту:

Проверь через get_account_state, развёрнут ли адрес UQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqEBI. Если состояние uninit — напомни, что первый депозит нужно слать в UQ-формате.

Связка получается такая: generate_wallet создаёт кошелёк (версии v3r2/v4/v5r1/highload_v3) и отдаёт адрес, который на момент создания гарантированно uninit — сеть про него ещё не знает. Значит, первый депозит на него идёт строго на UQ. Перед отправкой get_account_state подтверждает, что адрес и правда uninit, а parse_address гарантирует, что вы взяли именно non-bounceable представление. После пополнения удобно дёрнуть get_balance и убедиться, что монеты легли на адрес, а не отскочили.

Важный момент про генерацию: generate_wallet возвращает мнемонику, ключи и адрес пользователю — сервер их не хранит и не подписывает ничего за вас. Это некастодиальная механика, и она распространяется на все инструменты свапа, кроссчейна и кошелька.

Небольшое терминологическое уточнение: GRAM — это переименованный Toncoin (переименован в июне 2026), сама сеть по-прежнему называется TON.

Чек-лист: как не потерять первый депозит на TON

Короткий алгоритм на каждый первый перевод новому кошельку:

  1. Сгенерировали адрес (generate_wallet или свой SDK) — считайте его uninit по умолчанию.
  2. Проверьте состояние через get_account_state: uninit или active.
  3. Если uninit — приведите адрес получателя к UQ через parse_address и шлите первый депозит только на него.
  4. Если active — можно EQ, для контрактов это даже предпочтительнее.
  5. На смарт-контракты всегда шлите bounceable (EQ), чтобы при сбое деньги вернулись.
  6. После пополнения проверьте get_balance — монеты должны лечь на адрес, а не отскочить.
  7. Помните: EQ и UQ — один и тот же кошелёк (один raw-хэш); вы выбираете не адрес, а поведение при неудачной доставке.

Обе ключевые проверки — parse_address (офлайн) и get_account_state (он-чейн) — доступны сразу, без своей инфраструктуры. Возьмите бесплатный ключ Hobby (60 запросов/мин, без карты) и дёргайте оба инструмента прямо из ИИ-агента: https://tonnode.io/dashboard?plan=hobby.

А дальше по той же схеме удобно решать смежные задачи: ловить входящие USDT-платежи на TON, читать баланс USDT одним вызовом или вызывать get-метод контракта без SDK. Форматы адресов — это фундамент, на котором стоит всё остальное: разберётесь с EQ/UQ один раз — и «отскочивший» депозит больше не застанет вас врасплох.

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

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