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.

1

Install

terminal
curl -fsSL https://raw.githubusercontent.com/slvDev/sieve/main/sieveup/install | bash

Run sieveup anytime to update to the latest version.

2

Init

terminal
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:

.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.

3

Add contracts

From Etherscan

terminal
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

sieve.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.

4

Run

terminal
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.

output
  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.

during sync
  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.

5

Query

Open http://localhost:4000/graphql for the GraphiQL IDE, or query programmatically:

graphql
{
  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.

Next steps

Why Sieve how P2P indexing works and why it matters
Chains index Base, OP Mainnet, Unichain, or World Chain