Індексація The Graph: проектування subgraph та оптимізація

Ми часто стикаємося з ситуацією, коли фронтенд робить десятки `eth_call` та `getLogs` при кожному завантаженні сторінки. На mainnet це займає 2–3 секунди, на публічних RPC — ненадійно, а коли потрібна агрегація або історичні дані — просто неможливо через прямі виклики. [The Graph](https://en.wikiped

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

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

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

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

Ми часто стикаємося з ситуацією, коли фронтенд робить десятки eth_call та getLogs при кожному завантаженні сторінки. На mainnet це займає 2–3 секунди, на публічних RPC — ненадійно, а коли потрібна агрегація або історичні дані — просто неможливо через прямі виклики. The Graph вирішує цю проблему правильно: один раз пишеться subgraph, який індексує події контракту, і отримується GraphQL API з довільними запитами за мілісекунди. Економія на інфраструктурі може досягати 90% (до $2000 на місяць для типового DeFi-проекту), а швидкість запитів зростає в десятки разів. Нижче розберемо, як спроектувати та написати subgraph, щоб уникнути типових помилок і отримати максимум продуктивності.

Як спроектувати схему subgraph?

Subgraph складається з трьох компонентів, і критично важливо спроектувати схему під запити фронтенду, а не під структуру подій.

  • subgraph.yaml — маніфест. Описує джерела даних: які контракти слухати, з якого блоку (startBlock), які події та функції обробляти. Критично важливо: startBlock має бути блоком деплою контракту, а не нулем — інакше індексація займе дні.
  • schema.graphql — типи сутностей. Це те, що буде доступне через GraphQL. Проектується виходячи з потреб фронтенду, а не зі структури подій контракту — це різні речі.
  • mappings.ts — AssemblyScript обробники. Трансформують сирі події в сутності схеми.

Проектування схеми

Найчастіша помилка — робити схему дзеркалом подій контракту. Якщо подія Transfer(address from, address to, uint256 amount) — не потрібна сутність TransferEvent. Потрібно думати про запити: «який поточний баланс користувача», «топ холдерів», «обсяг за 24 години».

type Token @entity { id: ID! totalSupply: BigInt! holderCount: Int! } type Account @entity { id: Bytes! balance: BigInt! transfersIn: [Transfer!]! @derivedFrom(field: "to") transfersOut: [Transfer!]! @derivedFrom(field: "from") } type Transfer @entity(immutable: true) { id: Bytes! from: Account! to: Account! amount: BigInt! blockNumber: BigInt! timestamp: BigInt! } 

@entity(immutable: true) для Transfer — важлива оптимізація. Immutable сутності не зберігаються в undo-буфері, індексація швидша на 30–40%.

Обробники: кроки створення

В AssemblyScript немає повноцінного TypeScript — немає null через ?., немає Array.from(), немає стандартних JS методів. Це часте джерело помилок для розробників, що прийшли з фронтенду.

  1. Визначте подію, яку обробляєте (наприклад, Transfer).
  2. Завантажте або створіть сутність за допомогою Account.load(address) або new Account(address).
  3. Оновіть поля (баланс, посилання).
  4. Збережіть зміни через save().
// Правильне завантаження або створення сутності function getOrCreateAccount(address: Address): Account { let account = Account.load(address) if (account == null) { account = new Account(address) account.balance = BigInt.fromI32(0) } return account as Account } export function handleTransfer(event: TransferEvent): void { let from = getOrCreateAccount(event.params.from) let to = getOrCreateAccount(event.params.to) from.balance = from.balance.minus(event.params.value) to.balance = to.balance.plus(event.params.value) from.save() to.save() // Immutable — створюємо один раз, не завантажуємо let transfer = new Transfer( event.transaction.hash.concatI32(event.logIndex.toI32()) ) transfer.from = from.id transfer.to = to.id transfer.amount = event.params.value transfer.blockNumber = event.block.number transfer.timestamp = event.block.timestamp transfer.save() } 

Call handlers та block handlers

Окрім подій, The Graph вміє обробляти виклики функцій (callHandlers) і кожен блок (blockHandlers). Call handlers потрібні коли контракт не емітить події для потрібних операцій — legacy контракти грішать цим. Block handlers — для періодичних снапшотів (наприклад, денна статистика). Обидва типи значно сповільнюють індексацію, особливо block handlers — використовуйте лише якщо без них не обійтися.

Тип обробника Призначення Вплив на швидкість індексації
Event handler Обробка подій контракту Мінімальний (основний тип)
Call handler Відстеження викликів функцій Середній (потрібен архівний вузол)
Block handler Періодична обробка блоків Високий (виконується на кожен блок)

Чому The Graph швидше за прямі виклики RPC?

Прямі виклики RPC виконуються послідовно і завантажують ноду. The Graph індексує дані один раз і зберігає їх в оптимізованій базі, доступній через GraphQL. Запити виконуються за мілісекунди (типовий час від 50 до 200 мс), а пагінація через first/skip працює до skip: 5000 — для великих датасетів використовуйте keyset pagination через id_gt. За даними документації The Graph, пропускна здатність індексації може досягати 1000 подій на секунду на стандартному обладнанні. Економія на інфраструктурі може досягати 90%, що підтверджується досвідом великих DeFi-проектів — наприклад, Uniswap скоротив витрати на RPC на $3000+ на місяць після переходу на subgraph.

Який хостинг обрати: Hosted Service, Decentralized чи self-hosted?

Вибір варіанту розгортання subgraph залежить від вимог до доступності, контролю та бюджету.

Варіант Доступність Контроль Вартість
Hosted Service Базова (без SLA) Обмежений Безкоштовно для невеликих проектів
Decentralized Network Висока (децентралізовані індексери) Середній Потребує GRT (токен)
Self-hosted Graph Node Повна (власне обладнання) Повний Витрати на інфраструктуру ($1000+ на місяць)

Наша команда з десятирічним досвідом у блокчейні реалізувала понад 20 інтеграцій The Graph. Ми допомагаємо обрати оптимальний варіант під ваш проект і уникнути типових проблем.

Типові проблеми індексації

  • Subgraph fails з помилкою "store error" — перевірте non-nullable поля.
  • Індексація зависає на блоці — додайте обробку реверсованих транзакцій через receipt.status.
  • Розбіжність даних через reorgs — встановіть minEthereumBlockConfirmations.
  • Надмірне споживання газу при записі — використовуйте @entity(immutable: true) для незмінних даних.

Що потрібно знати про пагінацію та фільтрацію?

Тип запиту Приклад Обмеження
Pagination first: 100, skip: 0 skip до 5000
Keyset pagination where: { id_gt: "..." } Без обмежень
Фільтрація where: { balance_gt: "0" } Підтримуються всі оператори
Сортування orderBy: timestamp, orderDirection: desc За будь-яким полем сутності

Keyset pagination є кращим для великих наборів даних — вона швидша і не має обмеження по skip.

Інтеграція на фронтенді

Стандартний стек: Apollo Client або urql для React додатків. The Graph підтримує subscriptions через WebSocket — для realtime оновлень без поллінгу.

const POSITIONS_QUERY = gql` query UserPositions($account: Bytes!, $skip: Int!) { positions( where: { owner: $account, liquidity_gt: "0" } orderBy: createdAt orderDirection: desc first: 100 skip: $skip ) { id pool { token0 { symbol } token1 { symbol } feeTier } liquidity depositedToken0 depositedToken1 } } ` 

Терміни та що входить в роботу

За 2–5 днів: проектування схеми під завдання клієнта, написання mappings для всіх подій та calls, тестування на форку, деплой на Hosted Service або налаштування self-hosted ноди, базова інтеграція в існуючий фронтенд або надання GraphQL endpoint. Вартість розраховується індивідуально, але економія на RPC-запитах виправдовує інвестиції — типова окупність настає протягом 1-3 місяців.

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