AGENTS.md watermarks refreshed to HEAD (62ba6f2).
Content updates:
- root AGENTS.md: added Docker/LXD notes (apparmor=unconfined, umami port 3001),
viem v2 slot0 array pattern to Key Patterns
- services/ponder/AGENTS.md: documented LM_ADDRESS, POOL_ADDRESS, and
MINIMUM_BLOCKS_FOR_RINGBUFFER env vars; added zero-stats troubleshooting note
- web-app/AGENTS.md: added viem v2 slot0 array compat section
Grooming: no open issues.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.6 KiB
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/graphqlfor downstream consumers. - Support
BASE_SEPOLIA_LOCAL_FORK,BASE_SEPOLIA, andBASEenvironments through a single TypeScript codebase. - Tax Rate Handling: Import
TAX_RATE_OPTIONSfromkraiken-lib(synced with Stake.sol viascripts/sync-tax-rates.mjs). The schema stores bothtaxRateIndex(source of truth) andtaxRatedecimal (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_RINGBUFFERis 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.localfor 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 to0for local dev so early events populate the ring buffer from genesis.START_BLOCK— Deploy block number; written by bootstrap; used as the PonderstartBlockfor 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 -dstarts all services including PostgreSQL; bootstrap creates.env.localautomatically. - Focused debugging: within
services/ponder/, runnpm installthenPONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK npm run devonce the stack is already online. - For production-style runs, use
npm run buildfollowed byPONDER_NETWORK=BASE npm run startand pointDATABASE_URLto 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/logsand RPC quota usage before rerunning. - If protocol activity statistics show all zeros, verify
LM_ADDRESSandPOOL_ADDRESSare present in.env.local— the indexer silently watches the wrong (zero) address if they are missing.
Containerized Environment (Podman/Docker)
- Environment Loading:
.env.localmust be explicitly sourced in the entrypoint script beforenpm 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:DATABASE_URLis properly set and accessible- kraiken-lib ABIs exist (
onchain/out/Kraiken.sol/Kraiken.json) ./scripts/build-kraiken-lib.shhas been run sokraiken-lib/dist/index.jsexistsponder-env.d.tsis writable by the container user (chmod 666 or pre-create it)- Ponder version is 0.13.8+ (earlier versions had virtual module generation bugs)
- PostgreSQL Connection: Requires
DATABASE_URLenv var; Ponder falls back to PGlite if not set. The entrypoint must export this before Ponder starts. - File Permissions: Container runs as
nodeuser; ensureponder-env.d.tsis writable (created with 666 permissions on host). - API Endpoint Requirement: Ponder 0.13.8+ requires
src/api/index.tsto 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.