Skip to content

casatrick/oracle-resolution-worker

Repository files navigation

oracle-resolution-worker

Backend worker for prediction-market settlement:

  • polls Pyth, Switchboard, and sports APIs
  • performs source-consensus checks
  • triggers settlement on your backend/API
  • pushes retry/dispute tasks through an internal queue
  • schedules exponential-backoff retries
  • raises disputes when divergence or retry ceilings are hit
  • exposes /health and /metrics for ops visibility
  • supports memory or PostgreSQL repository backends

Architecture

  • src/services/resolutionWorker.ts - polling loop + orchestration
  • src/oracles/* - per-source adapters
  • src/settlement/settlementClient.ts - settlement trigger client
  • src/services/resolutionQueue.ts - async retry/dispute queue pipeline
  • src/services/disputeService.ts - dispute writes/logging
  • src/state/repository.ts - in-memory repository
  • src/state/postgresRepository.ts - PostgreSQL repository
  • src/observability/* - health and Prometheus-style metrics

Quick start

  1. Install dependencies
npm install
  1. Configure environment
copy .env.example .env
  1. Run locally
npm run dev

Docker demo stack

Run full stack (Postgres + worker + mock settlement API):

docker compose up --build

Then verify:

  • worker metrics: http://localhost:9090/metrics
  • worker health: http://localhost:9090/health
  • mock settlement health: http://localhost:8080/health

Notes:

  • seeded markets are in docker/postgres-init/01-seed.sql
  • worker service in docker-compose.yml uses REPOSITORY_BACKEND=postgres
  • one market uses live Pyth for demo; sports endpoint is placeholder unless you configure it

Configuration

  • WORKER_INTERVAL_MS: loop interval
  • MAX_RETRY_ATTEMPTS: max retries before dispute
  • BASE_RETRY_DELAY_MS: base backoff delay
  • QUEUE_POLL_INTERVAL_MS: async queue processing interval
  • MIN_ORACLE_SOURCES: minimum successful oracle reads
  • ORACLE_PRICE_DIVERGENCE_BPS: max tolerated spread before dispute
  • REPOSITORY_BACKEND: memory or postgres
  • DATABASE_URL: required when REPOSITORY_BACKEND=postgres
  • METRICS_PORT: HTTP port serving /health and /metrics
  • SETTLEMENT_API_*: backend settlement endpoint credentials/timeouts
  • PYTH_ENDPOINT: Pyth Hermes endpoint
  • SWITCHBOARD_ENDPOINT: Switchboard adapter/proxy endpoint
  • SPORTS_API_*: sports result provider endpoint and token
  • MARKETS_SEED_FILE: optional path to JSON market seed file

Markets seed JSON shape

Use MARKETS_SEED_FILE to point at a JSON array:

[
  {
    "id": "market-btc-hourly",
    "type": "price",
    "status": "ready_for_resolution",
    "symbol": "Crypto.BTC/USD",
    "expectedSources": ["pyth", "switchboard"],
    "retryCount": 0
  },
  {
    "id": "market-nba-game-1",
    "type": "sports",
    "status": "ready_for_resolution",
    "sportsEventId": "nba_2026_04_22_game_1",
    "expectedSources": ["sports"],
    "retryCount": 0
  }
]

Production notes

  • add idempotency keys on settlement calls
  • route disputes into your governance/manual resolution workflow
  • connect PostgresMarketRepository to migrations and managed backups
  • wire Prometheus/Grafana alerts off /metrics
  • externalize queue into Redis/SQS if multi-instance scaling is needed

PostgreSQL schema

Run the schema in src/state/postgres.schema.sql before booting with REPOSITORY_BACKEND=postgres.

CI

GitHub Actions workflow is included at .github/workflows/ci.yml and runs install, typecheck, and build on push/PR.

About

Oracle resolution worker for prediction markets: polls Pyth/Switchboard/sports feeds, settles markets, handles retries/disputes, and exposes health/metrics.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors