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.
- Quick Start
- Configuration
- Building from Source
- Running the Server
- Plugin System
- GraphQL API
- Releases
- Contributing
- License
The fastest way to try Analyser is via Docker Compose, which provisions both Postgres and the Analyser service:
docker-compose upTo use a prebuilt image directly:
docker pull ghcr.io/iotexproject/iotex-analyser:latestAvailable image tags:
:latest— latest tagged release (recommended):vX.Y.Z— pinned release version:main— bleeding edge frommain:sha-<short>— exact commit
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: infoNote: Never commit real credentials. Use environment variable substitution (
${VAR}) or a separate untracked config file.
Indexing from genesis takes time. Speed it up with a pre-indexed chain.db snapshot:
- Mainnet: https://t.iotex.me/mainnet-data-with-idx-latest
- Testnet: https://t.iotex.me/testnet-data-with-idx-latest
Drop the file at the path referenced by blockDB.dbPath and Analyser will resume from the snapshot.
- Go 1.23+
make- A working C linker (plugins use
-buildmode=plugin, which requires glibc — Alpine withoutgcompatwon't work for local builds)
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 developmentStart the server:
./iotex-analyser -c config.yml serverManage 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 infoEach 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.
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./iotex-analyser -c config.yml plugin load simple.so
./iotex-analyser -c config.yml plugin unload simple.soAfter load, you should see output from your plugin in the server logs, e.g.:
block height: 1
block height: 2
block height: 3
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
Hasura sits in front of the indexed Postgres database and serves a GraphQL API automatically.
- Hasura Console: https://iotexscout.io/hasura/console
- GraphQL endpoint: https://iotexscout.io/hasura/v1/graphql
Releases are cut manually using release.sh:
./release.sh v1.18.1The 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.
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 testsApache License 2.0 — see LICENSE.
