跳转到主要内容

概述

OrbitFlare 支持持久 WebSocket 连接,用于接收实时 Solana 数据。WebSocket 订阅在链上发生变化时主动推送更新到您的客户端——无需轮询。 WebSocket 端点使用 wss:// 协议,区域代码与 HTTP API 相同:
wss://{region}.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
自动路由的主网端点:
wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
您的许可证密钥可在 OrbitFlare Dashboard许可证部分找到。将其作为 api_key 查询参数传入——与 HTTP RPC 使用的密钥相同。

连接

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}`);
});
超过 60 秒没有任何消息交换的 WebSocket 连接将被服务器关闭。请发送 ping 或保持订阅活跃以维持连接。

订阅方法

accountSubscribe

当特定账户的 lamport 余额或数据发生变化时接收更新。
ws.on("open", () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "accountSubscribe",
    params: [
      "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
      { encoding: "base64", commitment: "confirmed" }
    ],
  }));
});
更新字段:
字段描述
lamports当前 lamport 余额
data账户数据(编码方式由 encoding 参数决定)
owner所有者程序公钥
executable账户是否为可执行程序
rentEpoch下次需缴纳租金的 epoch

logsSubscribe

实时接收交易日志消息。可选择过滤到特定程序。
// 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" }
  ],
}));
更新字段:
字段描述
signature交易签名(base-58 编码)
err成功时为 null,失败时为错误对象
logs日志消息字符串数组

slotSubscribe

每次处理一个槽时接收通知。
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "slotSubscribe",
  params: [],
}));
更新字段:
字段描述
slot当前槽编号
parent父槽编号
root最高已确认根槽

signatureSubscribe

当特定交易签名达到指定确认级别时,接收一次性通知。
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "signatureSubscribe",
  params: [
    "TRANSACTION_SIGNATURE_HERE",
    { commitment: "finalized" }
  ],
}));
发送第一条通知后,订阅自动关闭。

programSubscribe

接收特定程序所拥有的所有账户的更新。
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

每个区块被确认时接收完整区块数据。需要附加功能——请联系支持团队开启。
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 7,
  method: "blockSubscribe",
  params: ["all", { commitment: "confirmed", encoding: "base64" }],
}));

rootSubscribe

每次最高已确认根槽推进时接收通知。
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 8,
  method: "rootSubscribe",
  params: [],
}));

voteSubscribe

接收在 gossip 网络中观察到的原始投票交易。数据量大——请谨慎过滤。
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 9,
  method: "voteSubscribe",
  params: [],
}));

取消订阅

每种订阅方法都有对应的 Unsubscribe 方法。传入初始订阅响应中返回的订阅 ID。
// 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],
    }));
  }
});
可用的取消订阅方法:accountUnsubscribelogsUnsubscribeslotUnsubscribesignatureUnsubscribeprogramUnsubscribeblockUnsubscriberootUnsubscribevoteUnsubscribe

保持连接活跃

WebSocket 连接在闲置 60 秒后将被关闭。定期发送 JSON-RPC ping 以保持连接:
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));

重新连接

在生产应用中实现带指数退避的自动重连:
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);
  }
);

连接限制

WebSocket 连接与 gRPC 连接共享相同的每 IP 限制。详情请参阅认证与限制

另请参阅