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
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 2CLI Options
| Option | Description | Default |
|---|---|---|
-P, --port <port> | HTTP server port | 8550 |
-p, --providers <list> | Price providers (comma-separated) | all |
-a, --aggregation | Aggregation method (median/average) | median |
-m, --min-sources <n> | Minimum sources required for valid price | 1 |
Available Providers
| Provider | WebSocket Channel | Update Frequency |
|---|---|---|
binance | aggTrade | Real-time |
coinbase | ticker | Real-time |
kraken | trade | Real-time |
okx | tickers | ~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
| Symbol | Base Token | Quote Token |
|---|---|---|
| BTC/USDT | BTC | USDT |
| ETH/USDT | ETH | USDT |
| SOL/USDT | SOL | USDT |
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: 10Price Aggregation
The oracle aggregates prices from multiple sources using the configured method:
| Method | Description |
|---|---|
median | Middle value (default, resistant to outliers) |
average | Simple 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.50Integration 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 pausedIf 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.
