> ## 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 Client

> Real-time subscriptions for account changes, logs, slots, and signatures with auto-reconnect.

## Install

```bash theme={null}
cargo add orbitflare-sdk --features ws
```

## Building the client

```rust theme={null}
use orbitflare_sdk::{WsClientBuilder, RetryPolicy, Result};
use std::time::Duration;

let client = WsClientBuilder::new()
    .url("ws://ny.rpc.orbitflare.com")
    .fallback_url("ws://fra.rpc.orbitflare.com")
    .api_key("ORBIT-XXXXXX-NNNNNN-NNNNNN")
    .retry(RetryPolicy {
        initial_delay: Duration::from_millis(100),
        max_delay: Duration::from_secs(30),
        multiplier: 2.0,
        max_attempts: 0,
    })
    .ping_interval_secs(10)
    .max_missed_pongs(3)
    .build()
    .await?;
```

Minimal:

```rust theme={null}
let client = WsClientBuilder::new()
    .url("ws://ny.rpc.orbitflare.com")
    .build()
    .await?;
```

Note that `.build()` is async - it establishes the WebSocket connection before returning. If the connection fails, you get the error immediately.

### Builder methods

**`.url(url)`** - Primary WebSocket endpoint. Falls back to `ORBITFLARE_WS_URL` env var.

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

**`.urls(&[...])`** - Primary + fallbacks in one call.

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

**`.fallback_url(url)` / `.fallback_urls(&[...])`** - Add failover endpoints. On reconnect, the SDK rotates through them.

```rust theme={null}
.fallback_url("ws://fra.rpc.orbitflare.com")
```

**`.api_key(key)`** - License key. Falls back to `ORBITFLARE_LICENSE_KEY` env var.

```rust theme={null}
.api_key("ORBIT-XXXXXX-NNNNNN-NNNNNN")
```

**`.retry(policy)`** - Reconnection backoff. Default: 100ms initial, 30s max, 2x multiplier, infinite attempts.

```rust theme={null}
.retry(RetryPolicy {
    initial_delay: Duration::from_millis(200),
    max_delay: Duration::from_secs(15),
    multiplier: 2.0,
    max_attempts: 0,
})
```

**`.ping_interval_secs(n)`** - How often the SDK sends WebSocket `Ping` frames. Default: 10.

```rust theme={null}
.ping_interval_secs(15)
```

**`.max_missed_pongs(n)`** - Pings without a response before killing the connection. Default: 3.

```rust theme={null}
.max_missed_pongs(5)
```

## Available subscriptions

### `slot_subscribe()`

Fires every time a slot is processed, confirmed, or finalized.

```rust theme={null}
let mut sub = client.slot_subscribe().await?;
```

Each event is a JSON value with `slot`, `parent`, and `root` fields:

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

### `account_subscribe(address, commitment)`

Fires when the specified account's data changes.

```rust theme={null}
let mut sub = client.account_subscribe(
    "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "confirmed",
).await?;
```

Returns base64-encoded account data with lamports, owner, and executable flag.

### `logs_subscribe(mentions, commitment)`

Fires for transactions that mention the given addresses. Pass an empty slice for all transactions.

```rust theme={null}
let mut sub = client.logs_subscribe(
    &["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
    "confirmed",
).await?;
```

All logs:

```rust theme={null}
let mut sub = client.logs_subscribe(&[], "confirmed").await?;
```

### `signature_subscribe(signature, commitment)`

Fires once when a transaction reaches the given commitment level. Useful for confirming a transaction you just sent.

```rust theme={null}
let mut sub = client.signature_subscribe("5K8F2j...", "confirmed").await?;
```

## Reading events

All subscriptions return a `WsSubscription`. Call `.next()` to get the next event:

```rust theme={null}
while let Some(event) = sub.next().await {
    println!("{event}");
}
```

`.next()` returns `Option<serde_json::Value>`. `None` means the subscription was closed.

## Unsubscribing

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

This sends an unsubscribe message to the server. If you drop a subscription without calling this, the SDK detects the orphan and sends the unsubscribe automatically.

## Multiple subscriptions

All subscriptions run on a single WebSocket connection. The SDK routes notifications to the right subscription internally.

```rust theme={null}
let mut slots = client.slot_subscribe().await?;
let mut usdc = client.account_subscribe("EPjFWdd5...", "confirmed").await?;
let mut logs = client.logs_subscribe(&["6EF8r..."], "confirmed").await?;
```

You can add new subscriptions at any time while existing ones are running.

## Reconnection

If the connection drops, the background task reconnects with exponential backoff and re-subscribes everything automatically. Your `.next()` calls just keep working - events resume once the connection is back.

## Full example

A monitoring script that subscribes to slot updates and account changes for USDC, printing a live feed.

```rust theme={null}
use orbitflare_sdk::{WsClientBuilder, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let client = WsClientBuilder::new()
        .url("ws://ny.rpc.orbitflare.com")
        .build()
        .await?;

    let mut slots = client.slot_subscribe().await?;
    let mut usdc = client.account_subscribe(
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
        "confirmed",
    ).await?;

    println!("watching slots and USDC mint account...");

    loop {
        tokio::select! {
            Some(slot) = slots.next() => {
                let s = slot["slot"].as_u64().unwrap_or(0);
                let parent = slot["parent"].as_u64().unwrap_or(0);
                println!("slot {s} (parent {parent})");
            }
            Some(acct) = usdc.next() => {
                let lamports = acct["lamports"].as_u64().unwrap_or(0);
                let data_len = acct["data"][0]
                    .as_str()
                    .map(|s| s.len())
                    .unwrap_or(0);
                println!("USDC mint updated: {lamports} lamports, {data_len} bytes");
            }
        }
    }
}
```
