Skip to content

Repository files navigation

SRG20 Market Indexer

Small TypeScript service that ingests SRG20 events from BSC (or any EVM chain) and exposes REST endpoints with historical price, rolling volume, and liquidity data. Ponder keeps PostgreSQL in sync with on-chain events, while a lightweight Hono API serves aggregated, gap-free time series for charts or monitoring.

Architecture

  • Event indexing with Ponder. ponder.config.ts wires SRG20 contracts (addresses come from TOKENS_CONFIG_JSON) to a Postgres store. The handlers in src/handlers/handlers.ts listen to Bought, Sold, Transfer, and OwnershipTransferred events, maintain per-token supply/liquidity state, and persist every trade in the transactions table defined in ponder.schema.ts.
  • Derived liquidity tracking. Because SRG20 contracts do not emit AddLiquidity events, owner-to-contract transfers are detected and replay the same math as the contract so that liquidity and price stay in sync without querying the chain.
  • REST API on top of Postgres. src/api/index.ts is a Hono app mounted inside Ponder. It validates requests with Zod, buckets trades into hourly/daily/weekly intervals using SQL expressions, and fills missing buckets after retrieving datapoints from the db.
  • Config-driven deployment. All runtime specifics (RPC URLs, DB connection string, tracked tokens, chain ID/start block) sit in .env JSON strings, which keeps the codebase stateless and ready for multiple environments.
  • Tooling/observability. Viem handles EVM utilities, Pino logs structured messages, Biome enforces formatting/linting, and Docker Compose supplies a local Postgres instance.

Tech Stack

  • Runtime: Node.js 20+, pnpm, TypeScript
  • Indexer: Ponder with Postgres target
  • API: Hono + Zod validators
  • EVM utilities: Viem, SRG20 ABI (in abis/)
  • Tooling: Docker Compose (Postgres), Biome, dotenv-cli, Pino

Getting Started

  1. Install dependencies
    corepack enable pnpm
    pnpm install
  2. Provision Postgres (recommended via Docker)
    docker-compose up -d db
  3. Configure environment
    cp .env.example .env
    Fill in/separate secrets as needed. Key variables:
    • PONDER_RPC_HTTP_URL and PONDER_WS_HTTP_URL – RPC endpoints with archive access to your target chain.
    • DATABASE_URL – connection string for the Postgres instance Ponder will manage.
    • PONDER_CONFIG_JSON{ chainKey, chainId, startBlock }. The tokenAddresses array is auto-overridden with the values from TOKENS_CONFIG_JSON.
    • TOKENS_CONFIG_JSON – array of tracked tokens, including address, decimals, initialLiquidity, and totalSupply. These seed the liquidity cache before events are replayed.
  4. Run the dev server
    pnpm dev
    This runs dotenv -e .env -- ponder dev, which resets (drops + recreates) the tracked tables on every start so you always replay from scratch. Ponder will then sync the chain, apply handlers, and start the REST API on http://localhost:42069 (default).

Production build

pnpm build

This emits the compiled files to dist/; run the resulting JS with node or bundle into your deployment container alongside the same environment variables.

To run the indexer/API in production mode without dropping tables, use the dedicated script:

pnpm start

This executes dotenv -e .env -- ponder start with DATABASE_SCHEMA=prod, which keeps existing database state intact and simply continues syncing.

API Usage

  • Health check: GET /{ "status": "ok" }
  • Market history: GET /market/:chainId/:address?interval=hourly|daily|weekly
    • Returns { priceHistory, volumeHistory, liquidityHistory }. Each array contains { timestamp, value } pairs aligned to the requested interval. Volume is a rolling 24h window when the interval is set to hourly. Otherwise, it's the volume per interval.
    • Invalid chain IDs or addresses return 400 thanks to Zod + viem checksum validation.

Example request:

curl "http://localhost:42069/market/56/0x43C3EBaFdF32909aC60E80ee34aE46637E743d65?interval=daily"

Troubleshooting

  • Schema changes: When you alter ponder.schema.ts, restart pnpm dev; Ponder handles migrations automatically.
  • RPC throttling: Use a dedicated archive node URL; public endpoints often fail to serve the deep history required by SRG20 tokens.

Future Improvements / TODOs

  1. Auto-discover token metadata (name, symbol, decimals) directly from contracts instead of relying on .env JSON.
  2. Add caching (e.g., Redis) to reduce load for repeated market queries.
  3. Provide pagination/filtering endpoints for raw trades to complement the aggregated history.
  4. Implement integration tests that spin up a Postgres container and replay a small SRG20 fixture to guard against handler regressions.
  5. Ship a Dockerfile so the full stack can be built and deployed without relying on global pnpm/Node installations.
  6. Store supported tokens in the db and add an admin API to administer them.
  7. Add a /tokens endpoint in the API.
  8. Restrict time window on the API to avoid clients fetching the whole history which can leave to heavy resources usage on the API.
  9. Add an endpoint to return latest values instead of historical ones.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages