Система агрегації даних з блокчейнів: архітектура та реалізація

Система агрегації даних з блокчейнів: архітектура та реалізація Задача виглядає просто: «збирати дані з кількох блокчейнів». На практиці це одна з найскладніших технічних задач у Web3-інфраструктурі. Кожна мережа — це окрема модель даних, власна логіка фіналізації, свій RPC API, свої rate limits

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

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

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1452
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1310
  • 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
    1012

Система агрегації даних з блокчейнів: архітектура та реалізація

Задача виглядає просто: «збирати дані з кількох блокчейнів». На практиці це одна з найскладніших технічних задач у Web3-інфраструктурі. Кожна мережа — це окрема модель даних, власна логіка фіналізації, свій RPC API, свої rate limits та специфічні помилки. Ethereum живе в UTC з ~12-секундними блоками, Solana видає ~400ms слоти та вважає підтвердження інакше, TON має шардовану архітектуру, де «блок» — поняття умовне. Зібрати все це в єдиний API з консистентними даними — нетривіальна інженерна задача.

Наша команда має понад 5 років досвіду в розробці блокчейн-інфраструктури та реалізувала агрегатори для 15+ мереж. Ми знаємо всі підводні камені: від неочевидних реорганізацій до економії на RPC-викликах. Гарантуємо стабільність роботи 99.9% та готові оцінити ваш проєкт безкоштовно.

Які складнощі виникають при уніфікації даних з різних мереж?

Різні моделі даних

EVM-мережі (Ethereum, Arbitrum, Polygon, BSC) мають спільну модель: блоки, транзакції, receipts з logs. Але навіть тут є відмінності:

  • Arbitrum додає l1BlockNumber та специфічні системні транзакції (sequencer batch submissions)
  • Optimism/Base мають depositedTx тип для L1→L2 транзакцій, які не мають стандартного from
  • zkSync Era використовує Native AA — немає поділу на EOA та контракти, всі акаунти контракти

Solana взагалі інша парадигма: немає «транзакція викликала метод контракту» — є «інструкції в транзакції передалися програмам». Для декодування потрібен ABI аналог — IDL (Interface Definition Language, формат Anchor).

UTXO-моделі (Bitcoin, Litecoin) принципово відрізняються: немає балансів акаунтів, є unspent outputs. «Баланс адреси» — це сума всіх UTXO, де ця адреса є output.

Різна семантика фіналізації

Мережа Механізм Фіналізація
Ethereum PoS + Casper FFG ~15 хв (finalized checkpoint)
Arbitrum One Optimistic Rollup ~7 днів (fraud proof window) для L1 finality
Polygon PoS Heimdall checkpoints ~30 хв для Ethereum finality
Solana Tower BFT ~12-32 слоти (~6–16 сек)
Bitcoin PoW 6 підтверджень (~60 хв) — конвенційний стандарт

Якщо система не враховує це, дані будуть некоректні: транзакція здаватиметься «фінальною» за кількістю підтверджень, але виявиться реорганізованою.

Архітектура системи агрегації

Шар колекторів (Chain Collectors)

Кожен колектор — ізольований сервіс, що відповідає за одну мережу. Спільний інтерфейс:

interface ChainCollector { getLatestBlock(): Promise<UnifiedBlock>; getBlockRange(from: bigint, to: bigint): Promise<UnifiedBlock[]>; getTransactionsByAddress(address: string, fromBlock: bigint): Promise<UnifiedTx[]>; subscribeNewBlocks(callback: (block: UnifiedBlock) => void): Unsubscribe; } 

Уніфіковані типи нормалізують специфіку кожної мережі:

interface UnifiedTx { chain: ChainId; hash: string; blockNumber: bigint; timestamp: number; // unix from: string; // normalized lowercase hex для EVM, base58 для Solana to: string | null; value: bigint; // в найменших одиницях нативного токена status: 'success' | 'failed' | 'pending'; finality: 'unconfirmed' | 'safe' | 'finalized'; raw: unknown; // оригінальні дані мережі } 

Управління нодами та провайдерами

Проблема: публічні RPC ненадійні, rate limits непередбачувані, Alchemy/Infura дорожчають з масштабом.

Стратегія: tiered provider pool

Primary: Власні ноди (Geth+Lighthouse, Reth для архіву) ↓ failover Secondary: Alchemy / QuickNode (premium tier) ↓ failover Tertiary: Infura / публічні RPC (тільки для некритичних запитів) 

Circuit breaker на кожному провайдері: якщо error rate > 5% за 60 сек або latency > 2x p99 baseline — вимикаємо провайдер з rotation, health check кожні 30 сек.

Для архівних даних (історичні блоки > 128 blocks назад на Ethereum) потрібна archive node — це окрема історія. Erigon займає ~3TB для повного Ethereum архіву, Reth трохи менше. Для більшості проєктів дешевше використовувати Alchemy Archive або QuickNode Archive ніж тримати власну ноду.

Чому важлива власна нода або пул провайдерів?

Надійність RPC безпосередньо впливає на консистентність даних. Без резервування ви ризикуєте отримати лаги в зборі даних або втрату блоків при реоргах. Власні ноди знижують витрати в довгостроковій перспективі: кожен RPC-виклик коштує грошей, а при мільйонах транзакцій економія може скласти до 50% від бюджету на інфраструктуру. Ми рекомендуємо tiered підхід для балансу вартості та надійності.

Шар нормалізації та трансформації

Сирі блокчейн-дані рідко потрібні в початковому вигляді. Типові трансформації: Декодування ERC-20 Transfer подій

const ERC20_TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; function decodeTransfer(log: Log): TokenTransfer | null { if (log.topics[0] !== ERC20_TRANSFER_TOPIC) return null; return { token: log.address, from: `0x${log.topics[1].slice(26)}`, to: `0x${log.topics[2].slice(26)}`, amount: BigInt(log.data), }; } 

Збагачення даними токена: для кожного log.address потрібно знати symbol, decimals, USD price. Кешуємо metadata токенів в Redis з TTL 24h, ціни оновлюємо кожні 30 сек з CoinGecko/CoinMarketCap.

Агрегація cross-chain: якщо потрібно показати «сумарний баланс адреси у всіх мережах в USD», потрібно нормалізувати різні decimals, конвертувати через price feeds, обробити wrapped-версії одного токена (USDC на Ethereum ≠ USDC.e на Arbitrum).

Шар зберігання

Для hot даних (останні 7–30 днів): PostgreSQL з партиціонуванням по chain_id + даті. Індекси на (chain_id, address, block_number) та (chain_id, tx_hash). TimescaleDB гіпертаблиці, якщо даних багато — автоматична компресія старих партицій.

Для cold даних (архів): ClickHouse — колончаста БД, на порядок ефективніша за PostgreSQL для аналітичних запитів по великих періодах. Запит «всі транзакції USDC > $10k за минулий рік по всіх EVM мережах» на 100M+ рядках — ClickHouse дасть результат за секунди, PostgreSQL — за хвилини.

Для пошуку за адресами/хешами: ElasticSearch або просто PostgreSQL з LIKE — для точних збігів достатньо hash-індексу.

Як забезпечити консистентність даних при реорганізації блоків?

Це найскладніше місце в системі. Алгоритм:

  1. Кожен блок зберігаємо з прапорцем is_canonical = true та parent_hash
  2. Новий блок з тим же block_number але іншим hash — потенційний реорг
  3. Йдемо по parent_hash назад до знаходження спільного предка
  4. Всі блоки на «старій» гілці позначаємо is_canonical = false, додаємо блоки «нової» гілки
  5. Дані у вихідному API завжди фільтруються за is_canonical = true
  6. Webhooks/downstream системи отримують події tx.orphaned для відкликаних транзакцій

Для Ethereum глибина реоргу вкрай рідко > 2 блоків post-Merge. Для Polygon PoS — бачили реорги на 30+ блоків. Буфер спостереження: 128 блоків для EVM мереж.

Згідно зі специфікацією Ethereum після Merge, глибина реорганізації рідко перевищує 2 блоки.

API шар

REST + WebSocket для real-time:

GET /v1/address/{address}/transactions?chains=eth,arb,polygon&limit=50 GET /v1/tx/{chain}/{hash} GET /v1/address/{address}/token-balances?chains=eth,bsc WS /v1/subscribe?address={addr}&chains=eth,arb&events=transfer,swap 

GraphQL зручний, якщо клієнтам потрібна гнучкість у запитах: один запит отримує транзакції + баланси + metadata токенів. Але додає складність на бекенді — N+1 проблеми, потрібен DataLoader.

Rate limiting: per-API-key, sliding window, окремі ліміти для REST та WebSocket (WebSocket connections дорожчі). Redis + Lua script для атомарних інкрементів.

Моніторинг та операційна робота

Критичні метрики:

  • Collector lag — різниця між latest block timestamp в мережі та часом обробки цього блоку. Alert при lag > 2 хвилин.
  • Reorg depth — максимальна глибина реоргу за останні 24h. Alert при depth > 10.
  • RPC error rate — по кожному провайдеру та методу. Alert при > 1%.
  • Queue depth — якщо обробник не встигає за колектором, черга зростає. Alert при depth > 10k повідомлень.

Grafana дашборд з per-chain панелями: поточний блок, lag, TPS, error rate.

Деталі реалізації моніторингуВикористовуємо Prometheus для збору метрик та PagerDuty для алертів. На кожен колектор налаштовані health checks, у випадку недоступності ноди автоматично перемикаємося на резервного провайдера.

Стек

Компонент Технологія
Колектори Node.js (viem/ethers) + Go для високонавантажених мереж
Черга Apache Kafka (високий throughput) або RabbitMQ (moderate)
Hot storage PostgreSQL 15 + TimescaleDB
Cold storage ClickHouse
Cache Redis Cluster
API Node.js (Fastify) або Go (Fiber)
Monitoring Prometheus + Grafana + PagerDuty
Оркестрація Kubernetes з HPA на колекторах

Що входить до проєкту

  1. Архітектурна схема системи
  2. Вихідний код колекторів та API
  3. Документація з розгортання та експлуатації
  4. Моніторинг та алерти (Grafana дашборди)
  5. Технічна підтримка 2 місяці
  6. Навчання команди замовника

Терміни MVP (3–4 EVM мережі, без архіву, REST API): 8–12 тижнів. Повна система з 10+ мережами, ClickHouse, WebSocket, моніторингом — 5–7 місяців.

Економія на RPC-провайдерах за рахунок оптимізації запитів та власних нод може скласти до 50%.

Зв'яжіться з нами, щоб обговорити ваш проєкт. Оцінимо терміни та вартість безкоштовно. Отримайте консультацію протягом дня. Замовте розробку системи агрегації під ключ.