Мониторинг событий контракта (вебхуки/поллинг)

Настроишь отслеживание транзакций контракта: polling через TonAPI и вебхуки TonAPI Webhooks API.

Задача мониторинга

Контракт не «пушит» события в твой бэкенд сам. Ты либо периодически читаешь новые транзакции/события (polling), либо подписываешься на доставку (webhooks). Для продукта обычно: webhook как primary + polling/replay для дыр.


Polling через TonAPI

Храни lastLt (или event_id) и забирай только хвост:

typescript
// TonAPI v2 — polling account events
// ключ: tonconsole.com
const accountId = "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N"; // mainnet example

async function fetchEvents(accountId: string, beforeLt?: number) {
  const url = new URL(`https://tonapi.io/v2/accounts/${accountId}/events`);
  url.searchParams.set("limit", "50");
  // omit before_lt → самые свежие; иначе — страница старше курсора
  if (beforeLt != null) url.searchParams.set("before_lt", String(beforeLt));

  const res = await fetch(url, {
    headers: {
      Authorization: `Bearer ${process.env.TONAPI_KEY}`,
      Accept: "application/json",
    },
  });

  if (res.status === 429) {
    throw new Error("rate limited — backoff");
  }
  if (!res.ok) {
    throw new Error(`TonAPI ${res.status}`);
  }

  return res.json() as Promise<{
    events: Array<{ event_id: string; lt: number; actions: unknown[] }>;
  }>;
}

// первичная загрузка + пагинация назад по lt
const page = await fetchEvents(accountId);
for (const ev of page.events) {
  // идемпотентная обработка по event_id
  console.log(ev.event_id, ev.actions);
}
const oldestLt = page.events.at(-1)?.lt;
if (oldestLt != null) {
  const older = await fetchEvents(accountId, oldestLt);
  console.log("older page", older.events.length);
}

Интервал и лимиты подбирай под тариф; при 429 — exponential backoff (см. rate limit).


Вебхуки TonAPI

Webhooks API — private API key обязателен. Base: https://rt.tonapi.io.

  1. Создай webhook с публичным HTTPS endpoint:
bash
# TonAPI Webhooks API
curl -s -X POST "https://rt.tonapi.io/webhooks" \
  -H "Authorization: Bearer $TONAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endpoint":"https://api.example.com/ton/hooks/account-tx"}'
# → { "id": 123, ... }
  1. Подпиши аккаунт (raw-адрес предпочтителен):
bash
curl -s -X POST "https://rt.tonapi.io/webhooks/123/account-tx/subscribe" \
  -H "Authorization: Bearer $TONAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accounts": [
      "0:83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8"
    ]
  }'

Когда на аккаунте появляется транзакция, TonAPI шлёт POST на твой endpoint с account_id, tx_hash, lt. Дальше сам дочитай детали:

typescript
// обработчик webhook → дочитываем tx/event
export async function handleAccountTx(body: {
  account_id: string;
  tx_hash: string;
  lt: number;
}) {
  const res = await fetch(
    `https://tonapi.io/v2/blockchain/transactions/${body.tx_hash}`,
    {
      headers: { Authorization: `Bearer ${process.env.TONAPI_KEY}` },
    },
  );
  const tx = await res.json();
  // обработка + идемпотентность по tx_hash
  return tx;
}

Testnet webhooks: https://rt-testnet.tonapi.io.

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

  • Polling — простой и предсказуемый; платишь запросами и задержкой до interval.
  • Webhooks — push по подписке; нужна проверка доступности URL и идемпотентность (повторные доставки бывают).
  • Payload вебхука короткий — полный разбор через REST после сигнала.
  • Для оплаты/зачисления не доверяй одному push: сверяй on-chain состояние (get-метод / баланс) перед финализацией в БД.

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

Публичный HTTP endpoint без TLS / за NAT → вебхуки не доезжают. Нужен стабильный HTTPS с валидным сертификатом.

Обрабатываешь одно и то же tx_hash дважды → дубли в БД. Ключ идемпотентности: tx_hash или event_id.

Только webhook, без replay → пропустил простой webhook'а — дыра в истории. Храни last_lt и периодически догоняй через polling.


Что дальше

Материалы gramdocs.tech носят образовательный характер и не являются финансовой, юридической или инвестиционной рекомендацией. Работа с блокчейном TON и токеном Gram связана с рисками потери средств. Правовая информация