Skip to main content

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;
}
TypeDescription
bidA new bid was placed or a bid was exited
auction_updateAuction state changed (clearing price update, checkpoint resolved)
settlementSettlement step completed (finalize, sweep, pool create, settle)
heartbeatServer 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 CodeReason
1001Server shutting down
4001Global connection limit reached (max 1000)
4002Per-IP connection limit reached (max 10)
4003Origin not allowed
4004Invalid 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

LimitValue
Max total connections1000
Max connections per IP10
Backpressure threshold1 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.