Skip to main content

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:

  1. Connects to the same PostgreSQL database as the relayer
  2. Polls Sui blockchain events using suix_queryEvents
  3. Filters for AccountCreated events from the Walrus Memory package
  4. Inserts account_id → owner mappings into the accounts table
  5. Stores its event cursor in indexer_state so 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:

  1. PostgreSQL cache (delegate_key_cache), populated after a successful resolution
  2. Signed x-account-id, or MEMWAL_ACCOUNT_ID when the header is absent, one account object, not a registry walk
  3. 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:

VariableRequiredDefaultDescription
DATABASE_URLYesPostgreSQL connection string
MEMWAL_PACKAGE_IDYesWalrus Memory contract package ID to filter events
SUI_RPC_URLNoMainnet fullnodeSui RPC endpoint
POLL_INTERVAL_SECSNo5Seconds 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.