WebSocket
The indexer provides a WebSocket endpoint for receiving real-time push updates about auctions, bids, and settlement events.
Connection URL
wss://cca-indexer-production.up.railway.app/ws
Optional Filter
Subscribe to events for a specific auction by passing the auctionId query parameter:
wss://cca-indexer-production.up.railway.app/ws?auctionId=AbC123...
If no auctionId is provided, the client receives events from all auctions (global subscription).
Connection Example
const auctionId = "AbC123..."; // optional
const url = auctionId
? `wss://cca-indexer-production.up.railway.app/ws?auctionId=${auctionId}`
: `wss://cca-indexer-production.up.railway.app/ws`;
const ws = new WebSocket(url);
ws.onopen = () => {
console.log("Connected to Runner Protocol WebSocket");
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Event received:", data.type, data);
switch (data.type) {
case "bid":
console.log("New bid on auction:", data.auctionId);
break;
case "auction_update":
console.log("Auction state changed:", data.auctionId);
break;
case "settlement":
console.log("Settlement event:", data.auctionId);
break;
case "heartbeat":
// Server liveness check, no action needed
break;
}
};
ws.onclose = (event) => {
console.log("Disconnected:", event.code, event.reason);
};
ws.onerror = (error) => {
console.error("WebSocket error:", error);
};
Event Types
All events are JSON objects with a type field:
interface WsEvent {
type: "bid" | "auction_update" | "settlement" | "heartbeat";
auctionId?: string;
data?: unknown;
}
| Type | Description |
|---|---|
bid | A new bid was placed or a bid was exited |
auction_update | Auction state changed (clearing price update, checkpoint resolved) |
settlement | Settlement step completed (finalize, sweep, pool create, settle) |
heartbeat | Server liveness signal (sent via WS-level ping, not as a JSON message) |
Heartbeat and Reconnection
The server sends WS-level ping frames every 30 seconds. Clients that do not respond with a pong within 30 seconds are terminated.
Most WebSocket client libraries handle ping/pong automatically. If you are using a low-level implementation, ensure you respond to ping frames.
Reconnection Strategy
The server may close connections for the following reasons:
| Close Code | Reason |
|---|---|
| 1001 | Server shutting down |
| 4001 | Global connection limit reached (max 1000) |
| 4002 | Per-IP connection limit reached (max 10) |
| 4003 | Origin not allowed |
| 4004 | Invalid auctionId parameter |
Implement exponential backoff for reconnection:
let reconnectDelay = 1000; // Start at 1 second
const maxDelay = 30000; // Max 30 seconds
function connect() {
const ws = new WebSocket(url);
ws.onopen = () => {
reconnectDelay = 1000; // Reset on successful connect
};
ws.onclose = (event) => {
// Don't reconnect on explicit rejection
if (event.code >= 4001 && event.code <= 4004) {
console.error("Connection rejected:", event.reason);
return;
}
// Exponential backoff
console.log(`Reconnecting in ${reconnectDelay}ms...`);
setTimeout(connect, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, maxDelay);
};
}
connect();
Connection Limits
| Limit | Value |
|---|---|
| Max total connections | 1000 |
| Max connections per IP | 10 |
| Backpressure threshold | 1 MB buffered data |
Clients that exceed the backpressure threshold (1 MB of unsent buffered data) are terminated to prevent slow consumers from impacting the server.