IoTeX Analyser

IoTeX Analyser indexes data from the IoTeX blockchain into the database of your choice (PostgreSQL, MySQL, SQLite, ClickHouse) and exposes it for downstream querying — including a managed GraphQL endpoint via Hasura.
It is built around a dynamic plugin system: indexing logic ships as Go plugins (.so files) that can be loaded and unloaded at runtime, with no service restart. A growing library of 58+ built-in plugins covers common needs (blocks, actions, ERC20/721/1155, staking, rewards, gas tracking, account income, …), and you can drop in your own.

Table of Contents
Quick Start
The fastest way to try Analyser is via Docker Compose, which provisions both Postgres and the Analyser service:
docker-compose up
To use a prebuilt image directly:
docker pull ghcr.io/iotexproject/iotex-analyser:latest
Available image tags:
:latest — latest tagged release (recommended)
:vX.Y.Z — pinned release version
:main — bleeding edge from main
:sha-<short> — exact commit
Configuration
Analyser is configured via a YAML file. A minimal config.yml:
server:
# Plugins to load on startup
plugins:
- block.so
database:
driver: postgres # postgres | mysql | sqlite3 | clickhouse
host: 127.0.0.1
port: 5432
user: postgres
password: ${DB_PASSWORD}
name: iotex
iotex:
chainEndPoint: api.iotex.one:80 # mainnet (use api.testnet.iotex.one:80 for testnet)
blockDB:
dbPath: chain.db
log:
zap:
level: info
Note: Never commit real credentials. Use environment variable substitution (${VAR}) or a separate untracked config file.
Bootstrapping with a Snapshot
Indexing from genesis takes time. Speed it up with a pre-indexed chain.db snapshot:
Drop the file at the path referenced by blockDB.dbPath and Analyser will resume from the snapshot.
Building from Source
Requirements
- Go 1.23+
make
- A working C linker (plugins use
-buildmode=plugin, which requires glibc — Alpine without gcompat won't work for local builds)
Build
Clone and build the binary plus all plugins:
git clone https://github.com/iotexproject/iotex-analyser.git
cd iotex-analyser
make # binary + every plugin under plugins/
Or build individual targets:
make build # binary only
make plugin name=block # one plugin (produces block.so)
make dev # binary + all plugins with -race for development
Running the Server
Start the server:
./iotex-analyser -c config.yml server
Manage plugins at runtime via a second process (the running server picks up changes automatically):
./iotex-analyser -c config.yml plugin load simple.so
./iotex-analyser -c config.yml plugin unload simple.so
./iotex-analyser -c config.yml plugin info
Plugin System
Each plugin is a Go package compiled to a .so file with -buildmode=plugin, exposing a single Plugin variable that satisfies the Adapter interface:
type Adapter interface {
Name() string
Version() string
Type() Type
Start(context.Context) error
Stop(context.Context) error
PutBlock(context.Context, *block.Block) error
}
For better throughput, plugins may also implement PutBlocks(ctx, []*block.Block) error to process blocks in batches.
Writing a Plugin
package main
import (
"context"
"fmt"
"github.com/iotexproject/iotex-analyser/db"
"github.com/iotexproject/iotex-analyser/plugin"
"github.com/iotexproject/iotex-core/v2/blockchain/block"
)
type simplePlugin struct{}
func (simplePlugin) Name() string { return "simple" }
func (simplePlugin) Version() string { return "0.0.1" }
func (simplePlugin) Type() plugin.Type { return plugin.TypeStandard }
func (simplePlugin) Start(context.Context) error { return nil }
func (simplePlugin) Stop(context.Context) error { return nil }
func (s simplePlugin) PutBlock(ctx context.Context, blk *block.Block) error {
fmt.Printf("block height: %d\n", blk.Height())
return db.UpdateIndexHeight(s.Name(), blk.Height())
}
// Exported symbol — must be named "Plugin".
var Plugin = simplePlugin{}
Build it:
make plugin name=simple
Loading and Unloading at Runtime
./iotex-analyser -c config.yml plugin load simple.so
./iotex-analyser -c config.yml plugin unload simple.so
After load, you should see output from your plugin in the server logs, e.g.:
block height: 1
block height: 2
block height: 3
Built-in Plugins
A non-exhaustive sample — see plugins/ for the full list:
- Core blocks/actions: block, block_action, block_meta, block_supply, block_receipts
- Tokens: erc20, erc721, erc1155, token holder/meta variants
- Staking & delegation: candidate, staking_action, delegate, probation
- Accounting: account_meta, account_income, account_vote
- Other: gastracker, erc1967_proxy, clickhouse sinks
GraphQL API
Hasura sits in front of the indexed Postgres database and serves a GraphQL API automatically.
Releases
Releases are cut manually using release.sh:
./release.sh v1.18.1
The script validates the working tree, tags the commit, pushes the tag, and creates a GitHub Release with auto-generated notes. The tag push triggers GitHub Actions to build and publish the Docker image as both :vX.Y.Z and :latest on ghcr.io.
Contributing
Contributions are welcome. The general flow:
- Open an issue to discuss non-trivial changes before starting work.
- Fork and create a feature branch.
- Add tests for new functionality where possible.
- Open a PR against
main.
Useful commands while developing:
make dev # build with -race for local testing
go test ./... # run unit tests
License
Apache License 2.0 — see LICENSE.