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

# WebSocket Feeds

> Real-time orderbook data via standalone WebSocket clients

The SDK provides two standalone WebSocket clients for real-time market data. Both require no wallet or private key — they are read-only data feeds.

## KuruFrontendOrderbookClient

The frontend orderbook client (`orderbook_ws`) streams full L2 snapshots followed by incremental updates. Prices and sizes are pre-normalized to human-readable `Decimal` values.

### Usage

```python theme={null}
import asyncio

from kuru_sdk_py.configs import ConfigManager
from kuru_sdk_py.feed.orderbook_ws import KuruFrontendOrderbookClient, FrontendOrderbookUpdate

async def main():
    toml_config = ConfigManager.load_toml_config()
    market_config = ConfigManager.load_market_config(toml_config=toml_config)
    connection_config = ConfigManager.load_connection_config(toml_config=toml_config)

    update_queue: asyncio.Queue[FrontendOrderbookUpdate] = asyncio.Queue()

    client = KuruFrontendOrderbookClient(
        ws_url=connection_config.kuru_ws_url,
        market_address=market_config.market_address,
        update_queue=update_queue,
        size_precision=market_config.size_precision,
    )

    async with client:
        while True:
            update = await update_queue.get()

            if update.b:
                best_bid = update.b[0][0]  # Already a Decimal
            if update.a:
                best_ask = update.a[0][0]  # Already a Decimal

asyncio.run(main())
```

### FrontendOrderbookUpdate fields

| Field    | Type                                      | Description                                                              |
| -------- | ----------------------------------------- | ------------------------------------------------------------------------ |
| `events` | `list[FrontendEvent]`                     | Events describing what changed (trades, order placements, cancellations) |
| `b`      | `list[tuple[Decimal, Decimal]]` \| `None` | Bid levels — each entry is `(price, size)`                               |
| `a`      | `list[tuple[Decimal, Decimal]]` \| `None` | Ask levels — each entry is `(price, size)`                               |
| `v`      | `VaultParams` \| `None`                   | Updated vault params, if any                                             |

<Note>
  You can also subscribe via `KuruClient` instead of instantiating the client directly:

  ```python theme={null}
  client.set_orderbook_callback(on_orderbook)
  await client.subscribe_to_orderbook()
  ```
</Note>

***

## ExchangeWebsocketClient

The exchange WebSocket client (`exchange_ws`) streams incremental order book deltas in a Binance-compatible format. Unlike the frontend client, it does **not** send full snapshots — you must maintain a local order book.

### Update types

**`DepthUpdate`** — standard depth update:

| Field | Type                            | Description                                        |
| ----- | ------------------------------- | -------------------------------------------------- |
| `e`   | `str`                           | Event type (`"depthUpdate"`)                       |
| `E`   | `int`                           | Event time (milliseconds since epoch)              |
| `s`   | `str`                           | Symbol (market address)                            |
| `U`   | `int`                           | First update ID in the event                       |
| `u`   | `int`                           | Final update ID in the event                       |
| `b`   | `list[tuple[Decimal, Decimal]]` | Bid deltas — `(price, size)` pairs, pre-normalized |
| `a`   | `list[tuple[Decimal, Decimal]]` | Ask deltas — `(price, size)` pairs, pre-normalized |

**`MonadDepthUpdate`** — Monad-specific extension with blockchain state:

| Field         | Type                            | Description                                                      |
| ------------- | ------------------------------- | ---------------------------------------------------------------- |
| `e`           | `str`                           | Event type (`"monadDepthUpdate"`)                                |
| `E`           | `int`                           | Event time (milliseconds since epoch)                            |
| `s`           | `str`                           | Symbol (market address)                                          |
| `state`       | `str`                           | Blockchain state: `"committed"` \| `"proposed"` \| `"finalized"` |
| `blockNumber` | `int`                           | Block number where this update occurred                          |
| `blockId`     | `str`                           | Block hash (hex string with `0x` prefix)                         |
| `U`           | `int`                           | First update ID                                                  |
| `u`           | `int`                           | Final update ID                                                  |
| `b`           | `list[tuple[Decimal, Decimal]]` | Bid deltas                                                       |
| `a`           | `list[tuple[Decimal, Decimal]]` | Ask deltas                                                       |

### Usage

```python theme={null}
import asyncio

from kuru_sdk_py.configs import ConfigManager
from kuru_sdk_py.feed.exchange_ws import ExchangeWebsocketClient, DepthUpdate, MonadDepthUpdate

async def main():
    toml_config = ConfigManager.load_toml_config()
    market_config = ConfigManager.load_market_config(toml_config=toml_config)
    connection_config = ConfigManager.load_connection_config(toml_config=toml_config)

    update_queue = asyncio.Queue()

    client = ExchangeWebsocketClient(
        ws_url=connection_config.exchange_ws_url,
        market_config=market_config,
        update_queue=update_queue,
    )

    # Local orderbook — must be seeded and maintained manually
    orderbook = {"bids": {}, "asks": {}}

    async with client:
        while True:
            update = await update_queue.get()

            # Apply bid deltas (prices and sizes are pre-normalized Decimals)
            for price, size in update.b:
                if size == 0:
                    orderbook["bids"].pop(price, None)  # Level removed
                else:
                    orderbook["bids"][price] = size     # Level added or updated

            # Apply ask deltas
            for price, size in update.a:
                if size == 0:
                    orderbook["asks"].pop(price, None)  # Level removed
                else:
                    orderbook["asks"][price] = size     # Level added or updated

            # For MonadDepthUpdate, blockchain state is also available
            if isinstance(update, MonadDepthUpdate):
                print(f"Block {update.blockNumber} ({update.state})")

asyncio.run(main())
```

<Warning>
  A size of `0` in a delta means the price level should be removed from your local book. Always apply delta updates in sequence using the `U`/`u` IDs to detect gaps.
</Warning>

***

## Comparison

|                                   | `KuruFrontendOrderbookClient`          | `ExchangeWebsocketClient`      |
| --------------------------------- | -------------------------------------- | ------------------------------ |
| **Initial snapshot**              | Full L2 book on connect                | None (delta-only)              |
| **Update style**                  | Full levels at changed prices + events | Incremental deltas             |
| **Local book required**           | No                                     | Yes                            |
| **Event detail** (trades, orders) | Yes (`events` field)                   | No                             |
| **Blockchain state**              | No                                     | Yes (monad variant)            |
| **Message format**                | Text JSON                              | Binary JSON                    |
| **Example**                       | `get_orderbook_ws.py`                  | `get_exchange_orderbook_ws.py` |
