When you design a new blockchain explorer, commercial API, or wallet backend, start with two questions: what can the node answer on its own over standard JSON-RPC, and what can’t it? Everything you end up building — the index — lives in the gap between the two.
What the node can answer on its own
Out of the box, over standard JSON-RPC, the answer differs sharply by chain family.
UTXO chains (Bitcoin-like)
- Blocks and transactions by hash/height.
- Mempool contents and individual outpoint state (spent/unspent) by txid+vout.
- Fee estimates and chain state.
EVM chains (Ethereum-like)
- Point-in-time account state: balance, nonce, contract storage, code.
- Transactions and receipts by tx hash.
- Blocks by number, with full tx list if requested.
- Logs by filter over a block range (nodes typically index logs, but queries are range-based).
Rich-RPC chains (account-based — Solana, XRP, Stellar)
- Address → history, served by the node itself: Solana
getSignaturesForAddress (paginated by signature cursor), XRP Ledger account_tx, Stellar Horizon /accounts/{id}/transactions. - Address → token holdings, served by the node itself: Solana
getTokenAccountsByOwner (every SPL token account of an owner), XRP account_lines (trust lines / issued-asset balances), Stellar account balances (native + assets in one call). - Current balance of an arbitrary address directly — account ledgers keep balance as first-class state (
getBalance / account_info / Horizon account balances), with no UTXO aggregation needed.
What the node cannot answer
These are the address-level questions a plain node won’t serve without scanning the whole chain.
UTXO chains
- All transactions for a given address or xpub without scanning all blocks.
- Current balance for an arbitrary address without scanning all its txs/UTXOs.
- Address-level history, paging, or balance history over time.
EVM chains
- Address-indexed transaction history (not available in standard JSON-RPC).
- Token lists and balances for an address without scanning logs or traces.
- Internal transactions for an address without tracing each block/tx.
- Address-level history paging or balance history over time.
Rich-RPC chains
- Comparatively little — the node already answers the address-indexed queries above. What’s missing is mostly enrichment, not core relations: fiat pricing, human-readable labels, decoded instructions/memos, and cross-account analytics.
The index you have to build
So you design an indexing scheme with the bare minimum to serve address-balance and tx-history queries efficiently — the relations the node won’t give you, one set per chain family.
UTXO chains — missing relations
- Address → Transactions
Map any address (or xpub) to the set of txs that touch it, with ordering for paging. - Address → Current Balance
Aggregate spendable UTXOs per address (and optionally per xpub/account). - UTXO Set (txid:vout → state)
Track spend/unspent state for fast balance and spendability checks. - Address → History (time/height deltas)
For balance history charts, first/last activity, and pagination. - xpub → Derived Addresses (wallet layer)
Keypath-based derivation and grouping.
EVM chains — missing relations
- Address → Transactions
Map address to txs it sent/received (native transfers), with paging. - Address → Token Transfers
Map (address, token) to all token transfer events, with ordering. - Address → Token Balances
Maintain current ERC20/721/1155 balances without rescanning logs. - Contract → Holders / Holder Counts (optional)
Useful for analytics and token pages. - Internal Transfers → Addresses
Requires traces to index internal calls/transfers by address. - Address → Activity Summary
First/last activity, counts, volumes, etc., for fast UI queries.
Rich-RPC chains — (almost) nothing to index
Here the assumption flips: the node is already the address index. Solana, XRP and Stellar are account-based ledgers whose native API exposes address → history and owner → token holdings as first-class queries — exactly the relations you would otherwise have to build yourself.
- Address → Transactions / Token holdings
Provided by the node (getSignaturesForAddress + getTokenAccountsByOwner; account_tx + account_lines; Horizon account endpoints). No secondary index required. - What’s left for the backend
The wallet backend — usually the holder of the address index — can here talk to the node (almost) directly and shrinks to an enrichment + caching layer: fiat rates, labels, decoded data, fan-out / rate-limit smoothing, and pagination ergonomics.
In short
Nodes give you point-lookups — by hash, height, or account at a block — but not address-indexed history or token relationships. Those are the core relations an explorer or wallet backend must build; a UTXO node won’t even give you the balance of an arbitrary address.
The exception is account-based, rich-RPC chains (Solana, XRP, Stellar): the node already serves address → history and owner → token holdings, so there the backend — usually the holder of that index — shrinks to an enrichment and caching layer. For those chains the expensive address-and-token index is already paid for by the node, and a heavyweight indexer adds little beyond enrichment — the opposite of the UTXO/EVM case, where it’s mandatory.