Self-hosting the indexer
Configure the Go indexer against your own RPC + Postgres.
The indexer is a single Go binary. It polls an Arc RPC for new blocks, decodes contract events, and projects them into Postgres.
Build
Or run the prebuilt distroless image:
Configuration
Required env vars (see .env.example):
STABLECOIN_ADDRESSES is a comma-separated list of SYMBOL:address pairs (USDC and EURC) for the stablecoins Strimz accepts. The indexer resolves payment tokens through it and scans those contracts for refund-completion Transfer events. At least one entry is required.
ARC_CHAIN_ID, START_BLOCK, CONFIRMATIONS and TOKEN_WHITELIST_ADDRESS have no default. A missing or malformed value stops the indexer at boot with the variable named.
ARC_CHAIN_IDis5042002on Arc testnet and5042on Arc mainnet. At boot the indexer asks every RPC endpoint (ARC_RPC_URLand eachARC_FALLBACK_RPC_URLSentry) for its chain id. An endpoint on another chain stops the boot; an endpoint that does not answer is dropped with a warning.START_BLOCKis the block your core contracts were deployed at. A fresh database starts indexing there.TOKEN_WHITELIST_ADDRESSis theTokenWhitelistcontract. The indexer records its token changes and logs an error when a newly whitelisted token is missing fromSTABLECOIN_ADDRESSES.
Run one indexer and one database per network. The indexer's bookmarks are keyed by chain id, but the tables it projects into are not, so testnet and mainnet must not share a database.
Migrations
The indexer expects the Prisma schema from packages/db to be applied. From the repo root:
Confirmations
CONFIRMATIONS=1 keeps the indexer one block behind head. Arc has deterministic BFT finality — a committed block never reorgs — so one confirmation is plenty; the extra block only shields against an RPC replica that hasn't yet caught up to head.
Idempotency
The indexer's checkpoint is IndexerCursor. Truncate it and restart, and the indexer re-processes from the configured START_BLOCK. Every projection is idempotent (INSERT … ON CONFLICT DO NOTHING keyed on natural identifiers), so re-running is safe.
Observability
/healthz. Always 200 once the process is alive./readyz. 200 once the first batch has been processed./metrics. Prometheus endpoint with per-contract block lag, RPC latency, projection counts.
Failure recovery
If the indexer crashes mid-batch, the IndexerCursor does not
advance until the batch completes. On restart it picks up at the
last successful batch's end block. No event gets projected twice.
If the RPC returns malformed data (rare), the indexer logs the
error and skips the bad log. The rest of the batch processes
normally. Failed projections write to the AgentActivityLog, or to
stderr for a structural error like a schema mismatch.

