harb/services/ponder/AGENTS.md
2026-04-06 00:01:26 +00:00

4.6 KiB

Ponder Indexer - Agent Guide

Ponder-based indexer that records Kraiken protocol activity and exposes the GraphQL API consumed by the app and automation bot.

Responsibilities

  • Track Kraiken token transfers and staking events to maintain protocol stats, hourly ring buffers, and position state.
  • Serve a GraphQL endpoint at http://localhost:42069/graphql for downstream consumers.
  • Support BASE_SEPOLIA_LOCAL_FORK, BASE_SEPOLIA, and BASE environments through a single TypeScript codebase.
  • Tax Rate Handling: Import TAX_RATE_OPTIONS from kraiken-lib (synced with Stake.sol via scripts/sync-tax-rates.mjs). The schema stores both taxRateIndex (source of truth) and taxRate decimal (for display). Event handlers extract the index from contract events and look up the decimal value.

Key Files

  • ponder.config.ts - Network selection and contract bindings (update addresses after deployments).
  • ponder.schema.ts - Stats, hourly data, and position tables.
  • src/kraiken.ts / src/stake.ts - Event handlers; rely on Ponder v0.13 helpers for on-chain reads during sync.
  • src/helpers/stats.ts - Ring buffer logic; MINIMUM_BLOCKS_FOR_RINGBUFFER is configurable via env var (see below).
  • .ponder/ - Local SQLite/state cache (safe to delete when schemas change).

Environment Variables

  • LM_ADDRESS — LiquidityManager contract address; must be set in .env.local for correct contract binding. Bootstrap (containers/bootstrap.sh) writes this automatically.
  • POOL_ADDRESS — Uniswap V3 pool address; discovered from the Uniswap factory during bootstrap and written to .env.local. Ponder uses this for pool event indexing.
  • MINIMUM_BLOCKS_FOR_RINGBUFFER — Override the minimum block count before ring buffer data is populated (default: 100). Set to 0 for local dev so early events populate the ring buffer from genesis.
  • START_BLOCK — Deploy block number; written by bootstrap; used as the Ponder startBlock for all contract event sources.

Development Workflow

  • Primary path: nohup ./scripts/dev.sh start & boots Anvil, deploys contracts, and launches Ponder in watch mode.
  • Docker stack: docker-compose up -d starts all services including PostgreSQL; bootstrap creates .env.local automatically.
  • Focused debugging: within services/ponder/, run npm install then PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK npm run dev once the stack is already online.
  • For production-style runs, use npm run build followed by PONDER_NETWORK=BASE npm run start and point DATABASE_URL to PostgreSQL if persistence is required.

Operational Guidelines

  • Confirm handler timestamps are monotonic; large gaps (>168 hours) reset the ring buffer by design.
  • Regenerate typings after schema edits by restarting Ponder; generated artifacts live in generated/.
  • If the stack script fails during boot, check .ponder/logs and RPC quota usage before rerunning.
  • If protocol activity statistics show all zeros, verify LM_ADDRESS and POOL_ADDRESS are present in .env.local — the indexer silently watches the wrong (zero) address if they are missing.

Containerized Environment (Podman/Docker)

  • Environment Loading: .env.local must be explicitly sourced in the entrypoint script before npm run dev. Ponder's built-in env loader may not find it in containerized environments.
  • Virtual Module Errors: If you see Failed to load url ponder:registry/ponder:schema/ponder:api, check:
    1. DATABASE_URL is properly set and accessible
    2. kraiken-lib ABIs exist (onchain/out/Kraiken.sol/Kraiken.json)
    3. ./scripts/build-kraiken-lib.sh has been run so kraiken-lib/dist/index.js exists
    4. ponder-env.d.ts is writable by the container user (chmod 666 or pre-create it)
    5. Ponder version is 0.13.8+ (earlier versions had virtual module generation bugs)
  • PostgreSQL Connection: Requires DATABASE_URL env var; Ponder falls back to PGlite if not set. The entrypoint must export this before Ponder starts.
  • File Permissions: Container runs as node user; ensure ponder-env.d.ts is writable (created with 666 permissions on host).
  • API Endpoint Requirement: Ponder 0.13.8+ requires src/api/index.ts to exist, even if you only use GraphQL. Missing it causes "API endpoint file not found" errors.

Quality Checks

  • Avoid reintroducing legacy subgraph assumptions; rely solely on Ponder schema helpers.
  • Keep handler logic deterministic and idempotent; reorgs trigger replays.
  • Use the Ponder client helpers (context.client, context.contracts) instead of manual RPC calls where possible.