Поток перевода Jetton
Поток перевода Jetton — это цепочка из 3-4 сообщений между контрактами, и непонимание этого потока приводит к потере токенов, неправильному отображению балансов и ошибкам интеграции. Подобно банковскому переводу, где деньги проходят через несколько этапов (списание, клиринг, зачисление, уведомление), Jetton-перевод включает burn у отправителя, mint у получателя и уведомление конечного контракта.
В предыдущем уроке мы разобрали архитектуру Jetton 2.0: Jetton Master + отдельный Jetton Wallet для каждого пользователя. Теперь разберём, как именно происходит перевод токенов между двумя пользователями — это цепочка из 4 сообщений, каждое в отдельной транзакции.
Интерактивная диаграмма
Переключайтесь между вкладками, чтобы увидеть архитектуру, поток перевода и минтинг:
4 шага перевода Jetton
Когда User A хочет перевести токены User B, происходит следующая цепочка сообщений:
User A Jetton Wallet A Jetton Wallet B User B
| | | |
|-- 1. transfer ------->| | |
| (0xf8a7ea5) | | |
| |-- 2. internal_ ---->| |
| | transfer | |
| | |-- 3. transfer -->|
| | | _notification |
| | | (0x7362d09c) |
|<----------- 4. excesses (0xd53276db) -------| |
| | | |
Рассмотрим каждый шаг подробно.
Шаг 1: transfer (0xf8a7ea5)
User A отправляет сообщение в свой Jetton Wallet A (не напрямую получателю!):
| Поле | Описание |
|---|---|
destination | Адрес TON-кошелька User B |
amount | Количество токенов для перевода |
response_destination | Куда вернуть неиспользованный TON (обычно = User A) |
forward_ton_amount | Сколько TON переслать User B вместе с уведомлением |
forward_payload | Произвольные данные для User B (например, комментарий к платежу) |
Jetton Wallet A уменьшает свой баланс на amount и формирует следующее сообщение.
User A отправляет transfer в свой Jetton Wallet, а не в Jetton Wallet получателя. Это ключевое отличие от ERC-20, где transfer(to, amount) вызывается на контракте токена. В TON каждый пользователь взаимодействует только со своим Jetton Wallet.
Шаг 2: internal_transfer
Jetton Wallet A отправляет internal_transfer в Jetton Wallet B:
| Поле | Описание |
|---|---|
amount | Количество переводимых токенов |
from | Адрес TON-кошелька User A (отправитель) |
response_destination | Куда вернуть excesses |
forward_ton_amount | Сколько TON переслать получателю |
forward_payload | Данные для получателя |
Jetton Wallet B увеличивает свой баланс на amount. Если Jetton Wallet B не существовал ранее, он будет развёрнут автоматически — именно поэтому отправитель должен приложить достаточно TON для покрытия газа деплоя.
Шаг 3: transfer_notification (0x7362d09c)
Jetton Wallet B отправляет уведомление User B (получателю):
| Поле | Описание |
|---|---|
query_id | Идентификатор запроса (для отслеживания) |
amount | Количество полученных токенов |
sender | Адрес отправителя (User A) |
forward_payload | Данные от отправителя |
Это уведомление опционально — оно отправляется только если forward_ton_amount > 0. Смарт-контракты используют transfer_notification для реагирования на входящие токены (например, DEX обрабатывает swap при получении Jetton).
Шаг 4: excesses (0xd53276db)
Jetton Wallet B возвращает неиспользованный TON на response_destination (обычно User A):
Отправитель (User A) должен приложить достаточно TON для оплаты всей цепочки из 4 транзакций. Excesses-сообщение гарантирует, что лишние средства вернутся.
Всегда указывайте response_destination = адрес отправителя. Если не указать, неиспользованный TON останется на Jetton Wallet B и будет потерян. Для gas recovery это критично — цепочка из 4 транзакций может стоить 0.05-0.15 TON в зависимости от нагрузки сети.
Газ и forward_ton_amount
Правильная оценка газа — ключевой аспект Jetton-переводов:
Если User A приложит недостаточно TON, одна из транзакций в цепочке не будет выполнена из-за нехватки газа.
Bounce-обработка
Что происходит, если транзакция в цепочке не может быть выполнена?
Сценарий: Jetton Wallet B не может принять internal_transfer
Если internal_transfer bounced (отскочил), Jetton Wallet A получает bounce-сообщение и восстанавливает свой баланс. Токены не теряются — они возвращаются отправителю.
Это важнейший механизм безопасности Jetton 2.0:
- Jetton Wallet A уменьшил баланс и отправил internal_transfer
- Jetton Wallet B не смог обработать (ошибка, нехватка газа)
- TON отправляет bounce-сообщение обратно в Jetton Wallet A
- Jetton Wallet A обрабатывает bounce и прибавляет токены обратно
Bounce-обработка в Jetton — это реализация паттерна, который мы разбирали в M03, урок 05 (Messages и Bouncing). Каждый Jetton Wallet обязан обрабатывать bounced internal_transfer, восстанавливая баланс отправителя.
Opcodes: справочник
| Opcode | Hex | Сообщение | Направление |
|---|---|---|---|
| transfer | 0xf8a7ea5 | Инициация перевода | User -> свой Jetton Wallet |
| internal_transfer | - | Межкошельковый перевод | Jetton Wallet A -> Jetton Wallet B |
| transfer_notification | 0x7362d09c | Уведомление получателя | Jetton Wallet B -> User B |
| excesses | 0xd53276db | Возврат газа | Jetton Wallet B -> response_destination |
| burn | 0x595f07bc | Сжигание токенов | User -> свой Jetton Wallet |
| burn_notification | 0x7bdd97de | Уведомление о сжигании | Jetton Wallet -> Jetton Master |
Практическое значение
Понимание потока перевода Jetton необходимо для:
- Разработки DEX: DEX-контракт реагирует на
transfer_notificationдля обработки swap-запросов - Оценки газа: правильный расчёт прикреплённых TON для всей цепочки
- Отладки: отслеживание 4 транзакций в эксплорере при проблемах с переводом
- Безопасности: корректная обработка bounce-сообщений предотвращает потерю токенов
Частые ошибки
- Не отправляют forward_ton_amount при переводе, из-за чего получатель не получит уведомление (transfer_notification) и не узнает о входящем переводе.
- Путают transfer и internal_transfer: transfer инициируется владельцем кошелька, а internal_transfer — это внутреннее сообщение между Jetton Wallet контрактами.
- Не обрабатывают excesses: после успешного перевода неизрасходованные TON отправляются на response_destination; если он не указан, TON теряются.
- Считают перевод завершённым после отправки transfer, хотя на самом деле нужно дождаться подтверждения всей цепочки сообщений.
Проверка знанийПочему User A отправляет transfer в свой Jetton Wallet, а не напрямую получателю?
Проверьте понимание
Закончили урок?
Отметьте его как пройденный, чтобы отслеживать свой прогресс
Войдите чтобы оценить урок