Why indexing needs a plan on BOT Chain
Most indexers read events witheth_getLogs. BOT Chain documents that method as disabled on its public RPC endpoints. In our tests it answered for bounded block ranges, but you shouldn’t build production code on a method the chain says is off. See Known limitations.
That rules out pointing a standard indexing framework at the public RPC. You have these options today:
Avoid indexing if you can
Many apps don’t need an indexer at all:- Read state, not events. If the contract stores what you need, read it directly, and batch the reads with Multicall3.
- Read your own receipts. Events from a transaction you sent are in its receipt. Save them when the transaction confirms.
- Store a short history on chain. A ring buffer of recent activity can replace an event query for a feed.
Build a polling indexer
This indexer reads USDTTransfer events from the BOTScan API, a window of blocks at a time, and appends them to a file. It saves its progress, so each run starts where the last one stopped. Run it on a schedule, or in a loop with a pause.
Prerequisites
- Node.js 22 or later.
1
Create the project
2
Write the indexer
indexer.ts
- Fixed block windows. BOTScan returns at most 1,000 logs per request, and on 2026-10-02 its
offsetparameter didn’t limit results. Small block ranges keep each answer complete. If a window hits the cap, the script stops instead of silently missing logs. - A checkpoint after each window.
state.jsonholds the next block to read. It’s written after the data, so a crash means a window is read twice, never skipped. Make your writes idempotent, for example by using the transaction hash and log index as a key. - Confirmations. The indexer stays behind the newest block so it doesn’t record blocks that might still change. Pick the depth that matches how much risk your app can take.
3
Run it
Verify it worked
On testnet on 2026-10-02, the first run read from block 25,399,000 to the head. The output ended with:Output
transfers.jsonl held 10 transfers, one JSON object per line:
transfers.jsonl
Output
Take it further
- Write to a database instead of a file, and save the checkpoint in the same transaction as the rows.
- Add the retry helper from Use the BOTScan API.
- Index more than one contract by looping over addresses, with a checkpoint for each.
- Check important records against the chain. BOTScan is a third party, so confirm anything that moves money with a receipt from the RPC.
Run your own node
A node you run has no public endpoint limits, soeth_getLogs works over any range you allow. Any indexing framework that reads from an RPC can then point at it.
BOT Chain’s node documentation links to a deployment repository that returned 404 when we checked on 2026-10-01. Ask BOT Chain for current node instructions before you plan around this option. See Known limitations.
Uzo Index
Planned. This service is not live yet. This page explains what it will do and what to use in the meantime.
Troubleshooting
Window hit the 1,000 log cap
Window hit the 1,000 log cap
Lower
WINDOW, then delete state.json and the output file and run again, or set nextBlock back to the start of the failed window.No logs found
No logs found
BOTScan answers
{"message":"No logs found","result":[],"status":"0"} when a range is empty. The script treats that as zero transfers. If every window is empty, check the contract address and START_BLOCK.BOTScan answered 429 or 5xx
BOTScan answered 429 or 5xx
BOTScan is busy or rate limiting you. Wait and run again. The checkpoint means nothing is lost.
The first run takes a long time
The first run takes a long time
Set
START_BLOCK to your contract’s deployment block, which BOTScan shows on the contract’s page, instead of an early block.Next steps
Use the BOTScan API
Pagination, retries and decoding.
Events without getLogs
Patterns that avoid indexing.