null.
Using null

Running a node locally

Start the chain, relayer, indexer, app, and explorer against a local devnet.

Everything runs natively against a local chain. The services and their default ports:

ServicePortWhat
Chain node (sequencer)8899Solana-compatible JSON-RPC
Relayer8911gasless unshield
App3010shield / transfer / unshield UI
Indexer8921event → Postgres + read API
Explorer3020read-only public view
Docs3030this site

Chain node

# release binary (built for the local target)
sequencer --db ./chain-data/ledger --rpc-port 8899

The node serves standard Solana RPC plus the pool/bridge extensions (RPC reference). getHealth should return ok.

Relayer

relayer --keypair ./relayer-keypair.json --min-fee 2000000 \
        --chain-rpc-port 8899 --port 8911

Generates and persists a keypair on first run (gitignored — it holds a secret). GET /info returns the relayer address and minimum fee; the app binds these into the proof.

Indexer

cd indexer && npm install && npm start   # reads node on 8899, serves 8921

With no DATABASE_URL, the indexer uses an embedded Postgres locally. Set DATABASE_URL (a Neon connection string) for production — the SQL is identical.

App & explorer

cd apps/app && npm install && npm run dev        # http://localhost:3010
cd apps/explorer && npm install && npm run dev    # http://localhost:3020

To point the app's SDK at the indexer instead of the node directly, set NEXT_PUBLIC_USE_INDEXER=1 (node-direct is the default).

Circuit artifacts (joinsplit.wasm, joinsplit_final.zkey) are served statically by the app and cached in the browser on first proof.

On this page