Self-hosted Ethereum transaction indexer for native ETH and ERC-20 transfers, with PostgreSQL storage and a read-only PostgREST API.
Ethereum nodes cannot answer "list the transactions for this address". ETH-transactions-storage builds that index for you: it reads blocks from your execution client, writes native ETH transfers and ERC-20 transfer calls into PostgreSQL, and serves address transaction history over HTTP. No third-party data provider, no rate limits, no telemetry.
📖 Full documentation: https://eth-indexer.docs.adamant.im
Built and maintained by the ADAMANT developer community and cryptofoundry. Want custom crypto software, bots, payments or blockchain infrastructure built by engineers with production blockchain experience? Tell us what to build.
- Cryptocurrency wallets rendering per-account ETH and token history
- Block explorers and dashboards backing address pages with SQL
- Accounting and treasury tools exporting transfers for reconciliation
- Support and compliance systems looking up on-chain activity
- Monitoring services watching a known address set with the optional address filter
- Custom applications that want direct SQL access to transfer data
Works with Geth, Nethermind, Besu, and Erigon over HTTP, WebSocket, or IPC, and with EVM-compatible networks exposing the same JSON-RPC surface.
Ethereum node → ethsync.py → PostgreSQL → PostgREST → your application
JSON-RPC indexer ethtxs REST API
The indexer polls new blocks, parses transfers, and writes each block together with its checkpoint in a single database transaction. Restarts resume exactly where they stopped. PostgREST turns the table into a read-only HTTP API with filtering, ordering, and pagination, so there is no API code to write or maintain.
See Architecture for the full data flow.
git clone https://github.com/Adamant-im/ETH-transactions-storage.git
cd ETH-transactions-storage
cp .env.example .env && chmod 600 .env
cp filter/addresses.txt.example filter/addresses.txt && chmod 600 filter/addresses.txt
# set POSTGRES_PASSWORD and DOCKER_ETH_URL in .env
docker compose up -d
curl -s http://127.0.0.1:3000/max_blockThe stack runs PostgreSQL, PostgREST, an optional local Geth dev node, and the indexer image published to ghcr.io/adamant-im/eth-transactions-storage. Nothing is built locally.
Full walkthrough: Docker Compose quick start.
Follow the Manual and systemd quick start for the complete installation sequence. Apply the schema and required grants as a PostgreSQL administrator, then configure and start the indexer as the unprivileged api_user. The guide also covers the systemd unit and PostgREST setup.
Once the initial backfill has caught up, create the query indexes as the PostgreSQL administrator:
sudo -u postgres psql -v ON_ERROR_STOP=1 -d index < create_indexes.sql
sudo -u postgres psql -v ON_ERROR_STOP=1 -d index < create_indexes_add.sqlIndex maintenance requires the table owner or an administrator; the indexer's runtime grants do not permit it. On a live database, use CREATE INDEX CONCURRENTLY or a maintenance window, as described in the index guide.
| Endpoint | Purpose |
|---|---|
/ethtxs |
Indexed native ETH and ERC-20 transfers |
/max_block |
Highest processed block and indexer version |
/aval |
Availability probe |
# Last 25 native ETH transfers for an address, newest first
curl -s "http://127.0.0.1:3000/ethtxs?and=(contract_to.eq.,or(txfrom.eq.0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98,txto.eq.0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98))&order=time.desc&limit=25"Endpoint names, column names, and value encodings are a stable contract across upgrades. Full query syntax, encodings, filtering, and pagination: REST API reference.
Stored: native ETH transfers, and ERC-20 transfers submitted as a direct top-level transfer(address,uint256) call.
Not stored: internal ETH transfers, ERC-20 transfers routed through transferFrom, multisig, router, batch, or aggregator flows, other token standards, and event logs. These are properties of the current indexing logic, not settings. See what gets indexed.
Storage is the main planning constraint. A recent START_BLOCK, the recommended five-index set, and the optional address filter are the three levers: see storage planning.
| Page | Contents |
|---|---|
| Introduction | What it does, use cases, scope, limitations |
| Architecture | Components, data flow, sync loop, deployment topologies |
| Docker Compose quick start | The fastest path to a running stack |
| Manual and systemd | Bare-metal installation and the service unit |
| Configuration | Every environment variable |
| Address filter | Storing only the addresses you care about |
| Security | Read-only roles, row caps, proxy guards, secrets |
| Upgrading | Upgrade order, index migration, re-indexing |
| Troubleshooting | Diagnostics and common failures |
| REST API | Endpoints, encodings, filtering, pagination |
| Database and indexes | Schema, checkpoint, index strategy, storage planning |
| Docker image | Tags, architectures, running, upgrades, rollback |
ADAMANT maintains this project and runs it in production to power Ethereum and ERC-20 transaction history in its wallets: adamant-im for Web, PWA, Electron, and Android, and adamant-iOS on iOS.
That deployment is a documented adopter, not a requirement — no ADAMANT component is needed to run the indexer. It is useful to third-party operators as evidence: the API contract is exercised by shipping clients, and the recommended index set was derived from auditing real production query traffic, which is where the 90–110 GB saving over the legacy index set comes from.
The production query patterns, useful as a compatibility checklist for your own client, are documented on Used by ADAMANT.
Pull requests target dev. Development setup, the checks CI runs, the release process, and the security contact are in Contributing and Releases. Contributors working with AI assistants should also read AGENTS.md.
npm ci # documentation and Markdown tooling
npm run docs:dev # documentation site with hot reload
npm run lint:py # Python syntax checks
npm test # Python unit testsCopyright © 2025–2026 ADAMANT developer community
Copyright © 2020–2024 ADAMANT Foundation
Copyright © 2017–2020 ADAMANT TECH LABS LP
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
