Создание subgraph The Graph: проектирование, деплой и оптимизация

Мы часто сталкиваемся с проблемой: смарт-контракты не хранят историю состояния в удобном для запросов виде. `eth_getLogs` с фильтром по событиям — это грубый инструмент: нет сортировки, нет агрегации, нет связей между событиями разных контрактов. В итоге фронтенд либо тащит тонны данных и обрабатыва

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

Часто задаваемые вопросы

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

  • 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_getLogs с фильтром по событиям — это грубый инструмент: нет сортировки, нет агрегации, нет связей между событиями разных контрактов. В итоге фронтенд либо тащит тонны данных и обрабатывает их на клиенте, либо команда поднимает собственный индексирующий бэкенд. The Graph решает эту задачу стандартным способом — вы описываете, что индексировать, а сеть делает это за вас. Наша команда разработала более 20 subgraph для DeFi-протоколов и NFT-маркетплейсов, накопив опыт в оптимизации и отладке. Получите консультацию по вашему проекту — поможем спроектировать схему и выбрать стек.

Subgraph — это по сути декларация: какие контракты слушать, какие события обрабатывать, как трансформировать данные в entities. Написать его правильно с первого раза сложнее, чем кажется.

Как оптимизировать schema для GraphQL-запросов?

Схема должна проектироваться исходя из того, какие запросы нужны фронтенду — не из структуры событий контракта. Типичная ошибка: делать entities один-к-одному с событиями. Это ведёт к тому, что фронтенд делает N+1 запросов. Денормализованные entities с предагрегированными данными сокращают количество запросов в 3–5 раз.

Правильный подход — денормализованные entities с предагрегированными данными:

type Pool @entity { id: ID! # address пула token0: Token! token1: Token! feeTier: BigInt! totalVolumeUSD: BigDecimal! # накопительный объём — обновляем в каждом Swap totalValueLockedUSD: BigDecimal! txCount: BigInt! swaps: [Swap!]! @derivedFrom(field: "pool") } type Swap @entity { id: ID! # txHash + logIndex pool: Pool! sender: Bytes! recipient: Bytes! amount0: BigDecimal! amount1: BigDecimal! amountUSD: BigDecimal! timestamp: BigInt! blockNumber: BigInt! } 

@derivedFrom — виртуальная связь, не хранит массив ID в записи Pool. Это важно для производительности: пул с тысячами свапов не будет расти в размере записи. Пример запроса, который фронтенд может выполнять:

{ pools(first: 10) { id totalVolumeUSD swaps(first: 5) { amountUSD timestamp } } } 

Почему AssemblyScript опасен для разработчиков TypeScript?

AssemblyScript — строго типизированный язык, компилируется в WebAssembly. Привычки из TypeScript здесь опасны:

// НЕПРАВИЛЬНО — null reference в AS вызывает панику let pool = Pool.load(event.address.toHexString()) pool.txCount = pool.txCount.plus(BigInt.fromI32(1)) // pool может быть null // ПРАВИЛЬНО let poolId = event.address.toHexString() let pool = Pool.load(poolId) if (pool === null) { pool = new Pool(poolId) pool.txCount = BigInt.fromI32(0) pool.totalVolumeUSD = BigDecimal.fromString("0") } pool.txCount = pool.txCount.plus(BigInt.fromI32(1)) pool.save() 

BigDecimal для финансовых значений — обязательно. BigInt из контракта нужно конвертировать с учётом decimals токена:

function convertTokenToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { if (exchangeDecimals == BigInt.fromI32(0)) { return tokenAmount.toBigDecimal() } return tokenAmount.toBigDecimal().div( BigInt.fromI32(10).pow(exchangeDecimals.toI32() as u8).toBigDecimal() ) } 

Как отладить медленную синхронизацию?

Если subgraph синхронизируется медленнее ожидаемого, выполните проверку:

  1. Посчитайте количество callHandlers — замените на eventHandlers где возможно. eventHandlers в 5–10 раз быстрее.
  2. Убедитесь, что startBlock не слишком ранний. Идеально — блок деплоя контракта.
  3. Проверьте количество eth_call в handlers — каждый вызов контракта из mapping добавляет RPC-запрос.
  4. Используйте ipfs.cat минимально — это медленная операция.
Тип обработчика Скорость Применение
eventHandlers Быстро (2000–5000 блоков/мин) Любые события, эмитированные контрактом
callHandlers Медленно (в 5–10 раз медленнее) Если контракт не эмитит событий
blockHandlers Очень медленно Только когда нет альтернативы, с filter: { kind: once }

Типичные ошибки в обработчиках:

  • Забывают проверить null перед Pool.load
  • Указывают startBlock = 0
  • Используют callHandlers вместо eventHandlers там, где можно наоборот
  • Не конвертируют BigInt в BigDecimal с учётом decimals

Как выбрать между Hosted Service и Decentralized Network?

Для production протоколов рекомендуется децентрализованная сеть: она обеспечивает censorship resistance и устойчивость к отключению. Hosted Service бесплатен, но подходит только для разработки и тестирования. Сравнение:

Hosted Service Decentralized Network
Стоимость Бесплатно (сервис закрывается) GRT токены (Indexer fees)
Latency Низкая Выше (~100–500ms)
Censorship resistance Нет (centralized) Да
SLA Без гарантий Зависит от Indexers
Подходит для Разработка, тестирование Production с требованием decentralization

Для деплоя в децентрализованную сеть используйте Graph Studio:

graph auth --studio <deploy-key> graph codegen && graph build graph deploy --studio <subgraph-name> 

Подробнее об архитектуре можно прочитать в документации The Graph. Свяжитесь с нами для консультации по выбору сети и оптимизации схемы.

Процесс разработки subgraph: этапы и сроки

Мы работаем по следующей схеме:

  1. Анализ ABI контрактов и определение списка событий и вызовов для индексации.
  2. Проектирование GraphQL-схемы под конкретные запросы фронтенда (с упором на денормализацию).
  3. Написание AssemblyScript-обработчиков с учётом обработки null, конвертации BigInt и оптимизации производительности.
  4. Локальное тестирование с помощью graph-cli и дебаггинг медленных мест.
  5. Деплой в выбранную сеть и настройка мониторинга синхронизации.

Сроки зависят от сложности контрактов и количества сущностей: от 3 до 10 рабочих дней. Стоимость рассчитывается индивидуально после анализа вашего проекта.

Что входит в нашу работу по разработке subgraph

  • Анализ ABI контрактов и определение нужных events/calls
  • Проектирование schema под конкретные запросы фронтенда
  • Написание и тестирование AssemblyScript handlers
  • Оптимизация производительности (экономия до 40% на RPC-запросах за счёт денормализации)
  • Деплой и мониторинг синхронизации
  • Документация GraphQL endpoints и примеры запросов

Наша команда имеет многолетний опыт в разработке блокчейн-решений, более 30 успешных проектов на Ethereum, Polygon, BNB Chain, Solana. Закажите разработку subgraph у профессионалов и получите быструю индексацию без компромиссов.