Skip to main content

Overview

OrbitFlare supports persistent WebSocket connections for real-time Solana data. WebSocket subscriptions push updates to your client as they occur on-chain — no polling required. WebSocket endpoints use the wss:// scheme with the same region codes as the HTTP API:
wss://{region}.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
For the auto-routed mainnet endpoint:
wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
Your license key is found in the Licenses section of your OrbitFlare Dashboard. Pass it as the api_key query parameter — the same key used for HTTP RPC.

Connecting

const WebSocket = require("ws");

const ws = new WebSocket(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY"
);

ws.on("open", () => {
  console.log("Connected");
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  console.log("Received:", msg);
});

ws.on("error", (err) => {
  console.error("WebSocket error:", err);
});

ws.on("close", (code, reason) => {
  console.log(`Connection closed: ${code} ${reason}`);
});
WebSocket connections idle for more than 60 seconds without any message exchange are closed by the server. Send a ping or keep your subscriptions active to maintain the connection.

Subscription Methods

accountSubscribe

Receive updates whenever a specific account’s lamport balance or data changes.
ws.on("open", () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "accountSubscribe",
    params: [
      "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
      { encoding: "base64", commitment: "confirmed" }
    ],
  }));
});
Update fields:
FieldDescription
lamportsCurrent lamport balance
dataAccount data (encoding determined by the encoding param)
ownerOwning program public key
executableWhether the account is an executable program
rentEpochEpoch at which rent is next owed

logsSubscribe

Receive transaction log messages in real time. Optionally filter to a specific program.
// All transactions
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 2,
  method: "logsSubscribe",
  params: ["all"],
}));

// Filter to a specific program
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 3,
  method: "logsSubscribe",
  params: [
    { mentions: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] }, // Raydium AMM
    { commitment: "confirmed" }
  ],
}));
Update fields:
FieldDescription
signatureTransaction signature (base-58)
errnull if successful, error object if failed
logsArray of log message strings

slotSubscribe

Receive a notification each time a slot is processed.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "slotSubscribe",
  params: [],
}));
Update fields:
FieldDescription
slotCurrent slot number
parentParent slot number
rootHighest confirmed root slot

signatureSubscribe

Receive a one-time notification when a specific transaction signature reaches a given commitment level.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "signatureSubscribe",
  params: [
    "TRANSACTION_SIGNATURE_HERE",
    { commitment: "finalized" }
  ],
}));
The subscription automatically closes after the first notification is sent.

programSubscribe

Receive updates for all accounts owned by a specific program.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 6,
  method: "programSubscribe",
  params: [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token
    {
      encoding: "jsonParsed",
      commitment: "confirmed",
      filters: [{ dataSize: 165 }], // Standard token account size
    }
  ],
}));

blockSubscribe

Receive full block data as each block is confirmed. Requires an add-on — contact support to enable.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 7,
  method: "blockSubscribe",
  params: ["all", { commitment: "confirmed", encoding: "base64" }],
}));

rootSubscribe

Receive the highest confirmed root slot each time it advances.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 8,
  method: "rootSubscribe",
  params: [],
}));

voteSubscribe

Receive raw vote transactions as they are observed in the gossip network. High volume — filter carefully.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 9,
  method: "voteSubscribe",
  params: [],
}));

Unsubscribing

Each subscription method has a corresponding Unsubscribe method. Pass the subscription ID returned in the initial subscription response.
// Subscribe and capture the subscription ID
ws.on("message", (data) => {
  const msg = JSON.parse(data);

  // Subscription confirmation contains the subscription ID
  if (msg.id === 1 && msg.result !== undefined) {
    const subscriptionId = msg.result;
    console.log("Subscribed, ID:", subscriptionId);

    // Unsubscribe later
    ws.send(JSON.stringify({
      jsonrpc: "2.0",
      id: 10,
      method: "accountUnsubscribe",
      params: [subscriptionId],
    }));
  }
});
Available unsubscribe methods: accountUnsubscribe, logsUnsubscribe, slotUnsubscribe, signatureUnsubscribe, programUnsubscribe, blockUnsubscribe, rootUnsubscribe, voteUnsubscribe.

Keepalive

WebSocket connections are closed after 60 seconds of inactivity. Send a JSON-RPC ping periodically to keep the connection alive:
const pingInterval = setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ jsonrpc: "2.0", id: 0, method: "ping" }));
  }
}, 30_000);

ws.on("close", () => clearInterval(pingInterval));

Reconnection

Implement automatic reconnection with exponential backoff for production applications:
function connect(url, onMessage) {
  let ws;
  let delay = 1000;
  let attempt = 0;

  function createConnection() {
    ws = new WebSocket(url);

    ws.on("open", () => {
      console.log("Connected (attempt", attempt + 1, ")");
      delay = 1000; // reset backoff on successful connection
      attempt = 0;
      // re-subscribe to all channels here
    });

    ws.on("message", onMessage);

    ws.on("close", () => {
      attempt++;
      const nextDelay = Math.min(delay * 2, 30_000);
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(createConnection, delay);
      delay = nextDelay;
    });

    ws.on("error", (err) => console.error("WebSocket error:", err));
  }

  createConnection();
  return () => ws?.close();
}

const disconnect = connect(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY",
  (data) => {
    const msg = JSON.parse(data);
    console.log("Update:", msg);
  }
);

Connection Limits

WebSocket connections share the same per-IP limit as gRPC connections. See Authentication & Limits for details.

See Also