Skip to content

Index a bounded Mainnet range

Index 1,000 Ethereum Mainnet blocks and query the last Uniswap V2 pool-reserve observation in each hour. This uses public Xatu data, needs no API key, and stops after a finite range.

First install from source so leani and LEANI_SOURCE are available in your terminal. The commands below copy a complete configuration into a fresh temporary directory:

Bounded Mainnet run
LEANI_HISTORY_DIR="$(mktemp -d)"
cp "$LEANI_SOURCE/config/modes/windowed.toml" "$LEANI_HISTORY_DIR/leani.toml"
cd "$LEANI_HISTORY_DIR"
leani doctor --json
leani backfill \
--processor uniswap-v2-sync-30d --from 17000000 --to 17000999
leani serve
Use the checked-in configuration to index a finite Mainnet range.Verified source

doctor should report valid: true. The backfill report should show continuous coverage from 17000000 through 17000999. Leave serve running and query it from another terminal:

Query indexed Uniswap events
curl -s \
'http://127.0.0.1:8080/v1/processors/uniswap-v2-sync-30d/collections/uniswap_v2.sync_hourly/entities?limit=3'
curl -s \
'http://127.0.0.1:8080/v1/processors/uniswap-v2-sync-30d/status'
Read decoded Mainnet events and their exact processor coverage from the local API.Verified source

Expect five hourly entities for this range; limit=3 returns only the first page. Follow nextCursor to read the rest. Entities are ordered by their keys, so sort by bucketStartTimestamp when drawing a time series.

Each entity contains values.reserve0 (USDC, six decimals) and values.reserve1 (WETH, eighteen decimals). These are exact integer strings. The processor retains the last Sync observation per hourly bucket; it does not return every swap or an hourly average price.

Check coverage

The status response’s available intervals should cover the entire requested range. A high processedThrough alone does not prove that earlier blocks were indexed. Xatu’s finalized label is a dataset assertion; this profile has independent finality verification disabled.

Try an explicit range query, then one outside your indexed interval:

Terminal window
curl -s 'http://127.0.0.1:8080/v1/processors/uniswap-v2-sync-30d/collections/uniswap_v2.sync_hourly/entities?fromBlock=17000000&toBlock=17000999'
curl -s 'http://127.0.0.1:8080/v1/processors/uniswap-v2-sync-30d/collections/uniswap_v2.sync_hourly/entities?fromBlock=17001000&toBlock=17001999'

The first should return retained entities with complete requested coverage. The second should return range_incomplete, rather than an empty success. An indexed range whose output was subsequently pruned returns output_not_retained.

Decode a different contract event

The configuration’s processors.settings selects the contract address and Solidity event ABI. For a small WETH transfer example, use the complete config at examples/weth-transfers/node.toml:

Terminal window
LEANI_EVENTS_DIR="$(mktemp -d)"
cp "$LEANI_SOURCE/examples/weth-transfers/node.toml" "$LEANI_EVENTS_DIR/leani.toml"
cd "$LEANI_EVENTS_DIR"
leani doctor --json
leani backfill --processor weth-transfers --from 17000000 --to 17000009
leani serve

This example uses API port 8081 so it can run beside the Uniswap node. Query:

Terminal window
curl -s 'http://127.0.0.1:8081/v1/processors/weth-transfers/collections/weth.transfers/entities?limit=100'

Expect 205 transfers across three pages. Each entity’s values contains from, to, and value; WETH uses 18 decimals. Change the address, ABI, collection, instance name, and block range for your contract. Keep history_mode = "on_demand" for explicit backfills, and use a fresh data directory when changing processor identity or schema.

For a transformation beyond static event decoding, build your own processor with the Rust library.