DeFi-протокол втратив $600,000 через маніпуляцію ціною за допомогою флеш-кредиту. Причина — єдиний оракул. Ми розробляємо агрегатор курсів криптовалют, який вирішує цю проблему: збирає дані з 5+ джерел (Binance, OKX, Bybit, Kraken, Uniswap) та застосовує TWAP-фільтрацію. BTC/USDT на Binance відрізняється від Bybit, OKX, Kraken та від on-chain ціни в Uniswap пулі. Агрегатор обчислює єдиний «справедливий» курс або показує розкид для прайсингу в платіжних системах, відображення в гаманцях, арбітражних стратегій, риск-менеджменту, DeFi оракулів. Наш агрегатор обробляє десятки торгових пар з оновленням кожні 100 мс — критично важливо для арбітражу та ліквідності.
Розробник агрегатора: "TWAP-фільтрація запобігає маніпуляціям, які коштують мільйони."
Як розробляється агрегатор курсів криптовалют?
Єдиний оракул — точка відмови. Агрегатор курсів криптовалют знижує ризики маніпуляції, комбінуючи дані CEX та DEX з верифікацією через TWAP. Це запобігає втратам, які можуть сягати мільйонів доларів, як у випадку відомих flash loan атак.
Основні складнощі: синхронізація даних з різною затримкою (10 мс для CEX, 12-15 сек для DEX), захист від флеш-кредитних атак на пули, виявлення аномалій курсів. Ми вирішуємо їх через комбінацію VWAP та медіани з динамічним відкиданням викидів.
Як збираються дані з різних бірж?
Кожна біржа — окремий колектор з перепідключенням при розриві. Використовуємо TypeScript та подієву модель на Node.js.
import WebSocket from 'ws'; import { EventEmitter } from 'events'; interface PriceEvent { source: string; pair: string; // 'BTC/USDT' price: number; volume24h: number; timestamp: number; // ms } class BinanceCollector extends EventEmitter { private ws: WebSocket | null = null; private pairs: string[]; private reconnectTimer: NodeJS.Timeout | null = null; constructor(pairs: string[]) { super(); this.pairs = pairs; } connect() { const streams = this.pairs .map(p => `${p.replace('/', '').toLowerCase()}@ticker`) .join('/'); this.ws = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${streams}`); this.ws.on('message', (data: string) => { const msg = JSON.parse(data); if (msg.stream && msg.data) { const ticker = msg.data; this.emit('price', { source: 'binance', pair: this.normalizePair(ticker.s), price: parseFloat(ticker.c), volume24h: parseFloat(ticker.v) * parseFloat(ticker.c), timestamp: ticker.E, } as PriceEvent); } }); this.ws.on('close', () => { this.reconnectTimer = setTimeout(() => this.connect(), 5000); }); this.ws.on('error', (err) => { console.error('Binance WS error:', err.message); }); } private normalizePair(symbol: string): string { const quoteAssets = ['USDT', 'USDC', 'BTC', 'ETH', 'BNB']; for (const quote of quoteAssets) { if (symbol.endsWith(quote)) { return `${symbol.slice(0, -quote.length)}/${quote}`; } } return symbol; } } Аналогічні колектори для OKX, Bybit, Kraken. Для кожного джерела налаштовані автоматичні перепідключення та логування помилок.
On-chain ціни з Uniswap V3
Spot ціна з пулу — sqrtPriceX96. Декодування за допомогою viem:
import { createPublicClient, http } from 'viem'; import { mainnet } from 'viem/chains'; const UNISWAP_V3_POOL_ABI = [ { name: 'slot0', type: 'function', inputs: [], outputs: [ { name: 'sqrtPriceX96', type: 'uint160' }, { name: 'tick', type: 'int24' }, ], stateMutability: 'view', } ] as const; async function getUniswapPrice(poolAddress: string): Promise<number> { const slot0 = await client.readContract({ address: poolAddress as `0x${string}`, abi: UNISWAP_V3_POOL_ABI, functionName: 'slot0', }); const sqrtPriceX96 = BigInt(slot0.sqrtPriceX96); // price = (sqrtPriceX96 / 2^96)^2 * (10^token0Decimals / 10^token1Decimals) const price = Number((sqrtPriceX96 ** 2n * BigInt(1e18)) / (2n ** 192n)) / 1e18; return price; } TWAP з Uniswap V3 надійніше spot-ціни — маніпуляція вимагає утримання великого обсягу в пулі протягом кількох блоків. Для оракулів використовуємо TWAP за 30 хвилин.
Які методи агрегації ми застосовуємо?
Просте середнє — поганий агрегатор: одне джерело з помилковою ціною тягне середнє в сторону. Використовуємо комбінацію:
| Метод | Стійкість до викидів | Коли застосовувати |
|---|---|---|
| VWAP (зважене за обсягом) | Середня | Високоліквідні пари, CEX-джерела |
| Медіана | Висока | 5+ джерел, DeFi-аналітика |
| Відкидання викидів + медіана | Дуже висока | Завжди, як базовий фільтр |
VWAP розраховується як сума цін, зважених за обсягом. Медіана стійка до викидів. Виявлення аномалій — обов'язкове: відкидаємо ціни, що відхиляються від медіани більше ніж на 2%.
import statistics def filter_outliers(prices: list[float], threshold: float = 0.02) -> list[float]: median = statistics.median(prices) return [p for p in prices if abs(p - median) / median <= threshold] def vwap(prices: list[dict]) -> float: total_volume = sum(p['volume24h'] for p in prices) if total_volume == 0: return sum(p['price'] for p in prices) / len(prices) return sum(p['price'] * p['volume24h'] for p in prices) / total_volume Порівняння джерел: CEX vs DEX
| Параметр | CEX (Binance, OKX) | DEX (Uniswap V3) |
|---|---|---|
| Затримка | ~10-50 мс | ~12-15 сек (блок) |
| Обсяг | Високий, до $1B+ на день | Середній, залежить від пулу |
| Маніпуляція | Можлива через спред | Складніше, потребує флеш-кредитів |
| Надійність | Залежить від API біржі | Залежить від блокчейну |
Вибір між CEX та DEX залежить від вимог до затримки та стійкості. Для реального часу (трейдинг) кращі CEX, для DeFi-оракулів — DEX з TWAP.
Як ми забезпечуємо відмовостійкість?
- Circuit breaker: якщо джерело видає помилки > 5 разів за 30 секунд — відключаємо на 60 секунд.
- Staleness check: якщо дані не оновлювалися > 30 секунд — виключаємо з агрегації.
- Minimum sources: при активних джерелах < 2 повертаємо помилку замість невірного курсу.
- Метрики Prometheus:
price_sources_active,price_update_latency_ms,price_deviation_percent— алерт при аномаліях.
Всі компоненти контейнеризовані (Docker) та оркестровані через Docker Compose або Kubernetes. Кожен колектор запускається в окремому контейнері, агрегатор — в одному екземплярі з підтримкою горизонтального масштабування через Redis Pub/Sub. Для моніторингу використовуємо Prometheus та Grafana. Розгортання автоматизоване через CI/CD (GitLab CI).
Приклад архітектури
Агрегатор складається з: колекторів (по одному на джерело), ядра агрегації (Python, Redis), API-сервера (FastAPI) та дашборду (Grafana). Все упаковано в контейнери.Процес розробки: від проектування до продакшену
- Проектування (2-3 дні): узгоджуємо список пар та джерел, вимоги до latency, схему зберігання.
- Колектори (3-4 дні): розробка та тестування кожного джерела, нормалізація формату.
- Агрегація (2-3 дні): вибір алгоритму зважування, outlier detection, Redis зберігання.
- API (2-3 дні): REST + WebSocket, документація, rate limiting.
- Навантажувальне тестування (1-2 дні): 100+ пар одночасно, поведінка при втраті джерела.
Загалом 1-2 тижні для агрегатора з 3-5 джерелами та 50+ торговими парами.
Що входить в роботу
- Архітектурна документація (схеми, опис потоків)
- Репозиторій з вихідним кодом (колектори, агрегатор, API)
- Документація API (Swagger/OpenAPI)
- Звіт про навантажувальне тестування
- Скрипти для розгортання (Docker Compose/K8s маніфести)
- Інструкція по запуску та моніторингу
- Навчання команди (1-2 години)
Типові помилки при розробці агрегатора
- Використання лише spot-ціни замість TWAP — вразливість до флеш-кредитних атак.
- Відсутність outlier detection — одна помилкова ціна спотворює все середнє.
- Немає circuit breaker — при падінні біржового API агрегатор зависає.
- Занадто малий пул джерел (<3) — знижує надійність.
Уникнувши цих помилок, ви отримаєте стійкий до маніпуляцій агрегатор курсів криптовалют. Наш досвід: 10+ років у розробці блокчейн-рішень, 50+ проектів з криптовалютами, 5 років на ринку. Гарантуємо стабільну роботу агрегатора.
Зв'яжіться з нами для оцінки вашого проекту. Отримайте консультацію інженера та замовте розробку агрегатора курсів криптовалют, який захистить ваш проект.







