Set up a complete development environment for the explorer backend and indexer.
This guide covers the setup required for contributing to the OpenScan.AI backend and indexer repositories — the services that fetch blocks, index chain data, and serve the REST API.
Architecture overview
The backend is Blockscout-derived and consists of:
- Indexer — Elixir processes that fetch blocks, transactions, receipts, and internal transactions from a JSON-RPC endpoint and write them to PostgreSQL.
- API server — serves the REST API v2 (
/api/v2/...) from indexed data. - Frontend — a separate TypeScript/React application (see Frontend & Docs Setup).
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Git | any recent | Source control |
| Erlang/OTP | 26+ | Runtime for the backend |
| Elixir | 1.17+ | Backend language |
| PostgreSQL | 15+ | Indexed data storage |
| Docker | 24+ | Optional: containerized run |
| A JSON-RPC endpoint | any synced EVM node | Chain data source |
For a local chain data source, any EVM archive or full node works — a synced XDC node, an Anvil/Hardhat devnet, or a public RPC endpoint for light testing.
Clone and configure
git clone https://github.com/OpenScanAI/blockscout.gitcd blockscoutcp .env.example .envThe essential environment variables:
# DatabaseDATABASE_URL=postgresql://postgres:postgres@localhost:5432/blockscout
# Chain connectionETHEREUM_JSONRPC_HTTP_URL=http://localhost:8545ETHEREUM_JSONRPC_TRACE_URL=http://localhost:8545CHAIN_ID=50
# Instance identityNETWORK="XDC Network"SUBNETWORK="XDC Mainnet"COIN=XDCRun with Docker (recommended for a first look)
docker compose up --buildThis starts PostgreSQL, runs migrations, and boots the indexer plus API server. The explorer UI is available at http://localhost:4000 once indexing begins.
Run from source
# Install dependenciesmix deps.get
# Create and migrate the databasemix ecto.createmix ecto.migrate
# Start the indexer and API servermix phx.serverWatch the logs for the fetcher supervision tree starting up. The first sync indexes from the configured starting block; point ETHEREUM_JSONRPC_HTTP_URL at a small devnet to keep initial sync fast.
Running tests
# Backend test suitemix test
# With coveragemix coveralls
# Lint and format checksmix credo --strictmix format --check-formattedRun mix test before every commit in backend code. Fetcher changes should include tests covering the happy path plus at least one failure/retry scenario.
Common development tasks
Reset the local database
mix ecto.drop && mix ecto.create && mix ecto.migrateReindex a block range
Use the reindex tooling in apps/explorer or, for a local dev environment, drop and resync — it’s usually faster.
Debug a stuck fetcher
Fetcher logs include the module name (e.g. Indexer.Fetcher.Block). Filter logs by module, verify the RPC endpoint responds (curl -X POST $ETHEREUM_JSONRPC_HTTP_URL -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'), and check the fetcher’s retry backoff state.
Troubleshooting
- Migrations fail on start — PostgreSQL version mismatch or a dirty local database; drop and recreate.
- Indexer idle at block 0 — the RPC endpoint is unreachable or not synced; check
eth_syncingon the node. - API returns stale data — the indexer is behind; check
/api/v2/main-page/indexing-status.
Next steps
- Code Conventions
- Pull Request Process
- Self-Hosting — production deployment of an instance