Интеграция с Bitquery API
Bitquery — GraphQL API поверх индексированных данных более 40 блокчейнов. Привлекает разработчиков тем, что снимает необходимость разворачивать собственные ноды и писать indexer для каждой сети. На практике интеграция выходит сложнее, чем обещает документация: rate limits, различия в схемах между V1 и V2 (EAP), особенности запросов к DEX-данным — всё это требует понимания нюансов перед тем, как строить production-систему.
V1 vs V2 (EAP): принципиальные отличия
Bitquery развивает две параллельные версии API. V1 (api.bitquery.io) — старая, с широкой поддержкой сетей. V2 (streaming.bitquery.io, EAP — Early Access Program) — новая архитектура с поддержкой WebSocket-подписок для real-time данных.
Для новых проектов стоит сразу ориентироваться на V2, если нужные сети поддерживаются. V1 уходит в режим поддержки без активной разработки.
# V2: подписка на новые свапы Uniswap V3 в реальном времени
subscription {
EVM(network: eth) {
DEXTrades(
where: {
Trade: { Dex: { ProtocolName: { is: "uniswap_v3" } } }
}
) {
Block { Time Number }
Trade {
Buy { Amount Currency { Symbol Address } }
Sell { Amount Currency { Symbol Address } }
Dex { PoolAddress }
}
}
}
}
Типовые задачи и запросы
Мониторинг DEX-торговли
Задача получить историю торгов по конкретной паре на Uniswap V3 с OHLCV агрегацией:
query DEXOHLCVQuery($since: ISO8601DateTime!, $poolAddress: String!) {
EVM(network: eth, dataset: archive) {
DEXTradeByTokens(
where: {
Trade: {
Dex: { SmartContract: { is: $poolAddress } }
}
Block: { Time: { since: $since } }
}
orderBy: { ascendingByField: "Block_Time" }
limit: { count: 1000 }
) {
Block { Time(interval: { in: minutes, count: 5 }) }
Trade {
open: PriceInUSD(minimum: Block_Time)
high: PriceInUSD(maximum: Trade_PriceInUSD)
low: PriceInUSD(minimum: Trade_PriceInUSD)
close: PriceInUSD(maximum: Block_Time)
volume: sum(of: Trade_Side_AmountInUSD)
}
}
}
}
Отслеживание крупных переводов (whale monitoring)
query WhaleTransfers($minAmount: String!) {
EVM(network: eth) {
Transfers(
where: {
Transfer: {
Currency: { SmartContract: { is: "0xdac17f958d2ee523a2206206994597c13d831ec7" } }
Amount: { ge: $minAmount }
}
}
limit: { count: 50 }
orderBy: { descendingByField: "Block_Time" }
) {
Block { Time Number }
Transfer {
From To
Amount
Currency { Symbol }
}
Transaction { Hash }
}
}
}
Rate limits и стратегии работы с ними
Bitquery тарифицирует запросы в "points" — каждый запрос стоит определённое количество очков в зависимости от объёма возвращённых данных. Основные ограничения на платных планах: количество запросов в минуту и месячный лимит points.
Стратегия управления rate limits:
Кэширование на уровне приложения — исторические данные (сделки за прошлые дни) не меняются, их можно кэшировать в Redis или PostgreSQL на 24+ часов. Обращаться к Bitquery только за свежими данными.
Пагинация через cursor — запросы с limit возвращают максимум 1000–25000 записей. Для получения полного набора используется offset или cursor-based пагинация:
async function fetchAllTrades(poolAddress: string, since: string) {
const allTrades = [];
let offset = 0;
const limit = 1000;
while (true) {
const data = await bitquery.request(TRADES_QUERY, {
poolAddress, since, limit, offset
});
const trades = data.EVM.DEXTradeByTokens;
allTrades.push(...trades);
if (trades.length < limit) break;
offset += limit;
// Уважаем rate limit
await delay(200);
}
return allTrades;
}
Батчинг запросов — GraphQL позволяет объединять несколько операций в один HTTP-запрос, что экономит round-trip time, хотя points расходуются по-прежнему за каждую операцию.
WebSocket для real-time: особенности V2
V2 поддерживает подписки через graphql-ws протокол. Стандартная реализация на Node.js:
import { createClient } from "graphql-ws";
import WebSocket from "ws";
const client = createClient({
url: "wss://streaming.bitquery.io/eap",
webSocketImpl: WebSocket,
connectionParams: {
headers: { "X-API-KEY": process.env.BITQUERY_API_KEY }
},
retryAttempts: Infinity,
shouldRetry: () => true,
});
const unsubscribe = client.subscribe(
{ query: SWAP_SUBSCRIPTION },
{
next: (data) => processSwap(data.data.EVM.DEXTrades),
error: (err) => logger.error("subscription error", err),
complete: () => logger.info("subscription completed"),
}
);
Важно: V2 WebSocket требует отдельного API ключа (EAP access), который выдаётся по запросу отдельно от основного ключа V1.
Ограничения и когда Bitquery не подходит
Bitquery — managed сервис, и это означает зависимость: индексирование может отставать от chain tip на 1–3 блока, исторические данные иногда содержат gaps, поддержка нестандартных или новых сетей добавляется с задержкой.
Сценарии, где лучше собственный indexer или альтернативы:
- SLA < 1 секунды на данные (Bitquery не гарантирует задержку)
- Кастомные события от непопулярных контрактов без верифицированного ABI
- Объёмы данных, которые упрутся в monthly limits при разумном бюджете
- Compliance-требования к хранению данных на своей инфраструктуре
Альтернативы по задачам: Dune Analytics — для ad-hoc SQL аналитики; The Graph — для проектно-специфичных subgraph с гарантированной доступностью; Goldsky/Envio — для high-performance индексации с низкой задержкой.
Интеграция Bitquery как data source для дашборда или alert-системы занимает 1–2 недели с учётом нормализации данных, кэширования и обработки ошибок.







