Coopenomics Parser

Универсальный индексер блокчейнов EOSIO / Antelope: читает блоки из State History Plugin (SHiP) по WebSocket, декодирует actions и дельты таблиц с учётом исторических ABI, публикует унифицированный поток событий в Redis Stream. Потребители получают события через ParserClient с single-active-consumer lock'ом, recovery после сбоев и dead-letter для poison-messages.

CI npm License: MIT

Зачем

SHiP отдаёт сырые бинарные блоки — чтобы превратить их в прикладной поток событий, нужно: держать кэш ABI за каждый блок (контракты обновляют ABI, старые блоки декодируются старой версией), обрабатывать форки и переподключения, распределять нагрузку между подписчиками. Этот проект закрывает весь этот слой и отдаёт вам единый стрим action / delta / native-delta / fork событий.

Пакеты монорепы

Пакет Описание npm
@coopenomics/parser Ядро индексера (Parser) + подписочный клиент (ParserClient), CLI, observability @coopenomics/parser
@coopenomics/coopos-ship-reader Низкоуровневый WebSocket SHiP клиент с поддержкой 24 нативных системных таблиц @coopenomics/coopos-ship-reader

Быстрый старт

1. Установка

pnpm add @coopenomics/parser
# или если используете только SHiP-клиент без Redis-пайплайна:
pnpm add @coopenomics/coopos-ship-reader

Требования рантайма:

  • Node ≥ 20
  • Redis ≥ 7 (с persistence — AOF/RDB)
  • Доступ до SHiP endpoint блокчейн-ноды (ws://node:8080)
  • Доступ до Chain API ноды (http://node:8888)

2. Запуск парсера

Создай parser.config.yaml:

ship:
  url: ws://my-nodeos:8080
  timeoutMs: 15000
chain:
  url: http://my-nodeos:8888
redis:
  url: redis://localhost:6379
abiFallback: rpc-current
xtrim:
  enabled: true
  intervalMs: 60000
logger:
  level: info
  pretty: false
health:
  enabled: true
  port: 8081
metrics:
  enabled: true
  port: 9090

Запусти через CLI (после глобальной установки пакета):

parser start --config parser.config.yaml

Парсер подключится к SHiP, начнёт читать блоки с последней checkpoint-позиции (или с head если запускается впервые), и публиковать события в Redis stream ce:parser:<chainId>:events.

3. Подписка на события из приложения

import { ParserClient } from '@coopenomics/parser'

const client = new ParserClient({
  subscriptionId: 'my-app',
  filters: [
    { kind: 'action', account: 'eosio.token', name: 'transfer' },
    { kind: 'action', account: 'eosio.token', name: 'issue' },
  ],
  startFrom: 'last_known',
  redis: { url: 'redis://localhost:6379' },
  chain: { id: 'eb004c7dcb6e92f5ba9c98e0d86a616e79ec4e7c80bc1a66c0d6c8d6c...' },
})

for await (const event of client.stream()) {
  if (event.kind === 'action') {
    console.log(
      `${event.block_num} | ${event.account}::${event.name}`,
      event.data,
    )
    // Если обработчик упадёт (throw) — событие попадёт в dead-letter после 3 попыток
  }
}

Несколько реплик одного subscriptionId автоматически выберут одного active-потребителя через distributed lock; остальные встанут в standby и подхватят при падении active.

4. CLI-утилиты

# Посмотреть все зарегистрированные подписки и их отставание
parser list-subscriptions

# Сбросить cursor подписки на начало стрима
parser reset-subscription --sub-id my-app --start-from 0

# Посмотреть dead-letter сообщения
parser list-dead-letters --sub-id my-app

# Replay одного dead-letter обратно в основной поток
parser replay-dead-letter --sub-id my-app --dl-id 1699999999999-0

# Удалить старые ABI-версии (GC)
parser abi-prune --keep-last 10 --all-contracts

Архитектура

┌──────────────┐   WS   ┌──────────────┐            ┌──────────────┐
│  EOSIO node  │────────▶│   Parser     │──XADD────▶│              │
│  (SHiP+RPC)  │        │              │            │              │
└──────────────┘        │  • AbiStore  │            │    Redis     │
                        │  • Workers   │            │              │
                        │  • ForkDet.  │            │  Streams +   │
                        │  • XtrimSup. │            │  Hashes +    │
                        └──────────────┘            │  ZSets       │
                                                    │              │
                        ┌──────────────┐            │              │
                        │ ParserClient │◀─XREADGR──│              │
                        │   #1 active  │            │              │
                        └──────────────┘            └──────────────┘
                        ┌──────────────┐                    ▲
                        │ ParserClient │────────────────────┘
                        │   #2 standby │ (ждёт lock)
                        └──────────────┘

Подробности:

Разработка

Структура монорепы

.
├── packages/
│   ├── parser/            # @coopenomics/parser — ядро + CLI + ParserClient
│   └── ship-reader/       # @coopenomics/coopos-ship-reader — SHiP WS клиент
├── docs/                  # redis taxonomy, disaster recovery
├── examples/              # пример verifier-like подписчика
└── .github/workflows/     # CI + Release

Установка зависимостей

pnpm install

Сборка

pnpm build           # build всех пакетов
pnpm --filter @coopenomics/parser build   # только parser

Тесты

pnpm test            # unit во всех пакетах
pnpm --filter @coopenomics/parser test:unit
pnpm --filter @coopenomics/parser test:integration   # нужен Docker для блокчейн-ноды

Текущее покрытие:

  • @coopenomics/parser: 81% statements / 74% functions (205 unit-тестов)
  • @coopenomics/coopos-ship-reader: 81% statements / 86% functions (51 unit-тест)

Бенчмарк

pnpm --filter @coopenomics/coopos-ship-reader bench

Замеряет throughput wharfkit-десериализатора — используется для контроля регрессий перформанса между версиями.

Ветки и релизы

  • dev — рабочая ветка разработки; любой push сюда запускает CI (lint, typecheck, unit, integration, build)
  • main — релизная ветка; merge из dev автоматически публикует новую версию если packages/parser/package.json содержит новую версию

Процесс релиза:

  1. Сделать PR из dev в main
  2. Поднять версию в packages/parser/package.json (и/или packages/ship-reader/package.json)
  3. Смёрджить PR
  4. GitHub Actions release.yml автоматически:
    • опубликует обновлённые пакеты в npm (pnpm -r publish пропускает пакеты с неизменной версией)
    • создаст тег v<version> и GitHub Release с changelog из коммитов
    • соберёт и опубликует Docker образ в ghcr.io/coopenomics/parser:<version>

Лицензия

MIT. См. LICENSE и NOTICE для атрибуции third-party компонентов.

S
Description
No description provided
Readme 710 KiB
v1.3.0 Latest
2026-06-05 13:01:02 +00:00
Languages
TypeScript 99.7%
Dockerfile 0.3%