Skip to content

Repository files navigation

mapae-ponder

Self-hosted indexers for Mapae on GIWA — one app per protocol surface, one monorepo for all of them.

The Mapae explorer is a static SPA that reads the chain directly; it needs no backend to be correct. What an index buys is speed and history: pages served from a queryable store instead of one Blockscout round-trip per fact, and aggregates (total spent, per-principal activity, kill-switch history) that a browser should not recompute on every visit. The chain stays the source of truth — every table here is derivable from logs alone, so the whole database can be dropped and rebuilt at any time.

Apps

App Chain What it indexes
apps/mapae GIWA Sepolia (91342) The Mapae deployment: delegations, payments, identity-gate passes, period spends, kill-switch history, accounts

Planned: a real-issuer Dojang attestation registry (GIWA has no off-chain attestation query surface), and mainnet chains as they exist.

Design notes

  • Refusals recover themselves. A refused payment is a reverted transaction, and a reverted transaction has no logs — so the one thing a log indexer structurally cannot see is the thing Mapae treats as first-class. The manager is therefore indexed as an account source scanning transaction bodies, with includeReverted threaded through patches/ponder.patch: Ponder's runtime supports the flag but its config builder hardcodes it off for accounts. Every attempt — refused ones included — lands as a chain-derived row with its intent (authority, token, payee, amount) decoded from calldata.
  • History is bridged, deliberately. GIWA's only public RPC allows ~10 req/s and penalty-boxes bursts (measured), pricing a full 700k-block body scan at ~20 hours. So the account scan starts near the present and everything older is bridged from Blockscout's transaction list, decoded by the same decoder into the same shape and deduplicated on transaction hash — never on a block constant, which would blank out whatever the scan has not reached yet.
  • One slow source gates every fast one. Ponder advances a single checkpoint across all sources, so pointing the account scan at the deploy block does not merely delay refusals: it holds the log-derived tables at the same block, and delegations, payments and principals read as a fraction of the truth. Attempts survive it (the bridge fills the gap); the rest does not. /api/stats therefore reports ready, and consumers are expected to prefer their own slower path over a fast wrong number. Full-history self-recovery wants its own app, with its own checkpoint — not a lower ATTEMPTS_START_BLOCK on this one.
  • Per-payment amounts are reconstructed exactly. The period enforcer emits the cumulative within the current period, not the payment amount; the handler differences consecutive cumulatives of the same period, which mirrors the enforcer's own storage arithmetic.
  • Stateless enforcers are not indexed. AllowedPayeeEnforcer and PerPaymentLimitEnforcer emit nothing; their refusals surface as failed transactions and are handled by the point above.

Run

pnpm install
pnpm dev          # apps/mapae on :42069 - GraphQL at /graphql, REST under /api
Endpoint Serves
GET /api/stats Delegations, payments, principals, accounts, attempts, rejections
GET /api/activity Every redemption attempt against the manager — refused ones included, each with its decoded intent
GET /api/delegation/:hash One delegation: state, spends, gate passes, kill-switch history, attempts
POST /graphql The whole schema

PONDER_RPC_URL_91342 overrides the default public RPC. Dev mode runs on PGlite; production runs on Postgres via DATABASE_URL.

Deploy (VM)

Docker compose behind a host nginx. The indexer binds to loopback; nginx + certbot terminate TLS for index.mapae.org (infra/nginx/ has the site file and the five commands).

cp .env.example .env   # set POSTGRES_PASSWORD; optionally ATTEMPTS_START_BLOCK=31935476
docker compose up -d --build
curl -s localhost:42069/api/stats

The postgres volume carries the sync cache — after the full backfill grinds once on the public RPC (~20h), that volume is a day of work. Back it up like it owes you one.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages