Индексация данных: The Graph и subgraph

Нода плохо отвечает на вопросы «покажи историю и агрегаты». The Graph индексирует данные контракта и отдаёт их через GraphQL.

The Graph — протокол индексации блокчейн-данных. Subgraph — описание, какие события контракта собирать и в какие сущности складывать; фронт запрашивает их обычным GraphQL.

Мы уже видели: прочитать «все переводы за всё время» напрямую с ноды нельзя — eth_getLogs ограничен диапазоном, а агрегаций («топ-10», «сумма за неделю») у ноды нет вовсе. Для дашбордов, лент и поиска это тупик. The Graph решает его, превращая разрозненные события в нормальную базу с GraphQL-запросами.

Почему нельзя «просто читать с ноды»

  • Нода хранит текущее состояние, а не удобную историю запросов.
  • eth_getLogs по большому диапазону — медленно и ограничено провайдером.
  • Нет JOIN, GROUP BY, сортировки, пагинации — всё это пришлось бы делать на клиенте поверх тысяч логов.

Как устроен subgraph

Subgraph — это три части: схема сущностей (что хранить), манифест (какой контракт и события слушать) и маппинги (код, превращающий событие в запись). Индексатор проходит по всем блокам, ловит события и наполняет базу. Результат фронт запрашивает GraphQL'ом:

query {
  transfers(first: 10, orderBy: value, orderDirection: desc) {
    from
    to
    value
    blockNumber
  }
}

Это уже привычная фронтендеру работа: GraphQL-запрос, как к любому API. Никаких eth_getLogs и ручной агрегации.

Что остаётся на ноде, а что уходит в The Graph

Через ноду (ethers/wagmi)Через The Graph
Текущий баланс, текущее состояниеИстория переводов
Отправка транзакцииЛента активности, агрегаты
Чтение одного значенияПоиск, сортировка, пагинация

Правило: «сейчас и записать» — нода; «история и аналитика» — индексатор.

Как работает под капотом

Индексатор The Graph синхронизируется с сетью блок за блоком. На каждом блоке он смотрит, не сработали ли отслеживаемые события; если да — вызывает ваш маппинг, который создаёт/обновляет сущности в базе (обычно Postgres). Поверх базы поднят GraphQL-сервер. Фронт шлёт ему запрос и получает уже готовые, отсортированные, агрегированные данные. Важно: данные в subgraph чуть «отстают» от головы сети (индексация занимает время), поэтому для свежайшего состояния всё равно нужна нода.

Частые ошибки

  • Тянуть историю с ноды на клиенте. Не масштабируется; используйте индексатор.
  • Брать критичный текущий баланс из subgraph. Он может отставать; для «прямо сейчас» читайте ноду.
  • Считать The Graph обязательным для любого dApp. Для простого приложения без истории он избыточен.

Итоги

  • Нода не умеет историю и агрегаты — для них есть индексаторы.
  • The Graph через subgraph превращает события в GraphQL-API.
  • «Сейчас/записать» — нода; «история/аналитика» — The Graph.
Проверьте себя
1. Какую задачу решает The Graph, недоступную напрямую через ноду?
AПодпись транзакций
BИсторию, поиск и агрегацию данных контракта
CХранение приватных ключей
DОплату газа
2. Как фронт запрашивает данные из subgraph?
AЧерез eth_getLogs
BОбычным GraphQL-запросом
CЧерез personal_sign
DЧерез wallet_switchEthereumChain
3. Откуда лучше брать самый свежий текущий баланс?
AИз subgraph (он всегда мгновенен)
BС ноды через ethers/wagmi, т.к. subgraph может отставать
CИз IPFS
DИз localStorage