Advanced: Scalable Indexing with Envio
The basic indexer tutorial shows how to read logs with a hand-written script and store them in a database. That approach is great for learning how event logs work, but it does not scale well to production:
- You manage the sync loop yourself — batching
eth_getLogscalls, respecting RPC block-range limits, resuming after crashes, and tracking which blocks you have already processed. - No reorg handling — if the chain reorganizes, your database silently keeps stale rows.
- Manual ABI decoding — every event needs hand-written, error-prone decoding code.
- No query layer — you still have to build and secure an API on top of your database.
Envio HyperIndex solves all of this. You declare your contracts and events in a config file, define your data model as a GraphQL schema, and write type-safe TypeScript handlers. Envio manages the sync engine, automatic ABI decoding, chain-reorg rollbacks, checkpointing, and serves your data through a ready-made GraphQL API (Hasura). It is the same developer model as The Graph's subgraphs, but with faster sync, plain TypeScript instead of AssemblyScript, and a much simpler local development loop.
Reference project: the GinsengSwap indexer
This tutorial follows a real, production-grade indexer running on Conflux eSpace:
github.com/intrepidcanadian/indexer-example-conflux
It indexes GinsengSwap — a Uniswap V3-style DEX on Conflux eSpace — covering:
- The factory contract and every pool it creates (dynamic contract registration)
- Pool events:
Initialize,Mint,Burn,Swap,Collect - NFT position manager events for per-position liquidity history
- An ERC-4626 vault (Ginseng Earn) with a full governance/audit event trail
- Derived analytics: USD pricing, TVL, volume, fees, and day/hour aggregates
Clone it to follow along:
git clone https://github.com/intrepidcanadian/indexer-example-conflux
cd indexer-example-conflux
Prerequisites
- Node.js v22 or newer
- pnpm (recommended)
- Docker Desktop (runs the local Postgres + Hasura stack)
Starting a new indexer from scratch
For your own contracts, scaffold a project with:
pnpx envio init
Choose Contract Import → Local ABI and provide your contract's ABI JSON. (The block-explorer import flow does not list Conflux, so importing from an ABI file — or copying the structure of the reference project — is the way to go.)
An Envio project has three core pieces:
| File | Purpose |
|---|---|
config.yaml | Which chains, contracts, and events to index |
schema.graphql | The entities (tables) your handlers write and your app queries |
src/ handlers | TypeScript that turns decoded events into entity updates |
Configuring Conflux eSpace
Conflux eSpace is not yet on Envio's HyperSync network list, so the indexer uses RPC as the data source — Envio supports any EVM chain this way. The relevant part of the reference project's config.yaml:
name: gswap_v3
rollback_on_reorg: true # roll back cleanly on chain reorganizations
contracts:
- name: UniswapV3Factory
events:
- event: PoolCreated(address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool)
- name: UniswapV3Pool
events:
- event: Initialize(uint160 sqrtPriceX96, int24 tick)
- event: Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)
- event: Burn(address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)
- event: Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)
field_selection:
transaction_fields: [hash, gasPrice, from]
chains:
- id: 1030 # Conflux eSpace mainnet
start_block: 119639200 # deployment block of the factory — don't sync from genesis
rpc:
url: ${ENVIO_CONFLUX_RPC_URL:-https://evm.confluxrpc.com}
for: sync
contracts:
- name: UniswapV3Factory
address: 0x62Aa0294cB42Aae39b7772313eAdfa5d489146eC
- name: UniswapV3Pool # no address — pools are registered dynamically
Key points for Conflux:
id: 1030is Conflux eSpace mainnet (use71for testnet).rpcwithfor: synctells Envio to do historical sync over RPC. The public endpointhttps://evm.confluxrpc.com(testnet:https://evm-test.confluxrpc.com) works; for a large historical backfill, a dedicated endpoint from an RPC provider will sync considerably faster and avoid public rate limits. You can tune batch sizes with the advanced RPC parameters (initial_block_interval,interval_ceiling, etc.) to match your provider's limits.${ENVIO_CONFLUX_RPC_URL:-...}uses Envio's environment variable interpolation — the indexer defaults to the public endpoint, and anyone can point it at their own keyed RPC URL via.envwithout committing the key to source control.start_blockshould be your contract's deployment block, not 0.rollback_on_reorg: truekeeps the database consistent through reorgs — one line replaces logic that is very hard to hand-write.field_selectionadds transaction fields (hash, sender, gas price) to events where the handlers need them.