Purpose
The indexer keeps the backend in sync with onchain state so the relayer can resolve accounts quickly.
Why it exists
Delegate-key authentication does not walk AccountRegistry. A cold key is verified against the signed x-account-id, or against MEMWAL_ACCOUNT_ID when that env is set. The indexer is what fills the accounts table the existence check and owner-token lookup read.
How it works
The indexer is a standalone Rust service (services/indexer) that:
- Connects to the same PostgreSQL database as the relayer
- Polls Sui blockchain events using
suix_queryEvents - Filters for
AccountCreatedevents from the Walrus Memory package - Inserts
account_id → ownermappings into theaccountstable - Stores its event cursor in
indexer_stateso it can resume after restarts
Auth resolution flow
When the relayer receives a signed request, it resolves the delegate key's account in this order:
- PostgreSQL cache (
delegate_key_cache), populated after a successful resolution - Signed
x-account-id, orMEMWAL_ACCOUNT_IDwhen the header is absent, one account object, not a registry walk - Otherwise
401. A cold key with no account id is not looked up onchain
After a successful resolution, the mapping is cached in delegate_key_cache. The indexed accounts table is not part of this chain.
Configuration
The indexer reads these environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | Yes | PostgreSQL connection string | |
MEMWAL_PACKAGE_ID | Yes | Walrus Memory contract package ID to filter events | |
SUI_RPC_URL | No | Mainnet fullnode | Sui RPC endpoint |
POLL_INTERVAL_SECS | No | 5 | Seconds between event poll cycles |
Running
Source: indexer/purpose.md$ cd services/indexer
$ cargo run
The indexer is recommended for production but optional for development, the relayer can fall back to onchain resolution without it.