> ## 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 客户端

> 账户变更、日志、槽位与签名的实时订阅，支持自动重连。

## 安装

```bash theme={null}
npm install @orbitflare/sdk ws
```

`ws` 为可选对等依赖。仅在使用 WebSocket 客户端时才需要安装。

## 构建客户端

```ts theme={null}
import { WsClientBuilder } from '@orbitflare/sdk/ws';
import type { RetryPolicy } from '@orbitflare/sdk';

const client = await new WsClientBuilder()
  .url('ws://ny.rpc.orbitflare.com')
  .fallbackUrl('ws://fra.rpc.orbitflare.com')
  .apiKey('ORBIT-XXXXXX-NNNNNN-NNNNNN')
  .retry({
    initialDelayMs: 100,
    maxDelayMs: 30_000,
    multiplier: 2.0,
    maxAttempts: 0,
  })
  .pingIntervalSecs(10)
  .maxMissedPongs(3)
  .build();
```

最简配置：

```ts theme={null}
const client = await new WsClientBuilder()
  .url('ws://ny.rpc.orbitflare.com')
  .build();
```

注意 `.build()` 为异步 - 在返回前会建立 WebSocket 连接。若连接失败，Promise 会立即拒绝。

### 构建器方法

**`.url(url)`** - 主 WebSocket 端点。回退读取环境变量 `ORBITFLARE_WS_URL`。

```ts theme={null}
.url('ws://ny.rpc.orbitflare.com')
```

**`.urls([...])`** - 一次设置主端点与备用端点。

```ts theme={null}
.urls(['ws://ny.rpc.orbitflare.com', 'ws://fra.rpc.orbitflare.com'])
```

**`.fallbackUrl(url)` / `.fallbackUrls([...])`** - 添加故障转移端点。重连时 SDK 会轮换尝试。

```ts theme={null}
.fallbackUrl('ws://fra.rpc.orbitflare.com')
```

**`.apiKey(key)`** - 许可证密钥。回退读取环境变量 `ORBITFLARE_LICENSE_KEY`。

```ts theme={null}
.apiKey('ORBIT-XXXXXX-NNNNNN-NNNNNN')
```

**`.retry(policy)`** - 重连退避。默认：初始 100ms、最大 30s、2 倍乘数、无限次尝试。

```ts theme={null}
.retry({
  initialDelayMs: 200,
  maxDelayMs: 15_000,
  multiplier: 2.0,
  maxAttempts: 0,
})
```

**`.pingIntervalSecs(n)`** - SDK 发送 WebSocket `Ping` 帧的频率。默认：10。

```ts theme={null}
.pingIntervalSecs(15)
```

**`.maxMissedPongs(n)`** - 多少次 Ping 无应答后终止连接。默认：3。

```ts theme={null}
.maxMissedPongs(5)
```

## 可用订阅

### `slotSubscribe()`

在槽位被处理、确认或最终确定时触发。

```ts theme={null}
const sub = await client.slotSubscribe();
```

每条事件为含 `slot`、`parent`、`root` 字段的对象：

```json theme={null}
{"slot": 413014740, "parent": 413014739, "root": 413014708}
```

### `accountSubscribe(address, commitment)`

指定账户数据变更时触发。

```ts theme={null}
const sub = await client.accountSubscribe(
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  'confirmed',
);
```

返回含 lamports、owner 与可执行标志的 base64 编码账户数据。

### `logsSubscribe(mentions, commitment)`

提及给定地址的交易产生日志时触发。传入空数组表示所有交易。

```ts theme={null}
const sub = await client.logsSubscribe(
  ['6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P'],
  'confirmed',
);
```

全部日志：

```ts theme={null}
const sub = await client.logsSubscribe([], 'confirmed');
```

### `signatureSubscribe(signature, commitment)`

交易达到给定承诺级别时触发一次。适合确认刚发送的交易。

```ts theme={null}
const sub = await client.signatureSubscribe('5K8F2j...', 'confirmed');
```

## 读取事件

所有订阅返回 `WsSubscription`。调用 `.next()` 获取下一条事件：

```ts theme={null}
while (true) {
  const event = await sub.next();
  if (event === undefined) break;
  console.log(event);
}
```

订阅关闭时 `.next()` 解析为 `undefined`。

也可附加事件监听式回调：

```ts theme={null}
const off = sub.on((event) => {
  console.log(event);
});

// later: off();
```

## 取消订阅

```ts theme={null}
await sub.unsubscribe();
```

向服务器发送取消订阅消息。若丢弃订阅而未调用，SDK 会检测孤立订阅并自动发送取消。

## 多路订阅

所有订阅共用单一 WebSocket 连接。SDK 在内部将通知路由到正确订阅。

```ts theme={null}
const slots = await client.slotSubscribe();
const usdc = await client.accountSubscribe('EPjFWdd5...', 'confirmed');
const logs = await client.logsSubscribe(['6EF8r...'], 'confirmed');
```

可在已有订阅运行时随时添加新订阅。

## 重连

若连接断开，后台任务会以指数退避重连并自动重新订阅所有内容。`.next()` 调用会持续工作 - 连接恢复后事件会继续到达。

## 完整示例

监控脚本：订阅槽位更新与 USDC 账户变更，打印实时流。

```ts theme={null}
import { WsClientBuilder } from '@orbitflare/sdk/ws';

async function main() {
  const client = await new WsClientBuilder()
    .url('ws://ny.rpc.orbitflare.com')
    .build();

  const slots = await client.slotSubscribe();
  const usdc = await client.accountSubscribe(
    'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
    'confirmed',
  );

  console.log('watching slots and USDC mint account...');

  slots.on((slot) => {
    const s = slot?.slot ?? 0;
    const parent = slot?.parent ?? 0;
    console.log(`slot ${s} (parent ${parent})`);
  });

  usdc.on((acct) => {
    const lamports = acct?.lamports ?? 0;
    const data = acct?.data?.[0];
    const dataLen = typeof data === 'string' ? data.length : 0;
    console.log(`USDC mint updated: ${lamports} lamports, ${dataLen} bytes`);
  });

  await new Promise(() => {});
}

void main();
```
