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


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.