Skip to main content
In this guide you choose how to collect BOT Chain events into your own database, and build a small indexer that keeps itself up to date from the BOTScan API.

Why indexing needs a plan on BOT Chain

Most indexers read events with eth_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.
Events without getLogs shows each of these with code.

Build a polling indexer

This indexer reads USDT Transfer 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
The design choices:
  • Fixed block windows. BOTScan returns at most 1,000 logs per request, and on 2026-10-02 its offset parameter 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.json holds 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

Run it again to pick up new blocks. To keep it running, call it from a scheduler such as cron, or wrap the body in a loop with a pause between passes.

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
A second run started from the checkpoint and read only the new blocks:
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, so eth_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.
Uzo Index is a planned Uzo service for indexed BOT Chain events, so apps can query history without running their own indexer or node. It isn’t live, and its endpoints and pricing haven’t been published. Until it is, use the polling indexer above or your own node. Follow its status on the Uzo Index page.

Troubleshooting

Lower WINDOW, then delete state.json and the output file and run again, or set nextBlock back to the start of the failed window.
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 is busy or rate limiting you. Wait and run again. The checkpoint means nothing is lost.
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.
Last modified on October 2, 2026