Перейти к содержанию
Learning Platform
Глоссарий Troubleshooting
Урок 12.02 · 35 мин
Средний
Asset ProcessingJettonNFTIndexingOff-chainWebhooks

Обработка активов и off-chain индексирование

Обработка активов и off-chain индексирование — это основа для любого приложения, работающего с платежами, токенами или NFT. Блокчейн — это журнал транзакций, но для отображения балансов, истории переводов и уведомлений нужен индексатор, который преобразует raw-данные блоков в структурированные записи.

Production-приложения на TON — биржи, платёжные сервисы, маркетплейсы — не могут полагаться только на on-chain данные. Им необходимо отслеживать события в реальном времени: поступление депозитов, переводы токенов, смену владельца NFT. В этом уроке мы разберём, как устроена обработка активов в TON: от структуры транзакций и 3-message chain Jetton-переводов до стратегий индексирования и best practices.


Структура транзакций TON

Каждая транзакция в TON состоит из нескольких компонентов, важных для off-chain парсинга:

КомпонентОписание
in_msgВходящее сообщение, которое инициировало транзакцию
out_msgsСписок исходящих сообщений, сгенерированных смарт-контрактом
compute_phaseРезультат выполнения кода контракта (exit code, gas used)
action_phaseРезультат применения действий (отправка сообщений, изменение кода)
total_feesСуммарная комиссия за транзакцию
ltLogical time — порядковый номер транзакции аккаунта

Для off-chain мониторинга ключевыми являются in_msg и out_msgs — именно в них закодированы opcodes операций и payload данные.

TIP

Logical time (lt) гарантирует строгий порядок транзакций одного аккаунта. Используйте пару (lt, hash) как курсор при постраничном обходе истории транзакций через getTransactions.


Jetton-переводы: 3-message chain

Перевод Jetton (токена стандарта TEP-74) — это не одна транзакция, а цепочка из трёх сообщений между четырьмя участниками. Это фундаментальное отличие от ERC-20, где перевод — одна транзакция одного контракта.

Архитектура Jetton была подробно рассмотрена в модуле 5 (Стандарты Токенов). Здесь мы сфокусируемся на off-chain обработке этой цепочки.

Поток сообщений

Jetton Transfer: 3-message chain
Отправитель (Alice)
Jetton Wallet (Alice)
Jetton Wallet (Bob)
Получатель (Bob)
1. transfer (op: 0xf8a7ea5)2. internal_transfer (op: 0x178d4519)3. transfer_notification (op: 0x7362d09c)

Opcodes

ШагОперацияOpcodeНаправление
1transfer0xf8a7ea5Отправитель -> его Jetton Wallet
2internal_transfer0x178d4519Jetton Wallet отправителя -> Jetton Wallet получателя
3transfer_notification0x7362d09cJetton Wallet получателя -> контракт получателя

Парсинг transfer_notification

Для off-chain сервиса, принимающего Jetton-депозиты, ключевое сообщение — transfer_notification (шаг 3). Именно его получает ваш контракт или адрес:

// Структура transfer_notification (op: 0x7362d09c)
// query_id:uint64
// amount:Coins        -- количество переведённых Jetton
// sender:MsgAddress   -- адрес отправителя (Alice)
// forward_payload:Cell -- произвольные данные (комментарий, memo)
WARNING

forward_ton_amount — критический параметр. При отправке transfer отправитель указывает forward_ton_amount — количество TON, которое будет приложено к transfer_notification. Если установить 0, уведомление не будет доставлено. Минимум 1 наноTON необходим для доставки notification получателю.

Идентификация отправителя

Важный нюанс: transfer_notification приходит не от Alice напрямую, а от Jetton Wallet получателя (Bob’s Jetton Wallet). Чтобы узнать реального отправителя, нужно прочитать поле sender из payload сообщения.


Мониторинг NFT-событий

NFT в TON (стандарт TEP-62) также используют сообщения для уведомления о событиях. Основные операции для мониторинга:

ownership_assigned

При передаче NFT новому владельцу отправляется уведомление ownership_assigned:

// Структура ownership_assigned (op: 0x05138d91)
// query_id:uint64
// prev_owner:MsgAddress  -- предыдущий владелец
// forward_payload:Cell   -- произвольные данные

Парсинг метаданных NFT

NFT-метаданные в TON хранятся тремя способами:

СпособОписаниеИндикатор
On-chainДанные полностью в Cell смарт-контрактаНет префикса
Off-chainURL в Cell, данные по ссылке (IPFS/HTTPS)Префикс 0x01
Semi-chainЧасть данных on-chain, остальное по ссылкеКомбинация

Для off-chain мониторинга:

// Получение метаданных NFT item
const nftData = await client.nft.getItem(nftAddress);

// Off-chain метаданные: читаем URL из Cell
// Cell начинается с 0x01, далее UTF-8 URL
// Пример: 0x01 + "https://example.com/metadata.json"

Стратегии мониторинга коллекций

СтратегияКогда использовать
Мониторинг CollectionОтслеживание mint новых item в коллекции
Мониторинг отдельных ItemОтслеживание передач конкретных NFT
TonAPI Events APIАгрегированные события по аккаунту (включая NFT)

Подходы к индексированию

Для off-chain обработки событий TON существует три основных подхода, каждый со своими компромиссами.

1. Polling через TON Center

Простейший подход — периодический опрос getTransactions через TON Center API:

// Polling: получение новых транзакций
const transactions = await client.getTransactions(address, {
  limit: 20,
  lt: lastProcessedLt,    // logical time последней обработанной транзакции
  hash: lastProcessedHash, // hash последней обработанной транзакции
});

for (const tx of transactions) {
  // Парсинг in_msg для определения типа операции
  const opcode = tx.inMessage?.body?.beginParse().loadUint(32);

  if (opcode === 0x7362d09c) {
    // transfer_notification -- Jetton депозит
    await processJettonDeposit(tx);
  }
}

2. Webhooks/SSE через TonAPI

TonAPI предоставляет Streaming API для real-time мониторинга:

// SSE: подписка на события аккаунта через TonAPI
const eventSource = new EventSource(
  `https://tonapi.io/v2/sse/accounts/transactions?accounts=${address}`,
  {
    headers: { Authorization: `Bearer ${apiKey}` },
  }
);

eventSource.onmessage = (event) => {
  const tx = JSON.parse(event.data);
  // Обработка транзакции в реальном времени
  processTransaction(tx);
};

TonAPI также поддерживает webhooks — push-уведомления на ваш HTTP endpoint при возникновении событий.

3. Полные индексеры

Для сложных аналитических запросов существуют специализированные индексеры:

  • dton.io — GraphQL API для произвольных запросов по блокчейну
  • TON Center v3 — индексер с фильтрацией и агрегацией

Сравнение подходов

ХарактеристикаPolling (TON Center)Webhooks/SSE (TonAPI)Полный индексер (dton.io)
Задержка5-30 сек (зависит от интервала)< 1 сек< 5 сек
СложностьНизкаяСредняяВысокая
СтоимостьБесплатно (Free tier)Бесплатный tierЗависит от провайдера
Пропущенные событияВозможно при сбоеНет (persistent connection)Нет
Произвольные запросыОграниченыОграниченыGraphQL — любые
Self-hostingДа (TON Center)НетЗависит от решения
TIP

Для большинства dApp комбинация подходит лучше всего: webhooks TonAPI для real-time уведомлений + polling TON Center как fallback для пропущенных событий.


Mintless Jettons

Mintless Jettons — расширение стандарта TEP-74, позволяющее раздать токены без создания отдельных Jetton Wallet контрактов для каждого получателя. Вместо mint-транзакции для каждого адреса используется merkle-proof для подтверждения права на claim.

TIP

Mintless Jettons — сравнительно новый паттерн в TON. Он существенно удешевляет массовые раздачи (airdrops), но требует специальной обработки на стороне off-chain сервисов.

Как это работает

  1. Эмитент формирует merkle-дерево со всеми адресами и суммами
  2. Merkle root публикуется в Jetton Master контракте
  3. Получатель предоставляет merkle-proof при первом claim
  4. Jetton Wallet создаётся только при claim, а не при распределении

Влияние на off-chain обработку

  • Custom Payload API — сервисы должны предоставлять endpoint для генерации merkle-proof по адресу
  • Первая транзакция отличается — claim создаёт Jetton Wallet, последующие переводы идут стандартным 3-message chain
  • Balance может быть “виртуальным” — до claim баланс существует только в merkle-дереве, не в блокчейне

Лучшие практики

Идемпотентная обработка

Каждая транзакция в TON имеет уникальный хеш. Используйте его для дедупликации:

async function processTransaction(tx: Transaction) {
  const txHash = tx.hash;

  // Проверка: уже обработана?
  if (await isProcessed(txHash)) {
    return; // Пропускаем дубликат
  }

  // Обработка
  await handleTransaction(tx);

  // Отметка как обработанная
  await markProcessed(txHash);
}

Глубина подтверждения

В TON транзакция считается финальной после включения в masterchain block. На практике:

  • Транзакция в workchain подтверждается за 2-5 секунд в сети сейчас (legacy Catchain); с Catchain 2.0 (запуск Q1 2026) — за сотни миллисекунд (200–400 мс блок)
  • Для критических операций (крупные депозиты) рекомендуется ждать подтверждения в masterchain — это гарантирует необратимость
WARNING

Не полагайтесь на транзакцию в workchain до её подтверждения в masterchain. Хотя chain reorgs в TON крайне редки, для финансовых операций всегда ждите masterchain confirmation.

Обработка ошибок и ретраи

  1. Exponential backoff при ошибках API (429, 500, 503)
  2. Dead letter queue для транзакций, которые не удалось обработать после N попыток
  3. Alerting при нарушении SLA (задержка обработки > порога)

Мониторинг и алертинг

Ключевые метрики для production-мониторинга:

МетрикаПорог для алерта
Задержка обработки (lag)> 60 сек
Ошибки парсинга> 0 за 5 мин
Пропущенные транзакции> 0
API rate limit hits> 10 за минуту
Размер очереди необработанныхРастёт > 5 мин

Ключевые выводы

  1. Jetton-перевод — это 3 сообщения, а не одна транзакция: transfer (0xf8a7ea5) -> internal_transfer (0x178d4519) -> transfer_notification (0x7362d09c).
  2. Для приёма Jetton-депозитов слушайте transfer_notification — именно его получает контракт получателя. Не забудьте указать forward_ton_amount >= 1 наноTON.
  3. Три подхода к индексированию: polling (простой), webhooks/SSE (real-time), полные индексеры (аналитика). Комбинируйте для надёжности.
  4. Mintless Jettons используют merkle-proof для mass distribution без предварительного создания Jetton Wallet — требуют специальной обработки.
  5. Всегда реализуйте идемпотентную обработку с дедупликацией по хешу транзакции.
  6. Ждите подтверждения в masterchain для финансово критических операций.

Частые ошибки

  1. Определяют зачисление по одной транзакции вместо отслеживания всей цепочки сообщений: Jetton-перевод включает несколько транзакций.
  2. Не обрабатывают реорганизации (forks): блок может быть заменён, и транзакция, которую вы уже обработали, окажется невалидной.
  3. Используют polling с фиксированным интервалом вместо long polling или webhooks, что либо создаёт задержку, либо перегружает API.
  4. Не сохраняют lt (logical time) и hash последнего обработанного блока: при перезапуске сервиса повторно обрабатывают все транзакции.

Проверка знанийKnowledge check
Какой opcode получает контракт получателя при Jetton-переводе, и почему важно установить forward_ton_amount минимум в 1 наноTON?
ОтветAnswer
Контракт получателя получает transfer_notification с opcode 0x7362d09c -- третье сообщение в 3-message chain. Параметр forward_ton_amount определяет, сколько TON будет приложено к этому уведомлению. Если установить 0, transfer_notification не будет доставлен получателю, и off-chain сервис не узнает о переводе. Минимум 1 наноTON необходим для доставки notification.

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4