Building

Run the indexer

The charts, trade history, holder counts and the explorer are all served from a small event indexer. It's open — run your own copy against any RPC.

What it does

The indexer (web/indexer/run.mjs, viem + better-sqlite3) backfills and then polls the Launchpad's events — TokenLaunched, Bought, Sold, Graduated — into a local SQLite database at web/.data/indexer.db. The Next.js API routes read from that DB and expose it as JSON.

  • Idempotent. Each trade is unique on (txHash, logIndex), so re-running never double-counts.
  • Resumable. Progress is stored in a meta.lastBlock row; a restart picks up where it left off.
  • Derived views. Holder counts come from net trade balances; OHLC candles are bucketed from raw trades in JS.

Run it

bash
cd web

# one-shot backfill then exit
RPC_URL=https://rpc.testnet.chain.robinhood.com \
LAUNCHPAD_ADDRESS=0x4874AB389827d4BC9be9750163c59398D4C91Cd9 \
ONCE=1 npm run indexer

# or run continuously (backfill + poll for new blocks)
RPC_URL=https://rpc.testnet.chain.robinhood.com \
LAUNCHPAD_ADDRESS=0x4874AB389827d4BC9be9750163c59398D4C91Cd9 \
npm run indexer
Note.ONCE=1 backfills and exits — handy for cron. Without it the process stays up and polls. The web app auto-detects the DB; if the indexer isn't running it falls back to direct RPC reads, then to demo data.

Data endpoints it powers

These read straight from the indexed DB:

EndpointReturns
GET /api/tokensAll tokens with price, volume, holders.
GET /api/tokens/:addr/tradesRecent trades for one token.
GET /api/tokens/:addr/candlesOHLC candles (query interval, seconds).
GET /api/activityCross-token trade feed for the explorer.
GET /api/statsGlobal aggregates: volume, trades, traders.

The stable, versioned, CORS-open equivalents live under /api/v1/* — see the API Reference.