Skip to Content
SDK Referenceorderbook
Orderbook

Read-only client for the shared order discovery service.

import { SharedOrderbookClient } from "@zkscatter/sdk/orderbook";

The shared orderbook aggregates orders across all active relayers so your app can show liquidity without polling each relayer’s /api/orders endpoint individually.

Client

const orderbook = new SharedOrderbookClient("https://orderbook.zkscatter.xyz", { fetchImpl: globalThis.fetch, timeoutMs: 5000, }); await orderbook.isOnline(); // boolean (probes /health) await orderbook.getStats(); // SharedOrderbookStats | null await orderbook.getRelayers(); // SharedRelayer[] await orderbook.getOrders(500); // SharedOrder[] — flat, optionally limited await orderbook.getOrdersByPair("ETH/USDC"); // SharedOrder[] for one pair

Types

interface SharedOrderbookStats { totalOrders: number; pairs: number; relayers: number; } interface SharedRelayer { address: string; url: string; name?: string; // optional — relayer may not advertise one orderCount: number; lastHeartbeat: number; // unix seconds } interface SharedOrder { id: string; relayer: string; relayerUrl: string; nonce: string; pubKeyAx: string; sellToken: string; buyToken: string; sellAmount: string; // wire-format strings — parse as bigint when needed buyAmount: string; minFillAmount: string; maxFee: number; expiry: number; createdAt: number; }

Usage pattern

The orderbook is a read-only convenience layer — it never holds custody and cannot match. Submit orders directly to a RelayerClient chosen from the discovery list:

const [orderbookOrders, relayers] = await Promise.all([ orderbook.getOrders("ETH/USDC"), loadRelayersWithApiInfo(network.contracts.relayerRegistry, provider), ]); // Pick a relayer that's online and has the lowest fee. const target = relayers .filter((r) => r.online) .sort((a, b) => Number(a.fee) - Number(b.fee))[0]; const client = new RelayerClient(target.url); await client.submitOrder(order, signature);

Filtering client-side

The shared orderbook does not expose a per-relayer pair endpoint; fetch the full list with getOrders (or getOrdersByPair) and filter by order.relayer locally.

const all = await orderbook.getOrders(); const byRelayer = all.filter((o) => o.relayer === relayerAddress); const distinctPairs = new Set(byRelayer.map((o) => `${o.sellToken}/${o.buyToken}`));

Common errors

`isOnline()` returns false but `getStats()` succeeds

isOnline only succeeds for 200 OK on /health. Some deployments expose /api/health instead — pass a base URL with the suffix or bypass the check.

Stale `lastHeartbeat`

Treat anything older than ~60s as offline. The shared orderbook expires entries on its own schedule but display logic should not trust the bare value.

Last updated on