Skip to main content
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

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

FieldTypeDescription
eventslist[FrontendEvent]Events describing what changed (trades, order placements, cancellations)
blist[tuple[Decimal, Decimal]] | NoneBid levels — each entry is (price, size)
alist[tuple[Decimal, Decimal]] | NoneAsk levels — each entry is (price, size)
vVaultParams | NoneUpdated vault params, if any
You can also subscribe via KuruClient instead of instantiating the client directly:
client.set_orderbook_callback(on_orderbook)
await client.subscribe_to_orderbook()

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:
FieldTypeDescription
estrEvent type ("depthUpdate")
EintEvent time (milliseconds since epoch)
sstrSymbol (market address)
UintFirst update ID in the event
uintFinal update ID in the event
blist[tuple[Decimal, Decimal]]Bid deltas — (price, size) pairs, pre-normalized
alist[tuple[Decimal, Decimal]]Ask deltas — (price, size) pairs, pre-normalized
MonadDepthUpdate — Monad-specific extension with blockchain state:
FieldTypeDescription
estrEvent type ("monadDepthUpdate")
EintEvent time (milliseconds since epoch)
sstrSymbol (market address)
statestrBlockchain state: "committed" | "proposed" | "finalized"
blockNumberintBlock number where this update occurred
blockIdstrBlock hash (hex string with 0x prefix)
UintFirst update ID
uintFinal update ID
blist[tuple[Decimal, Decimal]]Bid deltas
alist[tuple[Decimal, Decimal]]Ask deltas

Usage

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())
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.

Comparison

KuruFrontendOrderbookClientExchangeWebsocketClient
Initial snapshotFull L2 book on connectNone (delta-only)
Update styleFull levels at changed prices + eventsIncremental deltas
Local book requiredNoYes
Event detail (trades, orders)Yes (events field)No
Blockchain stateNoYes (monad variant)
Message formatText JSONBinary JSON
Exampleget_orderbook_ws.pyget_exchange_orderbook_ws.py