Skip to content

Oracle Service

The Oracle Service aggregates real-time prices from multiple WebSocket sources and exposes an HTTP API for the Write node to pull prices.

Architecture

Oracle Architecture

Unlike traditional push-based oracles, Kaizen uses a pull model where the Write node requests prices at each checkpoint. This eliminates nonce management and ensures deterministic sequencing.

Running

# Development (all providers)
pnpm --filter @kaizen-core/oracle dev
 
# Production (specific providers, min 2 sources)
pnpm --filter @kaizen-core/oracle start -- -p binance,coinbase -m 2

CLI Options

OptionDescriptionDefault
-P, --port <port>HTTP server port8550
-p, --providers <list>Price providers (comma-separated)all
-a, --aggregationAggregation method (median/average)median
-m, --min-sources <n>Minimum sources required for valid price1

Available Providers

ProviderWebSocket ChannelUpdate Frequency
binanceaggTradeReal-time
coinbasetickerReal-time
krakentradeReal-time
okxtickers~100ms

HTTP API

GET /prices

Returns current aggregated prices for all supported pairs.

{
  "timestamp": 1733251200000,
  "prices": {
    "BTC/USDT": {
      "base": "0x0000000000000000000000000000000000000001",
      "quote": "0x0000000000000000000000000000000000000100",
      "price": "104250000000",
      "decimals": 6,
      "lastUpdate": 1733251199950,
      "sources": ["Binance", "Coinbase", "Kraken", "OKX"]
    },
    "ETH/USDT": {
      "base": "0x0000000000000000000000000000000000000002",
      "quote": "0x0000000000000000000000000000000000000100",
      "price": "3850000000",
      "decimals": 6,
      "lastUpdate": 1733251199980,
      "sources": ["Binance", "Coinbase", "OKX"]
    }
  }
}

GET /health

Health check endpoint with provider status.

{
  "status": "healthy",
  "uptime": 12345,
  "providers": [
    { "name": "Binance", "ready": true, "prices": 3 },
    { "name": "Coinbase", "ready": true, "prices": 3 },
    { "name": "Kraken", "ready": true, "prices": 3 },
    { "name": "OKX", "ready": true, "prices": 3 }
  ],
  "lastPriceUpdate": 1733251199950,
  "pairsWithPrices": 3,
  "totalPairs": 3
}

GET /providers

Detailed provider status and per-pair source breakdown.

{
  "providers": [
    { "name": "Binance", "ready": true, "prices": 3 },
    { "name": "Coinbase", "ready": true, "prices": 3 }
  ],
  "pairSources": {
    "BTC/USDT": {
      "sources": ["Binance", "Coinbase"],
      "price": "104250000000"
    }
  }
}

Supported Pairs

SymbolBase TokenQuote Token
BTC/USDTBTCUSDT
ETH/USDTETHUSDT
SOL/USDTSOLUSDT

Docker

oracle:
  build:
    context: .
    dockerfile: docker/Dockerfile.oracle
  ports:
    - "8550:8550"
  command:
    - --port
    - "8550"
    - --aggregation
    - median
    - --min-sources
    - "2"
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:8550/health"]
    interval: 5s
    timeout: 3s
    retries: 10

Price Aggregation

The oracle aggregates prices from multiple sources using the configured method:

MethodDescription
medianMiddle value (default, resistant to outliers)
averageSimple arithmetic mean

Example (Median)

Binance:  $104,250
Coinbase: $104,248
Kraken:   $104,251
OKX:      $104,249
 
Sorted: [$104,248, $104,249, $104,250, $104,251]
Median: ($104,249 + $104,250) / 2 = $104,249.50

Integration with Write Node

The Write node pulls prices every 100ms checkpoint:

[oracle]
service_url = "http://oracle:8550"  # Oracle service URL
timeout_ms = 10                      # 10ms timeout
max_stale_ms = 3000                  # Max staleness before RFQ paused

If the oracle is unreachable or times out, the Write node falls back to the last known prices. After 3 seconds of staleness, new RFQ theses are rejected.