Skip to main content
DarkPool’s backend is split into three workspaces: All three run as tsx processes off one Docker image. See Docker Compose.

Service map

Five services share one Postgres and one Redis. The api fronts REST + WS for the browser. The indexer streams Sui events into Postgres. The quote-worker keeps hot-strike quotes fresh. The resolver settles. The agent (optional) trades.

Ports

The agent ports start at 8083 because the resolver owns 8082.

Data stores

  • Postgres (5433 in dev, 5432 in compose). Indexer destination. Drizzle ORM. Migrations in packages/server/src/db/migrations/.
  • Redis. Quote cache + pubsub for WS fanout, plus self-sponsorship daily caps.
Both shared services come up via docker compose up -d redis postgres.

Bootstrap order

Verify with curl http://localhost:8081/health and check for [resolver] RESOLVER_KEY loaded. Signing as 0x… in the resolver logs.

What each process owns

  • api. Every /v1/* REST route and the /ws WebSocket hub. Writes nothing to chain. Reads Postgres and devInspect for live quotes. Signs the sponsor leg of POST /v1/sponsor.
  • indexer. Sui event poller. Persists cursors. Writes to Postgres via Drizzle. Streams: predict::PositionMinted, predict::PositionRedeemed, predict::oracle::*, darkpool::oo_resolution::*, darkpool::agent::*, darkpool::dark_pool::*, plus one binary::<slug> stream per registry entry.
  • quote-worker. Hot-strike predict::get_trade_amounts poller (QUOTE_POLL_MS, default 2000). Caches in Redis. Publishes updates over pubsub for WS fanout.
  • resolver. Two jobs in one process. HTTP settlement endpoint for OO and atomic Pyth-update PTBs. Auto-settle keeper that scans predict::PositionMinted events and submits per-position redeems for expired oracles.

Tighter dev loop

Skip Docker and run the four processes in separate terminals with tsx watch:
Don’t mix with the Docker services. They bind the same ports.