When to use the explorer, and when to use the RPC
The explorer is an indexer run by a third party. Treat its answers as convenient, not authoritative, and check anything that moves money against the chain.
What you’ll build
botscan.ts, a script with four parts:
- A fetch helper that retries when BOTScan is busy.
- Paged reads from the REST API (v2).
- Event logs from the Etherscan-style API, decoded with viem.
- A verified contract’s ABI, loaded through the Uzo SDK and used to call the contract.
Prerequisites
- Node.js 22 or later.
Steps
1
Create the project
2
Write the script
botscan.ts
wallet with the address you want to look up.3
Run it
Verify it worked
Output from a run on testnet on 2026-10-02:Output
How each part works
Retries
BOTScan doesn’t publish rate limits. Thebotscan helper retries on 429 and 5xx responses, waiting 1, 2, then 4 seconds. Other errors, such as 404, fail straight away because retrying won’t help. For anything that runs often, also cache responses: a confirmed transaction never changes.
Pagination
REST list endpoints takepage and page_size, and return total_pages so you know when to stop. Loop until page reaches total_pages, or until you’ve found what you need.
Event logs
The Etherscan-stylegetLogs returns raw logs. parseEventLogs from viem decodes them with an ABI, so you get typed args instead of hex topics.
Three details matter:
- Filtering by more than one topic needs an operator. When you pass both
topic0andtopic1, addtopic0_1_opr=and(oror). Without it, BOTScan answersRequired query parameters missing: topic0_1_oprandresultisnull. The same applies to other pairs, such astopic0_2_opr. - Don’t rely on
offsetto limit results. On 2026-10-02 the request above returned 6 logs withoffset=5and also withoffset=2. Limit the range withfromBlockandtoBlock, and slice the results in your code. - The raw logs aren’t quite RPC logs. BOTScan pads
topicswithnulland leaves outblockHash, so the script removes thenullentries and fills in the missing fields before decoding.
topic1 is the indexed from address, padded to 32 bytes. Use topic2 to filter by to instead.
Contract ABIs
createExplorerClient from @uzolabs/sdk/explorer wraps BOTScan’s contract endpoints. getContract returns the contract’s name, ABI, verified flag and, for proxies, the implementation addresses. With the ABI, viem can call any function by name.
Only use ABIs loaded at runtime for reading or display. For code that sends transactions, keep the ABI in your source so a change on the explorer can’t change what you sign.
Troubleshooting
Required query parameters missing: topic0_1_opr
Required query parameters missing: topic0_1_opr
You filtered by two topics without saying how to combine them. Add
&topic0_1_opr=and.result is null or an empty array
result is null or an empty array
Check
message in the response. If it says no records were found, check the address, the topics and the block range. Topic addresses must be lowercase and padded to 32 bytes.BOTScan answered 429
BOTScan answered 429
You sent too many requests. Raise
attempts, add a delay between pages, or cache responses.getContract returns an empty ABI
getContract returns an empty ABI
The contract isn’t verified on BOTScan. Verify it first. See Verify contracts.
Mainnet requests return different data
Mainnet requests return different data
The script uses
botChainTestnet. For mainnet, import botChain from @uzolabs/sdk/chains and use it in place of botChainTestnet. Both the explorer URL and the addresses follow the chain.Next steps
Events without getLogs
Show contract events in a frontend.
Index chain data
Options for larger data needs.