Розробка індексатора TON Blockchain: парсинг та API

Чому індексація TON потребує іншого підходу? [TON Blockchain](https://en.wikipedia.org/wiki/TON_(blockchain)) — одна з найскладніших блокчейн-платформ для індексації. Причина в архітектурі: infinite sharding — кількість шардів динамічно змінюється залежно від навантаження, від 1 до 256. Транзакці

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1270
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1011

Чому індексація TON потребує іншого підходу?

TON Blockchain — одна з найскладніших блокчейн-платформ для індексації. Причина в архітектурі: infinite sharding — кількість шардів динамічно змінюється залежно від навантаження, від 1 до 256. Транзакції всередині одного шарда фіналізуються швидко, але транзакція між акаунтами в різних шардах — це ланцюжок повідомлень, який потрібно відстежувати через кілька блоків і шардів. Кожне повідомлення серіалізоване в Cell і потребує рекурсивного парсингу. Стандартний підхід «слухаємо блоки по одному» тут не працює. Багато років ми працюємо з блокчейнами, брали участь в аудитах смарт-контрактів TON, індексували дані для великого DeFi-проєкту: понад 2 млн транзакцій на місяць. Індексація TON у 3–5 разів складніша, ніж аналогічне завдання для EVM-ланцюгів, і потребує спеціалізованого пайплайну.

Розробка індексатора для TON вимагає глибокого розуміння TVM (TON Virtual Machine) та BOC-формату. Ми використовуємо бібліотеку @ton/ton версій 0.57+ для роботи з блоками та транзакціями. На відміну від EVM, де кожна транзакція має один in-message, у TON одна транзакція може містити до 255 out-messages, що робить традиційні SQL-моделі неефективними.

Як архітектура TON впливає на індексацію?

TON складається з трьох рівнів:

  • Masterchain — головний ланцюг, фіналізує стан всіх воркчейнів
  • Basechain (workchain 0) — основний користувацький ланцюг
  • Shardchains — шарди workchain-а, їх може бути від 1 до 256

Кожен masterchain блок посилається на останні блоки всіх шардів (ShardStateUnsplit). Для повного індексування потрібно:

  1. Отримати masterchain блок
  2. З нього витягти список актуальних шард-блоків
  3. З кожного шард-блока витягти транзакції
  4. Для кожної транзакції — відстежити дочірні повідомлення (out messages)
MasterBlock[N] └─ Shard(0:0..7fff)[blockX] ├─ tx1 → out_msg → [інший шард або акаунт] └─ tx2 → out_msg → ... └─ Shard(0:8000..ffff)[blockY] └─ tx3 ... 

Hosted API vs власний вузол

Критерій Hosted API Власний вузол
Час до старту Хвилини Дні (збірка, синхронізація)
Навантаження Обмежено тарифом Повний контроль
Історичні дані Обмежений буфер Повний архів
Вартість Від безкоштовного рівня до корпоративних тарифів Витрати на сервер та дискове сховище: дешевше в 3-5 разів при великих обсягах
Складність експлуатації Мінімальна DevOps-інженер у штаті

Hosted API (TonAPI, TON Center, GetBlock) — правильний вибір для MVP. Для high-load продакшену та історичних запитів потрібен свій вузол. Повний архівний вузол TON займає ~2 TB і зростає на ~500 GB на рік. Ми допомагаємо вибрати архітектуру та розгорнути ноду.

Порівняння СУБД для зберігання TON-даних

СУБД Підходить для Особливості
PostgreSQL MVP, до 1 млн tx/день ACID, легке налаштування, обмежена швидкість вставки
TimescaleDB Висока частота запису, часові ряди Автоматичне партиціювання, неперервні агрегати
ClickHouse Аналітика, мільярди рядків Колоночне зберігання, в 5-10 разів швидше за агрегаціями

Що входить у роботу?

  • Проєктування схеми даних: під вашу бізнес-логіку (транзакції, Jetton, NFT, DeFi)
  • Реалізація індексатора на TypeScript/Node.js з використанням @ton/ton
  • Інтеграція з TonAPI або власним вузлом
  • Парсинг довільних повідомлень (op-коди, аргументи контрактів)
  • Трасування транзакцій (trace chain) для аналітики
  • База даних (PostgreSQL, TimescaleDB або ClickHouse для high-load)
  • REST API та WebSocket для клієнтів
  • Моніторинг (відставання, помилки, RPC latency)
  • Документація та навчання команди
  • Обробка форків: зберігання сирих BOC для перепарсингу без втрати даних

Як реалізувати основний цикл індексатора?

class TonIndexer { private client: TonClient4; private db: Pool; private lastMasterBlock: number; async indexLoop(): Promise<void> { while (true) { try { const masterInfo = await this.client.getLastBlock(); const currentSeqno = masterInfo.last.seqno; if (currentSeqno <= this.lastMasterBlock) { await this.sleep(2000); // ~5 сек на блок continue; } for (let seqno = this.lastMasterBlock + 1; seqno <= currentSeqno; seqno++) { await this.processMasterBlock(seqno); } this.lastMasterBlock = currentSeqno; } catch (e) { console.error('Indexer error:', e); await this.sleep(5000); } } } private async processMasterBlock(seqno: number): Promise<void> { const masterBlock = await this.client.getBlock(seqno); await this.processShardTransactions(-1, masterBlock.shards .filter(s => s.workchain === -1) .flatMap(s => s.transactions)); for (const shard of masterBlock.shards.filter(s => s.workchain === 0)) { const transactions = await this.getShardTransactions(shard.workchain, shard.shard, shard.seqno); await this.processShardTransactions(shard.workchain, transactions); } } } 

Парсинг транзакцій та Jetton-переказів

Транзакція TON містить in_msg (причина) та out_msgs (результат). Для Jetton Transfer використовується op-код 0x0f8a7ea5. Приклад вилучення даних:

function parseTransaction(rawTx: RawTransaction): IndexedTransaction { const inMsg = rawTx.inMessage; let opcode: number | undefined; if (inMsg?.body) { const slice = inMsg.body.beginParse(); if (slice.remainingBits >= 32) opcode = slice.loadUint(32); } return { hash: rawTx.hash().toString('hex'), lt: rawTx.lt, account: rawTx.address.toString(), value: inMsg?.info.type === 'internal' ? inMsg.info.value.coins : undefined, opcode, exitCode: rawTx.description.computePhase?.exitCode ?? 0, computeFee: rawTx.totalFees.coins, timestamp: rawTx.now, blockSeqno: rawTx.blockSeqno, }; } 

Якщо потрібне повне трасування транзакцій (наприклад, для DEX-аналітики), використовуємо TonAPI: виклик /v2/traces/{hash} повертає дерево пов'язаних транзакцій. Це дозволяє відстежити весь шлях від виклику користувача до фінальної події.

Схема бази даних для TON-індексатора

CREATE TABLE ton_transactions ( hash CHAR(64) PRIMARY KEY, lt BIGINT NOT NULL, account VARCHAR(66) NOT NULL, block_seqno INTEGER NOT NULL, timestamp TIMESTAMPTZ NOT NULL, in_msg_hash CHAR(64), value NUMERIC(38,0), opcode INTEGER, exit_code SMALLINT NOT NULL, compute_fee NUMERIC(38,0), raw_data BYTEA ); CREATE INDEX idx_ton_tx_account ON ton_transactions(account); CREATE INDEX idx_ton_tx_timestamp ON ton_transactions(timestamp DESC); CREATE INDEX idx_ton_tx_opcode ON ton_transactions(opcode) WHERE opcode IS NOT NULL; CREATE TABLE jetton_transfers ( id BIGSERIAL PRIMARY KEY, tx_hash CHAR(64) REFERENCES ton_transactions(hash), jetton_master VARCHAR(66) NOT NULL, from_address VARCHAR(66) NOT NULL, to_address VARCHAR(66) NOT NULL, amount NUMERIC(38,0) NOT NULL, timestamp TIMESTAMPTZ NOT NULL ); 

Моніторинг та надійність

Ключові метрики: відставання від masterchain (мета — менше 5 блоків), кількість помилок парсингу, RPC latency. Реорганізації в TON рідкісні, але можливі; ми зберігаємо сирі BOC для перепарсингу без повторних запитів.

Отримайте робочий індексатор TON у стислі терміни. Оцінимо навантаження, запропонуємо архітектуру та терміни при зверненні. Гарантуємо документацію, код та підтримку після запуску. Досвід: 5+ років у DeFi, понад 10 успішних індексаторів для різних мереж. Замовте розробку — отримайте готове рішення від 2 тижнів.