Get Started
Sieve indexes Ethereum and OP-Stack events over P2P. No RPC provider, no code. This page walks you through setup in five steps.
Install
curl -fsSL https://raw.githubusercontent.com/slvDev/sieve/main/sieveup/install | bash
Run sieveup anytime to update to the latest version.
Init
sieve init
Creates sieve.toml, .env, and abis/erc20.json with a working USDC Transfer config. Add --docker to also generate a docker-compose.yml with PostgreSQL.
Set your database connection and Etherscan key in .env:
DATABASE_URL=postgres://postgres:sieve@localhost:5432/sieve ETHERSCAN_API_KEY=your_key_here
Sieve indexes Ethereum mainnet unless you say otherwise. For Base, OP Mainnet, Unichain, or World Chain, set the chain key at the top of sieve.toml and give it its own database. See Chains.
Add contracts
From Etherscan
sieve add-contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --name USDC
Fetches the ABI, detects proxies, sets start_block to the contract's deploy block, and appends a [[contracts]] block to your config.
Manual TOML
[[contracts]] name = "USDC" address = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" abi = "abis/erc20.json" start_block = 21_000_000 [[contracts.events]] name = "Transfer" table = "usdc_transfers" context = ["block_timestamp", "tx_from"]
Columns are auto-generated from the ABI. Solidity camelCase is converted to snake_case automatically. SQL reserved words are handled.
Run
sieve
Sieve prints a startup banner showing your config, database, tables, and API endpoint. It then backfills from each contract's start_block, catches up to the chain head, and follows new blocks in real-time.
sieve 0.2.0 config sieve.toml database postgres://postgres:***@localhost:5432/sieve tables usdc_transfers api http://localhost:4000/graphql ✓ synced 98,417 blocks in 1m 34s (1,046 blk/s, 12,933 events) following | block: 24,663,894 | 3s ago | peers: 50
While the backfill runs, a progress line redraws in place on that same row. It is replaced by the ✓ synced line above once the backfill finishes, so it never appears in a finished transcript.
syncing ████████████████████████████░░ 93% | 92,471 / 98,417 | peers: 38 | 1,050 b/s | remaining: ~5s
Add --fresh to drop and recreate all tables before indexing. Nothing is committed until a peer quorum confirms the canonical hash of the segment the block belongs to and its own payload roots check out, so Sieve stops rather than write data it could not verify. See Integrity.
Query
Open http://localhost:4000/graphql for the GraphiQL IDE, or query programmatically:
{
usdc_transfers(
where: {
OR: [
{ from_address: "0xAbc..." }
{ to_address: "0xAbc..." }
]
value_gte: "1000000000"
}
orderBy: block_number
orderDirection: desc
first: 50
) {
block_number
tx_hash
from_address
to_address
value
block_timestamp
}
}Every table gets filter operators, cursor-based pagination, and sorting. All auto-generated from your TOML config. See the GraphQL API reference for full details.