A lightweight Ethereum L2 blockchain explorer with NFT support.
Atlas is a minimal, fast blockchain explorer designed for custom Ethereum L2 networks. It provides:
- Block and transaction browsing
- Address tracking with labels
- ERC-721 NFT indexing with metadata
- ERC-20 token indexing and balances
- Event log decoding
- Contract verification
- Proxy contract detection
- Etherscan-compatible API
- Universal search
atlas/
├── backend/ # Rust backend services
│ ├── crates/
│ │ ├── atlas-common/ # Shared types and database models
│ │ ├── atlas-indexer/ # Blockchain indexer + metadata fetcher
│ │ └── atlas-api/ # REST API server (Axum)
│ └── migrations/ # PostgreSQL migrations
├── frontend/ # React frontend (Vite + Tailwind)
├── docker-compose.yml # Container orchestration
└── docs/
└── PRD.md # Product requirements
- Docker and Docker Compose
- Bun 1.0+ (for frontend development)
- Rust 1.75+ (for backend development)
-
Set your RPC endpoint:
export RPC_URL=https://your-l2-rpc.example.com -
Start all services:
docker-compose up -d
-
Access the explorer at http://localhost:3000
Backend:
cd backend
# Start PostgreSQL
docker-compose up -d postgres
# Set environment variables
export DATABASE_URL=postgres://atlas:atlas@localhost/atlas
export RPC_URL=https://your-l2-rpc.example.com
# Run the indexer
cargo run --bin atlas-indexer
# In another terminal, run the API server
cargo run --bin atlas-apiFrontend:
cd frontend
bun install
bun run dev| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Required |
RPC_URL |
Ethereum JSON-RPC endpoint | Required |
START_BLOCK |
Block number to start indexing from | 0 |
BATCH_SIZE |
Number of blocks to index per batch | 100 |
REINDEX |
Set to true to wipe and reindex |
false |
RPC_REQUESTS_PER_SECOND |
Rate limit for RPC calls | 100 |
IPFS_GATEWAY |
IPFS gateway for NFT metadata | https://ipfs.io/ipfs/ |
METADATA_FETCH_WORKERS |
Concurrent metadata fetch workers | 4 |
API_HOST |
API server bind address | 0.0.0.0 |
API_PORT |
API server port | 3000 |
SOLC_PATH |
Path to solc binary for verification | solc |
| Endpoint | Description |
|---|---|
GET /api/blocks |
List blocks (paginated) |
GET /api/blocks/:number |
Get block by number |
GET /api/blocks/:number/transactions |
Get transactions in block |
| Endpoint | Description |
|---|---|
GET /api/transactions/:hash |
Get transaction by hash |
| Endpoint | Description |
|---|---|
GET /api/addresses/:address |
Get address info |
GET /api/addresses/:address/transactions |
Get address transactions |
GET /api/addresses/:address/nfts |
Get NFTs owned by address |
| Endpoint | Description |
|---|---|
GET /api/nfts/collections |
List NFT collections |
GET /api/nfts/collections/:address |
Get collection details |
GET /api/nfts/collections/:address/tokens |
List tokens in collection |
GET /api/nfts/collections/:address/tokens/:id |
Get token details |
GET /api/nfts/collections/:address/tokens/:id/transfers |
Get token transfer history |
| Endpoint | Description |
|---|---|
GET /api/tokens |
List ERC-20 tokens |
GET /api/tokens/:address |
Get token details |
GET /api/tokens/:address/holders |
Get token holders |
GET /api/tokens/:address/transfers |
Get token transfers |
GET /api/addresses/:address/tokens |
Get address token balances |
| Endpoint | Description |
|---|---|
GET /api/transactions/:hash/logs |
Get transaction logs |
GET /api/transactions/:hash/logs/decoded |
Get decoded transaction logs |
GET /api/addresses/:address/logs |
Get logs emitted by contract |
GET /api/logs?topic0=:sig |
Filter logs by event signature |
| Endpoint | Description |
|---|---|
GET /api/labels |
List address labels |
GET /api/labels/:address |
Get label for address |
GET /api/labels/tags |
List all tags |
POST /api/labels |
Create/update label |
DELETE /api/labels/:address |
Delete label |
| Endpoint | Description |
|---|---|
GET /api/proxies |
List proxy contracts |
GET /api/contracts/:address/proxy |
Get proxy info |
GET /api/contracts/:address/combined-abi |
Get combined ABI |
POST /api/contracts/:address/detect-proxy |
Trigger proxy detection |
| Endpoint | Description |
|---|---|
POST /api/contracts/verify |
Submit source for verification |
GET /api/contracts/:address/abi |
Get verified ABI |
GET /api/contracts/:address/source |
Get verified source code |
| Endpoint | Description |
|---|---|
GET /api?module=account&action=balance |
Get address balance |
GET /api?module=account&action=txlist |
Get address transactions |
GET /api?module=account&action=tokentx |
Get token transfers |
GET /api?module=contract&action=getabi |
Get contract ABI |
GET /api?module=contract&action=getsourcecode |
Get contract source |
POST /api?module=contract&action=verifysourcecode |
Verify contract source |
| Endpoint | Description |
|---|---|
GET /api/search?q=:query |
Universal search (blocks, txs, addresses, NFTs) |
All list endpoints support pagination:
page- Page number (default: 1)limit- Items per page (default: 20, max: 100)
Response format:
{
"data": [...],
"page": 1,
"limit": 20,
"total": 1000,
"total_pages": 50
}blocks- Block headerstransactions- Transaction dataaddresses- Known addressesnft_contracts- ERC-721 contract registrynft_tokens- NFT token ownership and metadatanft_transfers- NFT transfer historyerc20_contracts- ERC-20 token registryerc20_transfers- ERC-20 transfer eventserc20_balances- Token balances per addressevent_logs- All emitted eventsevent_signatures- Known event signatures for decodingaddress_labels- Curated address labelscontract_abis- Verified contract ABIs and sourceindexer_state- Indexer progress tracking
cd backend
cargo testcd backend
cargo build --releaseBinaries will be at:
backend/target/release/atlas-indexerbackend/target/release/atlas-api
cd frontend
bun run buildBuild output will be in frontend/dist/.
To reindex the chain from scratch:
# Option 1: Environment variable
REINDEX=true docker-compose up atlas-indexer
# Option 2: Truncate tables manually
psql $DATABASE_URL -c "TRUNCATE blocks, transactions, addresses, nft_contracts, nft_tokens, nft_transfers, indexer_state CASCADE;"MIT