Guide
Build an explorer or indexer
Which routes and streams an explorer needs for each page, how to index every finalized cut, and how to show payloads and miner tags safely.
On this page
The reference explorer is the quickest start: a React frontend and a small Node.js backend that reads a node through the SDK. It is open source, and you can change it into your own.
npm install
npm run build
npm startIt serves http://127.0.0.1:28783 and reads the node at TENRAI_URL, by default http://127.0.0.1:28701. Set TENRAI_TARGET=api to read the Tenrai API instead.
What each page reads
| Page | Routes |
|---|---|
| Overview | /v1/chain/head, /v1/chain/rates, /v1/chain/epoch, /v1/mempool, /v1/economics/supply, /v1/cuts?limit=, /v1/blocks/recent, /v1/transactions/recent |
| Cut | /v1/cuts/{height}, then /blocks and /transactions of that cut |
| Work block | /v1/blocks/{id} |
| Transaction | /v1/transactions/{id} and /v1/transactions/{id}/status |
| Address | /v1/address/{address}/balance, /history, /words, and POST /v1/mempool/pending |
| Mempool | /v1/mempool, /v1/mempool/transactions, /v1/fees/estimate |
| Validators | /v1/staking/validators, /v1/staking/uptime, /v1/staking/validators/{id}/positions |
| Charts | /v1/gateway/history on the Tenrai API |
Search
| Input | Is |
|---|---|
| Digits only | A cut height |
| 96 hexadecimal characters | A work block ID or a transaction ID. Ask both; one answers 404 |
Starts with trai1, ttrai1 or dtrai1 | An address. Check the checksum before the request |
Live updates
Subscribe on /v1/ws instead of polling: cuts for the head, blocks for new work blocks, mempool and rates for the counters, transaction for an open transaction page, addresses for an open address page. Serve many visitors from one upstream socket and one short cache; the reference explorer reads its overview at most once a second for everyone.
States to show
A work block's state is pooled, registered or executed; retained marks an older block the node still keeps. Its reward follows separately:
reward.state | Meaning |
|---|---|
pending | The anchor's registration window is still open, so the block's share of the subsidy can change |
queued | The amount is final and waits for its payout |
paid | Paid, with subsidy and fees |
For transactions, show the lifecycle and, once final, confirmations. One confirmation is final.
Index everything
To keep your own database of the chain:
- Open
/v1/eventsand store the height of eachcut_finalizedyou have handled. - For each cut read
/v1/cuts/{height}, its/blocks, its/transactionsin pages of up to 64 and its/changesin pages of up to 4,096. - Write a cut and everything belonging to it in one database transaction.
- After a restart reconnect with
?after_height=. If the gap is older than an hour, walk the missing heights over HTTP first.
Finalized cuts never change, so an index only ever appends. You can cache a finalized cut, block or transaction for good.
A node serves bodies back to the body_history_floor of GET /v1/storage. Index from a node in full or archive mode.
Burns
An output paid to the burn address is part of the transaction but never enters the output set: the cut that executes the transaction burns its amount. The /changes of a cut never list it, and an index that builds the output set from transaction bodies has to skip it. Show such outputs as burned; the SDK's isBurnAddress recognizes the address. burned in /v1/economics/supply counts every burn.
Text from the chain
Payloads and miner tags are written by whoever sent the transaction or mined the block. Treat both as hostile input.
- Show a payload as text only when it is valid UTF-8 without control, direction-changing or invisible characters. Otherwise show hexadecimal.
- Never render either as HTML, and never turn them into links.
- A transaction may carry one payload per recipient. The SDK's
recipientPayloadssplits it; show each entry beside its output. - A messenger frame is a chat message. Name it, for example "Messenger payload", and show none of its bytes;
isMessengerPayloadtells.
The SDK's payloadText applies the same rule the Tenrai wallets use.
