A high-performance validator reward statistics service for Ethereum validators. Tracks and caches validator rewards, providing a RESTful API for querying reward data and deposit analytics.This repo contains both backend (Go) and frontend. Set ENABLE_FRONTEND=false to run backend API only.
After nearly two years of running the Endurance beacon explorer, we found the upstream Beaconchain stack both hard to maintain (v1 errors and heavy technical debt) and hard to adopt (v2 relies on closed-source internal tooling) while locking operators into an expensive Bigtable/Redis/ClickHouse/Postgres footprint. We built this lighter service to pair with Dora and our own beacon/execution nodes instead of relying on a costly, half-open explorer; see the blog post for the full story.
git clone <repository-url>
cd beacon-rewards
cp .env.example .env # edit to match your nodes and DB
make deps
make run # builds, regenerates Swagger, and starts the serverVisit Swagger at http://localhost:8080/swagger/index.html. To disable HTML pages and run API-only, set ENABLE_FRONTEND=false.
docker build -t beacon-rewards .
docker run -p 8080:8080 --env-file $(pwd)/.env -v $(pwd)/data:/app/data --name beacon-rewards beacon-rewardsUse --restart=unless-stopped for long-running deployments.
Set environment variables or use .env (see .env.example):
| Variable | Description | Default |
|---|---|---|
SERVER_ADDRESS |
Listen address | 0.0.0.0 |
SERVER_PORT |
Listen port | 8080 |
ENABLE_FRONTEND |
Serve HTML pages/static assets | true |
BEACON_NODE_URL |
Beacon chain node endpoint(archive node) | http://localhost:5052 |
EXECUTION_NODE_URL |
Execution layer node endpoint (archive node) | http://localhost:8545 |
DORA_PG_URL |
Dora Postgres URL (required for deposit endpoints) | postgres://postgres:postgres@127.0.0.1:5432/dora?sslmode=disable |
DEPOSITOR_LABELS_FILE |
YAML mapping addresses to labels | depositor-name.yaml |
BACKFILL_LOOKBACK |
Relative backfill window before startup (duration like 1h; empty uses today's 00:00 UTC+8) |
unset |
EPOCH_CHECK_INTERVAL |
Polling interval for live sync | 12s |
EPOCH_PROCESS_MAX_RETRIES |
Max retries per epoch before skipping | 5 |
EPOCH_PROCESS_BASE_BACKOFF |
Initial backoff for epoch retries | 2s |
EPOCH_PROCESS_MAX_BACKOFF |
Max backoff for epoch retries | 30s |
BACKFILL_CONCURRENCY |
Workers used during backfill | 16 |
REWARDS_HISTORY_FILE |
Path to append-only reward history log | data/reward_history.jsonl |
LOG_LEVEL |
debug, info, warn, error |
info |
LOG_FORMAT |
text or json |
text |
-
Genesis timestamp is fetched from the configured beacon node via
/eth/v1/beacon/genesis; no configuration is required. -
Ensure the
data/directory is writable if you keep the defaultREWARDS_HISTORY_FILE. -
Backfills are intended to cover recent history only.
BACKFILL_LOOKBACKis rounded to the nearest epoch boundary. Larger windows can marginally improve initial reward accuracy, but returns diminish quickly; smaller values trade a tiny precision loss for faster startup. This is not an archive-mode reprocessing tool, very large ranges will significantly increase memory usage and RPC traffic. Therefore, we recommend using a window of no more than24hfor backfills.
GET /healthPOST /rewards– validator rewards for specific indicesGET /rewards/network– aggregate rewards snapshotPOST /rewards/by-address– rewards aggregated by depositor/withdrawal addressGET /deposits/top-withdrawals– staking leaderboard indexed by withdrawal addressGET /deposits/top-deposits– staking leaderboard indexed by depositor address
Full request/response shapes are documented in Swagger (/swagger/index.html).
We support labeling depositor/withdrawal addresses (e.g., exchanges, staking pools) to make them easily identifiable in the UI and API.
To add or update a label:
- Fork this repository.
- Edit the
depositor-name.yamlfile. - Add a new entry or update an existing one:
"0xYourAddressHere": "Your Label Name"
- Submit a Pull Request.
- Run tests:
make test - Lint:
make lint - Build + regenerate Swagger docs:
make build - Clean artifacts:
make clean - Docker helpers: see
Makefiletargets (docker-build,docker-run, etc.)
docs/ is generated by swag—do not edit by hand. Regenerate after handler or annotation changes.
- See
CONTRIBUTING.mdfor workflow and tooling. - Licensed under the GNU Affero General Public License v3.0 (see
LICENSE).