This guide reads Arrow directly with the Arrow reader
(
bloklake_arrow.py): its tables write to Parquet without any conversion. The
client libraries return JSON rows instead, which suit application code better.One file per range
Write each page as you receive it, so memory stays flat however large the export:bl.* metadata of the first page. Strip it if your tools
complain: table.replace_schema_metadata(None).
Partitioned exports
For a large history, write one file per block range, for example every 100,000 blocks. You can then re-export, verify or delete a single partition:finalized_block, so a partition never has to be rewritten after
a reorg. See Finality and reorgs.
Query with DuckDB
BLOB. hex() turns one into 64 uppercase hex characters;
substr(…, 25) keeps the last 40 (the address; DuckDB counts from 1), and lower() gives the
usual lowercase form.
Big amounts
value, gas prices and other amounts are 16-byte big-endian binary (32 bytes for the Arbitrum
retryable amounts). Parquet has no unsigned 128-bit integer. Three options:
- Convert to a decimal string when you write (simplest, as in
Index ERC-20 transfers), and cast to
HUGEINTorDECIMAL(38,0)in queries. - Convert to
decimal128(38, 0): fits any 128-bit value below 10³⁸ (every realistic wei amount), and engines can sum it natively. - Keep the bytes and convert in queries when needed.
Into a warehouse
- ClickHouse:
INSERT INTO t FORMAT ArrowStreamaccepts the response body of a single-stream query directly, or load the Parquet files. - BigQuery, Snowflake, Spark: load the Parquet files from object storage.
block_number and log_index (or transaction_index) on every row. Together
they’re a unique, stable key for re-runs and deduplication.