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.
| 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.
- 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
includeRevertedthreaded 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/statstherefore reportsready, 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 lowerATTEMPTS_START_BLOCKon 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.
AllowedPayeeEnforcerandPerPaymentLimitEnforceremit nothing; their refusals surface as failed transactions and are handled by the point above.
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.
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/statsThe 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.
MIT