> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitflare.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WebSocket API

> 账户、槽、日志等的实时 Solana 订阅

## 概述

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
```

<Tip>
  您的许可证密钥可在 [OrbitFlare Dashboard](https://orbitflare.com/dashboard) 的**许可证**部分找到。将其作为 `api_key` 查询参数传入——与 HTTP RPC 使用的密钥相同。
</Tip>

## 连接

```javascript theme={null}
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}`);
});
```

<Note>
  超过 **60 秒**没有任何消息交换的 WebSocket 连接将被服务器关闭。请发送 ping 或保持订阅活跃以维持连接。
</Note>

## 订阅方法

### accountSubscribe

当特定账户的 lamport 余额或数据发生变化时接收更新。

```javascript theme={null}
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

实时接收交易日志消息。可选择过滤到特定程序。

```javascript theme={null}
// 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

每次处理一个槽时接收通知。

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "slotSubscribe",
  params: [],
}));
```

**更新字段：**

| 字段       | 描述      |
| -------- | ------- |
| `slot`   | 当前槽编号   |
| `parent` | 父槽编号    |
| `root`   | 最高已确认根槽 |

***

### signatureSubscribe

当特定交易签名达到指定确认级别时，接收一次性通知。

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "signatureSubscribe",
  params: [
    "TRANSACTION_SIGNATURE_HERE",
    { commitment: "finalized" }
  ],
}));
```

发送第一条通知后，订阅自动关闭。

***

### programSubscribe

接收特定程序所拥有的所有账户的更新。

```javascript theme={null}
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

每个区块被确认时接收完整区块数据。**需要附加功能——请联系支持团队开启。**

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 7,
  method: "blockSubscribe",
  params: ["all", { commitment: "confirmed", encoding: "base64" }],
}));
```

***

### rootSubscribe

每次最高已确认根槽推进时接收通知。

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 8,
  method: "rootSubscribe",
  params: [],
}));
```

***

### voteSubscribe

接收在 gossip 网络中观察到的原始投票交易。**数据量大——请谨慎过滤。**

```javascript theme={null}
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 9,
  method: "voteSubscribe",
  params: [],
}));
```

## 取消订阅

每种订阅方法都有对应的 `Unsubscribe` 方法。传入初始订阅响应中返回的订阅 ID。

```javascript theme={null}
// 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],
    }));
  }
});
```

可用的取消订阅方法：`accountUnsubscribe`、`logsUnsubscribe`、`slotUnsubscribe`、`signatureUnsubscribe`、`programUnsubscribe`、`blockUnsubscribe`、`rootUnsubscribe`、`voteUnsubscribe`。

## 保持连接活跃

WebSocket 连接在闲置 60 秒后将被关闭。定期发送 JSON-RPC ping 以保持连接：

```javascript theme={null}
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));
```

## 重新连接

在生产应用中实现带指数退避的自动重连：

```javascript theme={null}
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 限制。详情请参阅[认证与限制](/authentication#websocket)。

## 另请参阅

<CardGroup cols={2}>
  <Card title="HTTP RPC API" icon="server" href="/rpc/http">
    JSON-RPC 2.0 请求格式、批量请求及所有可用方法。
  </Card>

  <Card title="错误码" icon="triangle-exclamation" href="/rpc/error-codes">
    HTTP 状态码、JSON-RPC 错误及处理方式。
  </Card>
</CardGroup>
