Система агрегації даних з блокчейнів: архітектура та реалізація
Задача виглядає просто: «збирати дані з кількох блокчейнів». На практиці це одна з найскладніших технічних задач у 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-індексу.
Як забезпечити консистентність даних при реорганізації блоків?
Це найскладніше місце в системі. Алгоритм:
- Кожен блок зберігаємо з прапорцем is_canonical = true та parent_hash
- Новий блок з тим же block_number але іншим hash — потенційний реорг
- Йдемо по parent_hash назад до знаходження спільного предка
- Всі блоки на «старій» гілці позначаємо is_canonical = false, додаємо блоки «нової» гілки
- Дані у вихідному API завжди фільтруються за is_canonical = true
- 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 на колекторах |
Що входить до проєкту
- Архітектурна схема системи
- Вихідний код колекторів та API
- Документація з розгортання та експлуатації
- Моніторинг та алерти (Grafana дашборди)
- Технічна підтримка 2 місяці
- Навчання команди замовника
Терміни MVP (3–4 EVM мережі, без архіву, REST API): 8–12 тижнів. Повна система з 10+ мережами, ClickHouse, WebSocket, моніторингом — 5–7 місяців.
Економія на RPC-провайдерах за рахунок оптимізації запитів та власних нод може скласти до 50%.
Зв'яжіться з нами, щоб обговорити ваш проєкт. Оцінимо терміни та вартість безкоштовно. Отримайте консультацію протягом дня. Замовте розробку системи агрегації під ключ.







