Documentation Index
Fetch the complete documentation index at: https://docs.dune.com/llms.txt
Use this file to discover all available pages before exploring further.
balances_<chain>.daily_updates is the default table for historical balance analysis. It is sparse: one row is written per (address, token_address) balance change, not one row per day per pair. Each row carries a validity interval [valid_from, valid_to) covering the days during which that balance was held. Adjacent intervals share the boundary day on valid_from / valid_to (no gap, no overlap). Refreshed hourly.
The interval layout lets you reconstruct the balance for any (address, token_address) on any past day by selecting the row where valid_from <= day < valid_to. To get per-day rows across a window, expand the interval against a calendar table (see Example Queries).
valid_to = '9999-12-31' marks the active (ongoing) interval. USD value is joined from prices.day at valid_from. Zero-balance periods are kept as their own intervals, so filter balance > 0 if you want to exclude empty holdings.
Table Schema
| Column | Type | Description |
|---|---|---|
blockchain | varchar | Chain identifier |
address_prefix | varchar | First byte of address, lower-hex (partition key) |
address | varbinary | Account address |
token_address | varbinary | Token contract address. Native tokens use the standardized address from dune.blockchains (zero address on most EVMs, 0x0000…1010 on Polygon). |
token_standard | varchar | native or erc20 |
token_symbol | varchar | Token symbol from tokens_<chain>.erc20 (nullable) |
balance_raw | uint256 | Balance in raw units while the interval is valid |
balance | double | Balance in display units (balance_raw / 10^decimals, falls back to 18 decimals when unknown) |
balance_usd | double | balance * prices.day.price at valid_from. NULL when no price is available for that token; coalesce(balance_usd, 0) if you need to sum across mixed-coverage tokens. |
valid_from | date | First day of the interval (inclusive) |
valid_to | date | First day after the interval (exclusive). 9999-12-31 for the active interval. |
balance_updated_at | timestamp | Block time of the underlying balance update |
Usage Notes
The table is partitioned byaddress_prefix, the first byte of address rendered as a 2-character lower-hex string ('00'..'ff'). For best performance, include all three of:
- A cohort filter on
addressand/ortoken_address. - A partition filter
address_prefix IN (...)matching the addresses in your cohort. For a hardcoded address the prefix is the first hex byte (e.g.0xd8dA…→'d8'). For a dynamic cohort, materialize the distinct prefixes in a subquery so the planner can prune partitions:address_prefix IN (SELECT DISTINCT lower(to_hex(varbinary_substring(address, 1, 1))) FROM <cohort>). - Day bounds on the interval:
valid_from <= <end_date> AND valid_to > <start_date>. These let the scanner skip files that fall outside the window. The active row (valid_to = '9999-12-31') is naturally included byvalid_to > <start_date>.
utils.days calendar table. For very large outputs (hundreds of millions of rows), CROSS JOIN UNNEST(sequence(...)) clips the day sequence at generation time and is typically faster.
Example Queries
Daily USDC balance for a wallet, last 30 days:cex.addresses, a curated table of known centralized-exchange wallets. The same pattern works for any cohort table or uploaded address list.