Интеграция с The Graph (индексация данных)

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Интеграция с The Graph (индексация данных)
Средний
~2-3 дня
Часто задаваемые вопросы

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

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1306
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1218
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    920
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1147
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    885

Интеграция с The Graph (индексация данных)

Типичная проблема, с которой приходят: фронтенд делает десятки eth_call и getLogs при каждой загрузке страницы. На mainnet это медленно, на публичных RPC-нодах — ненадёжно, а когда нужна агрегация или исторические данные — просто невозможно через прямые вызовы. The Graph решает эту проблему правильно: один раз пишешь subgraph, который индексирует события контракта, и получаешь GraphQL API с произвольными запросами.

Архитектура 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 методов. Это частый источник ошибок для разработчиков, пришедших с фронтенда.

// Правильная загрузка или создание сущности
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 — используйте только если без них не обойтись.

Деплой и эксплуатация

Hosted Service vs Decentralized Network

Hosted Service (The Graph Network hosted) — centralized, бесплатный, подходит для разработки и MVP. Не SLA-гарантированный, может быть недоступен.

Decentralized Network — индексеры получают GRT за запросы, сигнал курирования влияет на приоритет. Для production с требованиями к uptime — правильный выбор, но нужно понимать экономику: стоимость запросов зависит от объёма.

Self-hosted Graph Node — полный контроль, никаких затрат на GRT, но инфраструктурная нагрузка. Требует: PostgreSQL 14+, IPFS ноду, архивную ноду Ethereum (или Firehose). Минимальные требования для production: 16 CPU, 64GB RAM, NVMe SSD.

Типичные проблемы индексации

Subgraph fails с "store error" — чаще всего попытка сохранить сущность с null полем, который объявлен non-nullable в схеме. Проверяйте все поля перед save().

Индексация зависает на конкретном блоке — обычно это call handler на транзакцию, которая reverted. Нужно добавить обработку через receipt.status.

Расхождение данных с on-chain — subgraph не учитывает reorgs. Для критичных данных нужен minEthereumBlockConfirmations в манифесте или дополнительная логика в клиенте.

Интеграция на фронтенде

Стандартный стек: 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
    }
  }
`

Pagination через first/skip работает до skip: 5000 — дальше The Graph возвращает ошибку. Для больших датасетов нужна keyset pagination через id_gt.

Сроки и что входит в работу

За 2–3 дня: проектирование схемы под задачи клиента, написание mappings для всех событий и calls, тестирование на форке, деплой на Hosted Service или настройка self-hosted ноды, базовая интеграция в существующий фронтенд или предоставление GraphQL endpoint.