# Somnia Markets Documentation > Somnia Markets is a decentralized information and trading protocol on the Somnia network: spot pairs, binary information markets, and perps on one fully on-chain order-book engine. Guides for the TypeScript SDK and for SDK-less integration straight against the smart contracts (order placement, materializing the order book from events, market making), plus the full TypeDoc API reference. --- # /docs # Somnia Markets Somnia Markets is a decentralized information and trading protocol on [Somnia](https://somnia.network): one fully on-chain central limit order-book engine runs every market family — **spot** pairs, **binary** information markets, and **perps** — alongside a realtime on-chain index-price feed. Everything is on-chain and permissionless: order matching, escrow, settlement, market creation (per-venue), and resolution. The APIs below are conveniences over the same public contracts — nothing they do is privileged. **Spot markets** are plain base/quote order books (e.g. SOMI/USDC), each pool pushing a smoothed on-chain mark price straight from its own book. **Binary markets** are the information leg: a YES/NO question — such as an asset above a strike at expiry — whose outcome shares trade on the book at prices that *are* probabilities, so each book doubles as a live on-chain forecast. Shares are ERC-6909 positions backed 1:1 by collateral: a complete set (1 YES + 1 NO) always mints from and merges back to exactly one collateral unit, the winning side redeems 1:1 at resolution, and resolution itself is driven on-chain by the Prophecy oracle through Somnia's reactivity — no operator in the loop. Each market carries an on-chain kind tag (`marketType()`); future kinds (multi-outcome, dual-book) extend the same protocol. **Perps** are linear, collateral-settled perpetuals — cross-margin via the MarginBank, on-chain funding and liquidations — live on testnet. ## Ways to integrate **The TypeScript SDK — `@somnia-chain/markets-sdk`.** The fastest path for apps and bots in a JS runtime: realtime order books, trades, candles, and positions streamed with zero polling, plus a typed trader for placing orders, managing margin, and minting/redeeming outcome shares. Start with [The SDK](../../../packages/sdk/README.md), then [The exchange API](../../../packages/sdk/docs/EXCHANGE.md); the per-family guides — [Spot markets](../../../packages/sdk/docs/SPOT.md), [Binary markets](../../../packages/sdk/docs/BINARY.md), [Perps](../../../packages/sdk/docs/PERPS.md) — cover what differs per kind, and [Architecture](../../../packages/sdk/docs/ARCHITECTURE.md) explains how it works under the hood. **Raw smart contracts — no SDK.** Any language, any runtime, nothing but an RPC node and the ABIs: discover markets, place orders, and materialize a live local order book straight from contract events. [Raw Smart-Contract Integration](./RawIntegration.md) is the end-to-end guide; [Market Making](./MarketMakingTips.md) covers what is venue-specific for quoting operations — book encoding, escrow semantics, event caveats, market lifecycle. ## Going deeper - The [System page](/system) is the live deployment view: every protocol contract with its address, owner, and implementation, plus indexer health. - The API reference in the sidebar is generated from the SDK source (TypeDoc). - These docs are also served machine-readable at [`/llms.txt`](/llms.txt) and [`/llms-full.txt`](/llms-full.txt). --- # /docs/typescript # @somnia-chain/markets-sdk The TypeScript SDK for building on **Somnia Markets** — read live market data and place trades on the on-chain order book from your own app. - **Realtime data, no wallet required.** Order books, trades, candles, and a user's positions and open orders stream into your UI the moment they happen on-chain — no polling loops to write or manage. - **Trading with a signer.** Place and cancel orders, mint and redeem outcome shares, and more, through a typed trader bound to your wallet. - **Works anywhere, with first-class React.** Use plain async functions in any environment, or drop in the hooks for components that update themselves. ## Install ```sh pnpm add @somnia-chain/markets-sdk viem # npm / yarn / bun equivalents work too ``` `viem` is a peer dependency. `react` is an optional peer — only needed for the `@somnia-chain/markets-sdk/react` entry. > Versions up to 0.19.0 were published to GitHub Packages under the private > `@somnia-chain` scope; from 0.20.0 the package is public on npm — no > registry configuration or token needed. ## Create an exchange `new SomniaMarkets(config)` is the single entry point — the exchange owns everything: symbols, market data, watches, and writes. No global setup, no hidden singleton; each exchange is isolated. ```ts import { SomniaMarkets, SOMNIA_MAINNET_ADDRESSES } from "@somnia-chain/markets-sdk"; import { somniaMainnet } from "@somnia-chain/markets-sdk/chains"; // every Somnia network, incl. Shannon/Elwood/Hideki/local const exchange = new SomniaMarkets({ indexerUrl: "https://prd.smk.somnia.host/v1/graphql", // the production indexer chain: somniaMainnet, wsRpcUrl: "wss://api.infra.mainnet.somnia.network/ws", addresses: SOMNIA_MAINNET_ADDRESSES, // baked-in per-chain constants (SOMNIA_TESTNET_ADDRESSES for testnet) privateKey, // optional — needed for createOrder & friends }); await exchange.loadMarkets(); const book = await exchange.watchOrderBook("BTC-95000-31DEC26/USDC#YES"); // live, zero RTT const order = await exchange.createOrder("BTC-95000-31DEC26/USDC#YES", "limit", "buy", 10, 0.62); ``` For testnet, swap all four: `https://dev.smk.somnia.host/v1/graphql`, `somniaShannon`, `wss://api.infra.testnet.somnia.network/ws`, and `SOMNIA_TESTNET_ADDRESSES`. The raw engine tier — bigint-exact, address-keyed — is reached _through_ the exchange (`exchange.client`, `exchange.trader`), never constructed separately. The WebSocket opens lazily on first chain I/O, so an indexer-only exchange (e.g. server-side GraphQL reads) never opens one. Nothing is shared between instances: per-request servers, parallel tests, a second account — just construct another. Two exchanges never share watch state or sockets. One exchange spans several chains, so a multi-chain bot needs only one — but `exchange.client` and `exchange.trader` name no chain, so on an exchange with more than one chain binding they throw `InvalidInputError`. Reach the raw tier per chain with `exchange.engineFor(chainId)` and `exchange.traderFor(chainId)`. New to the SDK? The **[documentation map](https://prd.smk.somnia.host/docs/typescript)** groups every page by need: two tutorials that end with a cancelled order on testnet, goal-shaped how-to guides, reference tables for configuration, symbols, units, and errors, and explanations of the design. The area guides, in reading order: - **[The exchange API](https://prd.smk.somnia.host/docs/typescript/exchange)** — the `SomniaMarkets` class, the SDK's primary surface: symbols (`SOMI/USDC`, `BTC-95000-31DEC26/USDC#YES`), `fetch*`/`watch*`/`createOrder`, human-unit structs. Exchange-bot muscle memory (ccxt included) transfers directly — start here. - **[Spot markets](https://prd.smk.somnia.host/docs/typescript/spot-markets)** — base/quote books: ticks and lots, native-base escrow, market orders, and stop orders. - **[Binary markets](https://prd.smk.somnia.host/docs/typescript/binary)** — YES/NO information markets: probability prices, the four sides, mint/burn/redeem, and a maker loop. - **[Perps](https://prd.smk.somnia.host/docs/typescript/perps)** — live on testnet: cross-margin via the MarginBank, funding, positions, and how perps slot into the `marketType` union. - **[Price feeds](https://prd.smk.somnia.host/docs/typescript/prices)** — realtime BTC/ETH index prices from the on-chain EMA oracle: `watchPrice`/`getLivePrice`, one-shot history + candles, and the React hooks. - **[SomniaLend](https://prd.smk.somnia.host/docs/typescript/lend)** — the third-party money market wrapped as `client.lend`: supply idle collateral, borrow working capital, reserve rates as APYs. - **[Chains](https://prd.smk.somnia.host/docs/typescript/chains)** — every Somnia network as a viem `Chain` (mainnet, Shannon, Elwood, Hideki, local anvil) from `@somnia-chain/markets-sdk/chains`, plus `getSomniaChain(id)`. - **[Bridge](https://prd.smk.somnia.host/docs/typescript/bridge)** — moving tokens between Somnia networks over the Hyperlane warp routes: the token/network enums, the per-network registry, and `createBridgeTransfer` → the unsigned transactions that do it. - **[Native RPC](https://prd.smk.somnia.host/docs/typescript/native)** — the `somnia_*` namespace wrapped as ordinary calls: the native ledger block, chain statistics, protocol parameters, reactivity subscription reads, and **session transactions** (the node holds the key, tracks the nonce, signs, and returns the receipt). - **[Reactivity](https://prd.smk.somnia.host/docs/typescript/reactivity)** — Somnia's event-driven primitive via `@somnia-chain/markets-sdk/reactivity` (a pointer at the upstream `@somnia-chain/reactivity` package): events pushed _with_ the state that goes with them, into TypeScript (`watch`) or into a Solidity handler (`subscribe`). - **[The engine (advanced)](https://prd.smk.somnia.host/docs/typescript/engine)** — the raw tier behind the exchange (`exchange.client` / `exchange.trader`, or `engineFor(chainId)` / `traderFor(chainId)` when it spans several chains): bigint-exact reads, ref-counted watches, React hook wiring, raw writes. - **[Architecture guide](https://prd.smk.somnia.host/docs/typescript/architecture)** — diagrams of the whole machine: the watch seam, event routing, the local order book, the reconnect lifecycle, and the one-round-trip write path. ### Three ways to read | How | What it is | Returns | | ------------------------------------------ | ---------------------------------------------------------------------- | ------------------- | | `client.list*` / `client.get*` | **One-shot** read (indexer GraphQL or on-chain) | a `Promise` | | `client.getLive*` + `client.subscribeLive` | **Synchronous** read off the live store (within a `watchMarket` scope) | a value, now | | `use*` hooks (`/react`) | React bindings over the live store (auto-watching) | re-render on change | So `client.getFills` fetches once; `client.getLiveFills` reads the live tape; `useLiveFills` re-renders a component as it updates. In React, provide the client once with `` (from `@somnia-chain/markets-sdk/react`) and the hooks read it from context. Markets come from one discriminated union — `Market = SpotMarket | PerpMarket | BinaryMarket`, keyed on `marketType` — via `client.listMarkets` / `client.getMarket`. Binary-only callers can use `client.listBinaryMarkets` / `client.getBinaryMarket`, the same query pre-narrowed to `BinaryMarket`. (Note: _binary_, not _clob_ — a spot market is an order book too, so "CLOB" was never the right label for the binary surface.) Money crosses the API as raw integers (bigint on writes, decimal strings from the indexer) scaled by token decimals. Convert at the edges with `fromHuman` (input) and `toHuman` / `toHumanString` (display); for binary prices, `probabilityToPrice` / `priceToProbability` map a YES price ↔ a 0–1 probability. ## What's included - **Entry point** — `new SomniaMarkets(config)` → the exchange (symbols, `fetch*`/`watch*`/`createOrder`, human-unit structs). Its engine tier — `exchange.client` (`SomniaMarketsClient`, bigint-exact reads + watches) and `exchange.trader` (raw writes), or `engineFor(chainId)` / `traderFor(chainId)` on a multi-chain exchange — is reached through it; `ClientConfig` - **React** — `SomniaMarketsProvider`, `useSomniaMarketsClient`, and the hooks `useWatchMarket`, `useWatchUser`, `useLiveStatus`, `useIsTailing`, `useLiveFills`, `useLiveUserFills`, `useLiveMarketByPool`, `useLiveMarketByAddress`, `useLiveUserOrders`, `useLiveBinaryOrderBook`, `useLiveSpotOrderBook`, … — the pool-keyed data hooks **watch automatically** while mounted; the indexer, price, funding, and lend hooks are listed in the API reference - **Client reads** — `client.listMarkets`/`getMarket` (the `Market` union), `listBinaryMarkets`/`getBinaryMarket`, `getCandles`, `getBinaryOrderBook`, `getOpenOrders`, `getPortfolio`, `getSyncStatus`, `getMarketOnchain`, `getSystemInfo`, … (indexer reads **throw** on failure — an empty result always means "no rows", never "request failed") - **Order state at chain head** — `getOrderOnchain(pool, orderId)`, `getOwnOpenOrdersOnchain(pool, owner)`, `getAllOpenOrdersOnchain(pool, { isBid })` answer from the pool contract, so an order is readable the moment its block lands. Use these to read your own writes; use the indexed `getOpenOrders` / `getOrders` for history — the chain surface only knows what is open **now**. `getOrderOnchain(pool, orderId, { blockNumber })` reads at the end of a past block instead, which is how a log consumer recovers the side and owner of a maker order the fill already removed; the fill's own numbers stay with the event, and an old block needs an archive node - **Live watches (no React)** — `client.watchMarket(pool)` / `watchMarkets({ discover })` / `watchUser(account)` → ref-counted handles; `getWatchStatus`, `subscribeLive`, `getLiveStatus`, `getLiveMarkets`, `getLiveMarketByPool`/`…ByAddress`, `getLiveFills`, `getLiveUserFills`, `getLiveUserOrders`, and the locally materialized resting books `getLiveBinaryOrderBook` (binary, 4-sided) / `getLiveSpotOrderBook` — synchronous, zero round-trips, scoped to what you watch. Every market kind streams; a discovery watch picks up new markets from the creation events (the MarketCreator's rolling series AND direct `BinaryMarketsModule.createMarket` markets); binary status/resolution stays current from chain events. - **Smart accounts** — the factory account model of [`@somnia-chain/accounts-sdk`](https://www.npmjs.com/package/@somnia-chain/accounts-sdk), through this SDK alone: `client.createExecutor({ smartAccount, inner })` sends writes AS an account (a session key that owns the account signs nothing, and an approval and its order land in ONE account transaction), `client.accounts` derives, discovers, creates and administers accounts (every write comes back as an unsigned call for any executor to send), and `exchange.accounts` spans the chains — one signature creates the account on every covered chain, and `accountFor` builds the multi-chain account the exchange trades through. See [docs/ACCOUNTS.md](./docs/ACCOUNTS.md) - **Trading** — `client.createTrader(...)` → `placeOrder`, `cancelOrder`, `approveBuilder` (opt a routing/builder frontend in for per-order builder fees), `placeSpotOrder`, `placeSpotStopOrder`, `mintSet`, `burnSet`, `redeem`, `faucet`, `resolve`, `voidMarket`. Each write **awaits its receipt** and resolves to `{ hash, receipt }` (`placeOrder` adds `orderId` + `fills`). With a `privateKey`/local `account` the SDK signs locally with **fixed fees** and a locally-tracked nonce, and sends via `eth_sendRawTransactionSync` — send + confirm in **one round-trip**, zero fee/nonce/gas estimation RPCs. In the browser, pass a `walletClient` (confirm rides the newHeads subscription). - **Contract ABIs** — the minimal ABI data the SDK itself encodes and decodes with, exported so a caller that builds a transaction or reads a receipt by hand uses the SAME signatures: the order-placement writes (`binaryPoolWriteAbi`, `spotPoolWriteAbi`, `perpPoolWriteAbi`, `orderBookBatchWriteAbi`), the funding writes (`erc20WriteAbi`, `erc20VaultWriteAbi`, `marginBankWriteAbi`), operator delegation (`operatorRegistryWriteAbi`), the spot stop-order lifecycle (`spotStopRegistryWriteAbi` + `spotStopRegistryEventsAbi` — created, triggered, cancelled, inert-cancelled), the shared order-book events (`orderBookEventsAbi`), and the binary module / settlement / ERC-6909 / OracleHub ABIs. Hand-copying a signature instead is how one drifts in silence - **Operator delegation** — `client.getOperatorPermissionsRegistry(pool)` names the registry a SpotPool actually gates operator calls through (`null` when the pool is unwired), so a caller can discover the address instead of configuring `addresses.operatorPermissionsRegistry`. Read a grant back with `client.isApprovedForPool` / `isGloballyApproved` (the raw slots) or `client.isOperatorAuthorized` (the pool's resolved answer) - **Types & helpers** — `Market`/`SpotMarket`/`BinaryMarket` (+ `isSpotMarket`/ `isBinaryMarket`), `LiveFill`, `LiveOrder`, `BinarySide`, `TailStatus`, `kindOf`, `fillKind`, `fromHuman`/`toHuman`, `DECIMALS`, … - **Chains** (`@somnia-chain/markets-sdk/chains`) — `somniaMainnet` (5031), `somniaShannon` (Shannon, 50312), `somniaElwood` (50313), `hidekiTestnet` (50383, 10 ms blocks) and `somniaLocal` (anvil, 31337) as viem `Chain`s, plus `somniaChains` / `getSomniaChain(id)` / `isSomniaChainId`. Nothing here imports chains from `viem/chains` any more - **Bridge** (same `/chains` entry) — the Hyperlane warp routes between Somnia networks as live-verified data (`BridgeToken`, `ChainId`, `SOMNIA_BRIDGE`, `getBridgeToken`, `getBridgeNetwork`, …) plus `createBridgeTransfer(...)` → the ordered, tagged **unsigned transactions** (`approve` then `bridge`) that move a balance. The registry and planner are pure (no RPC, no signer); `sendBridgeStep` is the one opt-in sender. ⚠️ dev/test bridge — not for real funds - **Native RPC** (`@somnia-chain/markets-sdk/native`) — `createNative(client)` wraps the node's `somnia_*` namespace, exactly the twelve methods in the [public JSON-RPC reference](https://docs.somnia.network/developer/json-rpc-api): `getBlock` (the native ledger block), `getStatistics`, `listPrivilegedReceipts`, `getNodePublicKeys`, the reactivity subscription reads, and `sendSessionTransaction` — plus `sessionAddress(seed)` / `sessionPrivateKey(seed)`, derived locally with no round-trip. Takes any EIP-1193 client, needs nothing else from the SDK - **Reactivity** (`@somnia-chain/markets-sdk/reactivity`) — a pointer at [`@somnia-chain/reactivity`](https://www.npmjs.com/package/@somnia-chain/reactivity) (optional peer dep, re-exported verbatim — no second copy of it here): `createReactivity(exchange.client)` (or `exchange.engineFor(chainId)` when the exchange spans several chains) → `watch` (a `somnia_watch` socket subscription that delivers each event _together with_ `eth_call` results from the same block), `subscribe` / `subscribeRaw` / `unsubscribe` (Solidity handler subscriptions via the precompile) and `scheduleSubscriptionAt{Timestamp,Block,Epoch}`, plus `unwrap()` to turn upstream's `Error`-returns into throws Every method, hook, and type is listed in the **API reference**. ## Using a query library (TanStack Query, SWR, …) The SDK deliberately ships no cache-library wrapper. Two rules cover the whole surface: - **Live hooks need no cache.** The `useLive*` hooks read a push-fed store that is already a shared singleton — ref-counted watches and deduped hydration mean ten components on one pool cost one subscription. Wrapping them in a query cache would cache a value that is already live; don't. - **Async reads go in YOUR query library**, with an `exchange.client` method as the `queryFn` and the SDK's exported key factory as the `queryKey`. Every client read is a plain promise, which is already the ideal `queryFn`, and the key factories (`marketsKey`, `portfolioKey`, `candlesKey`, `syncStatusKey`, `marketOnchainKey`, …) are plain functions from the root entry — no query library is imported, so they work with any of them. (Client reads take no per-request `AbortSignal` — cancellation is client-scoped via `ClientConfig.signal`; pass your query library's `signal` to any fetching your `queryFn` does itself.) ```tsx import { useQuery } from "@tanstack/react-query"; import { candlesKey } from "@somnia-chain/markets-sdk"; const { data: candles } = useQuery({ queryKey: candlesKey(pool, 60, { limit: 500 }), queryFn: () => client.getCandles(pool, 60, { limit: 500 }), refetchInterval: 15_000, }); ``` After a write, invalidate by the same factory — `queryClient.invalidateQueries({ queryKey: portfolioKey(account) })` — or everything SDK-shaped at once with the `["somnia-markets"]` prefix (`QUERY_KEY_SCOPE`). Hand-written key strings drift; the factories are the one canonical spelling per read. On a multi-chain exchange, pass the read's chain as the last argument of every key, for example `candlesKey(pool, 60, { limit: 500 }, { chainId })`. A key without `chainId` is the single-chain key. As a prefix filter it also matches every chain's entry, but a chained key never matches an entry stored without a chain. Outside a query library, `useIndexerQuery(fn, deps)` remains the built-in option: it re-runs on dep changes, keeps `data`/`loading`/`error`, and aborts a superseded request via the `AbortSignal` it passes to `fn`. ## How the live feed works You get instant updates without running your own indexer — scoped to exactly the markets you watch. Opening a watch loads a consistent snapshot of that scope (the one and only indexer touch), then keeps it current by streaming its on-chain events over a WebSocket — so trades, orders, prices, and the resting order book itself update the moment they're final on-chain. There is no polling anywhere: the WebSocket is the only realtime transport, and if it drops the watches heal themselves by reconnecting with backoff and backfilling the missed blocks straight from chain. ## Debugging The SDK is silent by default. To see what a client is doing — every trader call, the sign/broadcast pipeline, live-tail hydration and block application — pass a `debug` sink in the config. Events are structured data (`DebugEvent`: log lines plus span start/end pairs with ids, explicit `parentId` links, durations, and errors), so the sink owns all filtering and formatting. The toggle mechanism belongs to your app, not the SDK: The bundled `consoleDebugSink()` renders the stream as an indented span tree (reconstructed from `parentId`, so it stays correct under concurrency): ```text [sdk] ▶ trader.placeOrder { params: { pool: "0x…", side: "BUY_YES" } } [sdk] ▶ trade.execute { functionName: "placeBinaryOrder", … } [sdk] liveTail applying logs { received: 3, … } [sdk] ▶ trade.signCall [sdk] ◀ trade.signCall 2.1ms [sdk] · trade.execute { hash: "0x…" } [sdk] ◀ trade.execute 38.2ms [sdk] ◀ trader.placeOrder 41.0ms ``` ```ts import { consoleDebugSink } from "@somnia-chain/markets-sdk"; // Browser (explorer dev) — flip on from devtools with // localStorage.setItem("sdk-debug", "1") and reload: const exchange = new SomniaMarkets({ ...config, debug: localStorage.getItem("sdk-debug") ? consoleDebugSink() : undefined, }); // Node bot — JSON lines behind an env var: const exchange = new SomniaMarkets({ ...config, debug: process.env.SDK_DEBUG ? (e) => console.log(JSON.stringify(e, (_, v) => (typeof v === "bigint" ? v.toString() : v))) : undefined, }); ``` In tests, `debugCollector()` captures the stream with typed filters: ```ts import { debugCollector } from "@somnia-chain/markets-sdk"; const c = debugCollector(); const exchange = new SomniaMarkets({ ...config, debug: c.sink }); await exchange.trader.placeOrder(params); expect(c.starts("trade.execute")).toHaveLength(1); ``` Span events map 1:1 onto OpenTelemetry (`name` ↔ span name, `data` ↔ attributes, `error` ↔ status, `parentId` ↔ context link), so a real tracer is just a sink that keeps a `Map` — `phase: "start"` calls `tracer.startSpan(...)` (linking `parentId` via OTel context) and `phase: "end"` calls `span.end()`. The OTel dependency lives entirely in your app; the SDK stays dependency-free. ## Book provenance and live-tail integrity Book reads expose `blockNumber` so consumers can identify the data they hold. A native chain read pins both sides to one block. Supply `blockNumber` in the read options, or let the SDK select one head. Empty chain books retain that pin. Unified `fetchOrderBook` accepts `{ limit, blockNumber }` and preserves the pin in YES and NO views. A caller-built book can omit provenance. Live books expose a per-scope materialization watermark. It is the snapshot seam or highest applied event block for that scope. It is not the observed chain head. It does not prove that all events in that block arrived, or that an indexed seed equals chain state. The displayed live book also filters expiry using the local wall clock. Use a pinned chain read when an exact as-of chain snapshot is required. Historical and streaming unified trades expose their source `blockNumber` and `logIndex`, including NO views. Historical native fill rows retain decimal block strings. These fields are optional on `FillRow` and `UnifiedTrade` for compatibility with caller-built values. SDK reads populate them from the source. If a caller-built row omits either field, its unified trade keeps that field `undefined`; the SDK does not substitute block zero or log zero. A later log delivery checks any intervening range with chunked RPC log reads. Recovered events apply before the triggering later events. Head-only activity makes no default recovery reads. An empty probe is a quiet range; only a nonempty successful recovery increments `getLiveStatus().healedGaps`. Background failures are contained and visible in `getLiveStatus().failure`, with a semantic SDK error. The tail retains its range and retries with bounded reconnect backoff. It does not apply later batches across a failed recovery. This detects bounded block gaps. Adjacent delivered blocks can conceal a partially missing block. Missing terminal activity has no default trigger if no later log arrives. The SDK does not claim a gapless transport protocol. Optional owner `reconciliation` accepts a positive bigint `blockInterval` and integer `depth` from 1 to 100. It is off by default. At each eligible checkpoint, it recovers logs through a fixed target and compares native top levels against both chain sides pinned to that target. It filters local expiry using the target's chain timestamp. Head work coalesces while one comparison runs. Each checkpoint costs chunked log reads, a block header, and two contract reads per watched pool. `lastDivergence` retains the pool, block, depth, and differing raw levels even after a later match. Read failures remain distinct from empty or matching books. Reconciliation never replaces the event-derived order history with a top-N ladder. It does not repair historical seed rows. Owner cleanup stops pending work. The following example compares provenance labels. `config` selects the local or deployed environment, and `pool` is a pool in that environment. Choose a block that exists on that chain for the pinned read. The two labels describe different read contracts; equal labels alone do not prove equal books. ```ts const owner = new SomniaMarkets({ ...config, reconciliation: { blockInterval: 100n, depth: 10 }, }); try { const watch = await owner.client.watchMarket(pool); const live = owner.client.getLiveSpotOrderBook(pool); const pinned = await owner.client.getSpotOrderBook(pool, { blockNumber: 123n }); console.log({ delivered: live.blockNumber, pinned: pinned.blockNumber }); console.log(owner.client.getLiveStatus()); watch.stop(); } finally { await owner.close(); } ``` --- # /docs/typescript/docs # Somnia Markets SDK documentation This page is the map of the `@somnia-chain/markets-sdk` documentation. The pages are grouped by what you need right now: to learn, to finish a task, to look something up, or to understand a design. Every TypeScript example has a compile-checked counterpart that uses the public package entrypoints and real dependency types. The tutorials were run on the testnet. ## Start here Two lessons take a newcomer from an empty directory to a cancelled order on the Somnia testnet. Follow them in order. Each one takes about 15 minutes. 1. [Stream a live order book](./tutorials/stream-a-live-order-book.md). No wallet needed. Install the SDK, load the markets, read a book, and watch it change. 2. [Place and cancel your first order](./tutorials/place-and-cancel-your-first-order.md). Fund a testnet key, rest a limit order, see it in your open orders, and cancel it. ## Do a task Goal-shaped guides for a developer who already knows what they want. - [Configure the SDK for testnet, mainnet, or a local chain](./how-to/configure-for-a-network.md) - [Get testnet funds](./how-to/get-testnet-funds.md) - [Run a quoting loop](./how-to/run-a-quoting-loop.md): place, amend, and cancel orders from a bot - [Detect when an order fills](./how-to/detect-fills.md) - [Sign with a browser wallet](./how-to/sign-with-a-browser-wallet.md) - [Trade through a smart account](./how-to/trade-through-a-smart-account.md): the accounts SDK's factory accounts as first-class actors - [Use the React hooks](./how-to/use-the-react-hooks.md) - [Handle errors and reverts](./how-to/handle-errors.md) - [Debug what the SDK is doing](./how-to/debug-the-sdk.md) ## Look something up Neutral descriptions of the machinery. Facts, defaults, and constraints, without instruction. - [Configuration](./reference/configuration.md): every field of `SomniaMarketsConfig`, with defaults - [Networks and endpoints](./reference/networks-and-endpoints.md): chain ids, RPC and indexer URLs, address constants - [Symbols](./reference/symbols.md): the symbol grammar and how raw references resolve - [Units and scales](./reference/units-and-scales.md): raw versus human values, decimals, basis points, ray, timestamps - [Read tiers](./reference/read-tiers.md): which methods read the live store, the chain, or the indexer - [Errors](./reference/errors.md): the SDK error classes and the contract error names they decode - The API reference, generated from the source, lists every method, hook, and type. On the docs site it sits in the sidebar under "TypeScript SDK". ## Understand the design Discussion for reading away from the keyboard. - [About the exchange instance](./explanation/about-the-exchange-instance.md): why one object owns the sockets, the store, and the signer - [About symbols and human units](./explanation/about-symbols-and-human-units.md): why the exchange API speaks in symbols and decimal numbers, and what that costs - [Binary pool recycling](./explanation/binary-pool-recycling.md): why one pool address can host successive markets and how to select safe reads - [Architecture](./ARCHITECTURE.md): the watch seam, event routing, the local order book, reconnects, and the write path ## Area guides One guide per market family or module. Each one covers reading, trading, and background for its area. - [The exchange API](./EXCHANGE.md), [Spot markets](./SPOT.md), [Binary markets](./BINARY.md), [Perps](./PERPS.md) - [Price feeds](./PRICES.md), [SomniaLend](./LEND.md), [Smart accounts](./ACCOUNTS.md) - [Chains](./CHAINS.md), [Bridge](./BRIDGE.md), [Chains walkthrough](./CHAINS_WALKTHROUGH.md) - [Native RPC](./NATIVE.md), [Reactivity](./REACTIVITY.md) - [The engine](./ENGINE.md): the raw client behind the exchange --- # /docs/typescript/exchange # The exchange API The `SomniaMarkets` class is the SDK's primary surface: markets keyed by symbols, `fetch*`/`watch*`/`createOrder` verbs, human-unit structs — the idioms every exchange bot already speaks (if you've driven a venue through ccxt, nothing here will surprise you, down to the field names). Under the hood it runs on the native engine (scoped watches, local books, one-round-trip writes), so the `watch*` channels are zero-round-trip and `createOrder` confirms in a single round-trip. ```ts import { SomniaMarkets } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ indexerUrl, chain, wsRpcUrl, privateKey }); // Use `chains` to configure multiple chains. await exchange.loadMarkets(); const symbol = "BTC-95000-31DEC26/USDC#YES"; const book = await exchange.watchOrderBook(symbol, 10); // live, zero RTT const order = await exchange.createOrder(symbol, "limit", "buy", 10, 0.62); // … later: await exchange.cancelOrder(order.id, symbol); ``` The raw engine stays available at `exchange.client` on a single-chain exchange, and at `exchange.engineFor(chainId)` on any exchange — bigint-exact, address-keyed — for anything the exchange verbs don't cover; see [the engine guide](./ENGINE.md). ## Symbols A **symbol names a market**; a **tradable symbol** names something you place orders on. For spot they coincide; for outcome markets each outcome is its own tradable: | Kind | Market symbol | Tradables | | -------------------- | ------------------------ | ------------------------ | | Spot | `SOMI/USDC` | `SOMI/USDC` | | Binary | `BTC-95000-31DEC26/USDC` | `…#YES`, `…#NO` | | Perp | `BTC/USDSO:USDSO` | `BTC/USDSO:USDSO` | | Categorical _(soon)_ | `US-ELECTION-28/USDC` | `…#TRUMP`, `…#NEWSOM`, … | Binary symbols are synthesized as `ASSET-STRIKE-DDMONYY/QUOTE` (quote = the collateral's ERC-20 symbol), with an `-HHMM` expiry component for intraday series markets (`ETH-171780-03JUL26-0930/TUSDC`); any residual collision gets a deterministic 4-hex market-id tiebreaker on the base side of the slash. Everything before `#` follows standard exchange symbol conventions; `#OUTCOME` is our extension (binary markets need one). **Any raw ref works wherever a symbol does** — a pool address, market id, or BinaryMarket address resolves to the same tradable (outcome markets default to `#YES`). Numbers are **human units in the tradable's own terms**: a `#NO` price of 0.38 _is_ the NO probability — the YES-terms complement, raw integers, and escrow math are all internal. Raw payloads ride on every struct's `info`. ## Verbs | Method | Backed by | Notes | | ---------------------------------------------------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `loadMarkets()` / `fetchMarkets()` | indexer (+ one-time `symbol()` reads) | builds the symbol registry; a failed registry read is contained and reported by `registryReadError`, not thrown | | `fetchOrderBook(symbol, limit?)` | chain | head-fresh one-shot | | `fetchTrades(symbol, since?, limit?)` | indexer | public tape | | `fetchOHLCV(symbol, "5m", since?, limit?)` | indexer | `1m 5m 15m 1h 4h 1d` | | `fetchOpenOrders(symbol?, limit?)` | indexer | authenticated; `limit` is per venue (default 200) | | `fetchMyTrades(symbol?, since?, limit?)` | indexer | authenticated; scoped + windowed at the query, newest-first across venues | | `fetchBalance()` | chain | wallet balances by currency code (incl. binary YES/NO ERC-6909 holdings, keyed by tradable symbol) | | `fetchStatus()` | local | watch/socket health | | `watchOrderBook(symbol, limit?)` | **local store** | zero RTT, current to last block | | `watchTrades(symbol)` · `watchOrders(symbol)` · `watchMyTrades(symbol)` | **local store** | streaming | | `createOrder(symbol, type, side, amount, price?, params?)` | chain write | 1-RTT confirm, fills decoded | | `cancelOrder(id, symbol)` | chain write | | | `mintSet` / `burnSet` / `redeem` `(symbol, amount)` | chain write | outcome markets only | | `fetchFundingRate(symbol)` | chain | perps: mark/index + funding rate | | `fetchPositions(symbols?)` | chain | perps: open MarginBank positions | | `depositMargin` / `withdrawMargin` `(symbol, amount)` | chain write | perps: cross-margin collateral | | `watchPrice(asset)` · `fetchPrice(asset)` | price feed | index price (EMA oracle) — see [Price feeds](./PRICES.md) | | `fetchPriceOHLCV(asset, "1m")` | price feed | index candles: `1m`/`1h`/`1d` | | `fetchTicker(symbol)` | indexer; best-effort chain read on perps | last, 24h change and volume; the two halves fail independently and each reports its own state. A failed candle read, or a market with `indexed: false`, gives `statsState: "unavailable"` with every 24h field absent. A failed `getPerpState` gives `perpState: "degraded"` with the 24h half intact | | `fetchOrders(symbol?, since?, limit?, { offset? })` | indexer | authenticated; order history as one offset-paged set | | `getOrderHistoryPage({ ref?, status?, limit?, offset? })` | indexer | authenticated; preferred indexed-history name; partial raw-row page with immutable identity and continuation | | `getOrdersPage({ ref?, status?, limit?, offset? })` | indexer | compatibility name for `getOrderHistoryPage` | | `fetchPortfolioAnalytics(timeframe, params?)` | indexer | authenticated; PnL, equity and holdings series | | `createStopOrder(symbol, type, side, amount, triggerPrice, price?, params?)` | chain write | spot only; see [Spot markets](./SPOT.md) | | `fetchOpenStopOrders(symbol?)` · `cancelStopOrder(id, symbol)` | indexer · chain write | spot stop orders | | `fetchFundingRateHistory(symbol, since?, limit?)` | indexer | perps: funding-rate history | | `setSigner({ privateKey \| account \| walletClient })` | local | bind or replace the signer after construction | | `priceToPrecision(ref, price)` · `amountToPrecision(ref, amount)` | local | snap a value down onto the market's tick or lot grid | | `market(ref)` | local | resolve any handle to its tradable | | `unwatchMarket(symbol)` | local | release one market's watch and channels; pending `watch*` calls on it reject with `AbortError` | | `close()` | local | release all watches, channels, and sockets; a Node script exits on its own afterwards | Still reserved: `watchPositions`, `setLeverage` (the raw `exchange.traderFor(chainId).setPerpLeverage` exists for the latter). For account fill history, `exchange.engineFor(chainId).getUserFillsPage` uses bounded opaque-cursor pages. Its `datasetGeneration` comes from the serving Fill database; continuation across a reindex or blue/green cutover throws a typed restart-required error when the replacement's hashed producer inputs differ. Handler changes that affect stored fills require a reindex; a code-only resume keeps the existing generation. See [Fill history pages and dataset restart](reference/fill-history-pages.md) before retaining pages across requests. ### Paginated order identity `getOrderHistoryPage` reads one bounded page for the configured account. Use it when the caller must retain the chain, account, market, pool, and order id together. `getOrdersPage` remains available as a compatibility name. The default limit is 100 and the default offset is 0. A `status` filter runs in the indexer. A `ref` also scopes the query to its pool, then verifies each raw market id so a recycled binary pool cannot cross market lifetimes. `rowsRead` counts raw indexer rows. `nextOffset` advances after a full raw page, even when outcome filtering removes every display order or every identity is unresolved. The `unresolved` list keeps rows whose immutable market id is absent or inconsistent in the loaded registry. A null binary side remains on the YES book. A NO scope excludes that row. Every result has `coverage: "partial"` and `source: "indexer-offset"`. These are indexed mutable records. They are not an immutable lifecycle log or a current Open Orders snapshot. The indexer orders rows by placement time without a frozen revision or a unique tie-break. Concurrent inserts or status changes can make pages skip or repeat rows. A short page does not prove complete account state. The `status` option filters indexed history. `status: "Open"` cannot establish completeness, removals, continuity, or action freshness. Use a separately supported current-state flow when the caller needs the SDK's current open-order view. Each flow retains its documented freshness limits. ```ts let offset = 0; while (true) { const page = await exchange.getOrderHistoryPage({ limit: 100, offset }); for (const order of page.orders) console.log(order.identity, order.status); if (page.nextOffset === null) break; offset = page.nextOffset; } ``` ### Portfolio analytics fill pages Portfolio analytics needs the full indexed fill history to calculate PnL. `fetchPortfolioAnalytics` reads the account's indexed SPOT fill history through cursor pages of up to 999 rows. The indexer applies the SPOT filter, so binary and perp fills are not transferred. The method reads all configured chains at the same time, with one page in flight per chain. A short nonempty page triggers a one-row continuation probe, so a positive Hasura row cap smaller than 1,000 cannot silently end the traversal. It computes PnL only after the final page. Its default is an exhaustive traversal of the rows visible to the configured indexer role, including older fills that establish the cost basis for recent sells. The deployment must establish a row cap of at least one; a zero cap is indistinguishable from an empty history through the same role. Set `params.maxFillPages` to a positive safe integer to bound logical pages for one call. The budget counts pages across all chains. Each page may use two indexer requests when a continuation probe is needed. If more history remains, the method throws `IncompleteHistoryError` with `reason: "pageBudgetExceeded"` and `pagesRead` instead of returning plausible but incomplete PnL. A repeated cursor throws the same class with `reason: "cursorCycle"`. `IndexerError` still signals a failed indexer request. A failure on one chain rejects the call and stops the other chains at their next page. On a multi-chain exchange, the `IndexerError` carries the `chainId` that failed. Each call starts with a fresh first-page read; an earlier empty result is not cached and cannot hide a newly indexed fill. Cursor continuation assumes an unchanged indexer dataset during the call; it is not a reindex generation or chain-head completeness proof. ### The `watch*` idiom Each `await` resolves when the channel next changes; the first call resolves immediately after the (ref-counted) market watch hydrates: ```ts while (running) { const book = await exchange.watchOrderBook(symbol, 5); // resolves per change requote(book.bids[0], book.asks[0]); } ``` **"Did my resting order fill?"** — watch your orders and look for the status flip: ```ts const orders = await exchange.watchOrders(symbol); // resolves per change const mine = orders.find((o) => o.id === orderId); if (mine?.status === "closed") … // filled ``` ### `createOrder` params - `type: "limit" | "market"` — market orders compute a crossing limit from the best opposite level ± `params.slippage` (default 1% on this surface; the engine's `quoteBinaryStake` / `quoteBinarySell` helpers default to 3% with a 10-tick floor) and send IOC; they throw `InvalidInputError` if the opposite side is empty. When the chain rejects an order you get a `ContractRevertError` whose `errorName` is the contract's own error — see [ENGINE.md § Errors](./ENGINE.md#errors--branch-on-the-type-never-the-message). - `params.timeInForce: "GTC" | "IOC" | "FOK" | "PO"` (or `postOnly: true`) — maps to the on-chain order types. - `params.builder` / `params.builderFeeBpsTimes1k` — attribute the order to a routing/builder frontend and pay it a per-order fee (pool bps×1000 unit). Requires a prior one-time `exchange.traderFor(chainId).approveBuilder({ pool, builder, maxFeeBpsTimes1k })` opt-in on the pool's chain (for example `exchange.traderFor(50383)` for a Hideki pool), else a non-zero fee reverts (`BuilderFeeExceedsCap` on binary, `BuilderNotApproved` on spot, `BuilderFeeExceedsApproval` on perp). Works on binary, spot and perp — but the approval is stored per pool, so opt in on each pool you attribute orders on. - `params.funding: "explicit" | "auto" | "skip"` — what to do when the order's collateral is not on the market's chain (a multi-chain exchange only; see below). `"explicit"` throws `CollateralOnWrongChainError` with a ready bridge plan and sends nothing; `"auto"` bridges the shortfall the way `exchange.ensureFunds` does, for the escrow token found by address, waits for delivery, then places; `"skip"` runs no balance check. The default is `"explicit"` once the exchange spans a second chain and `"skip"` on a single-chain exchange. - The returned order: `status: "open"` (rested), `"closed"` (fully filled in the same round-trip — `filled`/`remaining` say how much), or `"canceled"` (IOC remainder). `info` carries the receipt + raw fills, and `chainId` names the chain it was sent on. ## One exchange, several chains A market is unique to one chain, so a symbol names exactly one `(chainId, market)`. Configure every chain the account trades on and the exchange builds one engine per binding: reads merge, writes route to the market's chain, and every struct carries its `chainId`. Do not mix mainnet and testnet chains in one exchange. The example pairs the two testnets. ```ts import { SomniaMarkets, SOMNIA_HIDEKI_TESTNET_ADDRESSES, SOMNIA_TESTNET_ADDRESSES } from "@somnia-chain/markets-sdk"; import { hidekiTestnet, somniaShannon } from "@somnia-chain/markets-sdk/chains"; const exchange = new SomniaMarkets({ chains: [ { chain: somniaShannon, indexerUrl: "https://dev.smk.somnia.host/v1/graphql", addresses: SOMNIA_TESTNET_ADDRESSES, }, // Hideki has no hosted indexer. Indexed reads need an indexer you operate. { chain: hidekiTestnet, indexerUrl: hidekiIndexerUrl, addresses: SOMNIA_HIDEKI_TESTNET_ADDRESSES }, ], account: safeAccount, // one address on every chain, one executor per chain }); await exchange.loadMarkets(); const bal = await exchange.fetchBalance(); bal.USDso?.total; // summed across chains bal.USDso?.byChain[hidekiTestnet.id]?.total; const order = await exchange.createOrder("BTC/USDso:USDso", "limit", "buy", 1, 60_000); order.chainId; // the chain the market lives on ``` - The single-chain config is the one-element case and behaves exactly as before. - Each chain needs its own indexer. Two bindings that name one indexer URL, written with a different case or a trailing slash, also throw `InvalidInputError`. - Each engine checks its endpoints before it uses their data. Its first indexed read or hydration also reads the indexer's `chain_metadata`. The two requests go out together, and no row reaches the caller or the live store until the check passes: an indexer that does not index the binding's chain throws `NotConfiguredError`. On Hideki (50383), the first chain read first reads block 1: an RPC on the retired v1 genesis throws `NotConfiguredError`. - A bare pool address or market id that exists on two chains (the same CREATE2 pool on L1 and Hideki) is ambiguous: pass `{ chainId, id }` — a `ChainMarketRef` — wherever a symbol is accepted, and `{ chainId, pool, id }` to `cancelOrder`. - Live and history rows name their chain too. `LiveFill`, `LiveOrder`, `LiveFundingUpdate`, `LiquidationEvent` and `FundingPayment` carry `chainId`, the chain of the engine that produced the row. A fill id or an order id can repeat on two chains, so key merged rows on `(chainId, id)`. Price-feed rows are not in that set: a feed is configured separately from the chain, so one endpoint can serve two engines and a tick is not a per-chain row. - `exchange.client` and `exchange.trader` name no chain, so they throw `InvalidInputError` on an exchange with two or more chains. A pool address or market id can name a different market on each chain. Use `exchange.engineFor(chainId)` for raw reads and `exchange.traderFor(chainId)` for raw writes. - `exchange.watchUser()` hydrates the account's history on every chain behind one handle. The chains open at the same time. When one fails, the call stops every handle that opened and throws the error of the first failing chain in binding order. - Collateral must sit on the market's chain. `exchange.bridge` plans and executes transfers between the exchange's chains through the account's executors, and `exchange.ensureFunds({ code, chainId, amount })` is the helper behind `createOrder(…, { funding: "auto" })`. On a native route (STT), all three throw `BridgeLiquidityError` and send nothing when the destination router holds less than the amount. - A bridge waits for its own Hyperlane message on the destination, matched by message id. On the Hideki 2 lane the measured median is 7.5 s to 8.7 s per leg, and the default delivery timeout is 180 s. A router drained after the liquidity check stalls delivery until it is seeded again. On a timeout, `ensureFunds` and `createOrder(…, { funding: "auto" })` throw `BridgeDeliveryTimeoutError` with the `messageId` and place no order. Check `delivered(messageId)` on the destination Mailbox before you bridge again. See [the bridge guide](./BRIDGE.md#bridging-through-the-exchange). - On one exchange, `ensureFunds` and `createOrder(…, { funding: "auto" })` run one at a time per account, chain and currency. An auto-funded order keeps its place in that queue until it is sent. So two concurrent auto-funded orders bridge their combined shortfall once, and neither counts funds the other one needs. Each queued call can wait a full delivery timeout. A leg that timed out stays pending on the exchange. When the next call for the same key finds a shortfall, it waits for that message and sends no new leg for it. `close()` ends the delivery waits of every call that started before it, as a timeout, and the leg stays pending. This state is in memory only. - The account: `{ address, executors: { [chainId]: Executor } }`. Build an executor with `engine.createExecutor(spec)` — a private key, a wallet, a Somnia session seed, or a smart account with the executor that sends its outer transaction. Any object implementing `Executor` works too, for example for a safe that the accounts factory did not deploy: the SDK decodes the order from the receipt it returns and never fetches it again. When the executor returns an inner failure as `failure` on a success-status receipt, Trader writes throw it. - A factory smart account from `@somnia-chain/accounts-sdk` is a first-class actor: `engine.createExecutor({ smartAccount, inner })` batches through the accounts SDK's own MultiSend batcher with no configuration, signs nothing when the inner actor is a direct owner at threshold 1, and reaches an account owned by other accounts through `through`. The whole lifecycle — derive, create on every chain with one signature, manage owners, move funds — is `client.accounts` and `exchange.accounts`; `exchange.accounts.accountFor(accountId, index, { sessionSeed })` builds the multi-chain account above in one call. It signs locally from the seed's key, so the seed never goes to a node. A `{ sessionSeed }` executor, which sends the seed to the node, is refused as an account's `inner`. See the [Smart accounts guide](./ACCOUNTS.md) and [Trade through a smart account](./how-to/trade-through-a-smart-account.md). ### Reads across chains This section tells you what a read does when one chain of a multi-chain exchange fails, and how to read only the chains that answer. A single-chain exchange behaves as before. **Account reads fail closed.** `fetchBalance`, `fetchOpenOrders`, `fetchOrders`, `getOrdersPage`, `getOrderHistoryPage`, `fetchMyTrades`, `fetchPositions`, `fetchOpenStopOrders` and `watchUser` read every chain when you give no market and no chain. When one chain fails, the read throws. It does not return the rows of the other chains, because a merged result with one chain missing looks like "the account holds less". On an exchange with two or more chains, the thrown `IndexerError` or `RpcError` has `chainId` set to the chain that failed. The SDK sets this field on the original error. The class, the message and the `cause` do not change, so `instanceof` checks still work. A read scoped to one chain, by a market or by a chain filter, throws its error without `chainId`. **Read one chain with a chain filter.** Each of these reads accepts a `SomniaMarketsChainFilter` (`{ chainId }`): as the last argument, in `params` for `fetchOrders`, and in the options of `getOrdersPage` and `getOrderHistoryPage`. A filtered read calls only the engine of that chain. Use it to read each chain on its own and to show a failed chain as failed: ```ts const results = await Promise.allSettled(exchange.chainIds.map((chainId) => exchange.fetchBalance({ chainId }))); ``` - A `chainId` that the exchange does not span throws `NotConfiguredError`. - A market and a `chainId` on different chains throw `InvalidInputError`, with both chains in `chainIds`. - Before an account read, the exchange loads markets. That load reads only the chains that the read touches, so a filtered read never calls another chain. Of those chains, it reads a chain that no load has read yet. It also reads a chain whose last load failed, but at most once in 30 seconds after that chain's last load finished. Between those retries, the read uses the cached markets, and the failure accessors keep the recorded error and failing chain. A read that starts while a retry of its chain runs waits for that retry. A read can also wait while another market load runs, for example a read filtered to another chain on a new exchange. To avoid this, call `loadMarkets()` once before you read chains in parallel. **Chains with no indexer.** A chain bound with no `indexerUrl` (Hideki has no hosted indexer) keeps the parts of each read that come from the chain. `exchange.chainIdsWithoutIndexer` lists these chains, in binding order. | Read | On a chain with no `indexerUrl` | | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `fetchBalance` | ERC-20 and native balances. No binary outcome holdings, because holdings are indexer data | | `fetchOpenOrders` | Resting orders read from the chain, over the perp pools that `loadMarkets` found on that chain. These rows have no `txHash` and no `timestamp` | | `fetchPositions` | Complete. It needs no indexer | | `fetchOrders`, `getOrdersPage`, `getOrderHistoryPage`, `fetchMyTrades`, `fetchOpenStopOrders`, `watchUser` | The chain is skipped | - A skipped chain adds no rows. A missing chain in the result does not mean that the account has no orders or trades there. - A chain is skipped only when the read also spans a chain with an indexer. A read scoped to a chain with no indexer, or a read where no chain has an indexer, throws `NotConfiguredError`. It never returns a result that looks empty. **One pool's oracle does not fail `fetchPositions`.** `fetchPositions` reads the pool state (mark, index, funding) only for a pool where the account holds a position. When that read fails, for example because the pool's oracle reverts, the position still lists with `perpState: "degraded"`, and `markPrice` and `unrealizedPnl` are absent. The other positions are not affected. Branch on `perpState`, not on the absence of `markPrice`. `fetchPositions` returns its rows grouped by chain, in binding order. **Health and market loading report each chain.** These two surfaces keep answering when one chain fails: - `fetchDataStatus()` measures each chain on its own. `indexerByChain` holds every chain that was measured, and `null` there still means that the chain's metadata row is absent. `indexerErrorByChain` holds the original error of every chain that failed, and is present only when a chain failed. `indexer` (the primary chain) is absent when the primary chain failed. The call throws only when every chain fails. It then throws the primary chain's error, with `chainId` set on an exchange with two or more chains. - `loadMarkets()` does not throw on a failed registry read or a failed perp discovery. `registryReadErrorsByChain`, `perpDiscoveryErrorsByChain` and `perpDiscoveryPartialFailuresByChain` report the failures of each chain. `registryReadError`, `perpDiscoveryError` and `perpDiscoveryPartialFailure` still report one failure: the first failing chain, in the order of the `chains` config. - A bare `loadMarkets()` reads again each chain that failed on the last load. It also loads each chain that no load has read yet, for example after only reads filtered to another chain. The other chains keep their cached markets. A `NotConfiguredError` failure, for example the registry read of a chain with no indexer, is not retried. `loadMarkets(true)` reloads every chain. - A verb that loads markets for you, such as `fetchBalance`, `fetchMyTrades` or `fetchPositions`, retries a failed chain at most once in 30 seconds after that chain's last load finished. `loadMarkets()`, `fetchMarkets()`, `ensureFunds` and `loadMarkets(true)` retry at once. Between retries, the failure accessors stay populated with the error and the failing chain. - Symbols are unique across the loaded chains. When a chain loads later than the others, a symbol that it shares with a market on another chain changes on both chains. Call `loadMarkets()` before you keep symbols. ## Structs One set of shapes throughout: markets `{ id, symbol, type, base, quote, active, precision, limits, outcomes?, info }`; books as `[price, amount]` pairs, best first; orders `{ id, symbol, type?, side, price, amount, filled, remaining, status, timestamp, info }` (`type` is absent on orders read back from the indexer — the pools do not emit it); trades `{ id, symbol, price, amount, cost, side?, timestamp, info }`; balances `{ [code]: { free, used, total } }` (escrowed funds live in the pools, so wallet `free === total`); OHLCV rows `[ms, open, high, low, close, baseVolume]`. ## How each market kind maps - **Spot** — symbol is the tradable; `side` is base-buy/base-sell; done. - **Binary** — two tradables per market. The engine keeps one YES-terms book; the resolver presents each outcome's own view (prices, sides, candles all outcome-relative). `mintSet`/`burnSet`/`redeem` operate at market level. - **Perps** — `type: "swap"`, settle = quote (linear, collateral-settled); `createOrder` unchanged (margin locks from your MarginBank balance — `depositMargin` first); `fetchPositions`/`fetchFundingRate` read the MarginBank/pool live. - **Categorical / multi-outcome** _(teed up)_ — N tradables on one pool (outcome index = the order's `userData`, exactly as binary uses 0/1 today); same verbs, and cross-book complete-set fills will surface in `watchMyTrades` with a shared match id in `info`. The design intent: **the verbs never change again** — every future market kind is new data (a `type`, an `outcomes[]` list), not new API. --- # /docs/typescript/binary # Binary markets A binary market is an order book over a YES/NO question ("Will BTC be above $95k at expiry?"). Each market has its own `BinaryMarket` contract (lifecycle, resolution) and uses a `BinaryPool` (the CLOB + escrow) that can host later markets. Its YES and NO outcome tokens are backed 1:1 by collateral. This guide covers reading and trading them; [pool recycling](./explanation/binary-pool-recycling.md) explains why the pool address does not identify one binary market. The shared client mechanics (watches, read tiers, signers) are in [the engine guide](./ENGINE.md). ## The mental model - **Prices are YES probabilities.** Every price in the API is the YES price in raw collateral units per whole outcome token — `620000` with 6-decimal collateral means 0.62, i.e. a 62% implied probability. Convert with `probabilityToPrice` / `priceToProbability`, and `fromHuman` / `toHuman` at the UI edges, passing the selected market's `quoteDecimals`. On the active mainnet venue USDso has 18 decimals; on Shannon and Hideki tUSDC has 6. The NO side is always the complement: a NO at 0.38 _is_ a YES at 0.62. The pool keeps one book in YES terms. - **Four sides, one book.** `BinarySide` is `BUY_YES | SELL_YES | BUY_NO | SELL_NO`. Buys escrow collateral; sells escrow the outcome token you're selling. Opposite-side orders can match by _minting_ a fresh YES+NO pair from collateral (two buyers) or _burning_ one back to collateral (two sellers) — the `BinaryFillKind` on a fill tells you which. - **Lifecycle.** `Listed → Trading → Locked → Settling → Resolved | Voided → Finalized` (`BinaryMarketStatus`; `Finalized` once the settlement snapshot is swept and the pool released). Trading is only possible in `Trading`; after resolution the winning token redeems 1:1 for collateral, net of the venue's one-time settlement fee if it configured one. A voided market pays BOTH sides instead, from the payout vector it stored at void time, never fee'd — so redeeming one names the leg (see Complete sets and settlement). - **Markets roll themselves.** Each cadence (1m / 5m / 15m / 1h / 4h / 24h) is a _series_ that a `MarketCreator` contract advances autonomously — at every wall-clock boundary it creates the next `BinaryMarket`, uses a released `BinaryPool` when available or deploys a new one, and schedules the oracle question. Series markets are **reference-mode**: there is no fixed strike (the event's `strike` is always 0) — a market resolves YES iff its own oracle answer is at/above the previous boundary's _reference_ answer. Markets can also be created directly via `BinaryMarketsModule.createMarket` under an operator's venue (these can be bucket-mode, with a real strike). Discovery is event-driven either way: an all-markets watch with `discover` picks each new market up from the creation events (see below). You don't need to create markets — you watch, trade, and redeem them. ## The series, and how a market is born `MarketCreator` runs the whole protocol off **one** Somnia reactivity `Schedule` subscription (the precompile at `0x0100`). When it fires, a single callback drains that boundary's whole batch of due series in a **gas-bounded loop** — rolling series until the gas envelope runs low — then re-arms the `Schedule` sub for the next-earliest pending boundary. A batch too large for one callback (the 00:00-UTC collision, where every cadence lands at once) saves a resume index and arms a sub for the **next block** to finish the spill. Exactly one subscription is ever live. (Historical note: an earlier one-series-per-hop `RollNext` reentrancy chain was tried and removed — on live Somnia the self-emitted event wasn't re-queued after a heavy roll, so it stalled after one hop. The gas-bounded loop with next-block spill replaced it.) Each roll emits, from the `MarketCreator`: ``` MarketCreated( bytes32 marketId, address market, address pool, uint256 yesId, uint256 noId, address collateral, string asset, uint256 strike, // always 0 — series markets are reference-mode (no fixed strike) uint64 tradingStart, uint64 expiry, uint256 oracleQuestionId, string question, uint64 intervalSec // series cadence: 60 / 300 / 900 / 3600 / 14400 / 86400 ) ``` Every market — series-rolled or not — ALSO fires the `BinaryMarketsModule`'s own 20-field `MarketCreated`, the only creation event carrying the `(operatorId, venueId)` origin attribution. A discovery watch (`watchMarkets({ discover: true })`) listens to both, so module-created markets that never pass through a `MarketCreator` join the watch live too. - **Read cadence from `intervalSec`, and treat it as approximate.** A series' first market is a _bootstrap partial_ (trigger time → the next aligned boundary), so its window is shorter than the cadence. On the SDK's `BinaryMarket` type the cadence surfaces as `intervalSec?: string | null` (`null` when a market predates the field). For a `MarketCreator`-rolled market the indexer patches the exact cadence from `MarketCreator.MarketCreated.intervalSec`, so the field joins by equality. Module-created markets, and rows indexed before that patch existed, still carry the window-derived `expiry − tradingStart`, which a late roll shortens to 898s or 899s on a 15m series. `BinaryMarketFilter.intervalSec` bands the value (± `CADENCE_TOLERANCE_SEC`) and `snapToCadence` groups by the same rule, so both kinds of row match; use those rather than comparing the raw field. **Resolution is a separate loop.** `OracleCore` emits `AnswerPosted(uint256,uint8,string,int256,bool,uint8,uint256[])` when the oracle answers a question. `OracleHub` subscribes to that event on the `OracleCore` address and routes the answer through `BinaryMarketsModule`. The SDK sees a `Resolved` or `Voided` lifecycle event from the individual `BinaryMarket` — gate redemption on that, per the rule below. Permissionless `voidExpired()` can also emit `Voided` without an oracle answer. ### Event emitters For a raw log or Reactivity subscription, filter by the contract that **emits** the event. The module, settlement contract, market and pool are separate log sources. Use `config.addresses` for configured singletons on the selected chain, the selected market's `marketAddress` and `poolAddress` for clones, and `smart-contracts/deployments///addresses.json` for `OracleCore`. An existing receipt's `log.address` identifies its actual emitter. The SDK's `SOMNIA_TESTNET_ADDRESSES` and `SOMNIA_MAINNET_ADDRESSES` are generated from their respective deployment manifests. `marketCreator` names a configured creator; other venues can have their own creator, available as `creator` on the module's `MarketCreated` event. For historical `AnswerPosted` logs, select the OracleCore deployment that emitted those answers if the active core changed. | Event signature | Emitting contract | Filter address | | ------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------------ | | `MarketCreated` (series, 13 arguments) | `MarketCreator` on a series roll | Venue's `marketCreator` | | `MarketCreated` (module, 20 arguments) | `BinaryMarketsModule` on every creation, including a series roll | `binaryModule` | | `AnswerPosted(uint256,uint8,string,int256,bool,uint8,uint256[])` | `OracleCore`, **not** `OracleHub` | Matching manifest's `OracleCore.address` | | `Resolved(uint32,uint256[])` / `Voided()` | Individual `BinaryMarket` | Market's `marketAddress` | | `MarketFinalized(bytes32,address,uint256)` | `BinaryMarketsModule`; carries `marketId` | `binaryModule` | | `MarketFinalized(uint256,address,uint64,address,uint256,bool,uint256[])` | `BinarySettlement`; carries `netBacking` | `binarySettlement` | | `PoolFinalized(uint64,uint256)` | Individual `BinaryPool`; its backing was swept | Market's `poolAddress` and indexed `marketNonce` | | `PoolReleased(bytes32,address,address)` | `BinaryMarketsModule`; the pool can be reused | `binaryModule` | | `Redeemed(uint256,address,address,uint8,uint256,uint256)` | `BinarySettlement`; tokens burned; collateral paid or owed, possibly zero | `binarySettlement` | A series roll can produce both `MarketCreated` events for one market; deduplicate by `marketId`. Their canonical signatures for topic0 are: ```text MarketCreated(bytes32,address,address,uint256,uint256,address,string,uint256,uint64,uint64,uint256,string,uint64) MarketCreated(bytes32,address,address,uint256,uint32,bytes32,address,address,uint256,uint256,uint64,uint8,uint8,uint64,uint64,uint8,string,uint256,string,bytes) ``` A pool can serve later markets, so its address alone does not identify one market's `PoolFinalized`: match the selected market's `nonce` to the event's indexed `marketNonce` (topic1). The first `MarketFinalized` payload is `(marketId, pool, marketKey)`; the second is `(marketKey, pool, nonce, collateralToken, netBacking, voided, payoutNumerators)`. Their topic0 values differ. On Shannon, a subscriber for settlement `netBacking` must filter the settlement event at `SOMNIA_TESTNET_ADDRESSES.binarySettlement`, not the three-field module event at `SOMNIA_TESTNET_ADDRESSES.binaryModule`. The address is the settlement **proxy** (`0xbF4a49e0Dfd092e5FBE8E5761064C49533e6Ed23` in the Shannon `50312/testnet-development` manifest), not its implementation or the pool. See [Reactivity](./REACTIVITY.md) for `watch` and `subscribe` filter fields. ### Oracle question links An `oracleQuestionId` is scoped to its oracle deployment. Choose the host from the **market's chain ID**, not from the numeric ID: | Market chain | Question page | | ----------------------- | ------------------------------------------------------------- | | Shannon testnet (50312) | `https://dev.oracle.somnia.host/questions/` | | Somnia mainnet (5031) | `https://prd.oracle.somnia.host/questions/` | For example, a Shannon market's ID belongs at `https://dev.oracle.somnia.host/questions/`; a mainnet ID belongs at the production host. The same number is not a cross-host key. These are oracle **question** pages; the `price-feed.*.oracle.somnia.host` endpoints in the [network reference](./reference/networks-and-endpoints.md) serve price-feed GraphQL instead. For another chain, verify its oracle host before constructing a link. ## Reading Watch the market, then read the live store — synchronous, zero round-trips, current to the last block: ```ts const watch = await client.watchMarket(market.poolAddress); const book = client.getLiveBinaryOrderBookByMarket(market.id, { depth: 11 }); // { yesBids, yesAsks, noBids, noAsks } — NO sides derived as 1 − yesPrice const tape = client.getLiveFills(market.poolAddress, { limit: 40 }); const live = client.getLiveMarketByPool(market.poolAddress); // status, lastPrice, volumes ``` The book read above uses `market.id` so a page for an older market shows an empty book after its pool is recycled. The live market read describes the pool's current occupant. The pool-keyed tape can include fills from successive markets on that address; it does not identify one market. For a chain snapshot, `getBinaryOrderBook(pool)` also reads the pool's current book without a market-id check. See [pool recycling](./explanation/binary-pool-recycling.md) before using a pool address to read positions or history. In React, mount `useWatchMarketResult(pool)` or another pool-keyed watch hook alongside `useLiveBinaryOrderBookByMarket(marketId)` when the selected market is not yet in the live store. The market-scoped hook can watch the pool itself only after the market is known; it keeps an older market's book empty after recycle. `useLiveBinaryOrderBook(pool)` and `useLiveMarketByPool(pool)` describe the current occupant. Pool-keyed `useLiveFills(pool)` and `useLiveUserOrders(pool, account)` can include activity from successive markets. Discovery and history come from the indexer tier: `listLiveBinaryMarkets()` / `listPastBinaryMarkets({ limit, offset })` for the market lists, `getCandles(pool, interval)` for charts, `getPortfolio(account)` (trades default to the last seven days — `tradesSince` echoes the bound; pass `since` to widen) for a wallet's positions + orders + trades in one round-trip. To start a selected binary book when the indexer is down, pass `chainSeedPools={[{ chainId, pool }]}` to `SomniaMarketsProvider`. Every pool-watching hook under that provider uses the same chain seed policy, even when a child hook mounts first. The provider reads the pool's current market binding from chain and requires `addresses.binaryModule` on that chain's client. Set this list before mounting the provider; remount to change it. Unlisted spot and funding pools retain their normal indexer seed. Read `usePoolSeedStatus(pool)` for that pool's `seedSource` and `fillsLoaded`: a chain-seeded book can be live while fill history remains unloaded. Discovery, candles, portfolio and other indexed history still need the indexer. `listLiveBinaryMarkets()` with no argument returns every live market; pass a filter to narrow (all fields optional, applied server-side): ```ts await client.listLiveBinaryMarkets(); // all live markets await client.listLiveBinaryMarkets({ operatorId: 1 }); // one operator's live board await client.listLiveBinaryMarkets({ venueId: "0x5bc0…", asset: "BTC", intervalSec: 900 }); await client.listLiveBinaryMarkets({ status: "Trading" }); // active only ``` (`operatorId` is the uint32 operator id; `venueId` is the venue's opaque bytes32 hex id — enumerate the pairs in play with `listBinaryVenueIds()`.) For the underlying-asset universe and board size, use `listBinaryAssets()` (the distinct assets with markets, e.g. `["BTC","ETH"]`) and `countBinaryMarkets({ operatorId?, venueId?, asset?, status?, phase? })` (the total behind a filtered board, for pagination headers; `phase` splits live from past, and omitting it counts both). The same filter carries `resolvedSince` and `voided`, so `countBinaryMarkets({ venueId, resolvedSince: now - 86_400 })` and the same call with `voided: true` are a venue's settlement count and void count over the trailing day — keyed on the terminal timestamp, so a void before expiry counts too. Each row carries `marketAddress`, `poolAddress`, `operatorId`, and `venueId`, so a multi-venue UI can group the live board by origin without any contract-level call — market discovery is the indexer's job, not the MarketCreator's. One correctness rule: **gate writes on the selected market's live or on-chain status, never indexer status**. `getMarketOnchain(marketId).status` is a market-scoped chain read; `marketId` is the selected market's bytes32 id. Use the status from `getLiveMarketByPool(pool)` only after checking that the live row's `id` matches the selected market id. The pool can host another market after recycling, and indexed status lags. ### History + attribution (indexer) Beyond the live board and portfolio, the indexer serves the fee, resolution, router, and vault-credit history the live tail doesn't materialize — all one-shot reads: ```ts // How a market resolves: lifecycle events + the oracle reference link + the // posted numeric oracle answer (joined by oracleQuestionId), in one round-trip. const { events, reference, oracleAnswer } = await client.getMarketResolution(marketId); // Router-level collateral flow for a wallet (redeem / mint / merge complete set), // attributed to the TRUE end user even through the native/Permit2 periphery. const actions = await client.getRouterActions(account, { market, limit: 50 }); // The per-fill fee streams behind getMarketFees' running total (all filter by // `payer` — the order owner who funded the fee — plus recipient/market/pool). const protoFees = await client.listProtocolFees({ market, payer }); const bldFees = await client.listBuilderFees({ builder }); const settleFees = await client.listSettlementFees({ market }); // Builder-approval directory (the indexed complement to the on-chain point read // getBuilderApproval) — every user→builder cap, filterable by user or builder. const approvals = await client.listBuilderApprovals({ user }); ``` **Vault credits.** A payout that can't be delivered to the wallet is credited to the owner's `ERC20Vault` balance instead. That history is append-only — `client.getVaultPayoutFallbacks(owner, { token })` lists the credit log for one owner, and `client.listVaultPayoutFallbacks({ pool, from, order: "asc" })` lists it across every owner (an operator's alert or reconciliation reads it that way). Each row carries the `pool` whose vault holds the credit — but the vault's own credit/debit is silent (no event), so the **live claimable balance is a chain read**: `client.getVaultBalance({ vault: pool, owner, token })` (`ERC20Vault.getWithdrawableBalance`). Withdraw with `trader.withdrawVault({ vault, token, amount })`. ## Trading ```ts const trader = client.createTrader({ privateKey }); // Node — or { walletClient } in the browser const decimals = market.quoteDecimals; // indexed binary market's collateral scale // Rest a limit order: buy 10 YES at 0.62. const { orderId, fills, receipt } = await trader.placeOrder({ pool: market.poolAddress, side: "BUY_YES", price: probabilityToPrice(0.62, decimals), // raw collateral units per whole token quantity: fromHuman(10, decimals), // raw outcome-token units }); if (fills.length) console.log("crossed immediately:", fills); else console.log("resting as order", orderId); await trader.cancelOrder({ pool: market.poolAddress, orderId }); ``` For a chain-only market read, use `client.getMarketOnchain(marketId)` and its `decimals` and `pool` fields. A binding without `indexerUrl` has no indexed `quoteDecimals`. You can omit `indexerUrl` for chain-only reads and writes; indexed discovery and history need an indexer. [Networks and endpoints](./reference/networks-and-endpoints.md) lists the hosted indexers. That read uses six decimals only if the token lacks the `decimals()` view; other read failures throw. Verify a non-standard token's scale before writing. The SDK helpers also default to six decimals if you omit their `decimals` argument. Every write **awaits its receipt** — there is no bare hash to babysit, and `placeOrder` resolves with the decoded `orderId` + `fills` from the same round-trip. The escrow token (collateral for buys, YES/NO for sells) is approved automatically on first use; pass `autoApprove: false` to manage approvals yourself. - **Market orders** are `orderType: ORDER_TYPE.MARKET` (an IOC) placed at a crossing price — cross the best opposite level ± slippage so it sweeps and the remainder cancels. `ORDER_TYPE` also has `FILL_OR_KILL` and `POST_ONLY`. - **Sides and prices:** all four `BinarySide`s take the YES-terms price. A `BUY_NO` at YES-price 0.62 escrows `quantity × (1 − 0.62)` collateral. - Token wiring resolves from the pool contract automatically (cached); pass `outcomeToken`/`yesId`/`noId`/`collateral` explicitly to skip even that one-time read. ### Stake-sized market orders ("bet $50 on Up") A stake-first UI usually asks for a **collateral stake**, not a share quantity. `quoteBinaryStake` is the inverse of `quoteBinaryOrder`: it walks the live asks cheapest-first, sizing the largest quantity whose escrow at the worst level touched stays within the stake — so the quoted shares and payout match what actually fills, not a top-of-book estimate. The protective limit is padded with a slippage cushion (default 3%, min 10 ticks) so the IOC still crosses a moving book, aligned to the pool's on-chain tick grid, and the quantity is lot-aligned with escrow re-fit under the stake — off-grid prices and non-lot quantities are the pool's two rejection reasons, handled for you: ```ts const quote = await client.quoteBinaryStake({ pool: market.poolAddress, side: "BUY_YES", // Up; "BUY_NO" for Down stake: fromHuman(50, market.quoteDecimals), // raw collateral — the max loss }); if (quote) { await trader.placeOrder({ pool: market.poolAddress, side: quote.side, price: quote.yesPrice, // protective limit, YES terms quantity: quote.quantity, // shares = payout if this side wins orderType: ORDER_TYPE.MARKET, }); } ``` `null` means nothing is fillable (empty book, or a stake too small for one lot) — disable the control rather than sending a doomed order. Unwind a position with the sell-side sibling, which cushions a floor below the best bid the same way: ```ts const sell = await client.quoteBinarySell({ pool: market.poolAddress, side: "SELL_YES", quantity: position.balance, // lot-aligned down automatically }); if (sell) { await trader.placeOrder({ pool: market.poolAddress, side: sell.side, price: sell.yesPrice, quantity: sell.quantity, orderType: ORDER_TYPE.MARKET, }); } ``` Unlike the buy side, a sell's `quantity` is your position, not a book-sized fit — on a thin book the IOC fills what rests within the cushion and cancels the rest. Compare `sell.fillableQuantity` (with `sell.estProceeds`, the collateral it would raise) against `sell.quantity` and warn before submitting when the unwind would be partial. Both quotes read the live book (needs an active watch) plus the pool's tick/lot grid via one cached `eth_call` (`getBinaryBookParams`). The pure kernels — `quoteBinaryStakeOverBook` / `quoteBinarySellOverBook` / `slippageForCrossing` — are exported for callers that already hold a book. ### Builder / routing fees (optional) A frontend that routes orders can attach itself to each order and charge a per-order fee — but only after the trader has opted it in on that pool: ```ts await trader.approveBuilder({ pool, builder, maxFeeBpsTimes1k: 5_000n }); // allow up to 5 bps; 0 revokes await trader.placeOrder({ pool, side: "BUY_YES", price, quantity, builder, // the routing/builder frontend builderFeeBpsTimes1k: 5_000n, // per-order fee, pool bps×1000 unit }); ``` A non-zero `builderFeeBpsTimes1k` without a prior approval reverts `BuilderFeeExceedsCap` on a BinaryPool (`BuilderNotApproved` on a SpotPool, `BuilderFeeExceedsApproval` on a PerpPool). The enforced ceiling is the trader's approval clamped by the pool's protocol-wide cap — read it with `trader.getEffectiveBuilderApproval({ pool, user, builder })` (the pool-wide cap alone is `trader.getMaxBuilderFeeBpsTimes1k(pool)`). On the exchange surface the same rides `createOrder`'s `params.builder` / `params.builderFeeBpsTimes1k`, on binary, spot and perp alike — each pool holds its own approval, so opt in once per pool. ### Complete sets and settlement ```ts const amount = fromHuman(10, market.quoteDecimals); // raw collateral and outcome units await trader.mintSet({ pool, amount }); // collateral → equal YES + NO await trader.burnSet({ pool, amount }); // YES + NO → collateral back await trader.redeem({ market: marketAddress, amount }); // winning token → collateral (post-resolution) // A VOIDED market has no winner — both legs pay — so name the leg yourself. // One entry per leg claims both in a single transaction: await trader.redeemMany({ entries: [ { marketId, outcomeIdx: 0, amount: yesAmount }, { marketId, outcomeIdx: 1, amount: noAmount }, ], }); ``` `mintSet`/`burnSet` are how you take (or unwind) a both-sides position without touching the book; `redeem` pays out after resolution (it looks up the winning outcome on-chain if you don't pass it). That lookup is **resolution-only**: a voided market has no winning outcome, so `redeem` throws unless you pass `outcomeIdx` — it will not guess a leg for you, because on a void both legs are redeemable and only you know which you hold. An unresolved market also throws; the SDK reads the payout vector only after confirming resolution. If the venue configured a settlement fee, the pool skims it ONCE from the whole winning backing at the first winning redeem (`SettlementFeeCharged`) and every winner redeems for `1 − fee` — voided markets refund both sides with no fee. Demo-stack extras: `faucet()` mints the test collateral; `resolve`/`voidMarket` drive the FakeOracle. #### Unified exchange redemption The exchange wrapper takes display units rather than raw token amounts. A settled market is no longer in `fetchMarkets()` — a series market resolves, finalizes and hands its pool to the next market — but `fetchBalance()` still reports a holding on it under the market's own symbol, and that symbol still resolves for `redeem`. Every pool-routed verb (`createOrder`, `mintSet`, `burnSet`, the book, tape and ticker reads and watches) refuses a settled market, because its pool now serves the successor. On a resolved market `redeem` selects the indexed winner: ```ts const bal = await exchange.fetchBalance(); const winningAmount = bal[`${symbol}#YES`]?.total ?? 0; if (winningAmount > 0) await exchange.redeem(symbol, winningAmount); ``` A voided market has no single winner. Pass the leg you hold and call once for each leg you want to redeem: ```ts await exchange.redeem(symbol, yesAmount, { outcomeIdx: 0 }); ``` The SDK rejects a malformed or impossible final payout vector. Only an absent vector on a legacy market uses the compatibility fallback. ### A maker loop, end to end ```ts const watch = await client.watchMarket(pool); const trader = client.createTrader({ privateKey }); client.subscribeLive(async () => { const book = client.getLiveBinaryOrderBook(pool, { depth: 1 }); // zero RTT const mine = client.getLiveUserOrders(pool, me, { limit: 50 }).filter((o) => o.status === "Open"); // zero RTT // decide → place/cancel; each write resolves after its receipt arrives }); ``` The live store is the only state a quoting loop needs: the book, your working orders, and fills all update the moment the chain emits them. --- # /docs/typescript/spot-markets # Spot markets A spot market is a plain base/quote order book on a `SpotPool` (e.g. SOMI/USDC) — same OrderBook core as the binary pools, so the live machinery is identical; only the semantics differ. This guide covers reading and trading spot; the shared client mechanics (watches, read tiers, signers) are in [the engine guide](./ENGINE.md). ## The mental model - **Prices are quote-per-base.** Raw quote units per whole base token, scaled by the market's own `quoteDecimals`/`baseDecimals` (spot markets are NOT assumed 6dp — read the decimals off the `SpotMarket` row). - **Two sides.** `isBid: true` buys base (escrows quote); `false` sells base (escrows base — or sends native SOMI as `msg.value` when `baseIsNative`). ERC-20 approval checks use `requiredAmount`, which is the pool's worst-case reserve including fee headroom. A native sell sends `delta`, which subtracts the owner's current vault balance from that reserve. Sending only the bare quantity can revert with `InvalidMsgValue` on a fee-bearing pool. - **Book constraints.** Orders must respect the pool's `tickSize`, `lotSize`, and `minQuantity` (all on the `SpotMarket` row, kept live by the watch). - **Mark price.** Pools publish a smoothed `markPrice` (streamed live via `MarkPriceUpdated`) — it's what stop orders trigger on, distinct from `lastPrice` (last fill). ## Reading Discover markets first (indexer tier) — `listSpotMarkets` returns the board and `getSpotMarket` resolves one by id; both yield the `SpotMarket` rows the live reads key off: ```ts const markets = await client.listSpotMarkets({ limit: 50 }); // SpotMarket[]; filterable (base/quote/…) const spot = await client.getSpotMarket(id); // SpotMarket | null ``` ```ts const watch = await client.watchMarket(spot.poolAddress); const book = client.getLiveSpotOrderBook(spot.poolAddress, { depth: 11 }); // { bids, asks }, best first const tape = client.getLiveFills(spot.poolAddress, { limit: 40 }); const live = client.getLiveMarketByPool(spot.poolAddress); // markPrice, tick/lot, stats ``` React: `useLiveSpotOrderBook(pool)`, `useLiveFills(pool)`, `useLiveMarketByPool(pool)` — all auto-watch while mounted. History and wallet views come from the indexer tier: `getCandles(pool, interval)`, `getSpotPortfolio(account)` (open orders + pending stops + the last seven days of trades by default — `tradesSince` says which; pass `since` to widen), and `getSpotStopOrders(account, { pool })`. Holdings are plain balances — read them on-chain with `getErc20Balance` / `getNativeBalance`, not from the indexer. ## Trading ```ts const trader = client.createTrader({ privateKey }); // Rest a limit bid: buy 5 base at 1.25 quote. const { orderId, fills } = await trader.placeSpotOrder({ pool: spot.poolAddress, isBid: true, price: parseUnits("1.25", spot.quoteDecimals), quantity: parseUnits("5", spot.baseDecimals), quoteToken: spot.quoteToken, baseToken: spot.baseToken, baseIsNative: spot.baseIsNative, }); await trader.cancelOrder({ pool: spot.poolAddress, orderId }); // same core as binary ``` ### Per-order fields: expiry, attribution, self-match, user data `placeSpotOrder` takes these per-order fields as optional inputs. Each one has an SDK default that keeps today's behaviour, so an existing call is unaffected: ```ts await trader.placeSpotOrder({ ...order, expireTimestampNs: BigInt(Date.now() + 86_400_000) * 1_000_000n, // default: ~50y (GTC) builder: "0xYourFrontend", // default: the zero address (no attribution) builderFeeBpsTimes1k: 25_000n, // default: 0 selfMatchingOption: SELF_MATCHING_OPTION.CANCEL_MAKER, // default: CANCEL_TAKER userData: 7n, // default: 0 — an opaque tag, never interpreted }); ``` `placeSpotOrders`, `placeOrder` (binary), `placePerpOrder`, `amendOrder` and `amendOrders` take the same `selfMatchingOption`, and the batch verbs take it per request. **Self-match.** A pool matches your incoming order against your own resting order, and `selfMatchingOption` says which side loses. `CANCEL_TAKER` (0) drops the rest of the incoming order and leaves the resting one on the book; `CANCEL_MAKER` (1) cancels the whole resting order and lets the incoming one continue. **The 0 is the SDK's default, not the pool's** — the pool reads the value out of every order request and has no default of its own, so a raw integration must pass it. Reach for `CANCEL_MAKER` when the new quote matters more than the old one, such as re-pricing a ladder into your own resting rungs; keep `CANCEL_TAKER` when a self-cross means you made a mistake and want the order rejected. In a batch a `CANCEL_TAKER` self-match is one of the benign non-placements: the rung reports `outcomes[i].success === false` rather than taking the batch down. **The ceiling.** A non-zero `builderFeeBpsTimes1k` must stay within `trader.getMaxBuilderFeeBpsTimes1k(pool)`. Read that cap rather than assuming it: it is owner-updatable on a SpotPool, and while it is 0 the pool rejects builder codes outright, so the rail is off on that venue. **The approval.** A non-zero fee also needs a prior `trader.approveBuilder({ pool, builder, maxFeeBpsTimes1k })`. Spot pools implement the same builder calls as binary ones, but **the approval is stored per pool** — approving a builder on one pool grants nothing on another, and an unapproved placement reverts `BuilderNotApproved`. > **A past expiry reverts.** A placement whose `expireTimestampNs` is already > behind the chain clock fails with `OrderAlreadyExpired`. Earlier protocol > versions accepted it silently — the pool skipped the placement and returned no > order id, so the transaction still succeeded — but it now rejects outright. > The batch verb differs: `placeSpotOrders` rejects the offending request on its > own rather than taking the whole batch down, so there you check > `outcomes[i].success` — an already-expired expiry is one of the benign > non-placements it reports. > **Expiry does not refund by itself.** When a spot order lapses its escrow > stays locked in the pool until someone sweeps it — > `trader.cancelExpiredOrders({ pool, orderIds })` reclaims it, and is callable > by anyone, not only the owner. Set an expiry deliberately. Escrow is approved automatically (quote on buys, base on non-native sells; native-base sells pay via `msg.value` instead). A **market order** is `orderType: ORDER_TYPE.MARKET` with a crossing price — take the live book's best opposite level ± slippage, tick-aligned, so it sweeps and the remainder cancels: ```ts const best = client.getLiveSpotOrderBook(pool, { depth: 1 }); // zero RTT, last-block fresh const crossing = (best.asks[0].price * 10100n) / 10000n; // +1% slippage bound ``` ### Amending a quote set Re-pricing a ladder one order at a time costs two transactions per rung and leaves the book briefly one-sided. `amendOrders` cancels each old order and places its replacement in a single transaction: ```ts const { newOrderIds } = await trader.amendOrders({ pool: spot.poolAddress, amendments: [ { oldOrderId: bid1, newOrder: { isBid: true, price: newBid1, quantity: qty } }, { oldOrderId: bid2, newOrder: { isBid: true, price: newBid2, quantity: qty }, alwaysPlace: true }, ], }); ``` It is **all-or-nothing** — any bad request reverts the whole batch, so the book never sees a partial re-quote. `newOrderIds` is index-aligned with `amendments`. `alwaysPlace` handles the race where the order you meant to amend already filled or was cancelled. False (the default) reverts `AmendOldOrderGone`; true skips the cancel leg and places the replacement anyway. It never tolerates an ownership failure — a live order owned by someone else still reverts. For ONE order, use `amendOrder` rather than a one-element batch: ```ts const { newOrderId } = await trader.amendOrder({ pool: spot.poolAddress, oldOrderId: bid1, newOrder: { isBid: true, price: newBid1, quantity: qty }, }); ``` The difference is the error you get back. The singular raises the replacement's own landing-time reason — `PostOnlyWouldCross`, `FillOrKillNotFillable` and friends — where the batch wraps it as `AmendReplacementRejected(requestIndex, reason)`. With one order that index tells you nothing you did not already know, and you have to unwrap it to find the reason. Everything else matches: same `alwaysPlace` race rule, same lost queue priority, same non-payable funding constraint. Amend re-inserts at the back of the price-time queue. To shrink an order **without** losing queue priority, use `reduceOrder` instead. Three things to know before re-laddering with it: - **Replacements are not shielded from each other.** Cancelling all the old orders first protects a replacement from the order it replaces — but not from the _other_ replacements in the same batch. If a new bid crosses a new ask, `CANCEL_TAKER` (the SDK's default when you omit `selfMatchingOption`) rejects it, and because amend is all-or-nothing the whole re-ladder reverts. Keep the new set uncrossed, or set `selfMatchingOption` per replacement. - **The revert names the rung.** A rejected replacement reverts `AmendReplacementRejected(requestIndex, reason)` — `requestIndex` is the position in your `amendments` array and `reason` is the pool's `uint8` rejection code (the SDK does not export a name table for it). That is the signal to branch on; `AmendOldOrderGone` is a different, earlier failure from the cancel leg. - **Approve the escrow first.** Unlike `placeSpotOrder`, `amendOrders` does not auto-approve. On an auto-pull pool the cancel leg returns the freed tokens to your wallet and the place leg pulls them back, which needs an allowance — so a trader whose _first_ call is `amendOrders` hits `ERC20InsufficientAllowance`. Place once (or approve manually) before amending. **Not for BinaryPools** — amend places, and binary pools reject generic placement with `UseBinaryPlacement`. Spot and perp only. Note that error is what you hit on a _live_ binary market; a locked one reverts `TradingNotActive` and a malformed replacement reverts on validation first, so don't branch on `UseBinaryPlacement` alone to detect the wrong pool kind. ### Batches — place a ladder, pull a ladder Market making means many orders at once. `placeSpotOrders`, `cancelOrders` and `reduceOrders` each do a whole ladder in ONE transaction instead of a loop of sends: ```ts // Place a three-rung sell ladder. const placed = await trader.placeSpotOrders({ pool: spot.poolAddress, quoteToken: spot.quoteToken, baseToken: spot.baseToken, orders: [1.01, 1.02, 1.03].map((p) => ({ isBid: false, price: parseUnits(String(p), spot.quoteDecimals), quantity: parseUnits("1", spot.baseDecimals), })), }); // outcomes is index-aligned with `orders`; a rung that did not place is // success:false (e.g. a PostOnly that would have crossed), NOT an error. const ids = placed.outcomes.flatMap((o) => (o.success ? [o.orderId!] : [])); // Pull what is left. Best-effort: an id that filled meanwhile is skipped, so // the other rungs still come off the book. const pulled = await trader.cancelOrders({ pool: spot.poolAddress, orderIds: ids }); const skipped = pulled.outcomes.filter((o) => !o.cancelled).map((o) => o.orderId); ``` Three things to know before using them: - **They are non-payable.** Unlike `placeSpotOrder`, a batch sends no `msg.value`, so a **native-base sell** funds from the pool's vault balance — pre-deposit native to the vault first. ERC-20 auto-pull works normally, and the batch approves each escrow token once for the whole batch's total. - **`placeSpotOrders` is spot-only.** Binary pools reject generic placement with `UseBinaryPlacement` (the YES/NO kind must be explicit) — use `placeOrder` there. `cancelOrders` and `reduceOrders` are inherited from the shared order book, so they work on binary pools too. - **Cancel is best-effort, reduce is atomic.** A stale id in `cancelOrders` is skipped; a single invalid reduction in `reduceOrders` reverts the whole batch. A cancel `false` says the id emitted no event — it does not say _why_, so a benign fill race and a wrong id look the same. - **Every per-order field is per rung.** `orderType`, `expireTimestampNs`, `selfMatchingOption`, `userData`, `builder` and `builderFeeBpsTimes1k` are read off each request, so a ladder can attribute one rung to a builder and leave the next unattributed. A rung that omits a field gets the same default the single verb applies. - **Tag rungs with `userData` if exact attribution matters.** Outcomes are matched to requests on every field the `OrderPlaced` event echoes (side, price, quantity, userData, expiry). Two byte-identical adjacent rungs with different outcomes are indistinguishable from logs — the earlier index gets the credit; a distinct `userData` per rung removes the ambiguity. - **Read the tag back from the indexer.** `getOpenOrders` and `getOrders` return each row's `userData`, and `OrdersOptions.userData` filters on it, so a client can ask for the orders it tagged instead of keeping its own id map. The column is not indexed: pair the tag with `pool`/`pools` and a status to keep the scan small. ### Stop orders Spot pools with a `stopRegistry` support stop-loss / take-profit orders that rest OFF the book and fire when the **mark price** crosses the trigger: ```ts await trader.placeSpotStopOrder({ registry: spot.stopRegistry, pool: spot.poolAddress, isBid: false, // sell when the market drops… quantity: parseUnits("5", spot.baseDecimals), triggerPrice: parseUnits("1.10", spot.quoteDecimals), triggerOperator: 1, // 1 = LTE (mark ≤ trigger), 0 = GTE stopOrderType: 1, // 1 = MARKET at trigger, 0 = LIMIT (needs limitPrice) quoteToken: spot.quoteToken, baseToken: spot.baseToken, baseIsNative: spot.baseIsNative, }); await trader.cancelStopOrder({ registry: spot.stopRegistry, orderId }); ``` Under the hood the first stop order per account performs a one-time operator approval (so the registry may place the triggered order for you), funds the trigger gas with a small SOMI payment (`msg.value`, refunded on cancel), and ensures the pool can pull the escrow at trigger time — including pre-loading the pool vault for native-base sells. The SDK handles all of it; list pending stops with `getSpotStopOrders(account, { pool })` and stream their market context via the watch. A listed spot stop has no limit price: a LIMIT stop's limit price can't be read back after placement. Show it as unknown, never as zero, and keep the value you submitted if you need to display it. --- # /docs/typescript/perps # Perpetuals Perps are live on testnet: `BTC/USDSO:USDSO` and `ETH/USDSO:USDSO`, backed by PerpPool CLOBs riding the same shared OrderBook core as spot and binary. ## The shape `Market` is a three-way discriminated union — `SpotMarket | PerpMarket | BinaryMarket`, keyed on `marketType` (guards: `isSpotMarket` / `isPerpMarket` / `isBinaryMarket`). A `PerpMarket` is a plain base/quote book plus perp state: `marginBank`, `initialMarginBps`, `fundingRate`, `cumulativeFundingPerUnit`, `indexPrice`, `openInterest`, `fundingWindowSec`, `fundingIntervalSec`. > **`fundingRate` is per CALCULATION WINDOW** (`fundingWindowSec`, 28800s / 8h on every > live pool) — not per settlement interval and not annualized. Each settlement accrues > `rate / n` where `n = fundingWindowSec / fundingIntervalSec`: **8** on every live pool > (3600s settlement). It has been **96** at a 300s cadence, and the same value means a 12x > different per-interval accrual across that boundary — which still reaches anyone reading > indexed history, so read `n` off each row rather than assuming it. Normalize with the > helpers > (`fundingRate8h`, `fundingRate1h`, `fundingRatePerInterval`, `annualizedFundingRate`), > never with a hardcoded denominator. > > `openInterest` replaced `longOpenInterest` + `shortOpenInterest`: the contract keeps ONE > counter because the short side is provably equal in a matched CLOB. The removed pair was > `null` on every row — the subscription feeding it was dead. - **Watches and live reads are unchanged.** Perp pools emit the same order events, so `watchMarket(pool)`, `getLiveSpotOrderBook`-style depth, `getLiveFills`, `getLiveUserOrders`, and the React hooks just work. Funding (`FundingUpdated`) and open interest (`OpenInterestUpdated`) stream into the perp market row live. - **Margin, not escrow.** Collateral (USDso) lives cross-margin in the MarginBank: `trader.depositMargin` / `withdrawMargin` move it; `trader.placePerpOrder` (or plain `createOrder` on a perp symbol) locks margin from that balance — no per-order token approval. - **Re-quoting a ladder? Amend it atomically.** `trader.amendOrders` cancels N orders and places their replacements in one transaction (see SPOT.md for the full semantics). On a perp pool it needs no token fields at all — margin comes from the MarginBank, so there is no escrow to approve. - **Builder attribution.** `placePerpOrder` takes optional `builder` / `builderFeeBpsTimes1k` (alongside its existing `expireTimestampNs`), both defaulting to no attribution. A non-zero fee needs a prior `trader.approveBuilder({ pool, builder, maxFeeBpsTimes1k })` and must stay within `trader.getMaxBuilderFeeBpsTimes1k(pool)` — read it rather than assuming it, since it is owner-updatable on a PerpPool and the rail is off while it is 0. Perp pools implement the same builder calls as binary ones, but **the approval is per pool**: approving a builder on one pool grants nothing on another, and an unapproved placement reverts `BuilderFeeExceedsApproval` (a PerpPool has no separate "not approved" check — an absent approval is simply a zero cap). - **Positions are on-chain reads**, not indexed rows: `client.getPerpPosition({ marginBank, account, pool })` and `client.getMarginAccount(marginBank, account)` — or the unified `exchange.fetchPositions()`. Live pricing/funding comes from `client.getPerpState(pool)` / `exchange.fetchFundingRate(symbol)`. - **MONITORING a mark feed is a different read.** `client.getPerpFeedStatus(pool)` answers whether the mark is live and how much open interest rides on it. `getPerpState` batches with `allowFailure: false` and one of its legs is a bare `IOracle.getPrice()`, so a dead or rotated oracle rejects the whole read — losing the verdict in the one case it matters most. `getPerpFeedStatus` keeps the mark verdict and open interest as a pair no oracle can revert, and degrades the index timestamp to `undefined` instead. Use `getPerpState` when you want the full pricing and funding picture and a dead oracle should fail the call. - **…except when you want them all at once.** `client.listPerpPositions(account)` returns every pool's position in ONE indexer round-trip instead of a chain read per market — the right read for a positions _table_. It is a snapshot as of each row's `updatedAtBlock` and is **not marked to market**: unrealized PnL, liquidation price and margin health still need the chain reads above. Two things the shape will not let you get wrong, both documented on the type: `size` is **signed** (the entity stores magnitude and direction separately; they are folded back together here so a short can't read as a long), and the entry funding index is **absent by design** — it is not on the schema production serves, so it waits on the next reindex — and anything funding-sensitive belongs on `getPerpPosition`. Fully-closed positions are excluded unless you pass `includeFlat` — upserted rows are never deleted, so they linger at size 0 forever. - **Margin health is a chain read too.** `getMarginAccount` now also returns the requirements + status (`imReq` / `mmReq` / `cmReq` / `marginStatus`, from `MarginBank.getAccountHealth` + `getMarginStatus`); `client.getAccountHealth(marginBank, account)` is the lighter standalone read when only health matters, and `client.getLiquidationPrice({ marginBank, pool, account })` estimates the mark at which this pool's move alone would trip maintenance (null when flat). `MarginStatus` / `MARGIN_STATUS` / `AccountHealth` are exported; `exchange.fetchPositions()` now fills `UnifiedPosition.liquidationPrice`. - **Liquidation price: both sides of the inequality move with the mark.** Liquidation begins where `equity == mmReq`, and `mmReq` is recomputed on the _current_ mark (`ceil(|size| × mark × mmBps / (oneBase × 10000))`), so it shrinks under a falling long and grows under a rising short. Solving `equity(p) == mmReq(p)` therefore carries a `10000 ∓ mmBps` factor: ```text long p = mark − (equity − mmReq) × oneBase × 10000 / (|size| × (10000 − mmBps)) short p = mark + (equity − mmReq) × oneBase × 10000 / (|size| × (10000 + mmBps)) ``` `perpLiquidationPrice(...)` is that solve, exported as a pure function — no client, no block — so you can re-run it against a live store or a hypothetical. Both `getLiquidationPrice` and `previewPerpLiquidationPrice` go through it, which is why they cannot disagree on identical inputs. It is a **single-market** solve: other markets' contributions are held at the value baked into `equity`/`mmReq`, so a correlated move across several markets liquidates sooner. - **Where would an order put my liquidation price?** `client.previewPerpLiquidationPrice({ pool, marginBank, account, isBid, quantity, price, asMaker? })` answers that for an order not yet placed, returning `currentLiquidationPrice` beside `projectedLiquidationPrice` so a form can show the move. It ports all four of `MarginBank.settleTrade`'s cases — open, increase (floored VWAP entry), reduce/close (realized PnL at the fill price, entry untouched), and flip (old side closed, remainder re-opened) — and charges the fill's fee, defaulting to the taker rate. A reduce moves the price _away_ from the mark and an add moves it _closer_, so the four cases are not interchangeable. Note what it deliberately does **not** do: it applies the whole quantity rather than splitting it against `getReducingCapacity` (that split governs the collateral _lock_, not the position), and it does not judge whether the order would be accepted — that is `previewPerpOrderMargin`'s job. An unpriceable market returns `{ priceable: false }` rather than reverting, so an order form can still render. - **How much can I actually place?** `client.getMaxPerpOrderSize({ pool, marginBank, account, isBid, price })` — what a **Max** button should call. The inverse of `previewPerpOrderMargin`, which the protocol does not offer. It does not re-derive the sizing rule; it **binary-searches the forward one**, so the two cannot disagree. That matters because a max computed by a second, subtly different rule reverts on placement — and the term such a rule most often drops is the adverse mark-to-entry reserve, which on a 10%-above-mark bid cuts the affordable size by roughly two thirds. `maxQuantity` is aligned **down** to the pool's lot grid. **Check `placeable`.** A size below the pool's `minQuantity` is a revert, not a small order. `limitedBy` names the binding gate — `"collateral"`, `"initialMargin"`, `"maxPositionSize"` or `"voucherBlocked"`. Market-wide `maxOpenInterest` is deliberately not modelled: it is enforced at fill against a total every other trader moves, so no client-side number can be right about it for long. Nor is book depth — this is a placement limit, not a liquidity one. Nor are the two non-margin gates that reject the whole order rather than shrinking it: a close-only market (`PerpPool.isRestricted()`) and isolated-margin confinement. **Pass `autoPull: true` when the transaction sender will be the order owner.** The pool tops the in-bank balance up from the owner's wallet before it locks (`_onOrderPlaced` → `MarginBank.quoteOrderTopUp` → `depositFor`), so an account with an empty bank and a funded, approved wallet goes from a max of `0n` to whatever the wallet funds. `msg.sender == order.owner` is the pool's entire gate, and only the caller knows who will send — hence opt-in. Leave it off for `placeOrderFor`, an operator grant or the stop registry, where no pull happens. With it on, `topUpRequired` is the wallet spend to show beside the size, and `limitedBy` gains `"walletBalance"` / `"walletAllowance"` — different shortfalls with different fixes, so don't collapse them. `"restricted"` and `"isolated"` name the two gates that reject the whole order rather than resizing it. **A linked child is funded by two wallets, and both count.** The pool spends the owner's own wallet first and takes the residual from the main it is linked to, so `autoPull` reads `MarginBank.quoteFundingPayer` and adds the main's `quoteWalletCapacity` as a second leg. That matters most for the account the rail exists for: an isolated sub-account is meant to hold nothing, and sized off its own wallet alone it reads as unable to place anything at all. `fundingPayer` names the main **eligible** to fund a shortfall, or is `null` when the account funds itself — unlinked, a main itself, or the rail dormant on this deployment. Eligibility is not a debit: it resolves for every linked account, including an order needing no top-up and one whose own wallet covers the whole pull. `ownWalletPull` and `mainWalletPull` split `topUpRequired` between the two wallets in the order the pool spends them, and **only `mainWalletPull > 0n` proves a second wallet actually moves** — that is the figure to show before the trader signs. Read `topUpRequired` as the total REQUESTED, not one wallet's spend. Showing it as the child's debit over-states it by exactly the main's leg. `limitedBy` gains `"mainWallet"`, reported ahead of the two `wallet*` values whenever a main is in play: at a main-funded ceiling the child's own capacity is fully consumed, so `"walletBalance"` would also be literally true and would send a trader to fund a sub-account that is empty by design. It names the **preferred** remedy, not the only one — the two capacities add, so raising the child's balance or allowance lifts the ceiling just as well. **A partial pull is not a rejection on this path.** The unlinked pool asks for a fixed `topUpRequired` and the token reverts if the wallet is short. Both linked legs are `min(...)`-sized and neither can revert, so the pool pulls what it can and the margin gates judge the result — and `topUpRequired` includes the fee headroom, which is a reserve rather than part of the lock. So capacities that cover the lock but not the headroom fund an order the chain accepts, and `walletCoversTopUp` is informational there rather than a gate: read a `false` as "the position may be born close to its own initial margin", not as "this will be rejected". One case withholds the main's leg entirely. `MarginBank.depositForFromMain` allows one payer at a time, so while the child still owes a **prior** payer the pull reverts `PriorFundingPayerOutstanding` — reachable in one ordinary sequence: funded by main A, unlink, re-link to main B. `mainFundingBlocked` reports it and `limitedBy` says `"mainFundingBlocked"`; the fix is neither wallet but `trader.repayPerpMainFunding` against the old claim. It costs one extra read for an unlinked account and four for a linked one. The main's capacity arrives as a single `min(balance, allowance)`, which is all the bank exposes for another wallet, so a main-side shortfall does not say which of the two bound; read the main's token balance and allowance directly if you need that. Note the max is the top of the **contiguous** placeable region. Auto-pull makes the initial-margin gate non-monotone in quantity — it reduces to `(equity − unlocked) + feeHeadroom ≥ imRequirement`, whose only size-dependent term grows — so an account whose existing positions sit below their own initial margin can be rejected at a middling size and accepted at a much larger one. `previewPerpOrderMargin` reports that faithfully; the max deliberately does not offer sizes out of the disconnected region, because a slider has to be placeable at every value below its maximum. - **What do I get if I close?** `client.previewPerpClosePnl({ pool, marginBank, account, quantity?, price?, asMaker? })` — backs a close modal. Omit `quantity` for the whole position; `price` defaults to the mark, which is the right estimate for a market close. Two things it gets right that a hand-derived figure usually does not, and **both are silent** — the close succeeds, the number shown was just wrong: 1. **The size is aligned down to the lot grid first.** "Close all" on a position that is not a lot multiple leaves a remainder open. A modal reporting the position as flat is wrong, and it reads as a bug in the close button. 2. **Funding settles on the whole position, not the closed share.** `settleTrade` calls `_settleFundingWithValues` _before_ it touches the position, and that uses the full `pos.size`. So a 10% close settles 100% of the accrued funding; pro-rating it — the intuitive move — under-states the cash impact by the other 90%. `netProceeds` is the number to show: `realizedPnl − fundingSettled − fee`, with `fundingSettled` positive when the account pays. `realizedPnl` **floors** toward −∞ (`_realizedPnlForClose`), which is the opposite of the truncation unrealized PnL uses — the same inputs give `-1` here and `0` from `getPerpPositionAnalytics`, and both are correct. `placeable` is the pool minimum and nothing else. A close is only purely reducing up to `_reducingCapacity` — `|size|` minus what is already resting on the reducing side — so closing out while a reduce order is down leaves an increasing remainder that locks collateral and must clear `meetsIMForOrder`. Read `previewPerpOrderMargin` beside this one on an account with resting orders. `fee` is the pool's own maker/taker rate; a builder fee attached at placement is charged on the same notional and lands on top. - **What is this position actually doing?** `client.getPerpPositionAnalytics({ marginBank, pool, account })` for one, `client.listPerpPositionAnalytics({ marginBank, account })` for a positions table. Two reads for one position, `1 + 2n` for the table, all pinned to one block. This is the split `getAccountHealth` cannot give you: it returns **one** equity figure for the whole account, with every market's PnL and funding already summed and netted together, so a two-position trader cannot see which position carries the loss and cannot see funding at all. Back apart: | Field | Means | | ------------------------------------------------------------ | --------------------------------------------------------------------------------------- | | `unrealizedPnl` | `(mark − entry) × size / oneBase` — price only, **excludes** funding | | `accruedFunding` | funding **owed** since entry; **positive means you pay** | | `equityContribution` | `unrealizedPnl − accruedFunding` — what this position adds to equity | | `notional` | `\|size\| × mark / oneBase` | | `initialMarginRequirement` | "position margin" — the only per-position margin the protocol defines | | `maintenanceMarginRequirement` / `closeOutMarginRequirement` | the liquidation and takeover thresholds' shares | | `returnOnMarginBps` | `equityContribution` over the initial requirement, **net of funding**; `null` when flat | A direct port of `MarginBank._computePositionMetrics` and `_marketHealthFromSnapshot`, which is what lets the rows re-sum to the bank's own equity to the wei — a test pins that. **The two roundings differ and are not interchangeable**: unrealized PnL truncates toward zero, while funding ceils toward +∞ so a payer never underpays. For a negative quotient that is the opposite of rounding the magnitude up. `accruedFunding` uses the pool's _projected_ cumulative index, so it includes intervals no one has settled yet — settlement is permissionless and lazy, and measuring against the settled index under-reports what the account already owes. An unpriceable market comes back as `{ priceable: false }` rather than throwing, so one dead feed costs one row rather than the page. `initialMarginRequirement` uses the market's IMF only: an account leverage setting raises the bar for a _new_ order but never appears in health, so use `previewPerpOrderMargin` for the order-gating figure. The pure core is exported as `perpPositionAnalytics(...)` — no client, no block. - **How levered am I?** `client.getPerpLeverage({ marginBank, pool, account })`. **The protocol has no leverage view to call** — `getMaxLeverage` / `getMaxLeverageLimit` / `getVoucherLeverageCap` are all _cap configuration_ and none of them measures a position — so this derives it from mark notional over equity, and returns every denominator rather than picking one: | Field | Means | | ---------------------- | ------------------------------------------------------------------------------------------------------- | | `positionLeverageBps` | this position's notional over account equity | | `accountLeverageBps` | **Σ** notional over account equity — the figure that governs risk under cross margin | | `marketMaxLeverageBps` | `10000² / effectiveImfBps` — the most this market will open at, at _live_ OI-scaled IMF | | `accountMaxLeverageX` | the account's own per-market cap, `0` when unset (what `setPerpLeverage` writes, finally readable) | | `protocolMaxLeverageX` | the ceiling that clamps it | | `creditFloor` | the account's credit-voucher floor; `0n` on an ordinary account, and the switch that arms the two below | | `voucherLeverageCapX` | what a voucher account is confined to when it **increases**; `0` is a block, not "uncapped" | | `voucherMarketAllowed` | whether this market is on the voucher allowlist | The ceilings are **not** collapsed into one number, and they do not compose by taking a minimum. A voucher cap _replaces_ an unset or looser `accountMaxLeverageX` before `protocolMaxLeverageX` clamps the result, and it applies only to a position increase — `MarginBank._meetsIM` gates the whole voucher branch on `additionalSize > 0`, so a voucher holder can always close out or place a stop, even on a market since removed from the allowlist. The load-bearing half is that a voucher turns an _unset_ account cap into an enforced one: `accountMaxLeverageX === 0` means "no cap" on an ordinary account and "confined to `voucherLeverageCapX`" on a voucher one. For whether a _specific_ order passes, use `previewPerpOrderMargin`, which applies all of it and reports `voucherBlocked`. Every ratio is **bps of 1x** (`10_000` = 1.00x, `200_000` = 20x), matching the protocol's own unit for every margin figure. Position and account leverage are `null` on non-positive equity — an account with no equity left is insolvent, not infinitely levered; read `marginStatus` for that. `accountNotional` costs two extra reads per _other_ active market (the MarginBank exposes no aggregate, and `imReq` can't be inverted because each market applies its own IMF), so a single-market account pays nothing extra. - **Liquidation-keeper reads — who holds, and what a bankrupt position is worth.** The MarginBank keeps a per-(pool, side) holder array, so a keeper can find every open position from head state alone — no off-chain indexer: ```ts const { holders, asOfBlock } = await client.getPerpSideHolders({ marginBank, pool, isLong: true }); const prices = await Promise.all( // Priced at the SNAPSHOT's block — at head, a holder that closed since // the enumeration would revert NoOpenPosition and reject the sweep. holders.map((h) => client.getBankruptcyPrice({ marginBank, account: h, pool }, { blockNumber: asOfBlock })), ); ``` `getPerpSideHolders` pages through the bank's bounded slice view (many holders per round-trip) with every page pinned to ONE block; feed `asOfBlock` into `getBankruptcyPrice`'s `blockNumber` option (and into the other side's call) to keep a sweep on one consistent snapshot. The other position/health reads answer at head only. `getBankruptcyPrice` is the **contract's own figure** — the price at which the position's allocated share of the account's equity is exhausted — and it is a different quantity from `getLiquidationPrice`, not a better version of it: `getLiquidationPrice` is the SDK's client-side estimate of where liquidation _triggers_ (use it for UI and monitoring), while `getBankruptcyPrice` is what the contract computes a bankrupt position to be worth (use it for anything that settles or bids — a keeper pays against this number, and a client-side estimate can drift from contract rounding). It reverts rather than returning a sentinel: `ContractRevertError` with `errorName: "NoOpenPosition"` when the account is flat in that pool (branch on `errorName`, never message text). - **Protocol state — is the stack wired and solvent.** The plane below any one account or market, mirroring what the protocol repo's `perps:state` / `perps:health` ops tasks read: ```ts const cfg = await client.getPerpSystemConfig(marginBank); // the address book const fund = await client.getInsuranceFundState(cfg.insuranceFund); const eng = await client.getLiquidationEngineConfig(cfg.liquidationEngine); ``` `getPerpSystemConfig` is the entry point: every other contract in the plane is reachable from it, so nothing is hardcoded per chain, and it carries `fullyWired` — a single flag for "some part of this stack is half-configured", which is the state where liquidation and settlement degrade silently rather than reverting. Point the other two at the addresses it returns. `liquidationEngine` is the **proxy**: an implementation address answers with unset defaults (zero bidders, zero penalty), which reads as a configured-but-idle engine rather than the wrong address. `bidderCount === 0n` is itself operational — with no registered backstop bidders the takeover stage has nobody to take a position over, so the waterfall reaches ADL sooner than the configuration implies. For account-level health when a feed may be down: `tryGetPerpAccountEquity` returns `null` rather than reverting (null is "not computable", never "zero"), and `getPerpCollateralBasis` is a solvency floor that reads one storage pair and cannot revert at all. - **Take-profit / stop-loss listing.** `client.listPerpStopOrders({ account?, pool?, status? })`. The PerpStopOrderRegistry keeps pending orders in private storage behind no enumeration getter, so there is no chain read that answers "what stops do I have" — creation and triggering both work, but without this a trader cannot see, price or cancel what they created. It is indexed, and there is no chain fallback. One call covers every scope: `{ account }` for a trader's working stops (default status `PENDING`), `{ pool }` with no account for a market's whole pending book, and `status` for history. `account` is optional deliberately — a market-wide view of what will fire is a legitimate monitoring read. Read `dropReason` before calling a `TRIGGER_FAILED` order a failure: `ReduceOnly*` means the stop was overtaken by events (position already closed, flipped, or below the minimum), which is ordinary; only `PlacementFailed` is a rejection. SOMI is consumed on every fire either way. A listed row has no `limitPrice`. Fetch it for live stops with `client.getPerpStopOrders(refs)`. - **The registry may be holding SOMI for you.** Placing a perp stop pre-pays the trigger gas in SOMI. Cancelling refunds it by direct transfer — but when that transfer _fails_, the registry credits an unclaimed balance instead and emits `SomiRefundFailed`. That is the ordinary outcome for a contract owner with no payable receiver (most multisigs and smart accounts). A registry wind-down credits the same balance to **every** owner, EOAs included. ```ts const owed = await client.getUnclaimedPerpStopSomi({ registry: perp.stopRegistry, account }); if (owed > 0n) await trader.claimPerpStopSomi({ registry: perp.stopRegistry }); ``` Read before claiming — `claimSomi` reverts `NothingToClaim` on a zero balance, and the payout is a plain native transfer to the caller, so an owner that still cannot receive native reverts `WithdrawalFailed` and the balance stays put. Do not assume an EOA is owed nothing: the wind-down path reaches them too. Note the trigger path is the opposite of a refund — SOMI is consumed on every fire and never returned. - **Batching writes that have to be atomic.** One SDK write is one transaction, which is wrong for a flow that is only safe as one — an order with TP/SL attached (sent separately, the order can fill and sit with no stop on it), approve + deposit, withdraw + forward to the wallet. `trader.buildPlacePerpStopOrder`, `buildCancelPerpStopOrder(s)`, `buildDepositMargin` and `buildWithdrawMargin` take the same parameters as their sending twins and return the unsigned call (`{ to, data, value, description }`) for you to pack into one UserOp / Safe batch / multicall. Two gotchas. Approvals come back rather than going out — `operatorApproval` on a stop, `approval` on a deposit — and must execute **before** the call they enable; the perp stop's grant especially, because without it the trigger reverts and the prepaid SOMI is spent having placed nothing. And no ids come back, because you hold the receipt: read them with `decodePerpStopOrderIds(receipt.logs, registry)`. - **Where the registry address comes from.** Every stop write — `placePerpStopOrder`, `cancelPerpStopOrder`, `cancelPerpStopOrders` — takes the per-pool `PerpStopOrderRegistry` as a required `registry` argument. Read it off the market row: `stopRegistry` on `PerpMarket`, and on the market context attached to perp portfolio orders and fills. `null` there means the pool has no registry deployed, so TP/SL is unavailable on it — not that the address is elsewhere. - **One call for a market header.** `exchange.fetchTicker(symbol)` on a perp now returns `markPrice`, `indexPrice`, `fundingRate`, `fundingTimestamp` and `openInterest` alongside the 24h high/low/volume it already computed from candles. Those five are chain state, not candle-derived, so before this a header needed a second read the consumer had to know to make. They are `undefined` on spot and binary, and no chain round-trip is spent on a non-perp. They also survive an indexer outage. The candle read is contained, so a failed one gives `statsState: "unavailable"` with the 24h fields absent while these five still answer. Read `statsState` before reading a 24h field. `fundingRate` is on the **same per-8h axis** as `fetchFundingRate` and `fetchFundingRateHistory` — deliberately, because a header on one basis beside a chart on another is a wrong number that looks right. It is not the per-settlement amount. For one settlement's charge, divide by `n = fundingWindowSec / fundingIntervalSec` (8 on every live pool) — and for a HISTORICAL row that caught up over several intervals, multiply that by the row's `intervalsAccrued`, since one settlement can charge more than one interval's worth. Both figures ride on `info.perp`. `markPrice` is omitted rather than reported as 0 when the feed is stale. - **Previewing an order before you send it.** `client.previewPerpOrderMargin({ pool, marginBank, account, isBid, quantity, price })` returns what the pool will actually lock and whether it will accept the order — the read behind an order form's "margin required" row and its submit gate. Do **not** reach for `quoteMeetsIMForOrder`: it runs with the order's base margin treated as already reserved (true on the real path, where `lockCollateral` runs first), so called cold it counts the order's margin nowhere and returns `true` for almost any size. `meetsPerpImForFill` does charge base margin, but neither models the lock's **adverse mark-to-entry reserve** — a buy above mark (or sell below) opens underwater by that gap and the pool reserves it on top of initial margin. That term is the usual reason a `notional × IMF`-sized "max" order gets rejected. Two gates are reported separately because they fail for different reasons and imply different fixes: `hasCollateralForLock` (can the lock be taken at all) versus `meetsInitialMargin` (does what remains still cover the requirement) — "deposit more" versus "close something". Only the _increasing_ leg locks. An order that nets against an existing position locks nothing up to `effectiveReducingCapacity`, which resting opposite-side orders have already partly spoken for. **Pass `autoPull: true` when the sender will be the order owner**, and both gates describe the balance the pool will have topped up to from the wallet rather than the one already in the bank. `topUpRequired` is then the wallet spend to show beside the margin figure, and `wallet` carries the balance and MarginBank allowance it was measured against. `feeHeadroom` appears either way: it is not charged and not part of `lockAmount`, only an auto-pull addend that keeps a fresh max-leverage position out of `MarginCall` at birth. A `topUpRequired` of `0n` means three different things — no pull needed, or one of the pool's declines: a purely reducing order, an account already in debt, or a voucher-blocked increase. Read it beside `unlockedCollateral`, not on its own. Every read is pinned to one block, so the result is a statement about that block; the adverse-gap term moves with the mark, so re-quote near send time for anything close to the edge. - **Market discovery is a chain read, and "deployed" is not "tradeable."** `client.listPerpPoolStatuses({ factory })` enumerates the `PerpPoolFactory` and returns every market with the **two independent gates** that decide tradeability — they fail for unrelated reasons and both must pass: 1. `restricted` — the market is close-only. Position-increasing orders revert `MarketRestricted`; closes, reduces and cancels still work. These stay listed on purpose (holders must still exit), and it is reversible. 2. `registered` — the MarginBank has activated the pool. Coming from the factory only proves a pool is _authentic_; `addPerpPool` is what makes it usable. An unregistered pool rejects every quote view and settlement callback while reading as an ordinary market from the factory. (`getPoolTier` is **not** a substitute — it is itself gated on registration.) `tradeable` folds both together, and `listTradeablePerpPools` filters to it. You do not pass a MarginBank: it is a per-network singleton in practice, but each pool names its own and that is the bank its settlement path uses, so it is read per pool and returned on every row — ready for the `getMarginAccount` / `getPerpPosition` reads that follow. Do **not** build a market list from the factory's raw pool list: it is the deployment history, so listing it unfiltered presents wound-down markets as tradeable. Testnet today has 10 pools, four of them restricted `SBTC*` arena markets. This is also more complete than the indexer, whose perp set comes from a curated manifest — a market deployed after that manifest was written is invisible there and present here. - **Per-market risk parameters are a chain read.** `client.getPerpRiskParams(pool)` returns the pool's frozen config — initial / **maintenance** / close-out margin in bps, the OI and position caps, and the maker/taker rates. `maintenanceMarginBps` is exposed nowhere else (the indexed market row carries only `initialMarginBps`), and without it a client can show the real liquidation price of an open position but not the **projected** one for an order it hasn't placed. This read never reverts, so maintenance margin stays available when the mark feed is down — exactly when you most want to explain a liquidation. - **Initial margin is not a constant.** `initialMarginBps` is only the FLOOR of the curve: with dynamic IMF enabled the pool scales it with open interest, and `client.getEffectiveImfBps(pool)` is the rate actually charged. Sizing an order off the static base under-margins it whenever OI has pushed the curve up, and the pool rejects an order the client believed fit. Maintenance margin deliberately does **not** scale — a liquidation threshold must not move under a position because the market's OI grew. - **One call for a health walk.** `client.getPerpHealthSnapshot(pool)` returns `oneBase`, mark, projected cumulative funding, the effective IMF and both thresholds together; the contract added it so a cross-margin walk reads a market once instead of five times. It returns a discriminated union — an unpriceable market arrives as `{ priceable: false }` rather than an all-zero struct, because a `maintenanceMarginBps` of `0` reads as "can never be liquidated". Narrow on `priceable` before touching a field. ## Linked wallets (isolated margin) Isolated margin on perps is one wallet per position. The MarginBank is cross-margin, so a single account's collateral backs every position it holds; the only way to give one position its own collateral bucket is to open it from its own wallet. `setIsolated` does not do this — it is single-market confinement, which caps how many markets one account may touch and changes no margin math. One wallet per position used to mean one treasury operation per position. The linked-wallet rail removes that. A wallet links to a **main** wallet, and from then on the child's position-increasing orders draw their margin shortfall from the main's wallet. One funded main serves every child linked to it. Two layers, and they answer different questions: - `LinkedWalletRegistry` is the **consent** graph. It records who is linked to whom and grants no authority over funds. - `MarginBank` is the **money** layer, and it is armed separately. Until the bank holds a registry address the rail is dormant and no child can draw on any main, whatever the registry says. ### Linking a sub-account A link takes a two-sided handshake and **both wallets sign**. The main offers, the child accepts, and no wallet can act for the other: ```ts // The MAIN offers. Its own deposit leaves the standing allowance the rail spends. await main.trader.depositMargin({ marginBank, amount: fromHuman(1000, 18) }); await main.trader.proposePerpWalletLink({ marginBank, child: childAddress }); // The CHILD accepts, with its own signer and its own transaction. await child.trader.acceptPerpWalletLink({ marginBank, main: mainAddress }); // The child's own placement now pulls the shortfall from the main's wallet. await child.trader.placePerpOrder({ pool, isBid: true, price, quantity }); ``` Pass `registry`, `marginBank` or `pool` to any of the four consent writes. Only `registry` skips a chain read: the bank names the registry it treats as authoritative, so the SDK reads it from the bank rather than a manifest, and a bank holding none throws `NotConfiguredError` rather than sending consent nowhere. That read is never cached, because the bank's owner can rotate the registry. ### How the funding actually happens There is no funding call, and this is the part that surprises people. The main supplies USDso and an ERC-20 allowance to the **MarginBank**, and then sends nothing. `PerpPool` performs the pull inside the child's own order placement: - The child's own wallet pays first, sized by `min(balance, allowance)`. - The main's wallet pays the residual, sized the same way. - The pool's entire gate is `msg.sender == order.owner`. An order routed through `placeOrderFor`, an operator grant, a router or the stop registry pulls **nothing**, from either wallet. So the child must send its own orders, and it needs native SOMI for gas. Revoking the main's allowance stops the funding without touching the link. Funding does not wait for link maturity: the rail reads the raw graph, and `maturesAt` gates ADL netting only. What a main funds is a **claim, not a gift**. The bank records the funded principal against the child, and the child's `withdraw` frees at most `balance - principal` — so a compromised child key can trade the money and lose it, but cannot take it out. The child's own money is the junior tranche: a loss eats it first, and a child that genuinely lost the principal owes nothing. ### Getting the money back Read the outstanding claim with `client.getPerpMainFunding(marginBank, account)`. Two routes send it home, and they differ only in who signs: | Write | Signer | Use it when | | ------------------------------------------------- | --------- | ------------------------------------------- | | `trader.repayPerpMainFunding({ amount })` | the child | the child is finished and returns the money | | `trader.recallPerpMainFunding({ child, amount })` | the payer | the main pulls its capital back | Both pay the payer the bank snapshotted at funding time, not whoever is linked now, so an unlink or a re-link in between cannot misroute the money. Both **clamp** the amount to `min(amount, outstanding, present balance)`, so over-asking is safe and only a clamp that reaches zero reverts. Both recover principal and never winnings. `trader.unlinkPerpWallet({ counterparty })` dissolves the link from either end. It settles no money, so clear the claim first if the intent is to part cleanly. `PerpsUnlinkGuard` vetoes it while the leaver holds open positions and is at `PartialLiquidation` or worse; a healthy or flat wallet can always leave. ### Batching the two steps that need it Two steps have an ordering dependency inside one transaction, and each has a build-only twin for it: - `trader.buildAcceptPerpWalletLink` — accept, then open the isolated position, in one signature. - `trader.buildRepayPerpMainFunding` — repay, then withdraw the remainder. The withdrawal's own gate reads the claim the repayment clears, so it has to follow. The other four writes are standalone administrative calls and have no twin. ### Which read answers which question The six chain reads are live contract STATE — a value as of a block, which no log can reconstruct. The history is the opposite: the contracts expose no getter for any of it, so the events in the chain's logs are the only record, and the indexer is what makes them queryable. | Question | Read | Tier | | --------------------------------------------------- | ------------------------------------------------------ | ------- | | Is the rail on at all on this deployment? | `client.getPerpLinkedWalletRegistry(marginBank)` | chain | | Is a main eligible to fund this account, and which? | `client.quotePerpFundingPayer(marginBank, account)` | chain | | What is outstanding, and to whom? | `client.getPerpMainFunding(marginBank, account)` | chain | | What can a wallet actually contribute right now? | `client.getPerpWalletPullCapacity(marginBank, wallet)` | chain | | Who is in my group, and when did it mature? | `client.getPerpWalletLinkage(registry, wallet)` | chain | | Which children does this main have? | `client.listPerpLinkedChildren(registry, main)` | chain | | How many children may one main hold? | `client.getPerpMaxLinkedChildren(registry)` | chain | | How did it get to this state? | the three `list*` ledgers below | indexer | **Eligibility is not a prediction.** `quotePerpFundingPayer` takes no order and no sender, so it cannot say whether a given order will debit the main. Four things stop an eligible main from paying anything: the order needs no top-up, the child's own wallet covers the whole pull, the order is routed by someone other than its owner, or the main has no spendable capacity. Size the order with `client.previewPerpOrderMargin({ autoPull: true })` and read its `mainWalletPull` for the amount that would actually move. `quotePerpFundingPayer` returns a discriminated union rather than an address, because the contract's single zero collapses three situations a UI must not render alike. Narrow on `funded` first: ```ts const payer = await client.quotePerpFundingPayer(marginBank, account); if (payer.funded) { // A main is ELIGIBLE to cover what this account's own wallet cannot. Whether any // given order debits it is `previewPerpOrderMargin({ autoPull: true }).mainWalletPull`. console.log("eligible payer", payer.payer); } else if (payer.reason === "unlinked") { // The one case the user can fix, by linking. } else if (payer.reason === "dormant") { // The rail is off for everyone here. Linking would not help. } else { // "isMain" — linked, but funding flows main->child only. } ``` `getPerpMainFunding` reports the claim and the payer **snapshotted at funding time**, which is not necessarily whoever is linked now. When the two disagree, the snapshot is who gets repaid. It also carries `withdrawableFromPrincipal`, which is always `0n` — a field rather than prose because "why can I not withdraw my balance" is the commonest question this surface has to answer. ### Finding an incoming proposal The registry keeps pending proposals in a hashed map with **no getter**. So a child cannot discover from any chain read that a main has offered it a link, and `client.listPerpWalletLinkEvents` is the only evidence such an offer exists. That list yields **candidates, not accepts that will succeed**. `acceptLink` applies five live-state guards, and each is a current-state rather than an ever-happened question: 1. An offer stands only while the pair's newest row is the `Proposed` itself. Mind the direction: an unlink clears the pending proposal in **both** directions, so an `Unlinked` naming this wallet as the main can retire an offer it holds as the child. 2. The child must be free right now (`AlreadyLinked`). Accepting one main leaves the losing mains' proposals in storage, dead only while that link stands. 3. The main must not itself be a child right now (`CallerIsChild`). 4. The accepting wallet must not itself be a main (`CallerIsMain`). 5. The main must be under its child cap (`MaxChildrenReached`). All five are **derivable in principle** from a complete `Linked` / `Unlinked` replay — except the cap, whose value is owner-tunable and whose `MaxChildrenUpdated` event is deliberately not subscribed. In practice a paginated page of rows is not a complete replay, which is the real reason not to decide an accept off this list. So confirm on chain. `client.getPerpWalletLinkage(registry, wallet)` settles guards 2, 3 and 4 — read it on both parties, since `main` being non-zero means the wallet is already in a group. It does **not** carry the cap: that is `client.getPerpMaxLinkedChildren(registry)` against `client.listPerpLinkedChildren(registry, main)`. ### The two funding ledgers, which must not be summed Every proposal, link, pull, settle and return is indexed, because the chain keeps no history of any of it: ```ts const links = await client.listPerpWalletLinkEvents({ child: account }); // Proposed | ProposalCancelled | Linked | Unlinked const pulls = await client.listPerpMarginPulls({ account, source: "Main" }); // the POOL side — names the order const claims = await client.listPerpMainFundingEvents({ account }); // the BANK side — carries the running claim ``` **A MAIN-funded leg emits a row on each side for the same wei.** Adding `listPerpMarginPulls` to `listPerpMainFundingEvents` therefore double-counts every main-funded transfer. Read one or the other, never both as one total, and pick by the question: the pool side names the **order**, the bank side carries the **claim**. The overlap is exactly the main legs, and no more. An own-wallet pull has no bank-side twin: the bank's `DepositedFor` is deliberately not subscribed, because `PerpMarginPull(source: "OwnWallet")` already carries the same amount plus the order id. So `PerpMainFundingEvent` is the main legs only, while `PerpMarginPull` is both. One placement can produce two `PerpMarginPull` rows — an `OwnWallet` leg and a `Main` leg, in that order — because the child's own wallet contributes what it can before the main is touched. Filter on `source: "Main"` to see only what a main actually paid for. On `PerpMainFundingEvent`, a `Settled` row moved no cash: it records the child's losses discharging part of the claim, so its `amount` is `null` while `outstandingPrincipal` still drops. Fold by `kind` rather than summing `amount`. ## Credit vouchers (house money) A credit voucher is a one-time grant of collateral into a new account's MarginBank balance. The grant is non-withdrawable. The account can trade with it and can withdraw profit above it. A `VoucherDistributor` holds the budget and the campaign rules, and the bank names the live distributor, so no deployment address is needed. | Question | Read | Tier | | ----------------------------------------- | ------------------------------------------------------- | ----- | | Is a campaign live, and what does it pay? | `client.getPerpVoucherCampaign(marginBank)` | chain | | Can this account claim now? If not, why? | `client.getPerpVoucherEligibility(marginBank, account)` | chain | | How much house money does it hold? | `client.getPerpVoucher(marginBank, account)` | chain | Check eligibility before you claim. A failed claim still mines and costs gas: ```ts const eligibility = await client.getPerpVoucherEligibility(marginBank, account); if (eligibility.eligible) { await trader.claimPerpVoucher({ marginBank }); } else { // "dormant" | "notStarted" | "ended" | "notFlat" | "mainFunded" | "alreadyClaimed" | "budgetExhausted" console.log("cannot claim:", eligibility.reason); } ``` Rules to know before you build on it: - **One claim per address, for the distributor's life.** A new campaign window does not reset it. - **The account must be flat to claim.** No positions and no resting perp orders. - **The grant confines position increases.** Only allowlisted markets, at no more than the voucher leverage cap, and the account cannot change its own leverage setting. `getPerpLeverage` and `previewPerpOrderMargin` already apply these rules. - **Own funds can mix in.** A voucher account can still deposit, and an order placed with an ERC-20 allowance to the bank can pull wallet collateral in. To keep an account on house money only, do not ask it for that allowance. - **The grant expires.** After `expiresAt`, anyone can sweep the remaining floor back to the distributor, but only while the account is flat. A sweep never forces a close. - **Each grant is indexed.** It appears in `client.getMarginEvents` as `kind: "Credited"`. `trader.buildClaimPerpVoucher` returns the unsigned claim, so a claim and the first order can go out as one transaction. The claim must execute first. ## History (indexer) The CURRENT position/margin is the chain read above; the **append-only history** the chain doesn't expose is indexed (perp account plane), all one-shot indexer reads: ```ts const funding = await client.getFundingPayments(account, { pool, limit: 50 }); // signed funding paid/received const margin = await client.getMarginEvents(account, { limit: 50 }); // deposit/withdraw/lock/unlock const liqs = await client.listLiquidations({ account, pool }); // liquidation events const rates = await client.listFundingRateHistory(pool, { from, to }); // per-pool funding-rate series const candles = await client.listFundingRateCandles(pool, 3600, { from, to }); // 1h/4h/1d rollups for charting const oi = await client.getOpenInterestHistory(pool); // per-pool open-interest series ``` `listFundingRateHistory` / `getOpenInterestHistory` are the append-only counterparts to the overwrite-only `fundingRate` / `openInterest` fields on the perp `Market` row (which only carry the latest value). `getFundingRateHistory` is the deprecated alias of the first; it forwards verbatim. Liquidation history is served by the `LiquidationEngine` subscription, which is live — the contract is deployed and indexed from block 436,735,800. There is no `MarginBank`-sourced fallback: `MarginBank.Liquidated` was deleted from the protocol, so the rows that claim used to describe cannot exist. Per-position detail comes from `LiquidationEngine.PositionLiquidated`, and the waterfall's other outcomes (ADL, takeover, close-out, the residual and declined-coverage markers) arrive as sibling rows sharing a `txHash` — read `kind` to tell them apart, and read the TSDoc on `badDebt` / `insuranceCovered` / `deficit` / `coverageDeclined` before aggregating any of them, because only the flows are summable. ### Reading a liquidation's stage `AccountLiquidated` rows carry `stageReached`. It tells you how far down the waterfall a liquidation went. The number needs a mapping, because the protocol enum is 0-indexed with six members while the published waterfall numbers its stages 1 to 6: | `stageReached` | Enum member | Published stage | | -------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | 0 | `OrderCancellation` | before stage 3 — cancelling the account's resting orders alone restored health | | 1 | `CLOBPartial` | stage 3 | | 2 | `BidderTakeover` | stage 4 | | 3 | `InsuranceFund` | stage 5 | | 4 | `ADL` | stage 6 | | 5 | `Deferred` | not a stage — stage 3 hit its per-block rate limit, and stages 4 to 6 were not consulted. Ships dormant, so it does not appear yet | Published stages 1 (Healthy) and 2 (Margin Call) are account states, not actions. The engine cannot reach them, so no value maps to them. Two rules govern the number, and neither is visible in the value itself. **It names the deepest stage that acted, not the deepest stage consulted.** A stage that ran and moved nothing does not promote it. So a `BidderTakeover` (2) row sitting beside a `BadDebtAbsorbed` row is consistent. It means the insurance fund was asked and paid nothing. `BadDebtAbsorbed` fires on the request, not on the payment, so read `insuranceCovered` on that row to see whether the fund actually paid. A market the fund does not cover produces exactly this shape: the loss falls through as `ResidualBadDebt`. **`CLOBPartial` (1) is a fall-through marker.** It means stages 4 to 6 were consulted and none of them acted. It does not prove stage 3 filled anything. Against an empty book you get `CLOBPartial` with a `positionsProcessed` of 0, which means the account's orders were cancelled and no position was closed. Read `positionsProcessed` with it: ```ts const rows = await client.getLiquidations({ account }); const summary = rows.find((r) => r.kind === "AccountLiquidated"); // A real CLOB partial fill, not an empty-book no-op. const clobFilled = summary?.stageReached === 1 && Number(summary.positionsProcessed) > 0; ``` `counterparty` on a `BadDebtAbsorbed` row names the fund the engine asked. The address is recorded even when `insuranceCovered` is 0, so it does not mean the fund paid either. `marginStatusAfter` needs the same care. A flat account that still owes bad debt reports `CloseOut` (3) so the debt stays visible to monitoring. That is a terminal state, not an account that is still liquidatable. A `ResidualBadDebt` row in the same transaction identifies it. If you query the indexer's GraphQL directly rather than through the SDK, note that its own field descriptions still carry the older wording for `kind`, `counterparty` and `stageReached`. Correcting them changes the served schema and so needs a reindex; it is tracked separately. This section is the current reference. ## Watch the perp plane (liquidations + funding settlement) `watchMarket(pool)` gives a perp pool's book, funding RATE and open interest. `watchPerpMarkets()` gives the other half: the liquidation waterfall and per-account funding settlement, with the same snapshot-then-live guarantee. Neither implies the other, so a UI showing both opens both. ```ts const plane = await client.watchPerpMarkets(); const liqs = client.listLiveLiquidations({ account, limit: 50 }); const paid = client.listLiveFundingPayments({ account, limit: 50 }); const unsubscribe = client.subscribeLive(() => { // re-read; results are memoized per store version }); // Teardown: the listener and the watch are released separately. unsubscribe(); plane.stop(); ``` The rows are the SAME `LiquidationEvent` and `FundingPayment` types `listLiquidations` and `getFundingPayments` serve, in the same newest-first order, so the two merge without translation. The live window is hydrated from the newest indexed rows, so it OVERLAPS the newest indexed page: merge by `id`, never by concatenation, or legs and their amounts are counted twice. That order is a TOTAL key on all three paths — the live store, the hydration and the indexed reads: `(timestamp, blockNumber, id)` for liquidations, and `(timestamp, id)` for funding payments, which carry no block column. Every leg of one waterfall shares a timestamp, so the tie-break is what makes a `limit` boundary land on the same rows whichever path serves them. The last key is the row id and not the log index inside it, because the indexed reads can only order on a column that exists. React: ```tsx const status = useWatchPerpMarkets(); // "unwatched" | "hydrating" | "live" const liqs = useLiveLiquidations({ account }); const paid = useLiveFundingPayments({ account }); ``` The two read hooks acquire the plane themselves, so `useWatchPerpMarkets` is only needed for the status — or to pass `{ marginBank }`, which the read hooks have no way to supply: `useWatchPerpMarkets({ marginBank })`. Each of these hooks also takes `chainId` in its options. It reads that chain's engine on a multi-chain exchange. Without it, the hook reads the primary chain. ```tsx const liqsOnChain = useLiveLiquidations({ account, chainId }); ``` For error UI, use `useWatchPerpMarketsResult()`, which returns the typed acquisition result instead of only warning. Worth preferring on this feed: a plane that failed to start and a venue where nothing has been liquidated both render as an empty list, and only the result tells them apart. ### One scope for the whole venue There is no `watchPerpMarket(pool)`, and that is forced rather than chosen. MarginBank and LiquidationEngine are singletons, so the log subscription is one stream whatever you ask for. And the account-level waterfall legs (`AccountLiquidated`, `ResidualBadDebt`, `ResidualBackedByOpenPnl`, `CoverageDeclined`, ...) carry no pool at all, so a per-pool scope would either drop them or attach them to every pool. So filter at read time. A `pool` filter is honest but PARTIAL: it keeps only the per-position legs, exactly as the indexed read's nullable `pool` column does. Filter by `account` for one wallet's whole story. ### One liquidation is several rows Read `kind` first. The rows are stages of one mechanism sharing a `txHash`, not repetitions of one event. Seventeen kinds arrive here, and the SDK produces the same set the indexer does. Two of them key on a wallet you might not expect. `AutoDeleveraged` is keyed on the BANKRUPT account, so an account assigned in as the profitable counterparty has no row of its own — it appears in the `counterparty` column instead. The stage-4 flows (`PositionTransferred`, `CloseOutMarginSettled`) are keyed on `from`. Before aggregating anything, read the field TSDoc on `LiquidationEvent`. Only `insuranceCovered` and `coverageDeclined` are flows and safe to SUM. `badDebt` and `deficit` are LEVELS — overlapping per-stage views of one hole — so summing them double-counts, and `collateralAmount` is collateral that moved between accounts rather than a loss. Four columns the indexer keeps have no home on the published type (`blockVolume`, `volumeCap`, `keeperReward`, `panicCode`), because `getLiquidations` does not select them either. So `Throttled`, `KeeperReward` and `OrderPanicked` arrive as markers from both sources alike. ### What the watch costs One indexer request, at hydration. After that the plane is fed from chain logs only, and a socket drop is healed by resubscribe plus a chain backfill with no second indexer touch — the same contract `watchMarket` has. It also needs the plane's wiring. The MarginBank comes from an indexed perp market row, and `MarginBank.getSystemConfig()` reports the LiquidationEngine from there, so nothing is hardcoded per chain. Pass `watchPerpMarkets({ marginBank })` only for the case that cannot cover: an indexer with no perp rows at all, where there is nothing to ask. It is a FALLBACK, never an override: it is used when the indexer names no bank, including on a scope a read hook acquired a beat earlier with no hint to give, and it is ignored when the indexer named one. The hydrated rows are that bank's plane, so a hint that won would splice one venue's history onto another venue's stream. If that wiring read fails the watch is REFUSED rather than opened over the bank alone, which would stream funding settlements and silently no liquidations — indistinguishable from a venue with none. The rejection type is `SomniaMarketsClientWatchPerpMarketsError`. ## Watch from chain (event ABIs) Indexer history is one-shot and the chain reads are point-in-time. To see a perp event as it lands, decode the log yourself. The SDK publishes the event ABIs so your decoder uses the same signatures the SDK and the indexer use: | ABI | Contract | Scope | Carries | | ---------------------------- | ----------------- | -------------------- | ------------------------------------------------------------------------------------- | | `perpPoolEventsAbi` | PerpPool | one per market | funding rate, open interest, the maker pre-fill reason tags | | `marginBankEventsAbi` | MarginBank | singleton, all pools | positions, collateral flow, funding settlement, fees, the liquidation settlement legs | | `liquidationEngineEventsAbi` | LiquidationEngine | singleton, all pools | the liquidation waterfall stages and their costs | Both singletons serve every pool and every account, so a subscription is one stream. The pool and the account are indexed topics, not the log source. Get the addresses from the market row and the system config: ```ts import { getAbiItem } from "viem"; import { liquidationEngineEventsAbi, marginBankEventsAbi } from "@somnia-chain/markets-sdk"; const market = await client.getPerpMarket(perpMarketId); const { liquidationEngine } = await client.getPerpSystemConfig(market!.marginBank); const viem = client.getViemClient(); // shares the SDK's WebSocket // Per-wallet funding settlement. `payment` is signed: positive is what the // account PAYS. const unwatchFunding = viem.watchEvent({ address: market!.marginBank, event: getAbiItem({ abi: marginBankEventsAbi, name: "FundingSettled" }), args: { account }, onLogs: (logs) => { for (const log of logs) console.log(log.args.perpPool, log.args.payment); }, }); // Every liquidation on the venue. `PositionLiquidated` is pool-scoped, so filter // by pool here if you only want one market. const unwatchLiquidations = viem.watchEvent({ address: liquidationEngine, event: getAbiItem({ abi: liquidationEngineEventsAbi, name: "PositionLiquidated" }), onLogs: (logs) => { for (const log of logs) console.log(log.args.account, log.args.sizeDelta, log.args.markPrice); }, }); ``` Three things to know before you build on this. **The waterfall is split across both singletons.** LiquidationEngine emits the stages and their costs. MarginBank emits the settlement legs of the same liquidation — `AutoDeleveraged`, `PositionTransferred`, `CloseOutMarginSettled` and `BadDebtAbsorbed`. Subscribe both, or you see half of each event. **Account-level events carry no pool.** `AccountLiquidated`, `ResidualBadDebt`, `AdlPriceCapacityExhausted` and their siblings describe the account, not one market. A per-pool liquidation filter therefore drops them. Filter by pool only on the per-position events. **Not every field is summable.** `BadDebtAbsorbed` reports `badDebt` (the full negative balance, before coverage) beside `covered` (the wei the insurance fund moved). `ResidualBadDebt` reports the uncovered remainder of the same hole. Adding them counts one loss twice. The same applies to `collateralTransferred` on `PositionTransferred` and `amount` on `CloseOutMarginSettled`: both are flows between accounts, not losses. The signatures are pinned by topic0 against the compiled artifacts in `test/perpEventsAbi.test.ts`. A wrong signature is a different topic0, which means `watchEvent` filters on something no contract emits and your handler never fires, with no error to see. Use the published ABI rather than a copy. Note the SDK's own live tail does not subscribe either singleton yet, so `client.watchMarket(pool)` gives you funding-RATE updates (`FundingUpdated` on the pool) but not funding settlement, positions or liquidations. Those are the raw watch above until the tail covers them. ## Quick start ```ts const exchange = new SomniaMarkets({ chain, wsRpcUrl, indexerUrl, privateKey }); await exchange.loadMarkets(); await exchange.depositMargin("BTC/USDSO:USDSO", 1_000); // USDso → MarginBank await exchange.createOrder("BTC/USDSO:USDSO", "limit", "buy", 0.001, 62_000); const [pos] = await exchange.fetchPositions(); // long/short + uPnL const { fundingRate, markPrice } = await exchange.fetchFundingRate("BTC/USDSO:USDSO"); ``` ## One-shot reads (no watch) For a plain fetch without a live tail: ```ts const perps = await client.listPerpMarkets({ baseSymbol: "WBTC", limit: 20 }); const one = await client.getPerpMarket(perps[0].id); // null if not a perp const port = await client.getPerpPortfolio(account, { ordersLimit: 50, tradesLimit: 50, since }); const hist = await client.listPerpOrderHistory(account, { limit: 100 }); // FINISHED orders const state = await client.getPerpState(one!.poolAddress); // mark/index/funding/OI ``` `listPerpMarkets` takes a `PerpMarketFilter` (`baseSymbol` / `quoteSymbol`, all server-side); `getPerpPortfolio` takes the shared `PortfolioOptions` (`ordersLimit` / `tradesLimit` / `since`). Trades default to the **last seven days** — the result's `tradesSince` is the bound that was applied; pass `since` to widen it. Positions + collateral stay on-chain (`getPerpPosition` / `getMarginAccount`), not indexed rows. `getPerpPortfolio` returns **open** orders only, so `listPerpOrderHistory` is the other half — finished orders, most-recently-ended first. It excludes working orders by default and sorts by when each order _ended_ rather than when it was placed, so a long-resting order that just filled lands at the top of a history view instead of buried at its placement date. Pass `status` to narrow to particular outcomes. Sort axis is selectable — `orderBy: "ended"` (default) or `"placed"`. Watch `Closed`: it is terminal, not transitional. Every pool places an order as `Closed` and a following `OrderRested` promotes it to `Open`, so an IOC that partially filled without resting stays `Closed` forever — reading it as "still working" shows a finished order as live. ## Writing forward-compatible code ```ts const m = client.getLiveMarketByPool(pool); switch (m?.marketType) { case "BINARY": /* YES/NO book */ break; case "SPOT": /* base/quote book */ break; case "PERP": /* base/quote book + funding/positions */ break; } ``` Key on `marketType` (not on field presence), use the type guards, and read decimals off the market row rather than assuming. --- # /docs/typescript/lend # Lend — SomniaLend through the SDK SomniaLend is a third-party money market on Somnia mainnet and testnet (an Aave v3.0 fork — [docs.somnialend.finance](https://docs.somnialend.finance/)). The SDK wraps its deployed contracts behind the `client.lend` namespace, so trading capital can earn while idle: supply USDso between sessions, post it as collateral, borrow working capital against it. It lives on the master client as the `lend` namespace. Because SomniaLend is third-party, its addresses are not in the deployments manifests — wire them in config, with the published deployments available as constants: ```ts import { SOMNIA_MAINNET_LEND } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ ...config, addresses: { ...addresses, lend: SOMNIA_MAINNET_LEND }, }); const lend = exchange.client.lend; ``` `SOMNIA_MAINNET_LEND` (chain 5031) and `SOMNIA_TESTNET_LEND` (chain 50312) carry the two published deployments (Pool, PoolAddressesProvider, UiPoolDataProviderV3, WrappedTokenGatewayV3), verified against the on-chain contracts. Set one as `addresses.lend` and reach the surface through `client.lend`; that is the only entry point, so a lend read always rides the client's own chain transport. Everything else you need without the client comes from the root entry (`@somnia-chain/markets-sdk`): the types, both deployment constants, the ray-math helpers (`lendRayRateToApy`, `rayMul`, …) and the verified minimal ABIs. Targeting a different deployment means a **different client** — the addresses and the chain travel together, so `new SomniaMarkets({ chain, wsRpcUrl, addresses: { lend } })`. (A `createLend(client, addresses)` factory used to be exported; it took a whole client to use two of its members, and let one chain's addresses be grafted onto another chain's socket, which type-checked and silently read nothing.) ## Reads Two calls cover the whole surface — both are chain reads over the client's WebSocket, current to head, no indexer involvement (`useLendReserves` and `useLendAccount` in `@somnia-chain/markets-sdk/react` wrap them for components): ```ts const reserves = await lend.listReserves(); // every listed asset const account = await lend.getAccount(me); // health factor + positions ``` `listReserves` is one aggregated `eth_call` (UiPoolDataProviderV3): per reserve you get the config (LTV / liquidation threshold / caps / flags), live rates and indexes, available liquidity, total debt, and the oracle price. `getAccount` joins the Pool's risk aggregate (health factor, borrowing power) with every non-empty supplied/borrowed position. Units, in the SDK-wide convention (bigint raw units everywhere): - **Rates and indexes are ray (1e27).** Convert a rate for display with `lendRayRateToApy(r.liquidityRateRay)` — the per-second-compounded APY fraction Aave UIs show. - **`healthFactor` is a wad (1e18).** Below `1e18` the position is liquidatable; a debt-free account reports `maxUint256`. - **`*Base` aggregates** (`totalCollateralBase`, `availableBorrowsBase`, reserve prices) are denominated in the oracle base currency — USD with 8 decimals on this deployment (`baseCurrencyDecimals` rides along). - **`borrowCap` / `supplyCap` are whole tokens** (Aave convention), not raw units; `0` means uncapped. - Balances (`aTokenBalance`, `variableDebt`, `totalSupplied`, …) are raw underlying units, accrued to the read's timestamp with Aave's own interest math (linear for supply, compounded for debt) — they match what the Pool would settle, not the last stored checkpoint. ## Writes ```ts const lender = lend.createLender({ privateKey }); // or account / walletClient await lender.supply(usdso, 1_000n * 10n ** 18n); // auto-approves the Pool await lender.borrow(usdce, 500n * 10n ** 6n); // variable rate only await lender.repay(usdce, maxUint256); // maxUint256 = full debt await lender.withdraw(usdso, maxUint256); // maxUint256 = full balance await lender.setUseAsCollateral(usdso, true); ``` Same doctrine as the trader: writes resolve once mined (with the receipt), gas is a fixed generous ceiling, fees are the client's fixed EIP-1559 config, and ERC-20 pulls auto-approve `maxUint256` once per (token, spender) with an in-memory grant cache (`approve: false` opts out per call; `clearApprovalCache()` resets). Borrowing is variable-rate only — stable borrowing isn't surfaced. Native SOMI has gateway-routed siblings so you never touch WSOMI yourself: `supplyNative` / `withdrawNative` / `borrowNative` / `repayNative`. Two of them need a one-time grant the SDK also handles automatically: `withdrawNative` approves the gateway to pull your aWSOMI, and `borrowNative` delegates borrowing power on the WSOMI variable-debt token (`approveDelegation`). `repayNative` doesn't take `maxUint256` — overpay slightly instead; the gateway refunds the excess. ## Risk notes - A borrow that would push the health factor below 1 reverts; watch `getAccount(me).healthFactor` and size against `availableBorrowsBase`. - Liquidation pays the liquidator `liquidationBonusBps` out of your collateral — keep headroom, especially against WSOMI's price. - Reserve flags matter: `isFrozen` blocks new supplies/borrows, `isPaused` blocks everything; check them before sizing. - The SDK talks to SomniaLend's contracts as deployed — protocol risk (upgrades, oracle, listing params) is SomniaLend's admin surface, not this SDK's. See their [risks page](https://docs.somnialend.finance/risks). --- # /docs/typescript/prices # Price feeds A realtime index price for an asset (BTC, ETH) from the **on-chain EMA price oracle** — streamed the same way the order books are: hydrate a snapshot to get roughly up to speed, then tail live. It's a _read-only_ feed (an index price, not a tradable market), so there are no orders here — just `watch`/`fetch`. The shared client mechanics (read tiers, the reactive store, React wiring) are in [the engine guide](./ENGINE.md); how the number itself is produced — venue sourcing, weighted median, quantization, validator consensus, the EMA mark — is [Methodology](#methodology) at the bottom of this page. ## The mental model - **A separate service.** Prices come from a standalone EMA price-feed indexer (Hasura GraphQL), _not_ the markets indexer — its own endpoint, its own WebSocket. So price watches are independent of `watchMarket`: their own store, their own `subscribePrices` signal, their own health. - **One endpoint, every asset.** A single endpoint (`config.priceFeed`) serves every tracked asset (`"BTC"`, `"ETH"`, …); callers select an asset by symbol (case-insensitive). Discover what's tracked with `listPriceFeeds()`. With no `priceFeed` configured, the price methods throw with guidance. - **Snapshot, then live tail.** A watch first pulls an HTTP snapshot (current price + recent ticks), then Hasura subscriptions stream updates. The two heal differently on a reconnect. The current price is a full-state subscription: every push carries the current row, so re-subscribing is all it needs. The tick tape is a stream cursored on `requestId` — it is seeded from the newest tick in the snapshot and advances on every push, so a reconnect resumes from the last tick delivered rather than replaying the window. Both are handled with backoff internally; neither is anything a caller has to drive. - **One socket and batched snapshots per client.** Every watched asset on one endpoint shares one Hasura socket in the client. Each asset keeps its own two subscriptions, cursor and health. Watches that start in the same tick (for example `watchPrices`, or several hooks that mount together) share snapshot requests of up to 10 assets each. Each asset still receives its own 200 recent ticks. A failed snapshot request rejects only the watches it carried. Two clients never share a socket. - **Human numbers + exact raw.** Every price is a 1e18-scaled integer on the wire; the structs carry a display `number` (`price`, `ema`) _and_ the exact 1e18 string in `raw` — never round-trip money through the `number`. Timestamps are unix **seconds** (`blockTimestamp` is chain time, monotonic — use it as a series x-axis; `observedAt` is the oracle's own source time and can drift). ## Configuration ```ts import { SomniaMarkets, SOMNIA_TESTNET_PRICE_FEED } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ indexerUrl, chain, wsRpcUrl, priceFeed: SOMNIA_TESTNET_PRICE_FEED, // { url, quote } - the deployed dev feed, all assets // or your own: priceFeed: { url: "https://…/v1/graphql", quote: "USDC" } }); ``` `priceFeed` is `{ url, wsUrl?, quote? }`; `wsUrl` is derived from `url` (`http→ws`, `https→wss`) when omitted. Live subscriptions use the global `WebSocket` (browsers, Node ≥ 21). **`quote` is required to watch.** The feed indexes several quotes per base (`BTC/USDC`, `BTC/USDT`), so `base` alone is not a unique feed key. The tick tape streams on a `requestId` cursor, and one oracle request prices every symbol in the tick, so across quotes that cursor is not unique and a batch boundary between two rows sharing one would advance past the second and lose the tick. Rather than drop data quietly, `watchPrice`/`watchPrices` (and the price hooks) reject an unpinned feed with a `NotConfiguredError` naming `config.priceFeed.quote`. The one-shot reads (`fetchPrice`, `fetchPriceHistory`, `fetchPriceOHLCV`, `fetchPrices`, `listPriceFeeds`) still work unpinned, where matching every quote only double-counts a base (duplicate candle buckets, an arbitrary row per asset). Pin it anyway unless you want that. Both shipped constants are pinned to USDC, so anything built on `SOMNIA_TESTNET_PRICE_FEED` or `SOMNIA_MAINNET_PRICE_FEED` needs no change. ## Reading — live ```ts const watch = await client.watchPrice("BTC"); // snapshot + subscribe; ref-counted const now = client.getLivePrice("BTC"); // LivePrice | null — { price, ema, blockTimestamp, raw, … } const tape = client.getLivePriceTicks("BTC", { limit: 120 }); // recent ticks, newest first const info = client.getLivePriceFeedInfo("BTC"); // decimals, symbol, description, latest const state = client.getPriceStatus("BTC"); // "unwatched" | "hydrating" | "live" | "error" watch.stop(); // release (the last release ends this asset's subscriptions; the shared socket closes when no asset uses it) ``` **Batch variants** take/return arrays and are the ergonomic choice for a multi-asset ticker — one watch, one read: ```ts const handle = await client.watchPrices(["BTC", "ETH", "SOL"]); // snapshot + subscribe all; ref-counted const rows = client.getLivePrices(["BTC", "ETH", "SOL"]); // (LivePrice | null)[], index-aligned const status = client.getPriceStatus("BTC"); // "live" after snapshot/subscription setup handle.stop(); // release all in one call ``` Reads are synchronous, zero-round-trip, and current to the last pushed tick; subscribe to changes with `client.subscribePrices(listener)` (independent of the order-book `subscribeLive`). In React the hooks auto-watch while mounted: ```tsx import { useLivePrice, useLivePriceTicks, useWatchPrice } from "@somnia-chain/markets-sdk/react"; function Ticker() { const price = useLivePrice("BTC"); // updates the moment a tick lands const status = useWatchPrice("BTC"); // "hydrating" | "live" | "error" — render off this const ticks = useLivePriceTicks("BTC", 120); // for a sparkline if (status === "error") return price feed stopped; return {price ? `$${price.price.toLocaleString()}` : "…"}; } ``` ### The `"error"` state The status is `"error"` when the price-feed server rejected or terminated the asset's subscription. This happens on a validation failure after a schema change, or on a permission denial. The subscription will not heal by itself, so stop the watch and start a new one. Only the rejected asset enters `"error"`. Other assets on the shared socket keep streaming. A dropped connection is different: every asset on that socket becomes `stale` and heals on reconnect. Reads keep answering in this state. They return the last values they held, which have stopped updating. A view that renders a price without checking the status therefore shows a frozen price as a live one. Each rejection is also emitted as a `warn` event on the client's debug channel with the server payload. ## Reading — one-shot No watch, one HTTP round-trip each — for history, charts, or a server render: ```ts const info = await client.fetchPriceFeedInfo("BTC"); // metadata + current price const price = await client.fetchPrice("BTC"); // LivePrice | null const history = await client.fetchPriceHistory("BTC", { limit: 500, from, to }); // ticks, newest first const candles = await client.fetchPriceCandles("BTC", "M1", { from, to }); // OHLC, oldest first ``` Candle resolutions are `"M1"` / `"H1"` / `"D1"` (60s / 3600s / 86400s). `count` on a candle is the number of oracle updates in the bucket (update density), **not** trade volume. Like every indexer read these **throw** on request failure — an empty result means "no rows", never "request failed". ## From the exchange The unified [`SomniaMarkets`](./EXCHANGE.md) surface exposes prices by asset (these don't need `loadMarkets` — a price feed isn't a symbol-keyed market): ```ts const px = await exchange.fetchPrice("BTC"); // { symbol, price, ema, timestamp, … } | null for await (const _ of forever) { const tick = await exchange.watchPrice("BTC"); // resolves on each new tick } const ohlcv = await exchange.fetchPriceOHLCV("BTC", "1m"); // [ms, o, h, l, c, count][] — "1m"/"1h"/"1d" ``` The native `LivePrice` (raw strings + block metadata) rides on each struct's `info`. ## Methodology Everything above is the read surface. This section is how the number itself is produced: exactly what is measured, what is discarded, how it is aggregated, how it is encoded, and what a consumer is guaranteed when it reads a cell. Every constant is the value in the shipped code (`impl v9`). **One-line version.** A weighted median across seven venue mids, quantized to nine significant figures, medianed again across three independent validators, packed with its own provenance into one 256-bit storage word — every second, paid for by the contract itself. | | | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | Cadence | 1 s | | Scale | 18 decimals | | Sources | 7 centralised exchanges, top-of-book mid | | On-chain aggregation | 3-validator subcommittee, 2-of-3 threshold | | Networks | Somnia mainnet (5031) `0x1998C88D54a240b8C671493f27f58eC416b81D7F` · testnet (50312) `0x7ccAE31E45693475be1e4BAa2360D6997eB2D32B` | ```mermaid flowchart TB V["7 venues
top-of-book mid"] --> G["4 freshness gates
+ per-symbol quorum floor"] G --> M["weighted median
over the fresh set"] M --> Q["quantize
30-bit mantissa + 5-bit exponent"] Q --> B["48-bit slot per symbol
packed blob"] B --> C["3 validators submit
independently"] C --> M2["second median
per symbol, on-chain"] M2 --> E["EMA mark
alpha = 0.125"] E --> S["one 256-bit cell
spot + mark + provenance"] S --> R["consumer read
pull, never reverts"] ``` --- ### 01 — Source: seven venue mids, streamed A Go process — the **price-oracle agent** — connects to seven centralised exchanges through a pruned fork of `ccxt`. It does not fetch on demand. One goroutine per venue runs continuously, writing the latest quote for every tracked pair into an in-memory store; a price request is a read of that store, so it answers in about a millisecond with zero network I/O on the request path. The quantity collected is the **top-of-book mid**, `(bid + ask) / 2`, spot markets only. Four venues stream over WebSocket; three fall back to bulk REST polling on a 1-second ticker. | Venue | Weight | Transport | Why | | ------- | ------ | --------- | ---------------------------------------------------------- | | binance | 3 | ws stream | | | okx | 2 | ws stream | | | bybit | 2 | rest poll | `wss` endpoint geoblocked from the runners' datacentre IPs | | kucoin | 1 | ws stream | | | kraken | 1 | ws stream | | | gateio | 1 | rest poll | stream unimplemented in the fork | | mexc | 1 | rest poll | stream connects, never delivers | Total weight **11**. Weights are static configuration — **not** measured volume or depth. They are placeholders intended to be tuned against real per-venue liquidity. Measured source freshness: 70–220 ms on the streaming venues, 225 ms–3.3 s on REST. > `internal/exchange/ccxt.go`, `oracle.json` · 61 tracked pairs · > `POLL_INTERVAL` 1 s · `PER_CALL_TIMEOUT` 8 s · reconnect backoff doubles to > 30 s, jittered ### 02 — Admission: four gates, then a quorum floor Staleness is the first and strictest gate. A quote that sat in the cache longer than three seconds is not aggregated — it is not even reported as a number. | Gate | When | Rule | Effect | | ----------- | ----------- | ------------------------------------------------------------------- | ------------------------------------ | | Book sanity | ingest | both sides present, `bid > 0`, `ask > 0`, not crossed (`ask ≥ bid`) | quote discarded, never cached | | Spread | ingest | `(ask − bid) / mid ≤ 0.02` | quote discarded, never cached | | Dwell | aggregation | `now − UpdatedAt > STALE_AFTER (3 s)` | exclude, `excludedReason: "stale"` | | Never seen | aggregation | configured exchange has never returned this pair | exclude, `excludedReason: "no-cell"` | The first two run in `midPrices` as each venue's ticker batch is reduced to a mid, so a bad book never reaches the store at all — there is no exclusion reason for it, and a venue that only ever produces bad books is indistinguishable from one that has never returned the pair. `"stale"` and `"no-cell"` are the only two exclusion reasons that exist. - **The spread bound is loose on purpose.** Liquid USDT pairs run around 1 bp, so 2% only catches a book wide enough to be a manipulation surface. - **Dwell is measured on the agent's own ingest clock** (`now − UpdatedAt`), not the exchange's timestamp, so it is immune to venue clock skew. The comparison is strictly greater: exactly 3.000 s still counts. **Then a per-symbol quorum floor.** With fewer than `minSources` fresh venues the agent refuses to publish. The default floor is **3**, with a per-token override table (`SOMI/USDC: 1`, because it does not list on three of these venues). Below the floor the symbol's slot is written as **all zeroes** — not a small number, not a stale number, nothing. > `internal/store/store.go:136,198` · `internal/server/handlers.go:98–112, 406–437` · `maxMidSpreadFrac = 0.02` · `STALE_AFTER = 3s` ### 03 — Aggregation: a weighted median, not an average Sort the fresh quotes by price. Walk the weights. The first price whose cumulative weight crosses half the total is the index. One venue can be the whole answer. All seven venues fresh, total weight 11, half is 5.5: | Venue | Price | Weight | Cumulative | | ----------- | -------------- | ------ | -------------------------- | | kraken | 107,373.90 | 1 | 1 | | mexc | 107,374.05 | 1 | 2 | | okx | 107,374.18 | 2 | 4 | | **binance** | **107,374.21** | **3** | **7** ← first to cross 5.5 | | bybit | 107,374.44 | 2 | 9 | | kucoin | 107,374.60 | 1 | 10 | | gateio | 107,375.02 | 1 | 11 | The index is **107,374.21**. Drop `binance` (stale) and the total falls to 8, half is 4, and `bybit` at 107,374.44 becomes the index — a 23-cent step with no bad data anywhere. There is **no outlier or deviation rejection anywhere in the agent**. Robustness comes entirely from the choice of median over mean. ### 04 — Quantization: nine significant figures in six bytes The float becomes an 18-decimal integer, then is re-encoded as a 30-bit mantissa and a 5-bit exponent. Everything past the ninth digit was never real. Two lossy steps, in order: 1. **Scale-up.** The price is a `float64` the whole way through the agent, so multiplying by `10^18` in a `big.Float` pinned at a 53-bit mantissa re-rounds rather than shifting exactly. This is why BTC arrives on-chain looking like `63420.750000000000327680` — that tail is `float64` residue, not market data. 2. **Wire encoding.** Pick the smallest exponent whose mantissa still fits 30 bits, rounding half up. One symbol's wire slot is exactly 48 bits and exactly full: | Field | Bits | Range | Example — BTC at 107,374.21 | | ------------- | ---- | -------------- | ----------------------------------------- | | `mantissa` | 30 | `0 … 2^30 − 1` | `107374210` | | `exp` | 5 | `0 … 31` | `15`, so the value is `107374210 × 10^15` | | `sourceAgeMs` | 13 | `0 … 8191` | `120` | ### 05 — Transport: the packed blob The contract calls `getPricesSlots(string[],uint8)` and gets back a single `bytes` value of **exactly** `6 × nActive` bytes — no ABI element padding at all. The symbol at active position `p` lives at bytes `[6p, 6p+6)`, big-endian. Slots straddle 32-byte word boundaries by design. - 30 active symbols → blob length must equal **180 bytes**, exactly. - A **whole-zero slot** means "this validator did not price this symbol". - A **nonzero slot with a zero mantissa** is malformed and is dropped the same way. - **Any other length drops the validator entirely** — a stale cell, never a wrong price. ### 06 — Consensus: three validators, then a second median Nobody trusts one agent. A subcommittee of three runs the same code in three sandboxes against three separate caches, and the contract medians them again. Each elected subcommittee member detects the request, runs the agent in its own Docker sandbox, and submits its own blob on-chain. Because the agent answers from a continuously-updated cache, the three answers are legitimately different — which is why the platform finalises on **Threshold** consensus (2-of-3), not Majority, which would require identical result hashes. | Live parameter | Value | Consequence | | ------------------ | ------------- | --------------------------------------------------------------- | | `subcommitteeSize` | 3 | three independent agent runs per tick | | `threshold` | 2 | two contributors is the ordinary steady state; one is reachable | | `consensusType` | 1 (Threshold) | non-identical results are expected, not a fault | | `timeout` | 15 s | must exceed 10 s — the runner cancels at `deadline − 10s` | | `decimals` | 18 | the scale the agent is asked to pre-apply | **Four gates on the response, before a single cell moves.** | Rejection | Reason code | Why | | ---------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | not in the inflight ring | `not-inflight` | ring lookup and consume, so a duplicate callback is idempotent | | `status ≠ Success` | `AgentRequestFailed` | no cells written | | `block.timestamp − kickedAt > 3 s` | `stale-response` | the platform's timeout upkeep can deliver a quorum-met partial as `Success` hours late; ingesting it would sawtooth the feed and poison the EMA | | `symbolsVersion` moved | `symbols-version-mismatch` | responses carry no symbol identity, only array position — if the symbol list changed since the kick, position `i` may be a different asset | Any symbol-list mutation invalidates every inflight request; the next tick refills everything within one interval. **The second median — per validator, per symbol.** For each symbol the fill loop does one `calldataload` per validator, gates it, and medians the survivors. The gate is **per-validator**, which is the whole point: one garbage validator drops out instead of shifting the median. | Symbol | Validator A | Validator B | Validator C | Cell written | | ------------- | ----------- | ------------ | ----------- | ---------------------------------- | | BTC/USDC | 107,374.18 | 107,374.21 | 107,374.30 | 107,374.21 · vc 3 | | ETH/USDC | 3,142.07 | slot = 0 | 3,142.11 | 3,142.11 · vc 2 | | SOL/USDC | slot = 0 | mantissa = 0 | 184.62 | 184.62 · vc 1 | | FARTCOIN/USDC | slot = 0 | slot = 0 | slot = 0 | untouched — omitted from the batch | Insertion sort, then `values[n / 2]` — the **upper** middle on even counts, which at the ordinary 2-of-3 threshold means the higher of the two prices. On a 2-validator tick the median is not a blend; it is a pick. `vc` is `validatorCount`, the surviving contributor count, saturating at 7, with 0 meaning _unknown_ — never "none". ### 07 — Mark price: the same number, smoothed Mark is **not a different data source**. It is an EMA over the spot series, computed from the previous cell, and it costs no extra storage. Each tick the mark moves `emaAlpha = 0.125e18` — one eighth — of the way from the previous mark toward the new spot. At the 1 s cadence that is a smoothing horizon of τ ≈ 8 s. **Response to a genuine move.** After `n` ticks the fraction of a step captured is `1 − 0.875^n`. The conventional time constant τ is where that crosses 63%, and it lands exactly where `interval / alpha` predicts — 8 ticks: | Ticks | 1 | 2 | 4 | 6 | 8 (= τ) | 16 | 24 | | -------- | ----- | ----- | ----- | ----- | ------- | ----- | ----- | | Captured | 12.5% | 23.4% | 41.4% | 55.1% | 65.6% | 88.2% | 95.9% | **Alpha is per tick, not per second.** τ ≈ 8 s here, but τ ≈ 80 s in the DEX's oracles — same `emaAlpha = 0.125e18`, copied from their production values, but their cadence is 10 s. Rescale alpha if the cadence changes and the smoothing horizon should stay put. `emaAlpha = 1e18` disables smoothing entirely — mark becomes spot. ### 08 — Storage: everything in one slot Spot, mark, timestamp, source age and provenance share a single 256-bit word. One cold `SSTORE` per symbol per tick, one `SLOAD` to read all of it. | Field | Bits | Encoding, and what 0 means | | ------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `price` | 86 | spot median at 18 dp. Ceiling ≈ 77 M per unit. | | `quality` | 14 | packed sub-fields, below | | `mark` | 86 | EMA mark; always between the previous mark and this spot | | _reserved_ | 14 | | | `updatedAtMs` | 42 | `block.timestamp × 1000` — second-granular, shared by every symbol written in the same tick. A `maxAgeMs` bound below the tick cadence is not meaningful. Good to year 2109. | | `sourceAgeMs` | 14 | a delta below `updatedAtMs`, not an absolute stamp — capped at 16.383 s. The top value is the sentinel and reads back as `0 = unknown`, never "current", so a real age clamps one below it. | The 14-bit `quality` field expands to: | Sub-field | Bits | Meaning | | -------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `validatorCount` | 3 | contributors to the median, saturating at 7. `0 = unknown` (a cell written before the field shipped), never "none" — a written cell always had ≥ 1. | | `medianControlCount` | 3 | reserved. Always reads `0`. No room on the wire. Do not branch on it. | | `flags` | 2 | bit 0 `FLAG_MARK_RESYNCED`; bit 1 `FLAG_DEVIATION` reserved and never set. | | _reserved_ | 6 | | Removing a symbol deletes its cell. **Indices are append-only and never reused**, so an on-chain consumer can resolve index → symbol once off `SymbolAdded` and read by index forever — one `SLOAD` cheaper than the string-keyed path, with no risk that a removal elsewhere silently shifts the mapping. > `contracts/feed/lib/PriceCell.sol` · `lib/FeedHealth.sol` · > `lib/ActiveIndexSet.sol` ### 09 — Consumption: pull, and decide staleness yourself Reads never revert. Staleness is the caller's decision, always — the feed will not decide on your behalf what is too old. | Interface | Keyed by | Gives you | | --------------------- | ---------------- | ---------------------------------------------------- | | `IPriceFeed` | symbol string | spot, cell age, source age, tracked-symbol registry | | `IMarkPriceFeed` | symbol string | EMA mark (separate so `IPriceFeed`'s id never moved) | | `IIndexedPriceFeed` | stable `uint256` | the same data, one `SLOAD` cheaper | | `IQualifiedPriceFeed` | either | quorum, flags, feed liveness, and the safe reads | **Off-chain: one batched event, and history.** Each tick emits a single `PricesUpdated(requestId, updatedAtMs, indices[], prices[], marks[], sourceUpdatedAtsMs[], resyncedBits)` — one event for the whole batch, carrying only stable indices. An Envio + Hasura stack indexes it into `Feed` (latest per symbol, a Chainlink-ish `latestRoundData` analogue), `PricePoint` (the per-tick firehose), `Candle` (OHLC at M1 / H1 / D1) and `Symbol` (the index → pair registry). That GraphQL surface is what the price methods above read. > **GraphQL is for humans, not for settlement.** Testnet only, and observability > only. It lags the chain, can be resynced, and is not part of the support > contract. Never settle, liquidate, or price anything off it. **End-to-end latency.** | Leg | Time | | ---------------------------------------------------- | ----------- | | 1 — exchange → agent | ~0.1 s (ws) | | 2 + 4 + 5 — cache dwell + kick→response + cell write | ~0.8 s | | 6 — wait for your next read | 0–~1 s | Measured on testnet over 150 consecutive BTC/USDC ticks: cell cadence median 1 s (max 2 s), kick→cell median ~0.8 s ≈ 7 blocks at ~116 ms. A consumer acts on a price 1–2 s old; at the instant of the cell write it is ~0.9 s. The dominant and most actionable leg is kick→cell. REST-only venues are the other lever — they inflate leg 1 and can leave source age unmeasurable entirely. --- ### Sources Contracts and scheduler: - `smart-contracts/contracts/feed/PriceFeedScheduler.sol` - `smart-contracts/contracts/feed/lib/PriceCell.sol` - `smart-contracts/contracts/feed/lib/SlotResponse.sol` - `smart-contracts/contracts/feed/lib/FeedHealth.sol` - `smart-contracts/docs/price-feed-scheduler.md`, `price-feed-latency.md`, `price-feed-design-decisions.md` - `smart-contracts/script/config/feed-testnet-development.json` - `docs/price-feed-integration.md` - `price-feed/indexer/schema.graphql` Agent: - `somnia-agents/agents/price-oracle/internal/store/store.go` - `somnia-agents/agents/price-oracle/internal/server/handlers.go` - `somnia-agents/agents/price-oracle/internal/exchange/ccxt.go` - `somnia-agents/agents/price-oracle/oracle.json`, `agent.json` ## Delivery state and acquisition errors The price service is separate from the main indexer. Its results do not carry main-indexer watermarks. `hydrated` means the HTTP snapshot completed. `streaming` requires valid initial results from both the current-price and tick subscriptions. Empty arrays confirm delivery without creating a price. A connection acknowledgement alone does not establish streaming. `stale` means known delivery loss. It does not infer an expected oracle tick frequency. The asset retains its last values while reconnecting, and both streams must deliver again before `streaming` returns. `error` means hydration failed or a subscription was rejected. Each asset reports its own state, so a healthy sibling cannot conceal a stale one. Existing `getPriceStatus` and `useWatchPrice` keep `unwatched | hydrating | live | error`. The legacy `live` state means snapshot/subscription setup succeeded; it does not confirm operation delivery. A disconnect does not change that legacy state. Opt into `client.getPriceHealth(asset)` or `client.listPriceHealth()` for the precise states above. They share the existing price watches and `subscribePrices` notifications. No extra socket opens. Automatic hooks continue reporting acquisition failures through the debug/console warning channel. Use `useWatchMarketResult`, `useWatchUserResult`, or `useWatchPriceResult` for typed inline acquisition UI. Effects ignore superseded failures and release handles acquired after unmount. --- # /docs/typescript/chains # Chains Every Somnia network as a viem `Chain`, from one import — so nothing has to hand-roll a `defineChain({...})` or reach for `viem/chains` again. ```ts import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; ``` `chain` is a required field of every exchange/client config (it signs writes and sizes viem's waiting heuristics), and `wsRpcUrl` is the transport the live tail runs on — both come straight off these objects. Moving tokens _between_ these networks is the [bridge](./BRIDGE.md) — same module, same import. ## The networks | Export | Chain id | Native | Blocks | Multicall3 | Explorer | | --------------- | -------- | ------ | --------- | ---------- | -------------------------------------------------------------------------- | | `somniaMainnet` | `5031` | SOMI | 100 ms | ✅ | [explorer.somnia.network](https://explorer.somnia.network) | | `somniaShannon` | `50312` | STT | 100 ms | ✅ | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | `somniaElwood` | `50313` | STT | 100 ms | — | — | | `hidekiTestnet` | `50383` | STT | **10 ms** | ✅ | — | | `somniaLocal` | `31337` | STT | — | — | — | - **Shannon** (`somniaShannon`) is the public testnet and the default target for development. `https://dream-rpc.somnia.network` is an alias for the same network and is listed as a secondary endpoint. - **Elwood** is the testnet's regenesis: its own cluster, DNS zone and genesis, otherwise identical to Shannon. - **Hideki** is the low-latency Tokyo network — ~100 blocks/s. If you are measuring latency, measure here. - **`somniaLocal`** is the anvil stack (`demo-clob.sh up`, `DEPLOY_ENV=local`). It deliberately presents as _Somnia_/_STT_ rather than _Foundry_/_Ether_: the agent-facing docs read the chain name and native symbol out of this object, and a local stack should still read as Somnia there. Every definition carries **both** transports — `rpcUrls.default.http` and `rpcUrls.default.webSocket` — so an exchange can be built from the chain alone: ```ts import { SomniaMarkets } from "@somnia-chain/markets-sdk"; import { hidekiTestnet as chain } from "@somnia-chain/markets-sdk/chains"; const exchange = new SomniaMarkets({ chain, wsRpcUrl: chain.rpcUrls.default.webSocket[0], indexerUrl: "/v1/graphql", }); ``` ## Absences are deliberate Elwood and the local chain carry **no `contracts.multicall3`** and no `blockExplorers` — nothing is deployed there to point at. That is not an oversight to be filled in with the canonical `0xcA11bde05977b3631167028862bE2a173976CA11`: viem routes batched reads at whatever address it finds, so a Multicall3 entry with no code behind it turns every batched read into a failure. An absent field just makes viem fall back to individual `eth_call`s. Mainnet, Shannon and Hideki each have their **own** Multicall3 deployment at _different_ addresses (`0x5e44…5a11`, `0x841b…4223` and `0x540B…D131`) — don't copy one to another. Hideki's (deployed 2026-08-10 by the bridge infra) is the canonical runtime bytes at a **non-canonical** address: the presigned "Nick's method" deployment can never land on Somnia chains — contract creation costs ~4,928 gas per deployed byte here, far over that transaction's fixed 500k limit — and its nonce-0 deployer has already been burned on these networks, so `0xcA11bde0…` is unreachable for good. The values here — ids, cadence, Multicall3 addresses — were verified against the live networks (`eth_chainId`, block-timestamp deltas over 10k blocks, and a real `getBlockNumber()` call on each Multicall3 candidate), not copied from a chain list. ## Resolving a chain id you were handed Deployment manifests (and `NEXT_PUBLIC_CHAIN_ID`-style env) carry a plain `number`. `getSomniaChain` bridges that to a `Chain`, returning `null` when the id isn't one of ours: ```ts import { getSomniaChain, defineChain } from "@somnia-chain/markets-sdk/chains"; const chain = getSomniaChain(deployment.chainId) ?? defineChain({ id: deployment.chainId, name: "Somnia", nativeCurrency: { name: "STT", symbol: "STT", decimals: 18 }, rpcUrls: { default: { http: [rpcUrl] } }, }); ``` `somniaChains` is the same table, keyed by id — iterate it to build a network switcher. `isSomniaChainId(id)` is the type guard that narrows a `number` to `ChainId`, enough to index it without a cast. When the id flows the other way — your code names the network — **`ChainId`** is the constant to reach for: `ChainId.somniaShannon` is `50312`, keyed by the same export names as the definitions (`ChainId.somniaShannon === somniaShannon.id` by construction). ## Extending one `defineChain` and the `Chain` type are re-exported here, so overriding an endpoint (a private node, a fork) needs no second import: ```ts import { defineChain, somniaShannon } from "@somnia-chain/markets-sdk/chains"; const forked = defineChain({ ...somniaShannon, id: 31_337, name: "Somnia Testnet (forked)", rpcUrls: { default: { http: ["http://127.0.0.1:8545"], webSocket: ["ws://127.0.0.1:8545"] } }, }); ``` ## Relationship to `viem/chains` viem ships two of these networks as `somnia` and `somniaTestnet`; our `somniaMainnet` and `somniaShannon` carry the same content under the names the runbooks use (a test asserts field-for-field parity), and the module adds the three networks viem cannot ship — Elwood, Hideki and the local stack are ours, on our cadence. One import covers every target, and a new network lands when we bring it up rather than when viem next cuts a release. Each definition lives in its own file under `src/chains/definitions/`, written the way viem writes its own, so the two stay diffable. `src/chains/bridge/` sits alongside them with the warp-route registry — see the [bridge guide](./BRIDGE.md). --- # /docs/typescript/bridge # Bridge Moving tokens between Somnia networks. A specialised chain is only useful if value can reach it — Hideki is a ~10 ms-block network built for traders, and this is how balances get there from the general-purpose testnet. ```ts import { BridgeToken, ChainId, createBridgeTransfer, sendBridgeStep } from "@somnia-chain/markets-sdk/chains"; ``` It lives in the [chains](./CHAINS.md) module because that is what it is: verified static addresses, alongside the chain definitions and their Multicall3 entries. The registry and `createBridgeTransfer` are **pure** — no RPC, no client, no signer: `createBridgeTransfer` returns transaction data and you send it. `sendBridgeStep` is the one opt-in sender. > ⚠️ **This is a dev/test bridge.** One validator, a threshold-1 ISM, EOA owners — > one key is the entire bridge. `SOMNIA_BRIDGE.status` is `"dev-test"` and it means > it: **do not put real funds behind it.** ## What's live One lane — `somniatestnet-hideki2testnet` — with five routes. [Full deployment record](https://github.com/somnia-chain/hyperlane-bridge-infra/blob/main/docs/deployments/somnia-testnet-hideki2-testnet.md): | Token | Somnia Testnet (50312) | Hideki2 Testnet (50383) | Decimals | | ------- | ---------------------- | ----------------------- | -------- | | `STT` | native | native | 18 | | `USDso` | collateral | synthetic | 18 | | `WBTC` | collateral | synthetic | **8** | | `WETH` | collateral | synthetic | 18 | | `HBTT` | collateral | synthetic | 18 | ### Which Hideki this is This section explains which chain the lane above reaches. Read it before you reconcile any address against the bridge-infra repo. `ChainId.hidekiTestnet` (50383) is **Hideki 2**. Hideki 2 is the 2026-09-17 regenesis of Hideki. The lane above is Hideki 2's lane. Hideki 1 still runs. It has its own lane. This SDK does not ship that lane. Both chains use chain id 50383. Both use Hyperlane domain 50383. They differ only in network id: 50000258 for Hideki 1, and 50000259 for Hideki 2. No signature, wallet or Hyperlane message tells them apart. Each lane has its own core contracts on Somnia Testnet. Each warp router binds to one mailbox when it is deployed. This binding keeps the two lanes apart. Two consequences follow. - **Every Hideki-side address on this lane equals Hideki 1's.** The same deployer replayed its nonce sequence onto Hideki 2. That chain restarted its nonces at genesis. A matching Hideki address therefore does not identify the lane. - **Each Somnia-side address belongs to one lane only.** These addresses identify the lane. In the bridge-infra repo, this lane is `registry-hideki2/`. It is not `registry/`. Mainnet, Elwood and the local chain are **not** bridged — `getBridgeNetwork` returns `null` for them, and `createBridgeTransfer` throws rather than inventing a route. Bridging is also **not transitive**: a chain has to be a member of the token's own route. ## The enumerations ```ts BridgeToken.WBTC; // "WBTC" — the bridge's own enum ChainId.hidekiTestnet; // 50383 — from the chains module: the chain id IS the value ``` Both are `const` objects with a matching type, not TS `enum`s — the pattern the rest of this SDK uses. You get `BridgeToken.WBTC` for the value and `BridgeToken` for the type, plain literals still assign, and nothing non-erasable is emitted. Networks are named by **`ChainId`**, which lives with the [chain definitions](./CHAINS.md) rather than here — every Somnia network has a chain id; only some are bridged. Its keys are the definition export names, so `ChainId.hidekiTestnet === hidekiTestnet.id` by construction, and the id is the value because that is what wallets, manifests and viem speak — on this bridge the Hyperlane **domain id equals the chain id**, so one number identifies a network everywhere. ## Bridging ```ts const plan = createBridgeTransfer({ token: BridgeToken.WBTC, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: 100_000_000n, // 1 WBTC — 8 decimals, not 18 recipient: account.address, }); if (plan.approveStep) await sendBridgeStep(client, plan.approveStep, { account }); const receipt = await sendBridgeStep(client, plan.bridgeStep, { account }); ``` Two fields are the whole plan: **`bridgeStep`** — the `transferRemote` call, always present — and **`approveStep`**, the ERC-20 approval a collateral route needs first, simply **absent** on native and synthetic routes. Branching on `plan.approveStep` narrows it, so no `!` is ever needed; its role is the field name, and `description` is the human label. **`sendBridgeStep(client, step, { account })`** is the sender: it signs locally (fixed fees, fixed gas ceiling, never estimated) and broadcasts via Somnia's `eth_sendRawTransactionSync`, which blocks server-side and returns the **receipt in the same call** — send + confirm in one round-trip, so the approve-then-bridge ordering above is safe by construction. It throws on a reverted receipt, and on a node without the method (anvil, stock geth) it falls back to `eth_sendRawTransaction` + a receipt wait. It needs a **local** signer (viem `privateKeyToAccount`, a session account); with a browser wallet, spread the step into `walletClient.sendTransaction({ ...plan.bridgeStep, account })` instead — extensions don't sign raw transactions. One consequence of fixed ceilings worth knowing: Somnia's mempool admits a transaction only when the balance covers `gas × maxFeePerGas` (0.6 STT at the defaults) on top of its `value`, even though unused gas is never charged — fund small accounts for the envelope, not the expected fee. Each transaction is `{ chainId, to, data, value, description }` — everything you must send, nothing you must fill in. No `gas`, no `nonce`, no fees: those belong to the signer, and a builder guessing gas for a contract on another chain would be inventing numbers. `value` **is** ours, because it is protocol-semantic: | Route model | `value` | Approval | | ------------ | ---------------------------------------------- | ------------------------------------ | | `native` | **the amount** — the coin rides in `msg.value` | none | | `collateral` | `0n` | ERC-20 `approve` to the router | | `synthetic` | `0n` | none — the router burns your balance | Amounts are **bigint base units of the origin side's decimals**. Read them from `plan.origin.decimals` rather than assuming 18 — WBTC is 8 on both sides. **Browser wallets and JSON boundaries.** A viem wallet client takes a step as-is — including one on `custom(window.ethereum)`. For the raw `eth_sendTransaction` path, or to move a server-built plan across a JSON boundary (a step's `value` is a `bigint`, and `JSON.stringify` throws on bigints), `toEip1193Transaction(step, { from? })` returns the hex-quantified, JSON-safe request object — typed as viem's own `RpcTransactionRequest`. It deliberately drops `chainId`: an EIP-1193 wallet signs on its **active** chain, so switch with `wallet_switchEthereumChain` first. The [walkthrough](./CHAINS_WALKTHROUGH.md) shows both paths end to end. ## Bridging through the exchange A multi-chain `SomniaMarkets` exposes the same planner as `exchange.bridge`, bound to its own chains and executors. Both ends must be configured chains, the origin legs go through the origin chain's executor (a [smart account](./ACCOUNTS.md) packs the approval and the bridge call into one transaction, funded from the account itself), and delivery is observed on the destination engine's socket rather than polled. ```ts const plan = exchange.bridge.plan({ token: "USDso", from: L1, to: HIDEKI, amount: 100n * 10n ** 18n }); const result = await exchange.bridge.transfer( { token: "USDso", from: L1, to: HIDEKI, amount: 100n * 10n ** 18n }, { onStep: (s) => console.log(s.kind, s.status, s.hash) }, ); result.messageId; // the Hyperlane message id, from the origin receipt result.delivered; // true once the destination Mailbox processed that message ``` The SDK tracks one Hyperlane message per transfer. It reads the message id from the origin receipt: the origin Mailbox's `Dispatch` whose sender is the origin router, paired with the `DispatchId` after it. It then waits for the destination Mailbox's `ProcessId` for that id only. A delivery to the same recipient from another transfer does not end the wait. The wait first asks the destination Mailbox `delivered(messageId)`, so a message that landed before the wait started still counts. The wait times out 180 s after the origin transaction is mined by default (`deliveryTimeoutMs`). On a timeout, `exchange.bridge.transfer` resolves with `delivered: false` and the `messageId`. The transfer is not undone and can still land. Before you send again, call `delivered(messageId)` on the destination chain's Mailbox (`getBridgeNetwork(to).mailbox`). It is a view, `function delivered(bytes32 messageId) view returns (bool)`, that you can read with the engine's `getViemClient()`. A second transfer while the first is in flight moves the funds twice. A few `RpcError` operations also mean the origin leg was sent and the funds may be in flight: `bridge message id` (the receipt holds no single dispatch to decode) and `watch bridge delivery` (the destination watch failed). Look up the origin transaction before you retry. `exchange.ensureFunds({ code, chainId, amount })` builds on it: check the account's balance of a currency on one chain and bridge the shortfall from the richest other configured chain. `createOrder(…, { funding: "auto" })` bridges the same way for the order's collateral token. By default an order whose collateral is elsewhere throws `CollateralOnWrongChainError` carrying the plan instead. The route follows the collateral token's address in the bridge registry, not its symbol. A token the registry does not list gets no plan, even when its symbol is `USDso`. When the bridged message is not delivered in time, `ensureFunds` and `createOrder(…, { funding: "auto" })` throw `BridgeDeliveryTimeoutError` with `messageId`, `bridgeHash`, `from`, `to`, `token` and `amount`, and place no order. On one exchange, these calls run one at a time per account, chain and currency. The exchange keeps a leg that timed out as pending. When the next `ensureFunds` or auto-funded order for the same key finds a shortfall, it waits for that message first and sends no new leg for it. The pending leg lives in memory only. A new exchange instance, or another process, must check `delivered(messageId)` before it bridges again. A direct `exchange.bridge.transfer`, and an order with `funding: "explicit"` or `"skip"`, does not join this queue and does not check pending legs. ## Two failure modes worth preflighting **Native-route liquidity.** An `STT` transfer is native on both sides, so delivery is paid out of the _destination router's own balance_ rather than by minting. If that balance is short, `process()` reverts and the transfer sits in escrow until someone refunds the router — not lost, but stuck. The destination side's `requiresDestinationLiquidity` flags it. `exchange.bridge.transfer`, `exchange.ensureFunds`, and `createOrder(…, { funding: "auto" })` read the destination router's balance before they send. When it is below the amount, they throw `BridgeLiquidityError` and send nothing. The check is a read, not a reservation: another transfer can still drain the router before delivery. When you send the planner's transactions yourself, check the balance before you offer the transfer: ```ts if (plan.destination.requiresDestinationLiquidity) { const liquidity = await destinationClient.getBalance({ address: plan.destination.router }); if (liquidity < plan.amount) throw new Error("destination router is short — transfer would stall"); } ``` At the last verification the Somnia-side router held **0 STT** and Hideki's held 100, so a _first_ Hideki → Somnia transfer stalls until seeded. Seeding is a plain native transfer to the router. **The relayer is a liveness dependency.** No InterchainGasPaymaster is deployed, so `quoteGasPayment` is 0 on every router and the relayer pays delivery gas unmetered (`SOMNIA_BRIDGE.relayerPaysDestinationGas`). A sender attaches nothing for delivery — but if the relayer runs dry, transfers keep being accepted on the origin and stop being delivered. Should a gas quote ever be introduced, read it and pass it as `gasPayment`; it lands in `bridgeStep.value`. Delivery is asynchronous either way: `transferRemote` escrows and dispatches, and the far side is credited seconds later. The transaction you send does not wait for it. On the Hideki 2 lane, a 9-leg measurement on 2026-09-17 gave a median of 7.5 s in one direction and 8.7 s in the other. Most legs included a 5.1 s relayer retry. A single leg on 2026-09-23 took 3.0 s. The SDK's 180 s default delivery timeout is about 20 times the median. **A drained router shows up as a timeout.** The SDK refuses a native transfer when the destination router holds less than the amount. The check is a read, so another transfer can still drain the router before delivery. Then `process()` reverts on the destination, the message stays undelivered, and the wait ends with `delivered: false` (or `BridgeDeliveryTimeoutError` from `ensureFunds`). The message is delivered after someone seeds the router and the relayer retries. Check `delivered(messageId)` instead of sending again. ## Looking things up ```ts getBridgeToken(BridgeToken.USDso, ChainId.hidekiTestnet); // one side of one route, or null listBridgeTokens(ChainId.somniaShannon); // everything bridgeable from a network getBridgeNetwork(ChainId.somniaShannon); // mailbox / ISM / hooks, or null listBridgeNetworks(); // the bridged networks getBridgeRoute(BridgeToken.WBTC, 50312, 50383); // the lane, either order, or null getBridgeRouter(BridgeToken.STT, ChainId.somniaShannon); // just the router address SOMNIA_BRIDGE; // the lane: routes, trust model, docs ``` Lookups return `null` on a miss (the `get*` contract: a `get*` read answers with `null` for a real absence); `createBridgeTransfer` **throws**, because an unsupported triple is a programming error and its message names what would work. `warpRouterAbi` is exported too, for reading a router directly — `quoteGasPayment`, `routers`, `destinationGas`, `token`. ## How the values got here Every address, decimal and model in the registry was read off the **live chains**, not transcribed: all ten routers have code, are owned by one account, are wired to their chain's mailbox and ISM, and are mutually enrolled in both directions; the collateral routers' `token()` matches the canonical ERC-20; the synthetics' `decimals()` match; `quoteGasPayment` is exactly 0 everywhere. The `transferRemote` encoding was _simulated_ with `eth_call` — `value = amount` on the native route returns a real message id, while dropping the value, skipping the approval, or naming an unenrolled destination each revert. `test/bridge.test.ts` pins the calldata offline. `test/bridge.e2e.test.ts` re-runs the whole verification against both chains on demand — nothing signed, nothing sent: ```sh SOMNIA_E2E_BRIDGE=1 pnpm test ``` A note on one client-side trap the registry exists to avoid: a **native** router answers `token()` with the _zero address_ rather than reverting, so code that probes `token()` to decide "collateral or native" silently gets `0x0…0`. Use `plan.origin.model` / `BridgeTokenDetails.model` instead. ## Adding a token or a lane Both are data. `hyperlane-bridge-infra` is the source of truth — a new route there becomes a new entry in `src/chains/bridge/registry.ts`, and the types already carry it: `destinations` is a list, `SOMNIA_BRIDGE.routes` is a list, and every lookup is a filter. Adding a route needs no agent restart and no new core contracts; the validator and relayer are token-agnostic. --- # /docs/typescript/chains-walkthrough # Chains walkthrough A hands-on tour of `@somnia-chain/markets-sdk/chains`, end to end: pick a network, stand up clients, send a transaction, bridge STT both ways, fund a Hideki session account from a Shannon wallet, and run the live test suite that proves all of it against the real networks. The reference guides are [CHAINS.md](./CHAINS.md) (the network definitions) and [BRIDGE.md](./BRIDGE.md) (the warp-route registry and its trust model) — this page is the "follow along in a terminal" version. **You need:** Node + pnpm, `viem` (a peer dependency of the SDK), and an account holding STT on the networks you target. Shannon STT comes from the Somnia testnet faucet or a funded team key; Hideki has no public faucet — use a funded key. Everything below runs on the two bridged testnets and costs fractions of a (test) token. ```ts import { somniaShannon, hidekiTestnet } from "@somnia-chain/markets-sdk/chains"; ``` The module is **pure data + pure functions** — importing it performs no RPC. The networks it ships: | Export | Chain id | Blocks | Bridged | | --------------- | -------- | --------- | ------- | | `somniaMainnet` | `5031` | 100 ms | — | | `somniaShannon` | `50312` | 100 ms | ✅ | | `somniaElwood` | `50313` | 100 ms | — | | `hidekiTestnet` | `50383` | **10 ms** | ✅ | | `somniaLocal` | `31337` | — | — | This walkthrough sticks to the two bridged testnets: **Shannon** (`50312`, the general-purpose testnet) and **Hideki** (`50383`, the low-latency Tokyo network). ## 1. Create a client for different chains Every definition is a complete viem `Chain` — endpoints (HTTP _and_ WebSocket), block cadence, and Multicall3 where one actually exists. So a client is one call, and `http()` with no URL already means "the chain's default endpoint": ```ts import { createPublicClient, http, webSocket } from "viem"; import { somniaShannon, hidekiTestnet } from "@somnia-chain/markets-sdk/chains"; const shannon = createPublicClient({ chain: somniaShannon, transport: http() }); const hideki = createPublicClient({ chain: hidekiTestnet, transport: http() }); await shannon.getChainId(); // 50312 await hideki.getChainId(); // 50383 // The live tail and anything latency-sensitive should ride the WebSocket: const hidekiWs = createPublicClient({ chain: hidekiTestnet, transport: webSocket(), // hidekiTestnet.rpcUrls.default.webSocket[0] }); ``` When the chain id arrives as a plain `number` (a deployment manifest, a `NEXT_PUBLIC_CHAIN_ID` env), resolve it instead of switching on magic numbers: ```ts import { getSomniaChain, isSomniaChainId, somniaChains } from "@somnia-chain/markets-sdk/chains"; const chain = getSomniaChain(Number(process.env.CHAIN_ID)); // Chain | null if (!chain) throw new Error("not a Somnia network"); // somniaChains is the same table keyed by id — iterate it for a network switcher. // isSomniaChainId(id) narrows a number so somniaChains[id] indexes without a cast. ``` Two behaviors to know, both deliberate (details in [CHAINS.md](./CHAINS.md)): - **Every bridged network batches, at its own address.** Shannon, Hideki and mainnet each carry a `contracts.multicall3` — three _different_ addresses (Hideki's arrived 2026-08-10, at a non-canonical address, because the canonical `0xcA11bde0…` deployment can never land on Somnia chains). Elwood and the local chain have none, and viem silently falls back to individual `eth_call`s there. Don't "fix" an absence by pasting the canonical multicall address into an extended definition — there is no code at it, and viem would route every batched read into a failure. - **`blockTime` drives viem's waiting heuristics.** Hideki's `10` means `waitForTransactionReceipt` polls fast enough to return in tens of milliseconds; a hand-rolled `defineChain` without it would wait seconds. ## 2. Post a transaction A wallet client from a private key, a send, a receipt — the only chains-module-specific part is that the `Chain` object is the one import: ```ts import { createWalletClient, http, parseEther } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; const account = privateKeyToAccount(process.env.SOMNIA_TESTNET_PK as `0x${string}`); const wallet = createWalletClient({ account, chain: somniaShannon, transport: http() }); const hash = await wallet.sendTransaction({ to: "0x0000000000000000000000000000000000000001", value: parseEther("0.001"), }); const receipt = await shannon.waitForTransactionReceipt({ hash }); receipt.status; // "success" ``` The same code targets Hideki by swapping the chain and the key. Gas, nonce and fees are viem's job — the chain definitions carry everything viem needs to estimate them correctly per network. ## 3. Bridge STT both ways The bridge is the same import: a Hyperlane warp lane between Shannon and Hideki carrying `STT`, `USDso`, `WBTC`, `WETH`, `HBTT`. [`createBridgeTransfer`](./BRIDGE.md#bridging) is pure — it returns the unsigned transactions; you sign and send them. > ⚠️ It is a **dev/test** bridge — one validator, threshold-1 ISM. Testnet > value only. Shannon → Hideki, delivered and verified: ```ts import { BridgeToken, ChainId, createBridgeTransfer, sendBridgeStep } from "@somnia-chain/markets-sdk/chains"; import { parseEther } from "viem"; const amount = parseEther("0.05"); const plan = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.somniaShannon, // 50312 — the values ARE chain ids to: ChainId.hidekiTestnet, // 50383 amount, recipient: account.address, }); // STT is native on both sides → no approval, the amount rides in msg.value. // A collateral route (USDso/WBTC/WETH/HBTT leaving Shannon) needs an ERC-20 // approval first — plan.approveStep is present exactly when that's the case. // // sendBridgeStep signs locally (fixed fees, no estimation) and broadcasts via // eth_sendRawTransactionSync: the node blocks until the transaction // is executed and answers with the RECEIPT — send + confirm in one round-trip, // so each line below resolves confirmed. (No wallet client needed: the public // client is the wire, the account is the signer.) if (plan.approveStep) await sendBridgeStep(shannon, plan.approveStep, { account }); const receipt = await sendBridgeStep(shannon, plan.bridgeStep, { account }); receipt.status; // "success" — a reverted receipt throws instead ``` That receipt only proves **escrow + dispatch** on the origin. Delivery is asynchronous — the relayer credits the far side seconds later (on the Hideki 2 lane, a median of 7.5 s to 8.7 s per leg, measured 2026-09-17). Watch the destination: ```ts async function waitForDelivery(client, address, floor, timeoutMs = 180_000) { const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { const balance = await client.getBalance({ address }); // ERC-20 routes: readContract balanceOf if (balance >= floor) return balance; await new Promise((r) => setTimeout(r, 2_000)); } throw new Error("not delivered — is the relayer alive? is the destination router funded?"); } const before = await hideki.getBalance({ address: account.address }); // ... send the plan (previous snippet) ... await waitForDelivery(hideki, account.address, before + amount); ``` The reverse direction is the same call with `from`/`to` swapped and a Hideki-funded wallet — but preflight it, because **native-route delivery pays out of the destination router's own balance**: ```ts const back = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.hidekiTestnet, to: ChainId.somniaShannon, amount, recipient: account.address, }); if (back.destination.requiresDestinationLiquidity) { const liquidity = await shannon.getBalance({ address: back.destination.router }); if (liquidity < back.amount) { // Underfunded ≠ lost: the transfer would sit in escrow until the router is // seeded. Seeding is a plain native transfer to the router address — and // note the symmetry: every transfer OUT of a chain escrows on that chain's // router, which is exactly the balance a later reverse transfer draws on. throw new Error(`Shannon STT router holds ${liquidity} wei — seed it first`); } } ``` At the last live run the Shannon-side router held **0 STT**, so a first Hideki → Shannon transfer stalls until the router is seeded (or until an equal amount has been bridged Shannon → Hideki, which self-seeds it). Hideki's router held 100 STT. Mind the units: amounts are **bigint base units of the origin side's decimals** — read `plan.origin.decimals`, don't assume 18 (WBTC is 8 on both sides). Lookups (`getBridgeToken`, `getBridgeRoute`, …) return `null` on a miss; `createBridgeTransfer` **throws** on an unsupported triple, naming what would work. ### Signing in the user's browser Everything so far signed with a private key in Node. In a dapp the key lives in the user's wallet extension, and the order reverses: **connect first** — the sender (and usually the recipient) is the wallet's address, which you only know once it answers — _then_ build the plan, _then_ let the user confirm each step. Two distinct moments, worth keeping apart: 1. **The transaction is created** by `createBridgeTransfer` — a pure function that returns unsigned calldata. No RPC happens, nothing is sent, and there is nothing secret in the result. 2. **The transaction is signed** when a step is handed to the wallet — one prompt per step — and only then does anything reach the chain. The whole flow, self-contained: ```ts import { createPublicClient, createWalletClient, custom, http, parseEther } from "viem"; import { BridgeToken, ChainId, createBridgeTransfer, somniaShannon } from "@somnia-chain/markets-sdk/chains"; // 1. Connect — this is where the user's address comes from. const browser = createWalletClient({ chain: somniaShannon, transport: custom(window.ethereum) }); const [account] = await browser.requestAddresses(); // 2. Create the transaction(s): pure, unsigned, not yet sent anywhere. const plan = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: parseEther("0.05"), recipient: account, // the user's own address on the destination chain }); // 3. Sign + send — one wallet prompt per transaction; the wallet fills // gas/nonce/fees. The approval must land before the bridge call spends it. // (The sync path from §3 doesn't apply here: eth_sendRawTransactionSync // needs a locally-held key, and an extension won't sign raw transactions — // the wallet's own eth_sendTransaction is the browser's send path.) const shannon = createPublicClient({ chain: somniaShannon, transport: http() }); if (plan.approveStep) { const hash = await browser.sendTransaction({ ...plan.approveStep, account }); await shannon.waitForTransactionReceipt({ hash }); } const hash = await browser.sendTransaction({ ...plan.bridgeStep, account }); await shannon.waitForTransactionReceipt({ hash }); ``` Because step 2 is pure it can also run **server-side** (an API route, a server action): the browser sends the connected address up, the server builds the plan and returns the transactions. A `BridgeStep` doesn't cross that boundary as-is — its `value` is a `bigint`, and `JSON.stringify` throws on bigints — `toEip1193Transaction` is the JSON representation: the exact object `eth_sendTransaction` takes, every quantity hex-encoded. ```ts // On the server — build the plan for the address the browser sent: import { ChainId, createBridgeTransfer, toEip1193Transaction } from "@somnia-chain/markets-sdk/chains"; const plan = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: parseEther("0.05"), recipient: userAddress, }); return Response.json({ chainId: plan.bridgeStep.chainId, // the ORIGIN chain the wallet must be on approve: plan.approveStep && toEip1193Transaction(plan.approveStep, { from: userAddress }), bridge: toEip1193Transaction(plan.bridgeStep, { from: userAddress }), }); // bridge: {"from":"0x…","to":"0xB043…aB35","data":"0x81b4e8b4…","value":"0xb1a2bc2ec50000"} ``` ```ts // In the browser — no SDK import needed, the transactions are ready-made requests: import { numberToHex } from "viem"; const { chainId, approve, bridge } = await (await fetch("/api/bridge-plan")).json(); // ⚠️ eth_sendTransaction has NO chain field — an EIP-1193 wallet signs on its // ACTIVE chain. Switch to the origin chain first, or the transfer goes out on // whatever network the wallet happens to be on: await window.ethereum.request({ method: "wallet_switchEthereumChain", params: [{ chainId: numberToHex(chainId) }], }); if (approve) { // wait for this hash (public client / wallet UI) before submitting the bridge call await window.ethereum.request({ method: "eth_sendTransaction", params: [approve] }); } const hash = await window.ethereum.request({ method: "eth_sendTransaction", params: [bridge] }); ``` `toEip1193Transaction` deliberately drops `chainId` (see the warning above) and the `kind` / `description` tags (UI metadata — some wallets reject unknown keys), and pins `from` only when you pass it. Gas, nonce and fees stay with the wallet, same as everywhere else in this module. ## 4. Worked example: a Hideki session funded from Shannon Everything above, composed into the flow a trading UI actually runs: the user's wallet lives on Shannon, a disposable **session account** trades on Hideki, and the bridge is what moves gas and working capital between them. (Session accounts come from the [native module](./NATIVE.md) — a 32-byte seed the node can sign for, whose derivation is public, so the address is computable locally before any RPC. **The seed is a private key in another shape: store it like one.**) ```ts import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; import { sessionAddress, sessionPrivateKey } from "@somnia-chain/markets-sdk/native"; const seed = generatePrivateKey(); // any 32 random bytes, persisted like a secret const session = privateKeyToAccount(sessionPrivateKey(seed)); session.address === sessionAddress(seed); // true — the node derives the same address // The user's wallet signs on Shannon; the session signs on Hideki. const userAccount = privateKeyToAccount(process.env.SOMNIA_TESTNET_PK as `0x${string}`); const userWallet = createWalletClient({ account: userAccount, chain: somniaShannon, transport: http() }); const sessionWallet = createWalletClient({ account: session, chain: hidekiTestnet, transport: http() }); ``` **Fund it.** Two transfers out of the user's Shannon wallet: STT so the session can pay Hideki gas, and HBTT as working capital. HBTT is Hyperlane's open test token — anyone can `mint(address,uint256)` on Shannon, which is what makes this walkthrough self-service: ```ts import { parseAbi, parseEther, erc20Abi } from "viem"; const mintAbi = parseAbi(["function mint(address to, uint256 amount)"]); const hbtt = getBridgeToken(BridgeToken.HBTT, ChainId.somniaShannon)!; // Working capital exists first as the canonical ERC-20 on its home chain. await userWallet.writeContract({ address: hbtt.address!, abi: mintAbi, functionName: "mint", args: [userAccount.address, parseEther("10")], }); // Gas money: STT to the session (native route — §3, recipient swapped). // 1 STT, not a sliver: Somnia's mempool admits a transaction only when the // balance covers the full fee envelope (10M gas ceiling × 60 gwei = 0.6 STT), // even though unused gas is never charged. const gas = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: parseEther("1"), recipient: session.address, }); // Working capital: HBTT to the session (collateral route — approve, then bridge). const capital = createBridgeTransfer({ token: BridgeToken.HBTT, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: parseEther("10"), recipient: session.address, }); // Each sendBridgeStep resolves once its transaction is CONFIRMED (§3), so the // approve-before-bridge ordering holds by construction. await sendBridgeStep(shannon, gas.bridgeStep, { account: userAccount }); // STT: native, no approval if (capital.approveStep) await sendBridgeStep(shannon, capital.approveStep, { account: userAccount }); await sendBridgeStep(shannon, capital.bridgeStep, { account: userAccount }); ``` Watch both deliveries land on Hideki — the STT with `getBalance` as in §3, the HBTT by polling the synthetic's `balanceOf` (delivery _mints_, so no destination liquidity is involved; remember the synthetic token **is** its router address): ```ts const hbttHideki = getBridgeToken(BridgeToken.HBTT, ChainId.hidekiTestnet)!; await hideki.readContract({ address: hbttHideki.address!, abi: erc20Abi, functionName: "balanceOf", args: [session.address], }); // 10000000000000000000n once the relayer delivers ``` **Spend as the session.** On Hideki it is just an account with a key — the bridged STT pays its gas, the synthetic HBTT is a plain ERC-20: ```ts await sessionWallet.writeContract({ address: hbttHideki.address!, abi: erc20Abi, functionName: "transfer", args: [friend, parseEther("4")], }); ``` **Send what's left home.** Synthetic → collateral needs **no approval** — the router burns the session's balance, and the Shannon router releases the collateral it escrowed on the way out: ```ts const home = createBridgeTransfer({ token: BridgeToken.HBTT, from: ChainId.hidekiTestnet, to: ChainId.somniaShannon, amount: parseEther("6"), recipient: userAccount.address, }); home.approveStep; // undefined — the bridge call alone, signed by the session await sendBridgeStep(hideki, home.bridgeStep, { account: session }); // Poll the canonical HBTT on Shannon for userAccount — it comes back +6. ``` The runnable version of this exact flow (delivery polling, shortfall-only minting, delta assertions) is the session round-trip test in `test/chains.live.e2e.test.ts` — see the next section. ## 5. Run the live test suites Two opt-in suites under `packages/sdk/test/` prove everything above against the real networks. Both skip silently unless their env var is set, so plain `pnpm test` / CI never touch the network. **Read-only** — verifies the registry against the live deployment and simulates the planner's calldata via `eth_call` state overrides. No key, no funds, nothing signed: ```sh cd packages/sdk SOMNIA_E2E_BRIDGE=1 pnpm test test/bridge.e2e.test.ts ``` **Live + signed** — `test/chains.live.e2e.test.ts` checks every chain definition against its endpoints (HTTP + WS chain ids, Multicall3, block cadence, explorer), then **spends**: it bridges ~0.05 STT in each direction with real keys, waits for the relayer to deliver, signs + revokes a real collateral-route approval, and runs the §4 session round-trip for real — derives a session, bridges STT and 10 freshly-minted HBTT to it, pays 4 HBTT to another Hideki wallet as the session, and bridges the remaining 6 home. Needs a funded key per network: ```sh cd packages/sdk SOMNIA_E2E_CHAINS_LIVE=1 \ SOMNIA_TESTNET_PK= \ HIDEKI_TESTNET_PK= \ pnpm test test/chains.live.e2e.test.ts ``` Keys are accepted with or without the `0x` prefix and are read from the environment only — never hardcode them. Budget ≥3 STT on Shannon and ≥1 STT on Hideki. Per run: the two accounts trade ~0.1 STT of bridged value (plus gas), 1 STT of gas money parks with the session account on Hideki (the seed is deterministic, so reruns reuse it), the Hideki account gains 4 HBTT, and the Shannon account nets +6 of the 10 HBTT it mints. If a delivery toward Shannon times out, check the STT router's balance on Shannon — a drained router is the expected failure mode, not a bug in the suite. ## 6. One exchange over both chains Everything above drives the two chains by hand: one client per chain, a plan, a sender. The exchange does the same as one object — configure both chains, and reads merge, writes route to the market's chain, and `exchange.bridge` / `exchange.ensureFunds` move collateral between them through the account's executors. See [EXCHANGE.md § One exchange, several chains](./EXCHANGE.md#one-exchange-several-chains) and [BRIDGE.md § Bridging through the exchange](./BRIDGE.md#bridging-through-the-exchange). ## 7. Where to go next - [CHAINS.md](./CHAINS.md) — the definitions in full: why absences are deliberate, parity with `viem/chains`, extending a definition with `defineChain`. - [BRIDGE.md](./BRIDGE.md) — route models (native/collateral/synthetic), the relayer as a liveness dependency, how every registry value was verified. - Generated API reference: `pnpm docs` in `packages/sdk` writes it to `docs/api/` (gitignored). - The deployment record behind the registry: [hyperlane-bridge-infra](https://github.com/somnia-chain/hyperlane-bridge-infra/blob/main/docs/deployments/somnia-testnet-hideki2-testnet.md). --- # /docs/typescript/native # Native RPC Somnia's node serves a `somnia_*` namespace alongside the usual `eth_*`. It exposes things the Ethereum-compatible surface has no field for — the native ledger block, chain statistics, reactivity subscription reads — plus **session transactions**, where the node holds the key, tracks the nonce, signs, retries, and hands back the receipt, so a client can transact with no signer at all. This module wraps exactly the twelve methods in the [public JSON-RPC reference](https://docs.somnia.network/developer/json-rpc-api) (as ten TypeScript methods: the by-hash and by-number block and receipt reads, and the two `isReady` variants, fold together), and nothing else — see [Not wrapped](#not-wrapped). ```ts import { createPublicClient, http } from "viem"; import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; import { createNative } from "@somnia-chain/markets-sdk/native"; const client = createPublicClient({ chain: somniaShannon, transport: http() }); const native = createNative(client); const block = await native.getBlock("latest"); console.log(block?.consensusBlock.proposerAddress, block?.executionBlock.executionGasUsed); ``` `createNative` takes anything with an EIP-1193 `.request` — a viem client, the markets client's (`createNative(exchange.client.getViemClient())`), or an injected wallet provider. It needs nothing else from the SDK. ## Why a wrapper Because these endpoints are easy to call wrong, and the node's reply when you do is a bare `-32602 invalid parameters` that tells you nothing. Two shapes surprise everyone, both confirmed against a live node: | You'd write | The node wants | | --------------------------------------- | ----------------------------------------------------------- | | `params: [1]` | `params: ["0x1"]` — block numbers are hex **strings** | | `params: [[1, 2]]` for subscription ids | `params: ["0x1", "0x2"]` — the ids **are** the params array | And what comes back is the node's C++ member names verbatim, with no case conversion — so blocks are `snake_case` (`consensus_block.block_number`) while statistics are `camelCase` (`numSuccessfulTransactions`), purely because that is how the two structs happen to be written. Quantities are hex strings. This module takes `bigint`s and tags, hex-encodes them correctly, and decodes the replies into one consistent camelCase surface with `bigint` quantities. Receipts go through viem's own `formatTransactionReceipt`, so a session receipt is the same `TransactionReceipt` the rest of your code already handles. A session receipt also carries `executionTimeMicros` (a `number`) when the node reports it: the node-side time from request to answer. The untouched wire shapes are exported as `Rpc*` types if you want them. ### Read the node's message, not viem's Somnia reports mempool rejections as JSON-RPC **`-32000`**, with the useful text in `message` and a `MempoolStatusCode` byte in `data`. viem maps `-32000` to its `InvalidInputRpcError`, whose display text is the generic **"Missing or invalid parameters."** So the obvious thing to log claims your parameters are wrong when the real problem is an unfunded account: ``` error.message "Missing or invalid parameters. Double check you have provided…" error.details "account does not exist" ← what the node actually said ``` `getSomniaRpcError` recovers it, and decodes the status byte: ```ts import { getSomniaRpcError, SomniaMempoolStatus } from "@somnia-chain/markets-sdk/native"; try { await native.sendSessionTransaction({ seed, gas: 21_000n, to, value }); } catch (error) { const rpc = getSomniaRpcError(error); console.error(rpc?.message); // "account does not exist" if (rpc?.mempoolStatus === SomniaMempoolStatus.nonceTooSmall) retryWithFreshNonce(); } ``` Branch on `mempoolStatus` rather than matching message text — `nonceTooSmall` is retryable, `insufficientBalance` needs funding, and `accountDoesNotExist` means the _sender_ has never existed, which is a third fix. The codes come from `MempoolStatusCode` in the node source, so the set is complete rather than the three we happened to trip over. **Nothing needs bypassing.** viem preserves the original: `BaseError`'s constructor inherits `details` from a `BaseError` cause, so the node's text propagates up the whole wrapper chain from the `RpcRequestError` that set it, and the raw `{ code, message, data }` object is still the innermost `cause`. `getSomniaRpcError` walks to it structurally — no `instanceof` against viem's classes, so it also works on an error from a plain `fetch`-based requester that never went through viem. This cost real time during live testing: a correctly-encoded session send read as a parameter error until the raw HTTP body showed `account does not exist`. ## Reads ```ts await native.isReady(); // false while syncing await native.getBlock("latest"); // tag, number, or 32-byte hash await native.getStatistics(blockNumber - 100n, "latest"); // aggregate activity await native.listPrivilegedReceipts("latest"); // protocol-issued txs (usually none) await native.listReactivitySubscriptionIds(owner); // → bigint[] await native.getReactivitySubscription(1n); // → one, or null await native.listReactivitySubscriptions([1n, 2n]); // → many, one round-trip await native.getNodePublicKeys(); // address + 2 keys + 2 proofs ``` `getBlock` and `listPrivilegedReceipts` accept a tag (`"latest"`, `"earliest"`, `"pending"`, `"safe"`, `"finalized"`), a block number, **or** a 32-byte hash — a 32-byte hex value dispatches to the by-hash RPC, anything shorter is a number. A **ledger block** is not the Ethereum block: it pairs the consensus half (proposer, timing, the data-chain blocks it commits) with the execution half (gas, receipts hash, state snapshot). Note `consensusBlock.timestamp` is unix **milliseconds** — Somnia blocks are ~100 ms apart, so seconds would be useless. `getNodePublicKeys` returns all five fields the node publishes: the address, the secp256k1 and BLS public keys, and the two proofs that bind them together (a BLS proof of possession and a proof of address). The proofs are what make the rest meaningful, so they are not dropped. ## Session transactions A session is a **32-byte seed**. The node turns it into a key pair, assigns the nonce, signs, submits, retries transient failures, and returns the receipt — one call instead of sign + send + poll. Useful when a client shouldn't hold a key at all: load generators, bots, game backends. ```ts import { createNative, sessionAddress } from "@somnia-chain/markets-sdk/native"; const seed = "0x…"; // 32 bytes, and a SECRET — see below // Where to send funds. Derived locally: no RPC, no node involved. const from = sessionAddress(seed); const receipt = await native.sendSessionTransaction({ seed, gas: 21_000n, // enough ONLY if `to` already exists — see gas, below to: recipient, value: parseEther("0.1"), }); console.log(receipt.status, receipt.transactionHash); ``` Six things to know before using it: - **The seed is a private key in another shape.** The derivation is public and deterministic — `sessionPrivateKey(seed)` computes the very key the node uses. Anyone who learns a seed can drain its account without touching the node. Guard it as a key. A failed call does not hand it back: `sendSessionTransaction` and `getSessionAddress` throw an `RpcError` instead of viem's error, whose message would print the request body — seed included. When the node answered, `cause` is its own `{ code, message, data? }` and `getSomniaRpcError` reads it as before; when the transport failed first, `cause` is `{ name, message, status? }` with the request text kept and the seed blanked out. - **Give a node-side session account gas dust only.** `sendSessionTransaction` puts the seed on the wire with every call, so any RPC endpoint, proxy or request log on the way can read it. Never make a node-side session address an owner of an account that holds funds. For that, sign locally: `createExecutor({ privateKey: sessionPrivateKey(seed) })`, or `exchange.accounts.accountFor(accountId, index, { sessionSeed })` across chains. The SDK refuses a `createExecutor({ sessionSeed })` executor as the `inner` of a smart account. - **Pre-fund the account.** Use `sessionAddress(seed)`; an unfunded session cannot pay gas. `native.getSessionAddress(seed)` asks the node the same question if you want confirmation (the two are asserted equal by the live test suite). Note the node rejects a send from an account that has never existed with `account does not exist` (mempool code `0x02`), not with an out-of-gas. - **Paying a brand-new address costs ~30× the Ethereum figure.** Somnia has to bring the account into existence, and `21_000` is not enough: the transaction **reverts with `status: "reverted"` having consumed the entire limit**, and the recipient is not credited. Measured on Hideki, first payment to a fresh address: | gas limit | outcome | gasUsed | | ---------- | -------------------------------- | ------------------- | | `21_000n` | reverted, recipient not credited | 21,000 (all of it) | | `100_000n` | reverted, recipient not credited | 100,000 (all of it) | | `700_000n` | success | 421,000 | `eth_estimateGas` quotes ~631,500 for such a transfer. A second payment to the same address costs the ordinary 21,000. Since the node does not estimate for you, budget by whether the recipient already exists — and treat a `reverted` receipt whose `gasUsed` equals the limit as "the limit was the problem". - **The nonce space is shared** with `eth_sendRawTransaction` from the same address. Sending both ways at once corrupts the sequence — pick one per account. An address that signs locally (through `accountFor` or `sessionPrivateKey`) must not also send here. - **It blocks until the receipt exists.** The node retries with backoff, so a call can take a while; give the transport a generous timeout. There is no fire-and-forget variant. Omit `to` to deploy a contract, with `data` as the init code. The send goes out with transport retries **disabled** (`retryCount: 0`). viem retries a failed request three times by default, and the node's failures (a node-side ceiling, a full mempool) look retryable — so a default retry could submit the same transfer again under a fresh nonce. One attempt; the node already retries internally where that is safe. A missing receipt **throws** rather than resolving to `null`: a receipt is the whole contract of the call. Sessions live in the serving node's memory: they are not shared between nodes, and are rebuilt from the seed after a restart. Nothing is persisted, and the derived key is never written to disk. ### Deriving locally ```ts sessionAddress(seed); // the address, offline sessionPrivateKey(seed); // the key itself — sign locally instead of trusting the node ``` The algorithm is `keccak256(seed ‖ uint64_le(i))` for `i = 0, 1, 2, …`, taking the first candidate inside `[1, n-1]`. In practice `i = 0` always wins: a keccak output falls outside the curve order with probability under 2^-128. This is pinned against the node for four different seeds in `test/native.e2e.test.ts` — if Somnia ever changed its derivation, every funded session address would move, and that test is what would catch it. ## Not wrapped The wrapped set is the [public JSON-RPC reference](https://docs.somnia.network/developer/json-rpc-api). A node build serves more than that, but an undocumented endpoint is not part of the contract — it can change shape or vanish between node versions, and one of them is outright hazardous. All of them stay reachable via `native.request(...)`, which is the point: stepping off the documented surface should be a decision, not an accident. **`somnia_getStorageDatabaseEntries` — undocumented and dangerous.** Its handler loops over the caller's key list with no cap on the number of keys and no bound on the size of each value returned, so one request can make a node dump unbounded data. **A 256-key request took the public Shannon testnet down on 2026-07-31** (discovered by this SDK's own live testing). It is also not what the name suggests to an Ethereum developer: keys are node-internal `StorageKeyType` discriminants — one byte, or one byte plus a 32-byte body, where byte 0 must be a member of that enum — not contract storage slots. For those, `eth_getStorageAt` is the method you want. A malformed key is an **error**, not a miss. **`somnia_getProtocolParameters` — undocumented.** The key set is node-version dependent and its values are plain JSON numbers rather than hex quantities, so wrapping it would mean publishing a shape that cannot be kept stable. Reach it with `native.request("somnia_getProtocolParameters", ["latest"])` if you need it; that is how the account-creation gas figure below was read. **Operator-only** (`kProtected` on the node) — a public endpoint answers `{ code: -1, message: "unauthorized" }`, which `isUnauthorized(error)` recognises **by message**, not by code. That matters: `-1` is the node's default error code, shared with `invalid range`, `could not load statistics` and `Block does not exist` (all confirmed live), so keying on the code would report a bad block range as an auth failure. The methods: `somnia_connectToPeer`, `somnia_dumpMemory`, `somnia_createTransactionLog`, `somnia_byteStringBenchmark`. If you _are_ the operator, reach them with `native.request("somnia_dumpMemory")`. **Validator plumbing** — `somnia_submitBatchedTransaction` and `somnia_submitMerkleBatchSignature` carry smash-encoded consensus structs a JS caller can't construct. Not exposed. **`eth_sendRawTransactionSync`** (EIP-7966; Somnia's older name for it is `realtime_sendRawTransaction`) is not a `somnia_*` method, and it is already the SDK's write path: a local-signer write sends through it and gets its receipt in one round-trip (see the [engine guide](./ENGINE.md)). No need to call it yourself. ## Nodes that don't have these Every method here is node-version dependent, and a stock geth or a local anvil has none of them. Degrade instead of breaking: ```ts import { isMethodNotFound } from "@somnia-chain/markets-sdk/native"; const stats = await native.getStatistics("earliest", "latest").catch((e) => { if (isMethodNotFound(e)) return null; // not a Somnia node — hide the panel throw e; }); ``` Everything else throws: a failed read never resolves to `null`. `null` appears in exactly two places, both genuine by-id misses — an unknown block and an unknown subscription id. `isReady()` returns a boolean. `isReady({ withErrorCode: true })` calls the node's error-code variant, which **throws** on a not-ready node instead of returning `false` (that is the point of the variant — a health check keys on the error), so it never returns `false`. ## Where these come from The method list is `somnia/api/handlers/somnia_api_handlers.h` in [somnia-chain/somnia2](https://github.com/somnia-chain/somnia2), and session transactions are specified in its `docs/session_transactions.md`. Both were read — and then every endpoint was called against a live Shannon node, because the wire and the C++ types disagree in ways that matter (the field-name inconsistency above, and `token()`-style traps like a params array that is not what the signature suggests). `test/native.test.ts` pins the encodings offline against captured payloads; `test/native.e2e.test.ts` re-checks them against a real node: ```sh SOMNIA_E2E_NATIVE=1 pnpm test ``` --- # /docs/typescript/reactivity # Reactivity Somnia pushes events to you **with the state that goes with them**. That is the whole idea: on any other EVM chain, reacting to an event is "see the log, then fetch the state" — two round trips, racing the next block. Here the notification carries the log _and_ the results of a fixed set of `eth_call`s executed at that same block. This module is a **pointer, not a port**. The implementation is [`@somnia-chain/reactivity`](https://github.com/somnia-chain/reactivity) — the upstream repo owns the protocol, the Solidity side (`SomniaEventHandler`, in `@somnia-chain/reactivity-contracts`) and the client. `@somnia-chain/markets-sdk/reactivity` re-exports that package verbatim and adds only the glue a markets consumer needs, so there is no second copy of the ABIs or the validation rules to drift out of step. ```ts import { createReactivity, unwrap } from "@somnia-chain/markets-sdk/reactivity"; ``` ## Install `@somnia-chain/reactivity` is an **optional peer dependency** — exactly like `react` is for the `/react` entry. Only callers of this subpath install it: ```sh pnpm add @somnia-chain/reactivity ``` Both `@somnia-chain/reactivity` and `@somnia-chain/markets-sdk` (from 0.20.0) are on the public npm registry; no `.npmrc` scope configuration is needed. ## What this entry adds | Export | Why it isn't upstream | | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `createReactivity(client, { wallet? })` | builds the reactivity client from the markets client's viem client: reads and receipt waits reuse it; `watch` opens its own WebSocket from `chain.rpcUrls.default.webSocket[0]` | | `unwrap(result)` | upstream _returns_ `Error` objects; this SDK throws instead, so a failure stops the caller | | `SOMNIA_REACTIVITY_PRECOMPILE_ADDRESS` | not exposed by upstream's published build | | `DEFAULT_SUBSCRIPTION_OPTIONS` | the protocol's own `SomniaExtensions.DEFAULT_*` values: upstream ships them at runtime but omits them from its `.d.ts`, so they can't be re-exported with types (a test pins ours against upstream's) | | `isLocalPrecompileUnavailable(chainId)` | already lives in this package; the check to run before any Solidity subscription | Everything else — `Reactivity` / `SDK`, `SomniaReactivityPrecompileABI`, `SomniaEventHandlerABI` and every type — is upstream's, re-exported. A test asserts the re-exported classes are upstream's own identity, so this can never quietly become a fork. ## Two flavours - **WebSocket reactivity** (`watch`) — a TypeScript subscription over the socket (`somnia_watch`). Each matched log arrives with your `eth_call` results from the same block. Nothing on-chain, nothing to pay for, gone when you disconnect. - **Solidity reactivity** (`subscribe`) — a subscription registered _on-chain_ against the reactivity precompile, which makes validators call your handler contract's `onEvent(address,bytes32[],bytes)` when a matching log lands. Callbacks are paid out of the subscription owner's native balance (which must hold at least 32 SOMI/STT). This protocol already runs on the second one: `OracleHub` is the Solidity handler the precompile calls for `OracleCore.AnswerPosted`, and MarketCreator rolls are scheduled subscriptions. The admin `enableReactivity` and `setReactivityGasParams` methods configure these subscriptions. This module points the same primitive at _your_ contracts. ## Markets event emitters For `watch`, set `eventContractSources` to the emitter's address and `topicOverrides[0]` to the exact event's topic0. For an on-chain `subscribe`, set `filter.emitter` to that same address and `filter.eventTopics[0]` to the topic0 of the **exact** event signature. A handler or caller address is not automatically the log emitter. Use the SDK's matching-chain `config.addresses` for configured singletons and `smart-contracts/deployments///addresses.json` for `OracleCore.address`. An existing receipt's `log.address` identifies its actual emitter. The SDK's testnet and mainnet address presets come from those manifests; other venues can have different `MarketCreator` instances; the module's `MarketCreated` event carries the `creator`. Historical oracle answers may come from an older OracleCore deployment, so use the core that emitted those logs. | Event signature | Emitting contract | Filter address | | ------------------------------------------------------------------------ | ---------------------------------------------------------------- | ------------------------------------------------ | | `MarketCreated` (series, 13 arguments) | `MarketCreator` on a series roll | Venue's `marketCreator` | | `MarketCreated` (module, 20 arguments) | `BinaryMarketsModule` on every creation, including a series roll | `binaryModule` | | `AnswerPosted(uint256,uint8,string,int256,bool,uint8,uint256[])` | `OracleCore`, not the receiving `OracleHub` | Matching manifest's `OracleCore.address` | | `Resolved(uint32,uint256[])` / `Voided()` | Individual `BinaryMarket` | Market's `marketAddress` | | `MarketFinalized(bytes32,address,uint256)` | `BinaryMarketsModule`; carries `marketId` | `binaryModule` | | `MarketFinalized(uint256,address,uint64,address,uint256,bool,uint256[])` | `BinarySettlement`; carries `netBacking` | `binarySettlement` | | `PoolFinalized(uint64,uint256)` | Individual `BinaryPool`; carries `marketNonce` | Market's `poolAddress` and indexed `marketNonce` | | `PoolReleased(bytes32,address,address)` | `BinaryMarketsModule` | `binaryModule` | | `Redeemed(uint256,address,address,uint8,uint256,uint256)` | `BinarySettlement` | `binarySettlement` | A series roll can produce both `MarketCreated` events for one `marketId`. Their canonical signatures for topic0 are: ```text MarketCreated(bytes32,address,address,uint256,uint256,address,string,uint256,uint64,uint64,uint256,string,uint64) MarketCreated(bytes32,address,address,uint256,uint32,bytes32,address,address,uint256,uint256,uint64,uint8,uint8,uint64,uint64,uint8,string,uint256,string,bytes) ``` The pool can later serve another market; match `PoolFinalized` topic1 (`marketNonce`) to the selected market's `nonce`, as well as the pool address. For example, on Shannon (50312), a `watch` for settlement `netBacking` uses `eventContractSources: [SOMNIA_TESTNET_ADDRESSES.binarySettlement]`; an on-chain subscription uses `filter.emitter: SOMNIA_TESTNET_ADDRESSES.binarySettlement`. Both use the seven-field settlement `MarketFinalized` topic0 `0xb1884334e955f8d8727678d4fa52dd9fc7140ff5e4ad38d358453bd400ada178` (`topicOverrides[0]` or `filter.eventTopics[0]`). The three-field module event's topic0 is `0x8f396ac6cf2e01887362e2b39d8e56860042c604e5b1b481c87e6d9f90006e08`; filtering it at the settlement address silently matches nothing. The Shannon settlement proxy in `50312/testnet-development` is `0xbF4a49e0Dfd092e5FBE8E5761064C49533e6Ed23`. Use the installed SDK's matching-chain deployment addresses, not an implementation address or an address copied from another chain. Oracle question IDs are scoped to an oracle deployment. A Shannon market (50312) links its ID to `https://dev.oracle.somnia.host/questions/`. A mainnet market (5031) links its own ID to `https://prd.oracle.somnia.host/questions/`. The same number is not a cross-host key. These are question pages, not the `price-feed.*` GraphQL endpoints. Verify the host for any other chain before constructing a question link. ## Watching (TypeScript) `createReactivity` hands upstream the markets client's public client for reads and receipt waits; `watch` itself opens a second WebSocket to the same chain (see the note below): ```ts import { SomniaMarkets } from "@somnia-chain/markets-sdk"; import { createReactivity, unwrap } from "@somnia-chain/markets-sdk/reactivity"; import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; const exchange = new SomniaMarkets({ chain: somniaShannon, wsRpcUrl, indexerUrl }); const reactivity = createReactivity(exchange.client); // Every Transfer on the collateral token, with the sender's new balance read // at the very same block — one notification, no follow-up call. const watch = unwrap( await reactivity.watch({ eventContractSources: [collateral], topicOverrides: [transferTopic], ethCalls: [{ to: collateral, data: balanceOfCalldata }], onData: (n: ReactivityNotification) => console.log(n.result.simulationResults), }), ); await watch.unsubscribe(); ``` > **Use a chain definition from [`/chains`](./CHAINS.md).** Upstream's `watch` > opens its own socket with viem's `webSocket()` _without a URL_, so the endpoint > comes from `chain.rpcUrls.default.webSocket[0]`. viem's own `somniaTestnet` has > no WebSocket entry, so `watch` fails on it; every definition in > `@somnia-chain/markets-sdk/chains` carries one. Notes that matter in practice: - **Every filter is optional, and omitting one means "everything".** A bare `{ ethCalls: [], onData }` tails every event on the chain. - **`ethCalls` is the point.** Batch several reads into one call against Multicall3 where you can — the notification is only as fast as the calls it carries. `simulationResults` comes back in the order subscribed. - **`context`** splices event-sourced values into the `ethCalls` calldata (`topic1`…`topic4`, `data`, `address`), so one subscription can read state _about the thing that just happened_ rather than a fixed address. - **`onlyPushChanges`** suppresses notifications whose call results match the previous ones — a cheap way to watch for a _state_ change rather than an event. - **The payload is at `notification.result`** — `{ address, topics, data, simulationResults }`. Upstream's README and type docs say `notification.params.result`, one level deeper; that is stale, because viem's WebSocket transport unwraps the JSON-RPC envelope before calling `onData`. Type the callback with `ReactivityNotification` (upstream types it `any`) — the shape is asserted against a live node in `test/reactivity.e2e.test.ts`, which runs with `SOMNIA_E2E_WS` set. This is a different tool from `client.watchMarket`: the markets tail materializes the order book from indexed protocol events, while `watch` is a general-purpose log+state subscription for anything on the chain. ## Subscribing (Solidity) Deploy a handler extending `SomniaEventHandler` (from `@somnia-chain/reactivity-contracts`), then register it. The signer becomes the subscription **owner** and its balance funds every callback: ```ts import { createReactivity, unwrap, DEFAULT_SUBSCRIPTION_OPTIONS } from "@somnia-chain/markets-sdk/reactivity"; const reactivity = createReactivity(exchange.client, { wallet: walletClient }); const hash = unwrap( await reactivity.subscribe({ handlerContractAddress: handler, filter: { emitter: collateral, eventTopics: [transferTopic] }, options: DEFAULT_SUBSCRIPTION_OPTIONS, }), ); ``` Upstream validates the precompile's preconditions before spending gas — a non-zero handler, well-formed `bytes32` topics, at least one narrowing filter (a match-everything subscription is rejected), `0 < gasLimit <= 200_000_000`, `maxFeePerGas >= priorityFeePerGas + 6 gwei` (or `0` to skip that check), and the owner holding ≥ 32 SOMI/STT. Note that writes need a **wallet client**: pass one to `createReactivity`, or upstream's write silently resolves to `null`. Upstream sends each write on the wallet's chain, so the wallet must be on the engine's chain. When `wallet.chain` is set to another chain, `createReactivity` throws `InvalidInputError`. A wallet with no `chain` is not checked. On a multi-chain exchange, pass `exchange.engineFor(chainId)` instead of `exchange.client`. Cancel with `unsubscribe(subscriptionId)` (owner only), read one back with `getSubscriptionInfo(subscriptionId)`, and use `subscribeRaw` when you need the precompile's full struct including the protocol-reserved fields. ## Scheduling — cron, blocks, epochs The precompile emits its own system events (`Schedule`, `BlockTick`, `EpochTick`), so "call me later" is just a subscription to one of them with the tick as a topic filter: ```ts await reactivity.scheduleSubscriptionAtTimestamp({ timestampMs: Date.now() + 60_000, handlerContractAddress, options }); await reactivity.scheduleSubscriptionAtBlock({ blockNumber: head + 100n, handlerContractAddress, options }); await reactivity.scheduleSubscriptionAtEpoch({ epochNumber: 7n, handlerContractAddress, options }); ``` `scheduleSubscriptionAtBlock` with **no** `blockNumber` leaves the block topic a wildcard — a callback on _every_ block. Timestamps are unix **milliseconds** and must be at least a second out; a block must be past the head. ## Errors Upstream methods resolve to `T | Error` instead of throwing. Two ways to live with that, both fine: ```ts // 1. this SDK's contract — throw (recommended) const hash = unwrap(await reactivity.subscribe({ ... })); // 2. upstream's own idiom — check const result = await reactivity.subscribe({ ... }); if (result instanceof Error) throw result; ``` ## Local development The precompile does not exist on anvil or hardhat — check `isLocalPrecompileUnavailable(chainId)` before offering Solidity subscriptions in a UI, and note that it has no bytecode on _any_ chain, so `eth_getCode` can't probe for it. `somnia_watch` is a node feature too: a plain anvil node doesn't serve it. Test reactivity against Shannon (or Elwood/Hideki). --- # /docs/typescript/engine # The engine (advanced) This guide tours the **engine tier** — the raw `SomniaMarketsClient`: bigint-exact, address-keyed. It is not a second entry point: you reach it through the exchange — ```ts const exchange = new SomniaMarkets({ indexerUrl, chain, wsRpcUrl }); const client = exchange.client; // the engine: exact raw-unit reads + watches const trader = exchange.trader; // the raw write tier (needs a signer) ``` Most applications stay on **[the exchange API](./EXCHANGE.md)** itself; the engine is the tier for exact escrow math, custom reads, and anything the exchange verbs don't cover. An engine is bound to ONE chain — one config, one socket, one watch/store, one nonce lane. **Multi-chain is one exchange over several engines**: configure `chains: [...]` and the exchange builds an engine per binding. `exchange.engineFor(chainId)` and `exchange.traderFor(chainId)` reach each chain's engine and raw write tier. On a multi-chain exchange, `exchange.client` and `exchange.trader` throw `InvalidInputError`, because they name no chain. Every `UnsignedCall` a build verb returns names its `chainId`, so a call is never sent on the wrong chain. **Who signs is pluggable.** `client.createTrader({ executor })` takes any `Executor`; `client.createExecutor(spec)` builds the built-ins — a private key or local account, a wallet client, a Somnia session seed, or a factory smart account from `@somnia-chain/accounts-sdk` (`{ smartAccount, inner }`). A smart account sends an approval and its order as one account transaction, with no batching configuration. `through` reaches an account owned by other accounts. The lifecycle around it is `client.accounts`; see [Smart accounts](./ACCOUNTS.md). The writer decodes the order from the receipt the executor returns and never fetches it again; `decodePlaceOrder` / `decodeAmendOrder` / `decodeAmendOrders` are the same decoders, exported for a receipt you obtained yourself. **Retry rule for every executor.** When a send times out, its socket drops, or its receipt wait fails after the transaction left, the built-in executors throw `TransactionOutcomeUnknownError` with the transaction's `hash` (a session send has none). The transaction can still mine. Look up `hash`, or read the state the write changes, before you send the write again. A refusal the node answered stays a plain `RpcError` or `ContractRevertError`. A safe or smart-account executor passes the inner executor's error through, so `hash` is the outer transaction's hash. A custom executor gets the same pass-through from `asExecuteError`, but `asExecuteError` never creates this error: only the code that sent the transaction knows that it may have left. A custom executor that sends raw transactions constructs the error itself. For market-kind specifics, see the [binary markets](./BINARY.md) and [spot](./SPOT.md) guides. ## The three read tiers Every read on the client belongs to one of three tiers. The `getLive*` prefix marks the first; for the other two the method's API reference names its source (`getMarket`, `getFills`, `getOpenOrders` are indexer reads; `getMarginAccount`, `getPerpState` are chain reads). The method name tells you which — and the tier tells you the freshness and the cost: | Tier | Methods look like | Backed by | Cost & freshness | | -------------- | --------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------ | | **Live store** | `getLive*` (synchronous) | in-memory materialization of **watched markets** | zero round-trips, current to the last block | | **Chain** | `get*Onchain`, `getBinaryOrderBook`, balances | `eth_call` over the socket | one round-trip, current to head | | **Indexer** | `list*`, `getCandles`, `getPortfolio`, … | GraphQL (HTTP) | one or bounded multiple round-trips; lags the chain slightly | Rule of thumb: **anything that gates an action reads the live store or the chain; the indexer is for history and aggregates.** Indexer reads throw on request failure — an empty result always means "no rows", never "it broke". ## Errors — branch on the type, never the message Every failure the SDK raises is a typed class exported from the barrel, all extending `SomniaMarketsError`. Catch the family, or branch on the member: ```ts import { ContractRevertError, IndexerError, IndexerWaitTimeoutError, NotConfiguredError, } from "@somnia-chain/markets-sdk"; try { await exchange.createOrder("BTC-95000-31DEC26/USDC#YES", "limit", "buy", 25, 0.62); } catch (e) { if (e instanceof ContractRevertError) { // The chain rejected it. `errorName` is the contract's OWN error. if (e.errorName === "ExpiredOrderMustBeCancelled") await cancelFirst(); else if (e.errorName === "InsufficientBalance") await topUp(); else throw e; } else if (e instanceof IndexerError) { retryLater(); // the read didn't complete — never "no rows" } else if (e instanceof NotConfiguredError) { throw new Error(`missing config: ${e.what}`); // a deploy/config bug, not runtime } else throw e; } ``` Handle an indexer wait separately so the timeout branch wraps the method that can actually raise it: ```ts const targetBlock = 1_234_567n; // the confirmed transaction's block try { await exchange.client.waitForIndexedBlock(exchange.client.config.chain.id, targetBlock); } catch (e) { if (e instanceof IndexerWaitTimeoutError) { retryLater(); // the indexer answered but has not processed targetBlock yet } else if (e instanceof IndexerError) { retryLater(); // the metadata read did not complete } else throw e; } ``` | Class | Means | Your move | | --------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------- | | `InvalidInputError` | Bad argument, unknown symbol, wrong market kind (thrown before any I/O) | Fix the call | | `NotConfiguredError` | A needed address/URL was never passed (`what` names it) | Fix the config | | `SignerRequiredError` | The method writes; this client has no signer | Construct with a signer | | `CollateralOnWrongChainError` | `chainId`, `code`, `needed`, `held`, `shortfall`, `elsewhere`, `plan?` | The order's collateral sits on another configured chain | | `BridgeLiquidityError` | A native route's destination router cannot pay out; nothing was sent | Wait for the router to be seeded / bridge less | | `BridgeDeliveryTimeoutError` | A bridge was sent but its message was not delivered in time; `messageId` names it | Check `delivered(messageId)` before sending again | | `IndexerWaitTimeoutError` | The indexer stayed behind the requested block until the deadline | Wait longer / read chain | | `IndexerError` | An indexer read did not complete | Retry / degrade | | `IncompleteHistoryError` | Portfolio analytics could not read every indexed fill | Raise or omit `maxFillPages` / investigate a cycle | | `IndexerUnavailableError` | The SDK refused the read locally — `reason` says which gate | Branch on `reason` (see its TSDoc) | | `FillHistoryUnavailableError` | The indexer has no initialized fill-dataset generation | Deploy and reindex a compatible producer | | `FillHistoryRestartRequiredError` | A fill-page cursor belongs to another serving generation or predates generation binding | Discard pages; restart at page one | | `RpcError` | A node request did not complete, or the node refused a transaction | Read: retry / switch RPC. Write: check the chain first | | `TransactionOutcomeUnknownError` | A signed write may have reached the node; its receipt was not observed (`hash`) | Look up `hash` before sending again | | `ContractRevertError` | The chain rejected the call — `errorName` + `args` | Branch on `errorName` | | `InvariantError` | The SDK contradicted an invariant established by its own control flow | Report the SDK defect | Three things worth knowing: - **Revert names come from the contracts.** The SDK bundles every custom error the protocol declares and decodes revert data against it, so a failed write reports `MarketNotSettled` rather than hex. When the data matches nothing known you still get a `ContractRevertError`, with the raw `reason`/`data` preserved. - **A mined-but-reverted transaction throws.** You don't need to check `receipt.status` yourself; the SDK replays the call to recover the reason first. - **`cause` is always chained.** The original viem/fetch error is there for logs. - **Never match on `error.message`** — messages are not a stable API. Branch on the class and its fields (`errorName`, `what`, `operation`). ## Watches — scoped, ref-counted live data Nothing is streamed by default. You open a **watch** on what you care about, and the client becomes a local indexer of exactly that scope: ```ts const watch = await client.watchMarket(pool); // one market: book, fills, orders, status const book = client.getLiveBinaryOrderBook(pool); // synchronous, zero round-trips, last-block fresh // ... trade against it ... watch.stop(); // release (ref-counted, brief linger) ``` - [`watchMarket(pool)`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#watchmarket) — hydrates a consistent snapshot of that market (its row, recent fills, full resting book) and streams its events from the chain WebSocket. Resolves once reads are live. This is the right default: cost scales with what you watch, not with the protocol. - [`watchMarkets({ discover? })`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#watchmarkets) — every SPOT and PERP market and every BINARY market that is not finalized, for list views and multi-market bots. One snapshot hydrates at most 500 of them, newest first; when more exist, `getLiveStatus().allMarketsTruncated` is `true`. Read a finalized BINARY market with `getBinaryMarket(id)`. `discover: true` also watches the creation events (the `MarketCreator` factory AND `BinaryMarketsModule.createMarket`) so newly created markets — rolling-series or module-created — join live. - [`watchUser(user)`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#watchuser) — hydrates one account's order/fill _history_ (live events are attributed to every account automatically within watched markets). - [`getWatchStatus(pool)`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getwatchstatus) — `"unwatched" | "hydrating" | "live"`; this is how you distinguish "the book is empty" from "I'm not watching this pool". Watches are **ref-counted**: two watchers of the same pool share one snapshot and one subscription, and a released scope lingers ~30s before teardown so quick re-watches don't re-snapshot. If the socket drops, watches heal themselves — resubscribe with backoff, then backfill the missed blocks straight from chain (the indexer is only ever touched to hydrate a _new_ scope). While a market is watched, these answer synchronously with zero round-trips: [`getLiveBinaryOrderBook`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivebinaryorderbook) / [`getLiveSpotOrderBook`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivespotorderbook) (the resting book — **the one to render or quote against**), [`getLiveFills`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivefills) (tape), [`getLiveUserFills`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getliveuserfills) / [`getLiveUserOrders`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getliveuserorders) (one account's activity), [`getLiveMarkets`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivemarkets) / [`getLiveMarketByPool`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivemarketbypool) / [`getLiveMarketByAddress`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivemarketbyaddress) (market rows with live status + stats), and [`getLiveStatus`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlivestatus) (global health). Reactivity without React: [`subscribeLive`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#subscribelive) fires after every batch of changes — re-read whatever you need inside the callback: ```ts const watch = await client.watchMarket(pool); client.subscribeLive(() => { const { yesBids, yesAsks } = client.getLiveBinaryOrderBook(pool, { depth: 5 }); requote(yesBids, yesAsks); // runs within ms of the on-chain event }); ``` ## React Provide the client once; the hooks read it from context and **watch automatically** — rendering a market's book is what subscribes to it, and unmounting releases it: ```tsx import { SomniaMarketsProvider, useLiveBinaryOrderBook, useLiveFills, useWatchUser, } from "@somnia-chain/markets-sdk/react"; function App({ children }) { return {children}; } function Terminal({ pool, account }: { pool: string; account?: string }) { useWatchUser(account); // hydrate the user's history once const book = useLiveBinaryOrderBook(pool, 11); // auto-watches `pool` while mounted const tape = useLiveFills(pool, 40); // shares the same watch (ref-counted) // ... } ``` The live-store hooks: `useLiveBinaryOrderBook`, `useLiveBinaryOrderBookByMarket`, `useLiveSpotOrderBook`, `useLiveFills`, `useLiveUserFills`, `useLiveUserOrders`, `useLiveFundingUpdates`, `useLiveMarketByPool`, `useLiveMarketByAddress`, `useLiveMarkets`, `useLiveStatus`, `useIsTailing`, plus the explicit `useWatchMarket` / `useWatchUser` and `useSomniaMarketsClient`. The price (`useWatchPrice`, `useLivePrice`, `useLivePriceTicks`, `useLivePriceFeedInfo`), funding (`useFundingRateSeries`), lend (`useLendReserves`, `useLendAccount`) and directory (`useMarketCreators`, `useOracleAdapters`) hooks are listed in the API reference. Every pool-keyed data hook holds a ref-counted watch on its pool while mounted; `useWatchMarket` also returns the pool's `WatchStatus` for loading UI. For the **indexer** tier (history + directories, not the live store) there is a generic engine hook — `useIndexerQuery(fn, deps)` runs `fn(client)` on mount and whenever `deps` change, tracks `{ data, loading, error, refetch }`, and discards stale responses: ```tsx const { data: markets } = useIndexerQuery((c) => c.listBinaryMarkets({ limit: 20 }), []); ``` Concrete wrappers over the common reads: `usePortfolio`, `useMarkets`, `useCandles`, `useMarketFees`, `useOperators`. Separately, `useLiveMarkets` is the zero-round-trip live-store view of every watched market (pair it with a discovery watch), not an indexer fetch. ## Chain reads — head-fresh, no watch required One `eth_call` round-trip over the client's socket (concurrent calls pipeline): - [`getMarketOnchain`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getmarketonchain) — a BinaryMarket's full wiring + state. **Authoritative for write eligibility** (status, resolution), and works before the indexer has ever seen the market. - [`getBinaryOrderBook`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getbinaryorderbook) / [`getSpotOrderBook`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getspotorderbook) — the book from the contract; the one-shot fallback (or checksum) for the live variants. - [`getErc20Balance`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#geterc20balance) / [`getNativeBalance`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getnativebalance) — raw balances (use these, not indexer balances, to gate a write). - `getBalances(tokens, account)` — batch multi-token balance read (one round-trip for a whole wallet); `getOutcomeBalance({ outcomeToken, account, id })` — a single ERC-6909 outcome-id balance (the on-chain point read behind the indexer's `getOutcomeBalances`). - `getErc20Metadata(token)` / `getErc20Allowance(token, owner, spender)` — token name/symbol/decimals and a spender allowance (gate an `approve` on it). - `getContractMeta(address, { proxy })` — contract/proxy introspection; and `getMaxVenueFeeBps()` — the protocol's hard fee-rate cap (bps). - Perp margin health — `getMarginAccount` (now including `imReq`/`mmReq`/`cmReq`/ `marginStatus`), `getAccountHealth`, and `getLiquidationPrice` (all `MarginBank` reads); see [perps](./PERPS.md). - `getVaultBalance({ vault, owner, token })` — the LIVE claimable balance behind the append-only `getVaultPayoutFallbacks` credit log (vault credits emit no event, so the current balance must be read from chain). - [`getHeadBlock`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getheadblock), [`getStopOrderSomiPayment`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getstopordersomipayment), [`getSystemInfo`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getsysteminfo). ## Indexer reads — history and aggregates These are the only methods that touch the indexer besides a watch's initial snapshot. Most point and list reads below make one GraphQL round-trip; `getTradeContext` makes two because its second query depends on the first query's fill. The Ops section identifies the other exception: `waitForIndexedBlock` repeats a metadata query until the indexer reaches the target block or the wait deadline expires. - Markets: [`listMarkets`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listmarkets), [`getMarket`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getmarket), and the binary-narrowed [`listBinaryMarkets`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listbinarymarkets) / [`listLiveBinaryMarkets`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listlivebinarymarkets) / [`listPastBinaryMarkets`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listpastbinarymarkets) / [`getBinaryMarket`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getbinarymarket). - History: [`getCandles`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getcandles) (OHLCV, chart-ready), [`getFills`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getfills), and the account-scoped `getOrders(owner, opts)` (an owner's order history → `OrderRow[]`), `getUserFills(account, { market })` (an account's fills → `FillRow[]`; scope by `market` rather than `pool` on binary, where one pool is recycled across successive markets), and `getMarketStatusHistory(marketId)` (a market's lifecycle transitions). - Single-entity detail (the explorer's order/fill pages run on exactly these): [`getOrder`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getorder)`(pool, orderId)` — one order with owner + full lifecycle attribution (`OrderDetail`; ids never reuse, so the pair is a permanent name), [`getFill`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getfill)`(id)` — one fill by its `${block}_${logIndex}` id with both parties' order linkage (`FillDetail`), and [`getOrderFills`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getorderfills)`(pool, orderId, { limit })` — every fill one known order participated in, either side, as a bounded whole-history lookup. It accepts only `limit` and does not take `sinceBlock`; resume a pool or account tape by passing `sinceBlock` to `getFills` or `getUserFills`. All three embed a `MarketRef` (symbols + decimals + routing identity) so a detail view renders from one read. - Every fill of one market kind in a BLOCK RANGE, across every pool of that kind: [`getFillsPage`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getfillspage)`({ marketType, sinceBlock, toBlock })`. The read behind a published trade feed: it takes no pool, both bounds include their block, and rows arrive oldest first by `(blockNumber, logIndex)`, so successive ranges tile the chain exactly where a `since`/`until` window in seconds cannot. [`getLatestFillBlock`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getlatestfillblock)`(marketType)` is the head marker to bound it with — read from the fill data, so it never names a block the range read cannot serve. - ONE transaction in full: [`getTransactionActivity`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#gettransactionactivity). The same event union as `getMarketActivity`, selected by transaction hash and ordered forwards, plus the orders placed, the fees paid and the markets touched. Empty for a hash that touched no protocol contract. - ONE trade IN CONTEXT: [`getTradeContext`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#gettradecontext). `getFill` above names one fill and its market in a single query; this adds the surrounding context — both orders resolved, the fees its transaction charged, and that transaction's other fills — in two GraphQL round-trips. Returns `null` for an unknown id. Use it behind a trade detail page that shows the counterparties; use `getFill` when rendering the trade alone. - One market's whole transaction history: [`getMarketActivity`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getmarketactivity). It reads what `getFills` reads and four more streams — complete-set mints and merges, redemptions, oracle resolution, lifecycle transitions — and returns them interleaved by time as one discriminated union, in one round-trip. Use it for a market page's activity panel; use `getFills` when only trades matter. Every row names its transaction hash. A spot or perp market yields `TRADE` rows only, because the other four streams read binary-only entities. - Wallet views: [`getPortfolio`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getportfolio) (binary positions + orders + trades in one round-trip), [`getSpotPortfolio`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getspotportfolio), [`getSpotStopOrders`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getspotstoporders), [`getOpenOrders`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getopenorders), [`getOutcomeBalances`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getoutcomebalances). - Control plane: [`listOperators`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listoperators) / [`getOperator`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getoperator) / [`listVenues`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#listvenues) / [`getVenue`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getvenue) — the indexed MarketsCore operator/venue directory (venue ids are opaque bytes32; decode a BINARY_V1 venue's fee bytes with `decodeBinaryVenueFeeParams`). - Fee / resolution / router history (binary): `getMarketResolution`, `getRouterActions`, `listProtocolFees` / `listBuilderFees` / `listSettlementFees` (per-fill streams behind `getMarketFees`, filterable by `payer`), `listBuilderApprovals`, `getVaultPayoutFallbacks` — see [binary markets](./BINARY.md). - Perp account plane: `getFundingPayments`, `getMarginEvents`, `listLiquidations`, `listFundingRateHistory`, `listFundingRateCandles`, `getOpenInterestHistory` — the append-only history the chain doesn't expose; see [perps](./PERPS.md). - Lookups + totals: `getMarketByPool` (resolve a market by pool address) and `listMarketsByPool(pool)` (every market the pool has HOSTED, newest first — a binary pool is recycled across successive markets, so this is its full history; also `getSeries(creator, seriesId)` for one rolling series' current spec, the single-row sibling of `listSeries`), `countOrders` / `countUserFills` (history-page totals), and the board totals `countMarkets` / `countBinaryMarkets` / `countVenues` / `countOperators` (each takes the same filter as its `list*` sibling — use for pagination headers). `CANDLE_INTERVALS` is the exported bucket list `getCandles` accepts. - Ops: [`getSyncStatus`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getsyncstatus) — how far behind the indexer itself is, and [`waitForIndexedBlock`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#waitforindexedblock) — poll until it has processed a block, so a write can be read back from the index rather than after a guessed delay. Each poll sends one GraphQL round-trip. Two of these have faster live twins a trading loop should prefer: `getOpenOrders` → `getLiveUserOrders`, `getFills` → `getLiveFills`. ## The network tape — every order on the network, live ```ts const tape = client.createNetworkTape(); const stop = tape.subscribe(() => { render(tape.bids, tape.fills, tape.asks, tape.getStatus()); }); // … stop() closes the socket when the last listener unsubscribes. ``` [`createNetworkTape`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#createnetworktape) returns a [`NetworkTape`](https://prd.smk.somnia.host/docs/typescript/api/index/classes/NetworkTape) — a network-WIDE order-flow firehose: one topics-only chain-log subscription that sees `OrderPlaced` / `OrderFilled` from **every** pool (including pools created after it starts), no indexer on the hot path. It is not the live tail: no books, no snapshots — three newest-first ring buffers (`bids` / `fills` / `asks`) plus a session `(pool, orderId) → owner` map that attributes fills (takers always resolve — their placement follows the fill in the same tx; makers resolve when quoted while the tape ran, else `null`). Rows carry RAW units; join to `listMarkets` for symbols/decimals. Nothing connects until the first `subscribe`, and reconnect/stall handling (Somnia's silently-dying WS subs) is built in. For enriching a tape row's transaction, [`getTransactionSummary`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#gettransactionsummary)`(hash)` is the chain-direct companion: sender, gas used/limit, effective gas price, fee paid, status. It resolves to null for a malformed hash and for a transaction the node reports as not found. A read that does not complete throws `RpcError`, so an outage stays distinct from a transaction that never landed. ## Writes — `createTrader` ```ts const trader = client.createTrader({ privateKey }); // or { walletClient } in the browser const { orderId, fills } = await trader.placeOrder({ pool, side: "BUY_YES", price, quantity }); ``` [`createTrader`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#createtrader) binds a signer to this client's chain, fees, and socket and returns a [`Trader`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/Trader). The trader is **independent of the watches** — a pool's escrow tokens resolve from the pool contract itself (one cached read) when you don't pass them. With a local key the SDK signs locally with fixed fees and a fixed gas ceiling. Before each local send, it reconciles the pending nonce and serializes nonce consumption, signing, and broadcast acceptance. Some orders also need prerequisite funding reads or an approval transaction. `eth_sendRawTransactionSync` returns the mined receipt; every write resolves only once mined, with that receipt (and, for orders, the decoded `orderId` + `fills`). Market-kind specifics: [binary markets](./BINARY.md#trading), [spot](./SPOT.md#trading). Every write result also carries `executionTimeMicros` when the node reports it. It is the time in microseconds from the node receiving the send to its answer, and it covers mempool, finality and execution inside Somnia. The local-signer and session-key executors read it from the receipt that `eth_sendRawTransactionSync` and `somnia_sendSessionTransaction` return. It is absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. A custom executor can set it on `Executed` to pass it on. For the MarketsCore control plane there is a second, low-frequency write tier: `client.createOperatorAdmin({ privateKey })` returns an `OperatorAdmin` with `registerOperator`, `updateOperator`, `createVenue` (venues are typed by a `bytes4` market-type id — `MARKET_TYPE_BINARY_V1` — and get a contract-generated `bytes32` venue id back), `updateVenue`, `setVenueEnabled`, and the two-step operator-ownership transfer. Build a BINARY_V1 venue's fee bytes with `client.encodeBinaryVenueFeeParams({...})`. ## Escape hatch [`getViemClient()`](https://prd.smk.somnia.host/docs/typescript/api/index/interfaces/SomniaMarketsClient#getviemclient) returns the underlying viem WebSocket client for any read the SDK doesn't cover — your own contracts, or plain calls like `getBalance` / `getCode` / `waitForTransactionReceipt`. Same socket, same pipelining: a client of your own would open a second connection, and one-socket-per-client is deliberate here. **It is undecorated, and that is the point.** Every read reachable from the client interface goes through a _wrapped_ viem client. Its `readContract`, `call`, `multicall`, and `getBlockNumber` methods rethrow as [typed SDK errors](https://prd.smk.somnia.host/docs/typescript/api/index/classes/ContractRevertError). A revert arrives decoded, as its Solidity name. The client this method hands you does **not** do that: reads keep viem's own error contract, so `e instanceof ContractFunctionRevertedError` and the rest of your existing viem error handling still work. Pick accordingly. For a _protocol_ contract, prefer the SDK's own methods — the decoding is the value, and on a contract the SDK doesn't bundle the decoder can only report `errorName: undefined` anyway. For anything else, this is the door. **It belongs to the current connection.** `stopLive()` and `close()` close the socket the client uses. After that, requests on a client you kept reject with viem's `SocketClosedError`; the client does not reconnect. Call `getViemClient()` again after `stopLive()` to get a client on the new connection. --- Next: [binary markets](./BINARY.md), [spot](./SPOT.md), [perps](./PERPS.md), and the [architecture guide](./ARCHITECTURE.md) for how the machine works inside. --- # /docs/typescript/architecture # Architecture The SDK connects a configured `SomniaMarkets` owner to the main indexer, chain RPC, and a separate price-feed service. This page explains where live state comes from and which resources each capability uses. Market watches hydrate indexed snapshots and then apply chain events locally. This keeps repeated store reads synchronous, while startup, recovery, historical reads, and price feeds still have network costs. Watches limit materialization work to the scopes the application uses. - [System overview](#system-overview) - [The client](#the-client) - [Watches: the snapshot seam + chain materialization](#watches) - [Event routing and the reducer](#event-routing-and-the-reducer) - [The local order book](#the-local-order-book) - [Connection lifecycle](#connection-lifecycle) - [The write path](#the-write-path) - [Choosing a read](#choosing-a-read) ## System overview The exchange owns its `SomniaMarketsClient`. The main Envio/Hasura indexer supplies historical reads and market/user snapshots over HTTP GraphQL. The engine's lazy chain WebSocket carries its chain reads, log/head subscriptions, backfills, and sends. Price feeds use a separate Hasura service over HTTP and one shared Hasura socket per client and endpoint. Watches that start together hydrate in batched snapshot requests. Their `PriceStore` is separate from the market `MaterializerStore`. A subscribed network tape owns another chain socket. These capabilities do not share one universal realtime connection. ```mermaid flowchart LR subgraph app["Your app"] hooks["React hooks
useLiveFills, useLiveBinaryOrderBook, …"] node["Node / server code
bots, scripts, RSC"] end subgraph client["the engine (exchange.client)"] direction TB query["query.ts
one-shot indexer reads
listMarkets · getCandles · getPortfolio ·
getFills · getMarketResolution · getRouterActions ·
listProtocolFees · getFundingPayments · …"] reads["reads.ts / system.ts
one-shot chain reads
getBinaryOrderBook · getMarketOnchain ·
getAccountHealth · getLiquidationPrice ·
getVaultBalance · getErc20Balance · …"] subgraph live["live watches"] tail["liveTail.ts
watch registry + ingestion
ref-counted scopes · subscribe ·
backfill · seam"] reducer["reducer.ts
event → state
mirror of the indexer handlers"] store["store.ts
MaterializerStore
markets · orders · fills ·
book levels · status
versioned, memoized selectors"] end prices["priceFeed/
HTTP reads + asset watches
separate PriceStore"] tape["networkTape.ts
caller-owned activity tape
separate chain socket"] trader["trade.ts
writes
sign local · fixed fees ·
sync send"] end subgraph backends["Backends"] indexer["Envio / Hasura indexer
HTTP GraphQL
history · aggregates ·
cold-start snapshot"] feed["Price-feed Hasura
HTTP + one shared WebSocket"] chain["Somnia chain
engine WebSocket + separate tape sockets
eth_subscribe logs+heads ·
eth_call · getLogs ·
eth_sendRawTransactionSync"] end hooks -- "useSyncExternalStore" --> store node -- "getLive* (sync)" --> store node -- "await client.*" --> query node -- "await client.*" --> reads node -- "createTrader(…)" --> trader query -- "POST /v1/graphql" --> indexer prices -- "hydrate/fetch HTTP + subscriptions" --> feed hooks -- "price selectors" --> prices tape -- "own logs + heads subscription" --> chain tail -- "cold scope hydration
(again after teardown)" --> indexer tail -- "watchEvent · watchBlocks ·
getLogs (seam backfill)" --> chain reads -- "eth_call (pipelined)" --> chain trader -- "eth_sendRawTransactionSync
(send + receipt, 1 RTT)" --> chain tail --> reducer --> store ``` Key properties: - **Scoped.** Live materialization is opt-in per market via ref-counted watches. Cost — snapshot size, subscription filter width, event volume, reducer work — scales with what you watch, not with the protocol. - **One engine per chain, one exchange per account.** The engine tier (`SomniaMarketsClient`) is bound to exactly one chain: one socket, one indexer, one nonce lane. The exchange (`SomniaMarkets`) owns one engine per configured `ChainBinding`, merges reads across them, and routes each write to the chain its market lives on. A market is unique to one chain, so a symbol resolves to one `(chainId, market)` and every returned struct names its `chainId`. - **Isolation.** Every exchange owns its own config, stores, watches, and (lazily opened) sockets. Two exchanges never share state — per-request watches and parallel tests all just work. Two engines inside one exchange never share state either: each keeps its own nonce sequence and fee envelope. - **Shared engine chain transport.** Engine subscriptions, reads, backfills, and sends use its memoized chain transport. Parallel requests can overlap, but dependent reads, pagination, and cache misses still affect cost. Price watches and network tapes have separate sockets. - **Indexer startup dependency.** A new market or user scope needs indexed data to hydrate. After a successful market seam, chain events update that scope and chain backfill repairs reconnect gaps. A scope that was torn down needs hydration again. One-shot history and derived reads can continue to request the indexer while watches run. ## The client ```mermaid flowchart TB cc["new SomniaMarkets(config)"] --> ex["SomniaMarkets (exchange)"] -- ".client" --> pc["SomniaMarketsClient (engine)"] pc --> l1["live watches
watchMarket · watchMarkets · watchUser ·
getWatchStatus · stopLive · subscribeLive
getLiveStatus · getLiveMarkets · getLiveMarketByPool/ByAddress
getLiveFills · getLiveUserFills · getLiveUserOrders
getLiveBinaryOrderBook · getLiveSpotOrderBook"] pc --> l2["indexer reads (Promise, throw on failure)
listMarkets · getMarket · listBinaryMarkets · getBinaryMarket
getCandles · getFills · getMarketActivity · getOpenOrders · getOutcomeBalances
getPortfolio · getSpotPortfolio · getSpotStopOrders · getSyncStatus"] pc --> l3["chain reads (Promise)
getBinaryOrderBook · getSpotOrderBook · getMarketOnchain
getErc20Balance · getNativeBalance · getHeadBlock
getStopOrderSomiPayment · getSystemInfo"] pc --> l5["price feeds
fetchPrice · fetchPriceHistory · watchPrice
separate HTTP, Hasura sockets, and PriceStore"] pc --> l4["writes
createTrader({privateKey | account | walletClient | executor})
→ placeOrder · cancelOrder · placeSpotOrder ·
placeSpotStopOrder · mintSet · burnSet · redeem · …"] ``` The socket opens lazily on first chain I/O, so an indexer-only client (e.g. server-side GraphQL reads) never opens the engine chain socket. The mirror case holds too: `indexerUrl` is optional, so a chain-only client (smart accounts, executors, on-chain reads) constructs without one, and every indexer read or live watch on it throws `NotConfiguredError` naming the field. An individual chain read never makes an indexer request either way. ## Watches A market watch materializes its scope locally: it hydrates a consistent snapshot of that scope from Envio up to block X, then materializes X+1.. directly from chain logs. Scopes are ref-counted (two watchers of one pool share everything) and torn down after a short linger when the last handle stops. The seam is gap-free and double-count-free: ```mermaid sequenceDiagram autonumber participant App participant Tail as LiveTail (watch registry) participant Idx as Indexer (GraphQL) participant WS as Chain WebSocket participant Store as MaterializerStore App->>Tail: watchMarket(pool) Tail->>WS: eth_subscribe logs (+ pool) · newHeads Note over Tail,WS: the scope's logs BUFFER from this instant —
nothing past the head can be missed Tail->>Idx: scope snapshot (HTTP GraphQL) Note over Idx: the market row · recent fills ·
its full resting order set ·
chain_metadata.latest_processed_block = X Idx-->>Tail: rows consistent to block X Tail->>Store: mergeSnapshot (other scopes untouched) Tail->>WS: widen subscription (+ the market's
BinaryMarket address, now known) Tail->>WS: eth_getLogs [X+1 … head] for the scope WS-->>Tail: backfill logs Tail->>Store: decode → reduce → commit Tail->>Tail: replay the scope's buffered logs
(deduped by (block, logIndex)) Tail-->>App: watchMarket resolves — reads are live loop live — every block WS-->>Tail: pushed logs + head Tail->>Store: decode → reduce → commit (one notify per batch) Store-->>App: subscribers re-read (hooks re-render) end ``` `watchMarkets({ discover })` is the same seam with scope = every eligible market — SPOT, PERP, and BINARY markets that are not finalized, at most 500 per snapshot, with `allMarketsTruncated` set when more exist. When discovering, it also watches the creation-event sources: the MarketCreator factory AND the BinaryMarketsModule. `watchUser(user)` is snapshot-only (the account's past orders/fills — it opens no subscription of its own, and updates only from markets this client watches). Logs for a scope that is mid-hydration buffer in an inbox while other scopes keep applying live — one scope's seam never stalls another. Why this is safe on Somnia specifically: blocks have **instant BFT finality** — a delivered log is final, so there is no reorg handling. The dedupe set keyed by `(blockNumber, logIndex)` makes the buffer/backfill overlap harmless. Somnia logs carry no timestamp, so the `newHeads` stream doubles as the timestamp source (block number → timestamp map, pruned as the head advances). ## Event routing and the reducer One combined ABI (`liveEventsAbi`) decodes every watched log; the reducer routes by **event name + source address** and mutates the store exactly the way the Envio handlers mutate Postgres (`reducer.ts` mirrors `indexer/src/handlers/orderbook.ts` — keep them in lockstep): ```mermaid flowchart TB log["raw log from WS / backfill"] --> dec{"decodeEventLog
(liveEventsAbi)"} dec -- "source = a pool
(spot OR binary — byte-identical events)" --> ob["OrderBook events"] dec -- "source = a SpotPool" --> spot["spot-only events"] dec -- "source = MarketCreator /
BinaryMarketsModule" --> fac["MarketCreated"] dec -- "source = a BinaryMarket" --> bm["lifecycle events"] ob --> op["OrderPlaced → upsert order
(binary: side from isBid+userData, born Open;
spot: no side, born Closed)"] ob --> orst["OrderRested → rested=true
(spot: Closed → Open)"] ob --> ofill["OrderFilled → write LiveFill ·
patch maker order · bump market stats
(lastPrice, volumes, tradeCount)"] ob --> oc["OrderCancelled / OrderExpired /
OrderCancelledSelfMatch /
OrderReduced → patch order"] ob --> bk["SetMinted / SetBurned / Redeemed /
SettlementFeeCharged → market backing"] spot --> mp["MarkPriceUpdated → market.markPrice"] spot --> bp["OrderBookParametersUpdated →
tickSize · lotSize · minQuantity"] fac --> nm["build BinaryMarket row →
indexMarket → GROW the watch set →
catch-up getLogs for the creation range"] bm --> st["StatusChanged → status enum"] bm --> res["Resolved → status + winningOutcome"] bm --> vd["Voided → voided + status"] ``` Two ordering subtleties the reducer encodes: - **`OrderFilled` fires before the taker's `OrderPlaced`** in the same tx, so the taker is unknown at fill time. The fill stores `takerOrder_id` / `makerOrder_id` foreign keys; read-time selectors back-join owner + side from the order map (hydrated by the snapshot's open orders and live events). - **`MarketCreated` grows the discovery watch live.** Two creation events are watched. The `MarketCreator` factory rolls each series autonomously (a Somnia reactivity `Schedule` sub drains the due boundary's series in a gas-bounded loop, spilling to the next block when a batch is too large), emitting its 13-field `MarketCreated(marketId, market, pool, yesId, noId, collateral, asset, strike, tradingStart, expiry, oracleQuestionId, question, intervalSec)` — the trailing `intervalSec` is the series cadence (60 / 300 / 900 / 3600 / 14400 / 86400). The `BinaryMarketsModule` emits its own 20-field `MarketCreated` for EVERY market (rolled or created directly via `createMarket`) — the only creation event carrying the `(operatorId, venueId)` origin attribution — so module-created markets that never pass through a `MarketCreator` are discovered too. When an all-markets watch with `discover` is active, the tail re-subscribes with the new pool + market addresses and sweeps the creation range with a one-shot `getLogs`, so a market created seconds ago is fully tailed — the indexer is never asked again. ## The local order book The store _is_ the book. Every resting order is tracked through its lifecycle, so depth is an in-memory aggregation. Reading a hydrated book costs **zero round-trips** and reflects the events applied to that scope. Disconnection or recovery can leave it behind the head: ```mermaid flowchart LR subgraph store["MaterializerStore.orders"] o1["order: Open + rested
price 620000 · qty 50"] o2["order: Open + rested
price 620000 · qty 25"] o3["order: Open + rested
price 610000 · qty 10"] o4["order: Filled / Cancelled /
not rested → ignored"] end store --> agg["bookLevels(pool, depth)
group by (isBid, price) · sum qty ·
sort best-first · slice depth"] agg --> spotbook["getLiveSpotOrderBook
{ bids, asks }"] agg --> yes["YES-terms levels"] yes --> inv["toBinaryBook( )
NO side = 1 − yesPrice
(quantities carry over)"] inv --> binbook["getLiveBinaryOrderBook
{ yesBids, yesAsks, noBids, noAsks }"] ``` This matches the on-chain `getBookLevels` exactly because binary pools keep a _single_ book in YES terms — a NO order is expressed as `isBid`/`userData` with a YES-terms price, which is also how orders arrive in `OrderPlaced` events. The one-shot chain reads (`getBinaryOrderBook`/`getSpotOrderBook`) remain available as a separate source for callers that need a fresh node read. Stake and sell quotes also read a cached chain tick/lot grid and can resolve a missing pool through the main indexer; see [Read tiers](reference/read-tiers.md). Completeness note: live-witnessed orders are always present; orders that rested _before_ the watch opened come from the scope snapshot's open-order set — and because snapshots are per-scope, that set is the market's whole resting book, not a global cap's share of it. ## Connection lifecycle The following state machine describes market live-tail subscriptions. It does not describe price feeds or network tapes. Main-indexer hydration uses HTTP. The live tail relies on pushed chain logs and heads, with chain backfill for recovery. The live tail checks stalled heads every 15 seconds. After a stall it can request the chain head and reconnect if the subscription missed progress or the probe fails. A subscribed network tape checks for stalls every 5 seconds and has its own chain socket and recovery. These timers add background work; the SDK does not guarantee zero polling. ```mermaid stateDiagram-v2 [*] --> idle idle --> hydrating: first watchMarket / watchMarkets hydrating --> live: scope snapshot + backfill + replay OK hydrating --> reconnect_wait: snapshot / backfill failed live --> hydrating: new watch opens (its scope only —
existing scopes keep streaming) live --> reconnect_wait: WS error or stalled-head probe detects failure reconnect_wait --> live: resubscribe + getLogs
[lastBlock+1 … head] — CHAIN ONLY,
the indexer is not consulted note right of reconnect_wait exponential backoff 500ms → 1s → 2s → 4s → 8s (cap) reset to 500ms once live end note live --> idle: last watch released
(after a ~30s linger) live --> live: blocks stream in ``` Reconnects never re-snapshot: the store already holds state to block L, so the seam is simply `getLogs [L+1, head]` deduped against what's processed — chain truth heals chain gaps. This recovery path does not request the main indexer. A new or fully released scope still needs hydration, and one-shot indexer reads remain independent. Price watches first hydrate over the price-feed HTTP endpoint, then subscribe on one shared Hasura socket per client and endpoint. Watches that start together hydrate in batched snapshot requests. They keep a separate store and connection status. A rejected subscription sets `getPriceStatus(asset)` to `error` and retains stale price values; it does not fail market watches. Price scopes also linger for about 30 seconds after the last handle stops. `exchange.close()` releases its watches and channels and stops the client's market and price live machinery. One-shot fetches remain usable. `exchange.unwatchMarket(symbol)` releases one market's watch and channels and keeps the exchange open. Its live-tail scope then lingers like any other. A network tape returned by `createNetworkTape` is caller-owned. Release each subscription with its returned unsubscribe function; the last release closes the tape socket. Its lifecycle is separate from the exchange watches. ## The write path Two signer modes, one rule: **gas is not estimated and receipts are not polled.** ```mermaid sequenceDiagram autonumber participant Bot as Caller participant T as Trader (trade.ts) participant WS as Chain WebSocket rect rgb(235, 245, 235) Note over Bot,WS: LOCAL SIGNER (privateKey / account) — the fast path Bot->>T: placeOrder({pool, side, price, quantity}) Note over T: resolve funding requirements
uncached ERC-20 approvals may read + send;
native spot sells read the current vault shortfall Note over T: reconcile pending nonce;
serialize nonce consumption, signing,
and broadcast acceptance;
use fixed fees + fixed gas ceiling T->>WS: eth_sendRawTransactionSync(signedTx) Note over WS: node executes, blocks server-side
until the receipt exists WS-->>T: receipt WITH logs Note over T: decode OrderPlaced → orderId
decode OrderFilled → fills[] T-->>Bot: { hash, receipt, orderId, fills } end rect rgb(240, 240, 250) Note over Bot,WS: BROWSER SIGNER (injected walletClient) Bot->>T: placeOrder(…) T->>WS: eth_sendTransaction (wallet signs, fixed fees pinned) WS-->>T: tx hash T->>WS: getTransactionReceipt (immediate check) Note over T,WS: on miss: eth_subscribe newHeads —
re-check on each pushed head, first hit wins.
No poll, no timeout — socket errors reject. WS-->>T: receipt T-->>Bot: { hash, receipt, orderId, fills } end ``` An uncached (token, spender) pair does one `allowance` read. A short allowance causes one `approve(maxUint256)` transaction and then enters the cache. An existing effectively unlimited allowance also enters the cache. A finite allowance remains uncached because an order can consume it. The next order then reads the pool requirement and allowance again. Before each local write, viem reconciles the node's pending nonce with its in-memory offset. The trader serializes local nonce consumption, signing, and broadcast acceptance. One failed write therefore cannot invalidate a concurrent write's nonce reservation. A signer or broadcast failure resets the manager only after every earlier local write has reached a terminal send result. Measured on Somnia testnet with the `sdk-e2e` write suite (`E2E_WRITE=1`, which writes a gitignored `latency-report.md`): `placeOrder` confirm p50 ≈ **503ms**, within ~25ms of the raw transport floor. ### Spot funding preconditions The approval cache records only effectively unlimited allowances. A finite allowance is never cached, so the next order reads it again after the current order may have consumed it. Spot orders ask the pool for its exact fee-aware funding requirement when an approval check is needed. A native-base sell does that read every time so it can send only the current vault shortfall. ## Choosing a read Read selection depends on both the source and its startup state. [Read tiers](reference/read-tiers.md) contains the canonical Engine inventory, request costs, and method-specific exceptions. | You want | Use | Source and freshness | | --------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | A book for frequent rendering | `getLiveBinaryOrderBook` / `getLiveSpotOrderBook` / hooks | Main-indexer hydration, then applied chain events. Synchronous after startup; inspect watch status during recovery. | | Live trade tape or user orders | `getLive*` / hooks | Market store. User hydration adds history; updates cover watched markets only. | | Market state from the node | `getMarketOnchain` | Chain RPC at the block served by the node. | | Candles, portfolios, historical fills, or market activity | `getCandles` / `getPortfolio` / `getFills` / `getMarketActivity` | Main indexer; delay is variable. | | A market list without watches | `listMarkets` / `listBinaryMarkets` | Main indexer; indexed rows can lag discovery. | | Raw balances or wiring | `getErc20Balance` / `getSystemInfo` | Chain RPC; composite reads may make multiple calls. | | Oracle price history or streaming prices | `fetchPriceHistory` / `watchPrice` / price hooks | Separate price-feed Hasura service and PriceStore; values can be stale during errors or disconnection. | Derived reads can combine sources. For example, Exchange `fetchTicker` uses cached market metadata, indexed candles, and best-effort perp chain state. Both the candle read and the perp read are contained, and `statsState` and `perpState` report which of them answered. Its timestamp is response time. Engine `getOpenPositionsWithPnL` and `getClaimable` use indexed inputs, so neither guarantees current chain state. Choose an action's inputs with these limits in mind. React's `useIndexerQuery` invokes a caller-supplied callback on mount, owner/dependency changes, and `refetch`. It does not poll or automatically refresh on live events. The callback chooses the source; the hook does not certify freshness. It passes an abort signal and ignores superseded results, while request cancellation depends on the callback forwarding the signal. --- # /docs/typescript/migrating # Migrating This guide explains breaking SDK changes and the required migration steps. Each entry lists affected consumers in this repository. The same steps apply to external consumers that use those features. Only breaking changes appear here. Everything else is in the [changelog](../CHANGELOG.md). **0.31.0 was not published to npm.** A consumer on 0.30.0 moves directly to 0.32.0. Apply both sections below, in order: first 0.30.0 → 0.31.0, then 0.31.0 → 0.32.0. ## 0.30.0 → 0.31.0 This section has fifteen entries. Entries 1 to 12 cover the twelve breaking changesets queued for 0.31.0. Entries 13 and 14 cover two breaking changes that the 0.31.0 changelog did not mark as breaking. Entry 15 is a note, not a breaking change: it corrects earlier documentation about nonce handling. Three entries need attention even if your code compiles: - Registry read failures no longer throw from `loadMarkets()` (entry 5). - `getCandles` selects a field that does not exist on an indexer deployed before this release. **Reindex before you upgrade** (entry 8). - A `walletClient` adapter that implements only `writeContract` fails every write (entry 13). ### 1. Executor calls and wallet errors **Was:** `{ to, data, value, description }`. **Now:** `{ chainId, to, data, value, description, functionName? }`. Add the target `chainId` when you construct a call. SDK `build*` methods already set it. Built-in executors throw `InvalidInputError` before signing if the call names another chain. `functionName` is optional and supplies context for error messages. SDK-built calls include it. ```ts // before const call = { to: pool, data, value: 0n, description: "place" }; // after const call = { chainId: 50312, to: pool, data, value: 0n, description: "place" }; ``` **Affected:** custom relayers, bundlers, and fixtures that construct calls. The `call()` fixture in `packages/sdk/test/executor.test.ts` constructs these objects and already includes `chainId`. #### Wallet-client pre-send rejections **Was:** `"writeContract"`. **Now:** `"sendTransaction"`. The wallet executor sends an encoded transaction. Update checks for its operation name to `"sendTransaction"`. The error class and other fields are unchanged. **Affected:** code matching `err.operation === "writeContract"` for a wallet rejection. **No consumer in this repository branches on `RpcError.operation`.** ### 2. `BinaryMarket.strike` and `BinaryMarket.mode` are nullable **Was:** both always present. **Now:** both `| null`. Chain-seeded rows do not supply these fields. They can be `null` when you use `watchMarket(pool, { seed: "chain", marketId })`. Indexer rows still supply both. Check for `null` before use. The type change applies even if you do not use chain seeding. **Affected:** code reading `BinaryMarket.strike` or `.mode`. In this repository, the explorer uses them in `src/lib/seriesQueries.ts` and `src/components/clob/SeriesHistory.tsx`. ### 3. `FillRow` gains two required fields **Was:** no remainder fields. **Now:** `takerRemainingQuantity` and `makerRemainingQuantity`, both required. `getFills` and `getUserFills` return the quantities remaining after a fill. Add both fields to fixtures, mocks, or other code that constructs a `FillRow`. Code that only reads rows needs no change. **Affected:** in this repository, **the explorer** (`src/lib/orderFill.ts`) and **sdk-e2e** (`test/fills.test.ts`, `test/query.test.ts`). All of these read rows rather than build them, so they are affected only if they pin the row shape. ### 4. Failed reads throw instead of reporting absence Four reads now throw for transport failures instead of returning absent or zero values. Transport failures raise `RpcError`. Contract reverts raise `ContractRevertError` except for the documented capability checks below: - `getClosingPrice` — `null` means the pool does not declare `closingPrice()`. Catch errors to handle failed reads. - `tryGetPerpLeverageImSurcharge` — `null` only for a revert from the view itself. In a health sweep, catch per account and report that account as unknown rather than as having no surcharge. - `getSystemInfo` — configured contract read failures now throw instead of returning zero values. For pre-v2 modules without `settlement()`, the result uses the configured `binarySettlement` address, or `null` if none is configured. These fields are no longer nullable: `MarketCreatorInfo.owner`, `SystemInfo.oracle.owner`, `SystemInfo.oracle.binaryModule`, `SystemInfo.usdc.symbol`, and `SystemInfo.usdc.decimals`. Keep null checks on the `marketCreator`, `oracle`, and `usdc` objects: they remain `null` when their contracts are not configured. - `getTransactionSummary` — `null` only for a malformed hash, or a transaction the node reports as not found. To keep the previous best-effort behavior, add `.catch(() => null)` at the call site. `PriceFeedStatus` gains `"error"` for subscriptions the server rejects or terminates. Previously, the status stayed `"live"` with a stale price. Reads still return the last known values, so check the status before displaying them. Handle `"error"` in `getPriceStatus` and `useWatchPrice` consumers. The debug channel also emits a `warn`. Restart the watch to request a fresh snapshot. ### 5. Registry read failures use `registryReadError` **Was:** `loadMarkets()` threw when the registry read failed. **Now:** it reports the failure through `registryReadError`. This lets chain-based perp discovery continue when a factory is configured. Check the accessor after loading. Pass `true` to retry instead of using the cached registry. ```ts await exchange.loadMarkets(); if (exchange.registryReadError) { // Force a registry refresh. await exchange.loadMarkets(true); } if (exchange.registryReadError) throw new Error("market list may be short"); ``` Replace `try`/`catch` checks for registry outages with an accessor check. Without it, a failed registry read can look like a successful load. **Affected:** every `loadMarkets()` caller. In this repository: **market-taker** (`src/shared.ts`, called from `src/index.ts`) and **sdk-e2e** (`test/unified.test.ts`). For the four reads, any caller treating `null` or `0` as "failed" needs to catch instead. ### 6. Registry rows require `updatedAtBlock` **Was:** `IndexedOperator` and `IndexedVenue` had no block marker. **Now:** both require `updatedAtBlock: bigint`. Add this field to fixtures, mocks, or adapters that construct registry rows. Use `0n` in a fixture when its block number is irrelevant. The operator and venue list/get methods already supply it, so code that only reads rows needs no change. The marker tracks control-plane events, not trading rollups. Updates in the same block share a marker. A malformed wire value fails the whole read with `IndexerError`. **Affected:** code that constructs either row type. In this repository, `packages/sdk/test/registryRowUpdateBlock.test.ts` covers the field. Explorer readers include `src/components/operators/OperatorManagePanel.tsx` and `src/components/operators/VenueRow.tsx`; they receive the field from SDK reads. Check external adapters and mocks for object literals missing it. ### 7. Fill reads gain a block range, and a cross-pool fill read **Was:** `getFills(pool, …)` read one pool and `getUserFills(account, …)` read one account across pools, both bounded by `since`/`until` in seconds. No read returned every fill of a market kind. **Now:** `client.getFillsPage({ marketType, sinceBlock, toBlock })` is that read — every fill of one kind in an inclusive block range, across every pool, oldest first by `(blockNumber, logIndex)`. It takes no pool, so a consumer never enumerates them. The existing reads gain the same bounds through `FillsOptions.sinceBlock` and `.toBlock`. Both block bounds include their block, and `(blockNumber, logIndex)` totally orders the fill table, so `[a, b]` followed by `[b + 1, c]` reads every fill exactly once. Prefer the block range whenever successive reads must tile the chain: several Somnia blocks share a timestamp, so a seconds window drops or repeats the fills in them at every seam. An inverted range now rejects with `InvalidInputError` rather than answering with no rows. `client.getLatestFillBlock(marketType)` names the newest block carrying an indexed fill of that kind. It reads the fill data rather than the indexer's processed-block watermark, so it never returns a block `getFillsPage` cannot yet serve. Page through `nextCursor`. A full page always returns one, because an indexer row limit can truncate a page silently, so a range ending exactly on a page boundary costs one empty final page. A cursor binds the chain, endpoint, kind and both bounds, and is refused by any other range. **Affected:** implementations of `SomniaMarketsClient` other than the SDK's own must add `getFillsPage` and `getLatestFillBlock`. Consumers that only call the client are unaffected; the seconds window still works. In this repository the interface is implemented only inside the SDK; `packages/sdk/test/fillBlockRange.test.ts` covers the new reads. ### 8. `Candle` gains a required `lastFillId` — reindex first **Was:** no fill-level watermark on a bucket. **Now:** `lastFillId`, the id of the newest fill folded into the bucket, in the same `${blockNumber}_${logIndex}` key space as a fill's own id. **This one has an operational prerequisite.** `getCandles` selects `lastFillId`, so it errors against an indexer whose schema predates the field. Deploy the matching `indexer/schema.graphql` and run a full reindex **before** upgrading the SDK. Constructing `Candle` values yourself? Add the field. Read-only consumers just receive it, and gain the watermark needed to reconcile an open OHLCV bucket against the chain without a second fills read. **Affected:** every `getCandles` caller operationally, through the reindex — that half applies whether or not you read the field. In this repository **the explorer** receives it and deliberately drops it: `src/lib/candleTip.ts` types its chart rows as `Omit`, because a display bucket is not a cursor and its fold does not maintain one. Worth copying if your own derived types would otherwise promise a watermark they do not keep accurate. ### 9. Order reads carry `userData`, and stricter input validation **Was:** order rows carried no correlation tag; invalid runtime inputs reached the indexer. **Now:** `getOpenOrders` and `getOrders` return each row's `userData` as a decimal string, and it is required on constructed `OpenOrder` and `OrderRow` values. `OrdersOptions.userData` filters on that tag, so a client correlates rows with the orders it sent instead of keeping its own map. `OrdersOptions.market`, `.pools` and `.markets` scope a read the way the fill scope already did; an empty array matches nothing, a list caps at 100 entries, and supplying a singular scope alongside a list intersects both. Reads now reject bad input before any network I/O, with `InvalidInputError`: an empty owner on `getOpenOrders`, `getOrders` and `countOrders`, an empty account on `getUserFills` and `countUserFills`, a malformed order id on `getOrderFills`, and, on fill reads, a market, markets or pool identifier that is empty or not a string. Code that relied on those calls answering with no rows now sees an error instead. `sinceBlock` also bounds order reads, where it bounds the **placement** block — it does not report a later amend, fill or cancel of an order placed before the bound. `client.waitForIndexedBlock(chainId, block, opts)` resolves once the indexer has processed a block, and rejects with the new `IndexerWaitTimeoutError` on deadline — a different decision from a failed read. **Affected:** code constructing `OpenOrder` or `OrderRow` values, chiefly fixtures and mocks; implementations of `SomniaMarketsClient` other than the SDK's own must add `waitForIndexedBlock`. In this repository **sdk-e2e** builds and asserts on order rows (`test/query.test.ts`, `test/lifecycle.test.ts`), and the explorer reads `userData` on `src/app/pool/[pool]/order/[orderId]/page.tsx`. None of the new filter columns is indexed — pair a tag or block bound with a pool scope and a status to keep the scan small. ### 10. `pnlEventsFor` rejects malformed rows **Was:** `id` was never read; ordering used the timestamp alone, so a malformed `id` was ignored and its row stayed wherever the input happened to put it. **Now:** `pnlEventsFor` reads each row's `id` to order events by chain position and throws `InvalidInputError` when it is not `${blockNumber}_${logIndex}`. The same check covers every number the fold reads — `FillRow.quantity`, `FillRow.fillPrice` and a router action's `amount`. These went through a bare `BigInt` before, which threw a native `SyntaxError` on a corrupt value: an error outside the documented union of this function and both client methods that wrap it. **Affected:** callers passing indexed data straight through are unaffected — rows from `getUserFills` and the router-action reads already carry well-formed ids. A caller assembling its own `FillRow` or `RouterActionRecord` values, **test fixtures especially**, must set `id` to `` `${blockNumber}_${logIndex}` `` and give `quantity`, `fillPrice` and `amount` as unsigned decimal strings. ### 11. A live price watch requires `priceFeed.quote` **Was:** `watchPrice` accepted a feed configured with a url alone. **Now:** it rejects with `NotConfiguredError` naming the key unless the feed pins a quote: `priceFeed: { url, quote: "USDC" }`. The tape below it now streams on a `requestId` cursor, and one upstream request prices every symbol in a tick — so that id is unique within a feed but not across a base spanning several quotes. Such a stream can carry two rows sharing an id, and a batch boundary between them would skip the second permanently. An unpinned base was already double-counting on this path; refusing it is the alternative to silently losing ticks. The one-shot reads — snapshot, history, candles, batch prices, feed catalog — are unaffected and still work without a quote. `SOMNIA_TESTNET_PRICE_FEED` and `SOMNIA_MAINNET_PRICE_FEED` already pin `USDC`, so configurations built from those constants need no change. Two smaller shifts on the same path: `PricePoint.raw.price` and `raw.ema` now report `"0"` for a tick the feed recorded with no price, where they previously reported `null` despite being typed as strings; and a subscription the server rejects is now surfaced instead of leaving the tape silent while the feed still reads as connected. **Affected:** `watchPrice` and `useWatchPrice` consumers whose feed carries no quote. In this repository **the explorer** already pins one (`src/lib/priceFeeds.ts`, overridable through `PRICE_FEED_QUOTE`), so it needs no change. ### 12. `hidekiTestnet` (50383) now means the v2 regenesis **Was:** the chain rebuilt before 2026-09-17, reached at `api.hideki.infra.testnet.somnia.network`. **Now:** the v2 regenesis — a different genesis, different endpoints, and the canonical Multicall3 at `0xcA11bde0…` that v2 predeploys at block 1. The chain id did not change, which is exactly the hazard. Hideki was rebuilt on the **same id** with fresh state and the deployer's nonces restarted, so an address is no longer a stable identifier across the two chains: most v1 addresses hold a _different_ contract on v2, while the whole binary/CLOB family (deployed via CREATE3) and the bridged USDso synthetic come back at the _same_ address. A stale cache does not fail loudly — it answers with the other chain's history. **To move to v2 (recommended):** take the new definition and discard every piece of Hideki state you hold — indexer databases, address caches, block-height watermarks, saved deployment manifests. Do not reconcile v1 addresses against v2 ones, and do not carry a v1 start block across: v1 is past 586M blocks while v2 is near 2.4M, so a v1 watermark parks you at a head v2 will not reach for a long time. **To stay on v1:** pin the SDK to 0.30.0, or construct the chain yourself with viem's `defineChain` using the v1 host and Multicall3 `0x540B091b…`. Note that v1's `/ws` already answers 502, so a websocket consumer is broken there regardless. **Tell the two apart by height, never by chain id** — nothing in a signature, a wallet or this definition distinguishes them. **Affected:** anything pinned to 50383. In this repository, the explorer's chain and address maps (`src/lib/chains.ts`, `src/lib/addresses.ts`) and the bridge lane, whose five Shannon-side collateral routers moved while the Hideki-side deployment came back at its v1 addresses. ### 13. A `walletClient` signer must implement `sendTransaction` **Was:** the SDK sent each write with `walletClient.writeContract`. **Now:** the wallet executor encodes each call and sends it with `walletClient.sendTransaction`. The SDK does not call `writeContract`. A viem or wagmi wallet client implements both methods, so it needs no change. An adapter object that implements only `account` and `writeContract` still compiles when it is typed as a `WalletClient`. At runtime every write through it fails with `RpcError`, `operation: "sendTransaction"`, and no order is placed. Entry 1 covers the changed `operation` string. Such an adapter usually routes writes to a Safe or a sponsor relay. Check the built-in before writing one: `client.createExecutor({ smartAccount, inner })` covers an account from the accounts factory — see [Trade through a smart account](./how-to/trade-through-a-smart-account.md). Hand-write an `Executor` only when the submit path is your own: a sponsor relay, a custom co-signer, or a safe that built-in does not cover. An executor receives the encoded calls, sends them, and returns the receipt. An account holds **one executor per chain**, keyed by chain id, so build one for every chain the exchange spans. `exchange.client` is the PRIMARY (first) chain's engine only; reach the others with `exchange.engineFor(chainId)`. Registering a single chain's executor leaves writes on every other chain throwing `NotConfiguredError`. ```ts // before: 0.30.0 sent every write through the adapter's writeContract exchange.setSigner({ walletClient: safeAdapter }); ``` ```ts // after: the adapter becomes an executor import { assertCallsOnChain, InvalidInputError, type Executed, type Executor } from "@somnia-chain/markets-sdk"; // One executor per chain: `exchange.client` is the primary chain's engine only. const makeExecutor = (chainId: number): Executor => { const viem = exchange.engineFor(chainId).getViemClient(); return { chainId, actor: safeAddress, async execute(calls) { // Refuse an empty list or a call for another chain, as the built-in executors do. assertCallsOnChain(chainId, calls); let executed: Executed | undefined; for (const call of calls) { const hash = await submitThroughSafe(chainId, call); // your existing Safe or relay submit executed = { hash, receipt: await viem.waitForTransactionReceipt({ hash }) }; // Stop at the first mined revert. The SDK decodes it from the receipt. // A Safe can also mine a successful receipt around a failed inner call. // Detect that from the Safe's own events and return it as `failure`. if (executed.receipt.status === "reverted") break; } if (executed === undefined) throw new InvalidInputError("execute needs at least one call"); return executed; }, }; }; // Every chain the exchange spans gets one, so no write lands on an unconfigured chain. const executors: Partial> = Object.fromEntries( exchange.chainIds.map((chainId) => [chainId, makeExecutor(chainId)]), ); exchange.setSigner({ account: { address: safeAddress, executors } }); ``` A Safe transaction whose inner call fails can still mine with `status: "success"`. The SDK then treats the write as successful, unless the executor sets `failure` on the result it returns. If your Safe path can swallow an inner revert, detect it and set `failure` to a `ContractRevertError`. See `Executed` in the API reference. The SDK reads allowances and operator grants for `actor`, so set it to the address that holds the funds. An executor without `signTypedData` cannot run verbs that sign typed data, such as `signRedeemAuth`. Those verbs throw `SignerRequiredError`. If the account is a factory account from `@somnia-chain/accounts-sdk`, `exchange.client.createExecutor({ smartAccount, inner })` builds the executor for you. See the [Smart accounts guide](./ACCOUNTS.md). **Affected:** `walletClient` adapters that implement `writeContract` but not `sendTransaction`. The DreamDEX web app (dex-web) is affected: its Safe adapter implements only `account` and `writeContract`. In this repository, the explorer passes wagmi wallet clients, which implement `sendTransaction`, so it needs no change. ### 14. `Unified*` structs and `Tradable` carry a required `chainId` **Was:** these types had no chain field. **Now:** `chainId: number` is required on `UnifiedMarket`, `UnifiedOrderBook`, `UnifiedTrade`, `UnifiedOrder`, `UnifiedStopOrder`, `UnifiedTicker`, `UnifiedFundingRate`, `UnifiedPosition` and `Tradable`. Two more required fields arrive with it: `UnifiedBalance.byChain`, the balance per chain, and `UnifiedTicker.perpState`. The SDK sets these fields on every value it returns. Code that only reads the values needs no change. Code that constructs them must add the fields. This is mostly test fixtures, mocks, and adapters. A single-chain exchange sets `chainId` to its chain's id and reports one `byChain` entry. ```ts // before const market: UnifiedMarket = { ...marketFields }; const usdso: UnifiedBalance = { free: 10, used: 0, total: 10 }; ``` ```ts // after const market: UnifiedMarket = { ...marketFields, chainId: 50312 }; const usdso: UnifiedBalance = { free: 10, used: 0, total: 10, byChain: { 50312: { free: 10, used: 0, total: 10 } } }; ``` **Affected:** code that constructs these types. dex-web is affected: its `UnifiedMarket` test fixtures fail `tsc` until they add `chainId`. In this repository, market-taker and sdk-e2e only read `UnifiedMarket` values that the SDK returns, so they need no change. ### 15. Note: nonce lanes belong to the engine This entry is not a breaking change. It corrects earlier documentation and states the safe way to share a signing key. **Was:** each configured client owned one nonce lane. A 0.30.0 exchange had one client, so it had one lane. **Now:** each engine owns one nonce lane. A multi-chain exchange builds one engine per chain, so it has one lane per chain. A single-chain exchange still has one lane. Single-chain code sees no change. Earlier SDK documentation said that viem's nonce manager is process-wide. That was not true in 0.30.0, and it is not true now. Two exchanges never share nonce state, even when they sign with the same key on the same chain. If both write at the same time, they can take the same nonce, and the node rejects one of the transactions. Share one exchange per signing account per chain. ```ts // unsafe: two exchanges with one key on one chain, two nonce lanes const quoting = new SomniaMarkets({ ...config, privateKey }); const hedging = new SomniaMarkets({ ...config, privateKey }); ``` ```ts // safe: one exchange per signing account per chain, one nonce lane const exchange = new SomniaMarkets({ ...config, privateKey }); ``` **Affected:** code that constructs two exchanges that sign with one key on one chain and write at the same time. In this repository, sdk-e2e runs its test files one at a time so that its maker and taker keys never race on nonces (`sdk-e2e/vitest.config.ts`). ## 0.31.0 → 0.32.0 This section has fourteen entries, one for each breaking change in 0.32.0. Entry 3 has an operational step: deploy and reindex the indexer **before** you upgrade. Seven entries need attention even if your code compiles: - `getLiveUserOrders` no longer returns every terminal order (entry 5). - `exchange.client` and `exchange.trader` throw on a multi-chain exchange (entry 7). - A misconfigured chain binding now fails its first read (entry 8). - `ensureFunds` reports a delivery timeout and a native-route liquidity refusal with new error classes (entry 9). - A write whose outcome is unknown throws a new error class (entry 10). - A smart-account executor refuses a session-seed inner (entry 11). - A local-signer send failure names `eth_sendRawTransactionSync` as its `operation` (entry 14). ### 1. The bridge registry describes the Hideki 2 lane **Was:** `getBridgeNetwork(ChainId.somniaShannon)` returned the Somnia-side core addresses of the Hideki 1 lane. The lane id was `"somniatestnet-hidekitestnet"`. **Now:** it returns the Hideki 2 lane's `mailbox`, `interchainSecurityModule`, `merkleTreeHook`, `validatorAnnounce`, `interchainAccountRouter` and `proxyAdmin`. The lane id is `"somniatestnet-hideki2testnet"`. Every `route.id`, the Hideki network name (`"hideki2testnet"`) and both display names change with it. Routers, tokens and decimals do not change since 0.31.0 (entry 12 of the previous section covers the router move), so `createBridgeTransfer`, `sendBridgeStep` and `getBridgeToken` behave as before. Replace stored lane and route ids, and discard cached Somnia-side core addresses. Read both from the registry, so the next rename does not break your code. ```ts // before: a stored literal const wbtcRouteId = "WBTC/somniatestnet-hidekitestnet"; ``` ```ts // after: read ids and addresses from the registry import { BridgeToken, ChainId, getBridgeNetwork, SOMNIA_BRIDGE } from "@somnia-chain/markets-sdk/chains"; const wbtcRoute = SOMNIA_BRIDGE.routes.find((route) => route.token === BridgeToken.WBTC); wbtcRoute?.id; // "WBTC/somniatestnet-hideki2testnet" const mailbox = getBridgeNetwork(ChainId.somniaShannon)?.mailbox; // the Hideki 2 lane's mailbox ``` **Affected:** configuration, dashboards, analytics keys and fixtures that store lane or route ids, and monitoring that caches Somnia-side core addresses. No consumer in this repository stores these values. ### 2. `UnifiedTicker.baseVolume` and `quoteVolume` are optional **Was:** `fetchTicker` failed as a whole when its 24h candle read failed. Both volumes were always present. **Now:** `fetchTicker` contains an `IndexerError` from the candle read and still returns the perp fields. The new `statsState` field says whether the 24h fields were read: - `"ok"`: the volumes are present. A volume of `0` is a true zero. - `"unavailable"`: the candle read failed with an `IndexerError`, or the market is `indexed: false` and no candle read was sent. `open`, `high`, `low`, `change`, `percentage`, `statsAsOf`, `baseVolume` and `quoteVolume` are absent. Other errors still reject. The type does not narrow on `statsState`, so check the volume for `undefined` too. ```ts // before console.log(ticker.baseVolume.toFixed(2)); ``` ```ts // after if (ticker.statsState === "ok" && ticker.baseVolume !== undefined) { console.log(ticker.baseVolume.toFixed(2)); } else { console.log("24h volume unavailable"); } ``` **Affected:** `fetchTicker` callers that read the volumes, and code that constructs `UnifiedTicker` values, which must add `statsState`. dex-web is affected: its ticker hook shows the 24h volume. No consumer in this repository reads `UnifiedTicker`. ### 3. Historical fill pages need the `FillDataset` generation **Was:** `getUserFillsPage` read from any indexer, and its cursor did not name the dataset it came from. **Now:** each page reads the serving indexer's `FillDataset` generation. `UserFillsPage` gains a required `datasetGeneration`, and every cursor records it. `fetchPortfolioAnalytics` reads fill history through the same pages. - An indexer that does not serve the generation fails the read with `FillHistoryUnavailableError`. Deploy the matching indexer and reindex it before you upgrade the SDK. - A cursor from another generation fails with `FillHistoryRestartRequiredError`. A cursor that 0.30.0 produced has no generation and fails the same way. Discard every page you collected and start again at page one. ```ts import { FillHistoryRestartRequiredError, type FillRow } from "@somnia-chain/markets-sdk"; let fills: FillRow[] = []; let cursor: string | undefined; let restarted = false; for (;;) { try { const page = await exchange.client.getUserFillsPage(account, { limit: 100, cursor }); fills.push(...page.fills); if (page.nextCursor === null) break; cursor = page.nextCursor; } catch (error) { // Restart once. A second change means the indexer is still being replaced. if (!(error instanceof FillHistoryRestartRequiredError) || restarted) throw error; restarted = true; // The dataset changed under the cursor: the pages already read are stale. fills = []; cursor = undefined; } } ``` **Affected:** callers of `getUserFillsPage` and `fetchPortfolioAnalytics`, code that stores fill cursors, and code that constructs `UserFillsPage` values. Every indexer that serves these reads needs the reindex. No consumer in this repository calls either read. ### 4. Pool-routed verbs refuse a settled binary market **Was:** a verb given a settled binary market acted on that market's pool. A binary pool serves successive markets, so after settlement the pool serves the next market in the series. **Now:** `createOrder`, `mintSet`, `burnSet`, `fetchOrderBook`, `fetchTrades`, `fetchOHLCV`, `fetchTicker`, `watchOrderBook`, `watchTrades`, `watchOrders` and `watchMyTrades` throw `InvalidInputError` for a settled binary market. `redeem`, `fetchBalance` and the history reads still accept it. A caller that resolved a settled market by pool address must resolve it by market id, or by the symbol that `fetchBalance` reports for the holding, to call `redeem`. **Affected:** code that keeps a binary market's symbol or pool after the market settles. In this repository, market-taker selects active binary markets before it calls these verbs (`src/shared.ts`). ### 5. `getLiveUserOrders` keeps a bounded terminal history **Was:** `getLiveUserOrders` returned every order the live store had seen for the user, including every filled and cancelled one. **Now:** per pool, the live store keeps every open order, the orders that retained fills need, and up to 400 recent terminal orders that nothing else references. Older terminal orders drop out of the live read. **Affected:** code that reads order history from `getLiveUserOrders` or the `useLiveUserOrders` hook. Read older terminal orders with `getOrders`. In this repository, the explorer's order panels use the hook to show open orders only (`explorer/src/components/clob/UserPanel.tsx`, `explorer/src/components/spot/SpotTradePanel.tsx`), so they need no change. ### 6. Live and history rows carry a required `chainId` **Was:** these rows had no chain field. **Now:** `chainId: number` is required on `LiveFill`, `LiveOrder`, `LiveFundingUpdate`, `LiquidationEvent` and `FundingPayment`. It is the chain of the engine that built or read the row. Ids repeat across chains, so key rows merged from two engines on `(chainId, id)`. `PricePoint` does not change. The SDK sets the field on every row it returns. Code that only reads rows needs no change. Code that constructs them must add it: ```ts // before const fill: LiveFill = { ...fillFields }; ``` ```ts // after const fill: LiveFill = { ...fillFields, chainId: 50312 }; ``` **Affected:** code that constructs these types, mostly test fixtures and mocks. In this repository, the sdk-e2e order fixtures already set `chainId` (`sdk-e2e/test/expiry.unit.test.ts`). ### 7. `exchange.client` and `exchange.trader` throw on a multi-chain exchange **Was:** on an exchange with two or more chains, `exchange.client` and `exchange.trader` acted on the first chain. **Now:** both throw `InvalidInputError`. Its `chainIds` field lists the chains the exchange spans. A pool address or market id can name a different market on each chain, so a call without a chain could reach the wrong market. A single-chain exchange does not change. Name the chain instead: ```ts // before const viem = exchange.client.getViemClient(); const trader = exchange.trader; ``` ```ts // after const viem = exchange.engineFor(hidekiTestnet.id).getViemClient(); const trader = exchange.traderFor(hidekiTestnet.id); ``` Two related changes: - `createReactivity` now reads `config` as well as `getViemClient` from its first argument. An engine from the SDK has both. A hand-built `{ getViemClient }` object must add `config: { chain }`. - `createReactivity` throws `InvalidInputError` when the wallet's `chain` is set and is not the engine's chain. **Affected:** multi-chain exchanges that use `exchange.client` or `exchange.trader`, and code that passes a hand-built object to `createReactivity`. Every consumer in this repository builds a single-chain exchange, so none needs a change. ### 8. Chain bindings are checked against the chain they name **Was:** the SDK trusted each binding's endpoints. **Now:** a binding whose endpoints serve another chain fails on first use: - Construction throws `InvalidInputError` when two bindings name one indexer URL written two ways, for example with a different host case, a default port or a trailing slash. - The first indexed read of each engine reads the indexer's `chain_metadata`. When the indexer has no row for the bound chain, the read throws `NotConfiguredError`. So `getSyncStatus` and `getIndexerFreshness` for the client's own chain throw instead of returning `null` for a missing row. - On Hideki (50383), the first chain read on each connection reads block 1. An RPC on the retired Hideki v1 genesis throws `NotConfiguredError`. - `getIndexerFreshness` throws `NotConfiguredError` when the indexer is more than 10,000 blocks past the RPC head, instead of reporting lag 0. `waitForIndexedBlock` for the client's own chain rejects in the same case. **Affected:** code that treats a `null` from `getSyncStatus` or `getIndexerFreshness` as "not indexed yet", and deployments whose indexer or RPC URL points at another chain. Fix the configuration; the error's `what` names the chain, the URL and the chains the indexer reports. ### 9. The bridge waits for its own message, and its failures are typed **Was:** `exchange.bridge.transfer` ended its wait at any delivery to the recipient, including one from another transfer. On a delivery timeout, `ensureFunds` and `createOrder(…, { funding: "auto" })` threw `RpcError` with `operation: "ensureFunds"`. **Now:** the bridge waits for the Hyperlane message id of its own transfer. A delivery timeout throws `BridgeDeliveryTimeoutError`, which carries `messageId`, `bridgeHash`, `from`, `to`, `token` and `amount`. `ExchangeBridgeResult` gains a required `messageId`. The default `deliveryTimeoutMs` is 180 seconds instead of 120, counted from when the origin transaction is mined. A native route (STT) now reads the destination router's balance first. When the router holds less than the amount, `exchange.bridge.transfer`, `ensureFunds` and `createOrder(…, { funding: "auto" })` throw `BridgeLiquidityError` and send nothing. It carries `token`, `from`, `to`, `router`, `amount` and `available`. Before, the transfer was sent, the funds stayed in escrow on the origin, and the call waited out the delivery timeout. The two errors need different handling: a liquidity refusal is safe to retry once the router is funded, and a delivery timeout means a transfer is in flight. ```ts // before try { await exchange.ensureFunds({ code: "USDso", chainId: hidekiTestnet.id, amount }); } catch (error) { if (!(error instanceof RpcError) || error.operation !== "ensureFunds") throw error; console.log("bridge not delivered"); } ``` ```ts // after try { await exchange.ensureFunds({ code: "USDso", chainId: hidekiTestnet.id, amount }); } catch (error) { if (error instanceof BridgeLiquidityError) { // Nothing was sent. The destination router cannot pay out the amount yet. console.log("bridge refused", error.available); } else if (error instanceof BridgeDeliveryTimeoutError) { // The transfer may still arrive. Check delivered(messageId) on the // destination Mailbox before you bridge again from another exchange. console.log("bridge not delivered", error.messageId); } else { throw error; } } ``` **Affected:** code that catches the old `RpcError` or handles only a delivery timeout, and code that constructs `ExchangeBridgeResult` values, such as test mocks. No consumer in this repository calls the bridge. ### 10. A write with an unknown outcome throws `TransactionOutcomeUnknownError` **Was:** a write whose answer was lost threw a plain `RpcError`. **Now:** it throws `TransactionOutcomeUnknownError`. The built-in executors throw it when the sync send times out or its socket drops, when the receipt wait fails after the transaction was sent, and when a session send loses its answer. It carries `chainId`, `operation` and `hash`. `hash` is absent only for a session send. The transaction can still mine, so do not retry it blindly. The new class extends `RpcError`, so an `instanceof RpcError` check still catches it. Test for it first: ```ts try { await exchange.createOrder(symbol, "limit", "buy", 1, 0.5); } catch (error) { if (error instanceof TransactionOutcomeUnknownError) { // The write may still mine. Look up error.hash before you send it again. console.log("outcome unknown", error.hash); } else if (error instanceof RpcError) { console.log("rpc failure", error.operation); } else { throw error; } } ``` Code that tests `error.name === "RpcError"` no longer matches these failures. A failed receipt wait now reports `operation: "waitForTransactionReceipt"`. A session-key write with a gas limit of zero or less throws `InvalidInputError` before it is sent. **Affected:** write error handlers that retry on `RpcError`. No consumer in this repository retries writes on `RpcError`. ### 11. A session seed that controls an account signs locally **Was:** a session seed sent itself to the node with every write (`somnia_sendSessionTransaction`). Any RPC endpoint, proxy or request log on the way could read it. **Now:** `exchange.accounts.accountFor(accountId, index, { sessionSeed })` derives the key with `sessionPrivateKey(seed)` and signs locally. The session address does not change, so existing owner sets keep working. `createExecutor({ smartAccount, inner })` throws `InvalidInputError` when `inner` was built by `createExecutor({ sessionSeed })`. `accountFor` refuses a per-chain factory that returns such an executor in the same way. Let `exchange.accounts.accountFor` build the account. It derives the seed's key and gives the account a local-signing executor on every covered chain: ```ts // before const inner = client.createExecutor({ sessionSeed: seed }); const executor = client.createExecutor({ smartAccount: ACCOUNT, inner }); ``` ```ts // after const account = exchange.accounts.accountFor(owner, 0n, { sessionSeed: seed }); const executor = account.executors[hidekiTestnet.id]; ``` `owner` and `0n` are the account id and index the accounts factory derived `ACCOUNT` from, so `account.address` is `ACCOUNT`. Pass `account` itself as the `account` of a `SomniaMarkets` config to trade through it on every chain. `createExecutor({ sessionSeed })` stays available for a session account that holds gas dust only. Local and node-side sends from one seed share one nonce space: after a seed signs locally, do not also send from it through `createExecutor({ sessionSeed })` or `sendSessionTransaction`. **Affected:** code that builds a smart-account executor on a session-seed inner. No consumer in this repository does. ### 12. The generic Safe executor is removed **Was:** `createExecutor({ safe, inner, mode?, multiSend?, detectFailure? })` built an executor for a threshold-1 Gnosis safe, in `"owner"` or `"module"` mode. The root exported seven values and types for it: `safeExecAbi`, `preValidatedSignature`, `packMultiSend`, `PackMultiSendError`, `detectGnosisFailure`, `SafeFailureDetector` and `SafeExecutionMode`. **Now:** the `{ safe, inner }` spec and the seven exports are gone. A spec with a `safe` key no longer type-checks. At runtime, `createExecutor` refuses it with `InvalidInputError`. For an account that the accounts factory deployed, use the smart-account spec. It batches several calls into one account transaction without a `multiSend` address. Build `inner` with a local signer, not with `{ sessionSeed }`: ```ts // before const session = client.createExecutor({ privateKey: sessionKey }); const executor = client.createExecutor({ safe: account, inner: session, multiSend }); ``` ```ts // after const session = client.createExecutor({ privateKey: sessionKey }); const executor = client.createExecutor({ smartAccount: account, inner: session }); ``` For any other safe, write a custom `Executor` and pass it to `createTrader({ executor })`. Return an inner failure as `failure` on the result, and Trader writes throw it. For the pre-validated signature and the Safe ABI, use `prevalidatedSignature` and `safeAbi` from `@somnia-chain/accounts-sdk`. **Affected:** code that builds a `{ safe, inner }` executor or imports one of the seven exports. No consumer in this repository does. ### 13. `getPoolBindings` is renamed `listPoolBindings` and returns one page **Was:** `client.getPoolBindings(pool)` returned the whole binding history of a pool in one response. A recycled pool gains one binding for each market, so the response had no upper bound. **Now:** `client.listPoolBindings(pool, { limit, offset })` returns one page, newest nonce first. `limit` is 50 by default, from 1 to 1000. `offset` is 0 by default, from 0 to 2147483647. A bad `limit` or `offset` throws `InvalidInputError` before the request. The row type `PoolBindingRecord` does not change. Rename the call. A caller that only reads the current binding needs no other change: it is the first row. A caller that needs the whole history pages until a page is shorter than `limit`, and deduplicates on `id`. New bindings move older rows down between two requests. The TSDoc of `listPoolBindings` has a compile-checked example. **Affected:** code that calls `getPoolBindings`. No consumer in this repository does. ### 14. Local-signer sends use `eth_sendRawTransactionSync` **Was:** `"realtime_sendRawTransaction"`. **Now:** `"eth_sendRawTransactionSync"`. A local-signer write now sends through `eth_sendRawTransactionSync` (EIP-7966). It is the current name for Somnia's `realtime_sendRawTransaction`, and it also returns the receipt in one round-trip. When this send fails, the `operation` of the `RpcError` or `TransactionOutcomeUnknownError` names the new method. Update checks for the old name. A node that does not serve the method still gets `eth_sendRawTransaction` and a receipt wait. **Affected:** code matching `err.operation === "realtime_sendRawTransaction"`. **No consumer in this repository branches on `RpcError.operation`.** --- # /docs/typescript/release-notes # Release notes ## 0.32.0-rc.1790343344035 ### Minor Changes - BREAKING: the exchange bridge now waits for its own Hyperlane message, and a delivery timeout in `ensureFunds` is a typed error. `exchange.bridge.transfer` reads the message id from the origin receipt and resolves only when the destination Mailbox processes that id. Before, any `ReceivedTransferRemote` to the recipient ended the wait, including a delivery from another transfer. - `ExchangeBridgeResult` has a new required field, `messageId`. Code that builds this type, such as a test mock, must add it. - `exchange.ensureFunds` and `createOrder(…, { funding: "auto" })` throw the new `BridgeDeliveryTimeoutError` on a delivery timeout, with `messageId`, `bridgeHash`, `from`, `to`, `token`, and `amount`. Before, they threw `RpcError` with `operation: "ensureFunds"`. Replace a check for that `RpcError` with `instanceof BridgeDeliveryTimeoutError`, and call `delivered(messageId)` on the destination Mailbox before you bridge again. - `exchange.bridge.transfer` still resolves with `delivered: false` on a timeout, and now carries `messageId`. - The default `deliveryTimeoutMs` is 180 s instead of 120 s. It is counted from when the origin transaction is mined. - A mined origin receipt without exactly one Mailbox dispatch from the origin router to the destination throws `RpcError` with `operation: "bridge message id"`. - A native bridge route (STT) is now refused before anything is sent when the destination router cannot pay out. `exchange.bridge.transfer`, `exchange.ensureFunds`, and `createOrder(…, { funding: "auto" })` read the destination router's balance first. When it is below the amount, they throw the new `BridgeLiquidityError` with `token`, `from`, `to`, `router`, `amount`, and `available`. Before, the SDK sent the transfer, the funds stayed in escrow on the origin, and the call waited out the delivery timeout. `ExchangeBridgeTransferError` is the new exported union of the errors `exchange.bridge.transfer` can throw. A failed native balance read now throws `RpcError` with `operation: "getBalance"` instead of a raw viem error. - Query-key factories and five React hooks now respect the chain on a multi-chain exchange. - Every query-key factory except `syncStatusKey` takes an optional trailing `{ chainId }` (`QueryKeyChainOptions`). A key with a chain ends in a `{ chainId }` element. A key without one is unchanged, so existing caches keep their entries. On a multi-chain exchange, pass `chainId` on every key. - `useWatchPerpMarkets`, `useWatchPerpMarketsResult`, `useLiveLiquidations` and `useLiveFundingPayments` take `chainId` in their options object (`UseWatchPerpMarketsOptions`, `UseLiveLiquidationsOptions`, `UseLiveFundingPaymentsOptions`). Before, they always read the primary chain. - `useFundingRateSeries(pool, interval, window, { chainId })` now reads the series and the indexer sync status from that chain's engine. Before, it read them from the primary chain and used `chainId` only for its live updates. - BREAKING: live and history rows now name their chain in a required `chainId: number` field. - `LiveFill`, `LiveOrder`, `LiveFundingUpdate`, `LiquidationEvent` and `FundingPayment` carry `chainId`. It is the chain of the engine that built or read the row. These rows come from one chain's events or from its indexer, so their ids repeat across chains: key rows merged from two engines on `(chainId, id)`. - Every row source sets it: live events, the chain seed, the indexer snapshot, the perp plane, and the indexed reads `getFundingPayments`, `listLiquidations` and `getLiquidations`. - `PricePoint` is unchanged. A price feed is configured independently of the chain (`config.priceFeed`), and one feed endpoint can serve clients on two chains, so a tick is not a per-chain row. - Market rows from a chain seed or from a live `MarketCreated` now set the optional `Market.chainId` too, as indexer rows already did. - Migration: code that only reads these rows needs no change. Code that builds one of these objects, such as a test fixture or a mock, must add `chainId`. - BREAKING (multi-chain exchanges only): `exchange.client` and `exchange.trader` now throw `InvalidInputError` on an exchange with two or more chains. They name no chain, and a pool address or market id can name a different market on each chain. Before, they acted on the first chain without an error. Replace `exchange.client` with `exchange.engineFor(chainId)` and `exchange.trader` with the new public `exchange.traderFor(chainId)`. The error's `chainIds` field lists the chains the exchange spans. A single-chain exchange is unchanged. `traderFor(chainId)` writes through `account.executors[chainId]` when the signer is a `SomniaMarketsAccount`. `setSigner` now validates the new signer before it replaces the old one. After a throw, the previous signer stays bound. `createReactivity` now throws `InvalidInputError` when the wallet's `chain` is set and is not the engine's chain. A wallet with no `chain` is not checked. BREAKING (type only): `createReactivity` now reads `config` as well as `getViemClient` from its first argument. An engine from the SDK already has both. A hand-built `{ getViemClient }` object must add `config: { chain }`. - BREAKING: the generic Safe executor, `createExecutor({ safe, inner })`, is removed. It covered a threshold-1 Gnosis safe in owner or module mode, beside the smart-account executor that covers the accounts factory's safes. Two executors for one kind of account taught two paths, and no consumer used the generic one. - The `{ safe, inner, mode?, multiSend?, detectFailure? }` spec is gone. A spec with a `safe` key no longer type-checks, and `createExecutor` refuses it at runtime with `InvalidInputError`. - The root no longer exports `safeExecAbi`, `preValidatedSignature`, `packMultiSend`, `detectGnosisFailure`, `SafeExecutionMode`, `SafeFailureDetector` or `PackMultiSendError`. - This supersedes the session-seed note in the same release, which says `createExecutor({ safe, inner })` refuses an `inner` built by `createExecutor({ sessionSeed })`. That spec no longer exists; the refusal now applies to `createExecutor({ smartAccount, inner })` only. How to migrate: - For an account that the accounts factory deployed, use `createExecutor({ smartAccount, inner })`. It batches without a `multiSend` address. Build `inner` with `createExecutor({ privateKey })`. - For any other safe, write a custom `Executor` and pass it to `createTrader({ executor })`. `prevalidatedSignature` and `safeAbi` come from `@somnia-chain/accounts-sdk`. - BREAKING: `SomniaMarkets` now checks that each chain binding's endpoints serve the bound chain. - Construction throws `InvalidInputError` when two bindings name one indexer URL written two ways, for example with a different host case, a default port or a trailing slash. - The first indexed read of each engine, of any kind, first reads the indexer's `chain_metadata` once. When the indexer has no row for the bound chain, the read throws `NotConfiguredError`, and `what` names the chain, the URL and the chains the indexer reports. So `getSyncStatus` and `getIndexerFreshness` for the client's own chain throw instead of returning `null` for a missing row. - On Hideki (50383), the first chain read or session send on each connection first reads block 1. An RPC on the retired Hideki v1 genesis throws `NotConfiguredError`. - `getIndexerFreshness` throws `NotConfiguredError` when the indexer is more than 10,000 blocks past the RPC head, instead of reporting lag 0. `waitForIndexedBlock` for the client's own chain reads the RPC head once when it would resolve, and rejects with `NotConfiguredError` in the same case. A client with no chain endpoint skips that read. - A binding refusal on a write path crosses as the `NotConfiguredError` itself. The session executor previously read any non-node failure as "the transaction may have been sent" and reported `TransactionOutcomeUnknownError`; a check that refuses the endpoint never sends, so there is no hash to look up. - BREAKING: a session seed that controls an account now signs locally. The seed no longer goes to a node. `exchange.accounts.accountFor(accountId, index, { sessionSeed })` sent the raw seed to each chain's node (`somnia_sendSessionTransaction`) with every write. The seed is a private key in another form, and the session address is an owner of the account that holds the funds. Any RPC endpoint, proxy or request log on the way could read it. - `accountFor(..., { sessionSeed })` now derives the key with `sessionPrivateKey(seed)` and signs locally on each chain, on that engine's nonce lane. No request carries the seed. The session address does not change, so existing owner sets keep working. - `createExecutor({ smartAccount, inner })` and `createExecutor({ safe, inner })` throw `InvalidInputError` when `inner` was built by `createExecutor({ sessionSeed })`. `accountFor` refuses a per-chain factory that returns such an executor in the same way. - `createExecutor({ sessionSeed })` stays available for session accounts that hold gas dust only. How to migrate: - Build an account's inner with `createExecutor({ privateKey })`. For a Somnia session seed, the key is `sessionPrivateKey(seed)`, imported from `@somnia-chain/markets-sdk/native`. Across chains, `accountFor(accountId, index, { sessionSeed })` does this for you. - Do not mix local and node-side sends from the same seed. Both modes share one nonce space. After a seed signs locally, do not also send from it through `createExecutor({ sessionSeed })` or `sendSessionTransaction`. - BREAKING: a write whose signed transaction may have reached the node, and whose receipt was not observed, now throws the new `TransactionOutcomeUnknownError` instead of a plain `RpcError`. The built-in executors throw it when the realtime send times out or its socket drops, when the receipt wait fails after the transaction was sent, and when a session send loses its answer. It carries `chainId`, `operation` and `hash` (absent only for a session send). The transaction can still mine, so look up `hash` before you send the write again. A refusal the node answered stays a plain `RpcError` or `ContractRevertError`; a refusal is recognised by the mempool status byte the node puts in the error's `data`, since it reports every mempool verdict — including its own send timeout — as JSON-RPC `-32000`. Migration: test for `TransactionOutcomeUnknownError` before `RpcError` in every write's error handler, and do not retry it blindly. It extends `RpcError`, so an existing `instanceof RpcError` arm still catches it. Code that tests `err.name === "RpcError"` no longer matches these failures. A failed receipt wait now reports `operation: "waitForTransactionReceipt"`. After a lost realtime answer, the SDK reads the transaction by hash once. When it has mined, the write now resolves with its receipt instead of throwing. A session-key write with a gas limit of zero or less now throws `InvalidInputError` before it is sent. ### Patch Changes - The multi-chain collateral pre-check in `createOrder` now finds the collateral token by address, not by currency code. The check reads the balance of the exact token the order escrows. It finds the bridge route by that token's address in the bridge registry. A token the registry does not list has no route, even when its symbol matches a bridge token, so `CollateralOnWrongChainError` carries no plan and an empty `elsewhere`. A registry token under another market label, for example `bUSDso`, now gets its route. `elsewhere` now lists only the other chains the registry lists that token on. `ensureFunds` still takes a currency code. It resolves the code on the target chain to the native coin, then to the bridge registry's token for that code, then to a listed market's token, and continues by that token's address. When no token on the chain carries the code, `ensureFunds` now throws `InvalidInputError` for a positive amount. `CollateralOnWrongChainError.token` is now always lowercased, so it no longer differs in casing between the `ensureFunds` and `createOrder` entry points. - `exchange.ensureFunds` and `createOrder(…, { funding: "auto" })` no longer bridge the same shortfall twice. On one exchange, calls for the same account, chain and currency run one at a time, and an auto-funded order keeps its place in that queue until it is sent. Two concurrent auto-funded orders now bridge their combined shortfall once. Each queued call can wait a full delivery timeout. - A leg that timed out stays pending on the exchange. When the next `ensureFunds` or auto-funded order for the same account, chain and currency finds a shortfall, it waits for that message and sends no new leg for it. When the balance already covers the amount, it does not wait. The pending leg is in memory only, so a new exchange instance must still check `delivered(messageId)` before it bridges again. - `exchange.close()` now ends the delivery waits of every `bridge.transfer`, `ensureFunds` and auto-funded order that started before it. `bridge.transfer` resolves with `delivered: false`, and `ensureFunds` throws `BridgeDeliveryTimeoutError`. The leg stays pending. - Avoid scanning and sorting unrelated live orders on every user-order read. - Complete the migration guide from 0.30.0 to 0.32.0 in `docs/MIGRATING.md`. The guide now says that 0.31.0 was not published, so a consumer on 0.30.0 applies both of its sections. The 0.30.0 → 0.31.0 section gains three entries: the wallet executor's `sendTransaction`, the required `chainId` on `Unified*` values and `Tradable`, and per-engine nonce lanes. A new 0.31.0 → 0.32.0 section covers the four breaking changes in 0.32.0. Each code example in the guide is compile-checked. The guide also documents three points that earlier release notes stated incorrectly. The notes themselves are published and are not edited here: - `indexerUrl` is optional on every chain, including Hideki. A client used only for chain reads and writes needs none. - A `walletClient` signer must implement `sendTransaction`. The SDK does not call `writeContract`. An adapter that implements only `writeContract` fails every write with `RpcError`. - `UnifiedTicker.statsState` does not narrow `baseVolume` or `quoteVolume`. Check the volume for `undefined` too. Other documentation fixes: the two-chain example in `docs/EXCHANGE.md` imported `hidekiMainnet`, which does not exist, and now pairs `somniaShannon` with `hidekiTestnet`. `docs/reference/networks-and-endpoints.md` names the chain exports of `@somnia-chain/markets-sdk/chains`. `docs/explanation/about-the-exchange-instance.md` describes per-engine nonce lanes. - `SOMNIA_TESTNET_ADDRESSES` and `SOMNIA_HIDEKI_TESTNET_ADDRESSES` now set `perpPoolFactory`. A binding that uses either preset lists its perps from the chain, also when it has no `indexerUrl`. Before this change, a Shannon or Hideki binding without an indexer listed no perps. `SOMNIA_MAINNET_ADDRESSES` does not set `perpPoolFactory`. A configured `perpPoolFactory` takes precedence over the factory that the margin bank reports. At release, each preset value matched the factory that its bank reports. To use the bank's factory instead, remove `perpPoolFactory` from the addresses you pass. The networks and endpoints reference now lists the Hideki indexer, `https://hideki-dev.smk.somnia.host/v1/graphql`. It is development-grade and does not index the Hideki spot pools yet. - The smart-account executor (`createExecutor({ smartAccount, inner })`) now refuses an account that does not exist on the chain, and runs signed writes through one account one at a time. Before its first write, the executor reads the account's code once. An account with no code on the chain raises `InvalidInputError` before anything is signed or sent. Before this change, a write to such an account succeeded and executed nothing. A failed code read raises `RpcError`. Successful checks are cached. This is a new chain read on the path with no `signer` and no `through`, which read nothing before. On a client with no chain transport, that write now throws `NotConfiguredError` instead of sending. With a `signer` or `through`, the engine now runs one write at a time per account, including writes from two executors built for the same account. Before this change, two concurrent writes could sign the same account nonce. The account then refused the second write with `GS026`. The queue belongs to one engine: two processes that write through one account can still sign the same nonce. - The multi-chain collateral pre-check in `createOrder` now sizes a spot order by the pool's `getAutoPullRequirement`, the same number the pool pulls. The check now counts the pool's fee headroom and the account's pool vault balance. A spot order that the vault covers places with no wallet read and no `CollateralOnWrongChainError`. A wallet that holds only the principal on a fee-bearing pool now gets a typed shortfall before anything is sent, instead of a revert. A native-base sell is sized the same way. Under the pool's manual vault mode, a vault shortfall throws `CollateralOnWrongChainError` with no bridge plan, also under `funding: "auto"`, because the pool does not pull from the wallet. ## 0.32.0-rc.1790260897085 ### Minor Changes - `BinaryMarketFilter` gains two facets for counting settlements inside a window, and the binary count helpers no longer require a lifecycle phase. - `voided?: boolean` narrows to markets that settled by void (`true`) or to every other market (`false`). It reads the explicit `voided` flag every void path writes, not the event-derived `status`. - `resolvedSince?: number | bigint` is an inclusive lower bound, in unix seconds, on the market's terminal timestamp. It takes a `bigint` from a chain read or an indexed row as well as a `number` from the clock, and sends either as an exact decimal string. It implies `resolved: true`: a market with no terminal event never matches. - `countBinaryMarkets` and `countBinaryMarketsBounded` take `BinaryMarketCountOptions`, on which `phase` is now optional. Omitted, the count spans live and past markets alike. Existing calls that pass `phase` behave exactly as before. Together they give a venue's settlement count and void count over a trailing window in two server-side counts: `countBinaryMarkets({ venueId, resolvedSince })` and the same call with `voided: true`. Both are keyed on the terminal timestamp rather than on `expiry`, so a market voided before it expired is counted, which a `phase: "past"` count would miss. - BREAKING: `getLiveUserOrders` now keeps up to 400 recent unreferenced terminal orders per pool, along with every open order and orders needed by retained fills. Use `getOrders` for older terminal history. - Add `client.listVaultPayoutFallbacks(options)`: the vault-credit fallback log across every owner, filtered by `owner`, `token` and/or `pool`, windowed with `from`/`to`, ordered `asc` or `desc`, paginated. Each `VaultPayoutFallback` row now also carries `pool`, the pool whose vault holds the credit, so the live claimable amount can be read with `client.getVaultBalance` without a second lookup. `getVaultPayoutFallbacks` is unchanged apart from the new field. - Add `listMarketResolutionEvents` and `listMarketReferenceLinks` — cross-market sweeps over resolution health, where `getMarketResolution` reports one market. `listMarketResolutionEvents` filters on `market`, `kinds` (a new `MarketResolutionKind` union, matched exactly) and `sinceTimestamp`, so a caller watching for `"Skipped"` / `"Failed"` pays for its window instead of over-fetching. `listMarketReferenceLinks` filters on `pending` and `market`, and returns oldest first so the longest-stuck market heads the list. `MarketReferenceLink` now also carries `blockNumber` and `timestamp`; while `pending` is true, that timestamp is when the market went pending, which is the age of the stall. ## 0.32.0-rc.1790179106799 ### Minor Changes - Portfolio analytics now reads cursor-paged fill history and supports an optional page budget that rejects incomplete PnL. A short nonempty page uses one additional indexer request to check for continuation under a positive role row cap. - BREAKING: the bridge registry now describes the **Hideki 2** Hyperlane lane. Six Somnia-side core addresses change. The lane's public string identifiers change with them. **What was wrong.** Somnia Testnet (50312) hosts two independent Hyperlane deployments. One serves the Hideki 1 lane. The other serves the Hideki 2 lane. This separation is structural. Both Hideki chains use chain id 50383 and Hyperlane domain 50383. Lane isolation therefore rests on two things: each lane has its own core contracts, and each warp router binds to one mailbox. `ChainId.hidekiTestnet` has meant Hideki 2 since the 2026-09-17 regenesis. The Somnia-side routers moved to Hideki 2 at that time. The Somnia-side core block did not. It kept the Hideki 1 lane's contracts. `getBridgeNetwork(ChainId.somniaShannon)` therefore returned a mailbox, ISM, merkle hook, validator announce, ICA router and proxy admin from a different bridge than the routers beside them. `createBridgeTransfer` and `sendBridgeStep` were not affected. They use the router addresses, which were already correct. Only `getBridgeNetwork` and `listBridgeNetworks` exposed the wrong values. An explorer link, an ISM trust-model check or a monitoring probe reads those. | `getBridgeNetwork(ChainId.somniaShannon)` | was (Hideki 1 lane) | now (Hideki 2 lane) | | --- | --- | --- | | `mailbox` | `0x46bA2807…e0A9` | `0xF805734a…54f9` | | `interchainSecurityModule` | `0xa831F40f…1B6c` | `0x99e1D7E9…d843` | | `merkleTreeHook` | `0xD7C2E95c…332D` | `0x64aa1c6a…D50C` | | `validatorAnnounce` | `0xB0834b2d…F44e` | `0x81b741D6…1033` | | `interchainAccountRouter` | `0x1384Ed70…22eF` | `0x2fbF56e1…2E19` | | `proxyAdmin` | `0x735653D2…D775` | `0x79f22212…1FaE` | **Why this release is breaking.** The lane now uses the names the `hyperlane-bridge-infra` repo uses. A consumer can store or compare these values. - `SOMNIA_BRIDGE.id`: `"somniatestnet-hidekitestnet"` becomes `"somniatestnet-hideki2testnet"`. - Every `route.id`: `"WBTC/somniatestnet-hidekitestnet"` becomes `"WBTC/somniatestnet-hideki2testnet"`. - `getBridgeNetwork(ChainId.hidekiTestnet).network`: `"hidekitestnet"` becomes `"hideki2testnet"`. - `getBridgeNetwork(ChainId.hidekiTestnet).displayName`: `"Hideki Testnet"` becomes `"Hideki2 Testnet"`. - `SOMNIA_BRIDGE.displayName`: `"Somnia Testnet ↔ Hideki Testnet"` becomes `"Somnia Testnet ↔ Hideki2 Testnet"`. - `SOMNIA_BRIDGE.docs` points to the Hideki 2 deployment record. **How to migrate.** - **Stored lane ids or route ids.** Update them to the `hideki2testnet` spelling. Config files, dashboards, analytics keys and test fixtures hold these. Compare against `SOMNIA_BRIDGE.id` or `route.id` instead of a literal if you want this to survive the next rename. - **Cached Somnia-side core addresses.** Discard them. Read them again from `getBridgeNetwork`. A cached Hideki 1 mailbox does not fail loudly. It describes a live bridge. That bridge is not the one your routers use. - **Display strings.** `displayName` is presentation text. Pin your own string if you need a stable one. - **Nothing to do** if you call only `createBridgeTransfer`, `sendBridgeStep` or `getBridgeToken`. No router, token or decimal value changed. **Chain definitions do not change.** `hidekiTestnet` and `ChainId.hidekiTestnet` keep their names. Both still resolve to 50383. Only the bridge lane's identifiers move. This release adds no second chain export, because `somniaChains`, `ChainId` and the deployment manifests are keyed by chain id, and both Hideki chains use 50383. **One trap is now documented.** Every Hideki-side address on this lane equals Hideki 1's. The same deployer replayed its nonce sequence onto Hideki 2, and that chain restarted its nonces at genesis. The ISM is derived by CREATE2 from the factory and the shared validator set. A matching Hideki address therefore does not identify the lane. Only the Somnia-side addresses do. The registry header states this. **How this was verified.** Every value was read from the live chains on 2026-09-21. `test/bridge.e2e.test.ts` (`SOMNIA_E2E_BRIDGE=1`) now pins all six core addresses to the lane. It checks that each address holds code. It checks that every warp router binds to the registry's mailbox. It then checks that the mailbox's `defaultIsm`, `defaultHook` and ERC-1967 admin slot agree with the registry, and that `validatorAnnounce.mailbox()` and `interchainAccountRouter.mailbox()` return that same mailbox. It also checks the ISM is a 1-of-1 message-id multisig on the advertised validator. That test fails against the pre-fix registry. It passed before this change only because CI does not set the flag. A live STT round trip from Somnia to Hideki 2 and back delivered in 3.8 s and 3.0 s, and router liquidity returned to its starting values. - BREAKING: `UnifiedTicker.baseVolume` and `quoteVolume` are now optional, and `fetchTicker` no longer fails whole when the candle read fails. `fetchTicker` opened with `getCandles`, an indexer read, and did not contain it. An indexer outage threw before the perp enrichment ran, so a perp trader lost mark price, index price, funding rate, next funding time and open interest — five chain reads that would have worked — to a candle outage. Those numbers decide liquidation risk. The candle read is now contained the way the perp read already was. A new `statsState` field says which state the 24h half is in: - `"ok"` — the window was read. The volumes are present, and they are `0` when the window held no fills. That zero is a true value, unchanged from before. - `"unavailable"` — the candle request failed with an `IndexerError`, or the market is `indexed: false` and no request was sent. Then `open`, `high`, `low`, `change`, `percentage`, `statsAsOf`, `baseVolume` and `quoteVolume` are all absent, the call still resolves, and the perp block still runs. The containment is narrow. Only `IndexerError` is caught; every other error propagates. Migration: `baseVolume` and `quoteVolume` are now `number | undefined`. Read `statsState` before reading them. ```ts // Before console.log(ticker.baseVolume.toFixed(2)); // After if (ticker.statsState === "ok") console.log(ticker.baseVolume.toFixed(2)); else console.log("24h volume unavailable"); ``` The dreamDEX web ticker hook (`web/hooks/use-tickers.ts`) polls `fetchTicker` every 10 seconds and shows the 24h volume. It is the known consumer to update: it gains the outage-resilient perp header, and it must handle an absent volume. - BREAKING: Historical fill pages now require an indexer that serves the `FillDataset` generation. Deploy and reindex the producer before upgrading the SDK; handle `FillHistoryUnavailableError` as a producer rollout failure, and discard accumulated pages and start at page one on `FillHistoryRestartRequiredError`. - Add `SOMNIA_HIDEKI_TESTNET_ADDRESSES` for chain 50383 from the deployment manifest. The preset omits `collateralRouter` and `lend` because Hideki has neither deployment. Their helpers report not-configured. Hideki has no hosted indexer. Supply a consumer-operated `indexerUrl`, which the SDK requires even for chain reads and writes. The mainnet and Shannon presets are unchanged. - Bound how hard one client pushes its indexer. Every indexer read now passes three gates owned by the configured client: a cap on requests in flight, a circuit breaker fed by consecutive endpoint failures, and a jittered backoff schedule. Configure them with the new `ClientConfig.indexerLimits`; the defaults in `DEFAULT_INDEXER_LIMITS` are conservative and only ever reduce load. The gates exist because a slow API used to become a retry storm. A client that retried a 30-second timeout on a fixed 3-second interval added a query to the server instead of replacing one, because nothing cancels an abandoned query. Once every client was doing that, the load sustained itself after the original slow query stopped mattering. What each gate does: - **In-flight cap** (`maxInFlight`, default 12). Further reads queue inside the client, where they hold no indexer connection, and start as earlier reads settle. A queued read still honours its caller's abort signal. The queue is bounded too (`maxQueued`, default 100): past it a read is refused rather than parked, so a client whose arrivals outrun the cap sheds load instead of growing a backlog. - **Circuit breaker** (`breakerThreshold`, default 5 consecutive endpoint failures; `breakerCooldownMs`, default 30 s). While it is open the client sends nothing and fails at once with the new `IndexerUnavailableError`. After the cooling period one trial read decides whether to close the breaker. Only timeouts and the 429/502/503/504 family count: a GraphQL validation error proves the endpoint is alive and resets the count. - **Backoff schedule** (`baseDelayMs`, `maxDelayMs`, `maxAttempts`). The new `nextBackoffDelayMs` helper returns exponential backoff with full jitter, so clients that retry together do not come back together. The caller passes the random draw (`Math.random()`), so it is pure and a polling loop outside the SDK can pace itself on the same schedule. `IndexerUnavailableError` extends `IndexerError`, so existing `instanceof IndexerError` handling keeps working unchanged and every documented error union stays true. For `breaker-open`, `breaker-trial`, and `queue-full`, catch the narrower type to distinguish “we did not send” from “the indexer did not answer”. A `live-reset` can instead end a retry backoff after an earlier attempt was sent. Its `reason` says which gate refused, because the four cases want different things and only one of them is a fixed wait: | `reason` | Your move | | --- | --- | | `breaker-open` | Sleep `retryAfterMs`, then retry | | `breaker-trial` | Retry shortly; the trial read decides | | `queue-full` | Back off on your own schedule, or send less | | `live-reset` | Retry on the same client; `stopLive()` leaves it usable | `SomniaMarkets.close()` stops each engine before it awaits cached watches, so a hydration still queued for a slot is refused rather than waited on; shutdown no longer stretches to the queue ahead of it. `retryAfterMs` is meaningful only for `breaker-open`, and is `0` elsewhere — there the wait is the caller's own backoff, not a period the SDK knows. The boundary itself does not retry. `maxAttempts` defaults to 1, so this cannot multiply retries a caller already performs. Raise it only when nothing above the SDK retries. When a gate refuses a retry after an earlier attempt reached the endpoint, the read fails with that attempt's `IndexerError`, not an `IndexerUnavailableError`: a gate refusal always means nothing was sent. Breaker and cap state belong to the client that owns them. Two clients built against the same endpoint keep separate counters, so one client's outage never fails another client's reads. `stopLive()` closes the client's gate. A read already on the wire still runs to completion, but one waiting for an in-flight slot is rejected with `IndexerUnavailableError` — the client that would have admitted it is gone. Only a caller that exceeds `maxInFlight` concurrent reads can observe this, and the rejection is an `IndexerError`, which every indexer read could already throw. The gates cover live-tail hydration as well as ordinary reads, so a watch cannot add ungoverned indexer load. A limit that would make the governor unusable is rejected with `InvalidInputError` when the client is built: a count that is not a whole number of at least 1, a delay of `0` or less, or any non-finite value. `nextBackoffDelayMs` rejects the same inputs directly, since a zero, negative or `NaN` bound yields a delay every timer fires immediately. `DEFAULT_INDEXER_LIMITS` is frozen, so one consumer cannot retune every client in the process. - Add `client.getOpenOrdersOnchain(pools, owner, opts?)`, which lists an owner's full resting orders from chain at one pinned block, and give `getOwnOpenOrdersOnchain` a `blockNumber` option. `getOpenOrders` is the read a bot uses to list its own resting orders, and it is an indexer read. During an outage it throws, and the dangerous consumer pattern is to wrap it in a catch that returns an empty list: the bot then believes it has nothing resting, so it skips its cancel or quotes again on top of its own live orders. The SDK threw correctly, but offered no equally convenient chain read to point that consumer at. The chain already had every field. What a consumer could not do was join the two existing reads at one block, because `getOwnOpenOrdersOnchain` took no `blockNumber`, and a consumer-side join also cost one un-batched call per order. The new read does the join in two stages at one block: one direct id read per pool, then one batched `getOrder` for every id. The id read is never routed through Multicall3 — the pool's view answers for `msg.sender`, so through an aggregator it would return that contract's empty order set, which is silently wrong rather than a revert. Limits, stated in the TSDoc: the caller supplies the pool list, because resolving pools by symbol is itself an indexer read; rows carry `isBid` and no YES/NO side, which is not derivable on a binary pool; there is no market, symbol or history. `getOpenOrders` is unchanged and does not fall back to chain. - Add `client.getSeedStatus(pool)`, which reports one watched pool's own seed status. `getLiveStatus()` carries one set of seed fields for the whole tail, and each seed overwrites the last. With several watched pools neither flag could be trusted: pool B's seed wrote `seedTruncated: false` over pool A's `true`, and `fillsLoaded` turned `true` as soon as any pool's fill lane landed, even when another pool's lane had failed. Both flags exist to prevent a silent wrong answer, and both were silent again the moment a second pool was watched. `seedTruncated` says a book is short at its deep end. `fillsLoaded: false` says a tape was never loaded, which is a different state from a tape that is genuinely empty (SDK-IO-002). `getSeedStatus(pool)` returns `{ seedSource, seedBlock, seedTruncated, fillsLoaded }` for that pool, or `null` when the pool has no hydrated watch. An entry is written at every site that hydrates a pool: the scoped indexer snapshot, the chain seed, the discover-all snapshot, the fill lane, and a pool discovered live through `MarketCreated`. That last one takes no seed at all — it is born inside the stream — and is recorded as complete from its creation block. A released watch drops its entry, and `stopLive` clears them all, so `null` always means what the accessor says it means. The global fields stay as they are and are now documented as LATEST SEED rather than an aggregate. Deriving them from the per-pool values would have changed what existing single-pool consumers read. N pools is N `watchMarket` calls, which already worked and is now tested and documented as the supported route. The TSDoc gives the read cost: `2 × maxPages` contract reads per pool in the worst case, 80 at the defaults, plus one module read for the market row. - Add `exchange.perpDiscoverySkipped`, which reports that `loadMarkets` did not look for perp pools at all. `loadMarkets` finds the PerpPoolFactory either from a configured `addresses.perpPoolFactory`, or from the `marginBank` of an indexed perp row. With neither — a reachable indexer carrying no perp rows, and no configured address — discovery returned an empty perp set and every error accessor stayed `null`. Nothing failed, so nothing was reported, and a consumer could not tell "this venue has no perps" from "the SDK had no way to look". The new accessor is `{ reason: "no-factory-route" } | null`. It is a separate accessor rather than a variant of `perpDiscoveryError`, because that one is typed `SomniaMarketsError | null` and means something failed. The value resets on every load. It reports "the SDK had no way to look", so it is not set when a read failed. A failed registry read leaves it `null`, because an empty row set is then a symptom of that failure and `registryReadError` already names it. For one engine it is likewise never set together with `perpDiscoveryError`. On a multi-chain exchange both CAN be non-null at once, each reporting a different chain. It is informational, not an alert. A non-null value is normal and permanent on a venue with no perps plane, which is Somnia mainnet today and any local anvil deployment. The TSDoc says so. `config.ts` and `docs/reference/configuration.md` no longer describe `perpPoolFactory` as normally unnecessary without naming this consequence. - Add `client.getPoolMarketBinding(pool)`, which reads from chain alone which market a binary pool currently hosts. The chain seed, `watchMarket(pool, { seed: "chain", marketId })`, needs the pool's current `marketId`. The ordinary source of that binding is the indexer, which is the service that is unreachable when a chain seed is needed. This read closes that gap: the pool names its market and the module maps that address to its id, so a caller can cold-start a live book with no indexer request. Both chain reads are made at one block, and the result carries it. The read resolves to `null` only when the pool's market does not belong to the module; a failed read throws. It verifies the pair before returning it, so a module record that disagrees with the pool throws instead of yielding a binding that would filter a book on the wrong market. `client.getMarketIdOnchain(marketAddress)` is the same reverse lookup for a caller who holds only the market address, such as a market page whose route carries the contract address. The indexer answers that question through `getBinaryMarketByAddress`; this read survives an outage. A chain-seeded `watchMarket` now also rejects a `marketId` that is not the pool's current one. It checks both ways an id can be wrong: the module records that market on a different pool, or the id names a PREVIOUS generation of this same pool. A pool address is stable across recycles, so only the market nonce separates the generations — this is the module's own staleness test. Either mistake previously painted a book that could never advance, with nothing to say so. - Add provider-level chain seeding for selected binary pools and a React hook for each pool's seed status. Pool-watching hooks share the provider policy, so a binary book can start from chain while the indexer is unavailable regardless of hook mount order. - The unified exchange identifies binary rows by market id, not by pool. A binary pool is recycled across successive markets, so `fetchMyTrades`, `fetchOrders`, `fetchOpenOrders` and `fetchBalance` used to label rows from an earlier market with the symbol of the market currently on the pool, and a ref-scoped `fetchMyTrades` or `fetchOrders` on a binary market returned every market that ever used its pool. Rows now resolve and scope by market id. `fetchTrades` is scoped the same way, so the public tape of a live binary market no longer includes the fills of earlier markets on its pool. A settled binary market a wallet still holds a position, a fill or an order in stays resolvable: `fetchBalance` reports the holding under that market's own symbol and `redeem` accepts the symbol, while `fetchMarkets()` keeps listing only tradable markets. A position on a market the indexer cannot name now makes `fetchBalance` throw `IndexerError` instead of silently omitting the key. BREAKING: pool-routed verbs (`createOrder`, `mintSet`, `burnSet`, `fetchOrderBook`, `fetchTrades`, `fetchOHLCV`, `fetchTicker`, `watchOrderBook`, `watchTrades`, `watchOrders`, `watchMyTrades`) throw `InvalidInputError` on a settled binary market, because its pool now serves the next market in the series. Redeem, balances and history remain available. A caller that resolved a settled market by pool address should resolve it by market id or by its symbol from `fetchBalance`. ### Patch Changes - Document market-specific binary collateral decimals and use them in SDK order examples. - Document binary event emitters and chain-specific oracle question links. - Explain that binary pool addresses can host successive markets, and show market-scoped book and outcome-balance reads. - Clarify that Hideki requires a consumer-operated `indexerUrl`, including for clients used only for chain reads and writes. No hosted indexer is provided. Unreachable indexer requests fail with `IndexerError`. - Correct the `UnifiedTicker.lastSource` documentation and the read-tiers reference. `lastSource` is present on both paths that produce a `last`, not only on the candle path. The cached fallback stamps the market row's `lastTradeAt`, so the field is absent only when `last` is absent or that timestamp is null. The previous text described absence as the ordinary stale signal, which understated how narrow that case is. The `read-tiers.md` reference gains the same correction, a corrected `getOpenPositionsWithPnL` row, separate rows for `fetchPositions` and `fetchFundingRate`, and a new section that lists what still works during a main-indexer outage. - Refresh the revert-decoding table (`contractErrorsAbi`) against the current perps contracts. Adds the thirteen market wind-down errors a caller can now hit — `MarketSettled`, `SettlementAlreadyScheduled`, `DelistEscrowActive`, `MarketNotEmpty`, `SettlementParametersNotConfigured` and the rest — which previously reached callers as opaque hex. It also drops twelve signatures no deployed contract can throw: eleven belong to the oracle-adapter surface removed by the Oracle v2 redeploy, and the last corrects `NotExpired(uint64)` to the `NotExpired()` the protocol actually declares. - Document where a stop order's limit price is available. Perp stop rows from `listPerpStopOrders` don't include `limitPrice`; fetch it for live stops with `getPerpStopOrders`. A spot LIMIT stop's limit price can't be read back after placement, so `getSpotStopOrders` and `fetchOpenStopOrders` leave it out. Treat a missing limit price as unknown, never as zero. Documentation only; no behaviour changes. - Count reads now send fixed, named GraphQL documents. The count methods (`countMarkets`, `countBinaryMarkets`, their `Bounded` variants, `countOrders`, `countUserFills`, `countOperators` and `countVenues`) no longer build their query text at call time. Each counted entity has one document for the `_aggregate` count and one for the bounded row-count fallback. A Hasura query allowlist can therefore list every query that the SDK sends. The method signatures, the `{ count, truncated }` result, the 10,000-row fallback cap and the fallback on roles without `_aggregate` do not change. When a count read fails, `IndexerError.operation` now names the entity's own document, such as `MarketCount` or `OrderCountFallback`. Before, it was the shared `Count` or `CountFallback` for an indexer failure, and `aggregateCount` for a response that did not contain the counted field. Update any code that compares `operation` with the old names. ## 0.31.0 ### Minor Changes - Add an ordered batched read for known perpetual stop orders. The read pins every Multicall3 chunk or fallback point read to one block, and preserves known absence and per-order contract or transport failures without discarding neighboring results. - `BinaryMarketFilter` gains `resolved?: boolean` — narrow a binary-market list to markets with an indexed terminal event (`true`) or without one (`false`). Omitted, it does not constrain. It applies wherever the filter does: `listBinaryMarkets`, `listLiveBinaryMarkets`, `listPastBinaryMarkets`, `countBinaryMarkets`. It is a filter on `resolvedAtTimestamp`, not on `status`, and the distinction is the reason it exists. `status` is derived from lifecycle EVENTS, and the timestamp-implicit Listed → Trading → Settling transitions emit none: a market whose oracle never answers stays indexed as `"Trading"` for as long as it is stuck. Selecting unanswered markets by status therefore returns nothing in exactly the case a caller wants them — the query succeeds and the problem is invisible. Every terminal path (resolve or void, on the module event or the market contract's own) stamps `resolvedAtTimestamp`, so its absence is the durable "still waiting". `listPastBinaryMarkets({ resolved: false })` is the pair that names a stuck market: expired, and with no indexed terminal event yet. Note this says nothing about WHEN an unanswered market became late. The protocol's deadline is `expiry + settlementWindow`, and `settlementWindow` is frozen on each BinaryMarket clone at construction — read it from the market's own address, not from the creator's current series configuration, which a later `registerSeries` can change under markets that were already minted. - Books now carry block provenance, and unified trades expose their source block and log position. Chain book reads pin both sides to one block. Live tails recover intervening log ranges and expose failures in status. Optional reconciliation compares native levels at fixed chain checkpoints without replacing order history. Fill and trade provenance fields are optional for caller-built values. SDK reads populate them from the source. Native historical fill blocks use decimal strings; unified trade blocks use bigint. Missing caller provenance remains undefined. - BREAKING: Fill reads gain an inclusive block range, and a new read returns every fill of one market kind in that range across every pool. Custom `SomniaMarketsClient` implementations must add `getFillsPage` and `getLatestFillBlock`. `client.getFillsPage({ marketType, sinceBlock, toBlock })` returns the fills of one market kind in an inclusive block range, across every pool of that kind, oldest first by `(blockNumber, logIndex)`. This is the read behind a published trade feed: it takes no pool, so a consumer never enumerates them. Pages hold 500 rows by default and continue through `nextCursor`. The cursor binds the chain, the endpoint, the kind and both bounds, so a cursor from one range is refused by another. A full page always returns a cursor, because an indexer row limit truncates a page silently; a range that ends exactly on a page boundary therefore costs one empty final page. Prefer the block range to the `since`/`until` window in seconds whenever successive reads must tile the chain exactly. Several Somnia blocks can share a timestamp, so a seconds window drops or repeats the fills in them at every seam. Both block bounds include their block, and `(blockNumber, logIndex)` is a total order over the fill table, so `[a, b]` followed by `[b + 1, c]` reads every fill once. `client.getLatestFillBlock(marketType)` returns the newest block carrying an indexed fill of that kind, with the block timestamp, or `null` when none is indexed. It reads the fill data rather than the indexer's processed-block watermark, so it never names a block `getFillsPage` cannot yet serve. `FillsOptions.toBlock` bounds `getFills`, `getUserFills`, `countUserFills` and `getUserFillsPage` from above, alongside `sinceBlock`. Both bounds are inclusive and merge into one comparison. An inverted range rejects with `InvalidInputError` instead of answering with no rows. `Fill` rows now carry the market kind, and the indexer indexes `(marketType, blockNumber, logIndex)`, so the range read is one index seek and its rows arrive already ordered. Every amount field on `FillRow` stays as a raw decimal string. - Add `trader.cancelAllOrders(pool)`, a kill switch that pulls every resting order the signer holds on one pool. It reads the resting ids and cancels them in one call, so a bot that holds no local ids — after a restart, or after a send with an unknown outcome — does not have to chain a read and a cancel itself. The default source is one chain read. Pass `{ source: "live" }` to take the ids from the live tail instead, which makes the cancel the only round trip; that source needs an active market watch on the pool and throws `NotConfiguredError` without one, because an unwatched tail cannot tell an empty book from an unseen one. An empty book is a success: the result is then `{ sent: false, orderIds: [], outcomes: [] }` and no transaction goes out. Branch on `sent`; a sent result carries the same per-id `outcomes` as `cancelOrders`. The two sources differ on an expired order that still rests. The pool's own open-orders view hides it from the chain source, so the default source leaves it on the book — use `cancelExpiredOrders` for that residue. The live source still lists it and forwards its id, and the cancel goes through: the pool gates a best-effort cancel on owner and id rather than on expiry, so the order is removed and reported `cancelled: true` (its removal emits `OrderExpired`). Add `trader.buildCancelOrders` and `trader.buildReduceOrders`, which return the unsigned call instead of sending it, so a batch cancel or reduce can ride in the same transaction as other writes. Both encode through the same path as the sending verbs, so the calldata cannot differ. - BREAKING: `Candle` gains a required `lastFillId` field and `getCandles` now selects it. `lastFillId` is the id (`${blockNumber}_${logIndex}`, same key space as a fill's id) of the newest fill folded into the bucket — the exact fill-level watermark a live consumer needs to reconcile an open OHLCV bucket against the chain without a separate fills read. Migration: - Reindex first. `getCandles` selects `lastFillId`, so it errors against an indexer whose schema predates the field. Deploy the matching `indexer/schema.graphql` and run a full reindex before upgrading the SDK. - Constructing `Candle` values? Add `lastFillId` (a `${blockNumber}_${logIndex}` string). Read-only consumers just receive the new field. - BREAKING: `BinaryMarket.strike` and `BinaryMarket.mode` are now nullable. A chain-seeded row cannot know either, and reporting a guessed `"0"`/`"reference"` would mislabel a fixed-strike market as up/down. Narrow both before use; a row read from the indexer always carries them. A market watch can now start without the indexer. `watchMarket(pool, { seed: "chain", marketId })` seeds the book from the pool contract at one pinned block, so a trading view paints while the indexer is unreachable. The option is opt-in: a `watchMarket(pool)` call with no options keeps the indexer snapshot and the existing meaning of `snapshotBlock`. Supply the market id the pool currently serves, because pools are recycled across markets and book reads filter on it. The seed reads that market's row from the BinaryMarketsModule alongside the book, so a chain-seeded watch needs `addresses.binaryModule` configured and covers exactly one pool. The row is what every later order and fill event attributes through. It carries what the module answers — collateral, decimals, nonce and lifecycle state — while indexer-only fields (the question text, the creation history, the traded volume and the origin attribution) stay empty. These do NOT fill in later: a pool that has been seeded is not re-hydrated, and the row survives `stop()`, so the seeded row persists for the store's lifetime. Read the indexer directly when the prose is needed. A chain seed never blanks a richer row. If the same pool was watched from the indexer before, that row's indexer-only fields survive the seed field by field, while every field the module answers is replaced by the fresher chain read. `BinaryMarket.strike` and `BinaryMarket.mode` are now `string | null` and `BinaryResolutionMode | null`. A chain-seeded row carries null for both, because the pool contract answers neither and a strike of `0` is the protocol's sentinel for reference (up/down) mode — writing it would permanently mislabel a fixed-strike market. `boundaryPrice` returns `null` for such a row, which every surface already renders the same way it renders an unposted opening answer. An indexer-sourced row is unchanged and always carries both. Seeded orders likewise carry an empty `createdAt`/`txHash`, so they sort last in `userOrders` until a snapshot dates them. `getLiveStatus()` reports four new fields. `seedSource` says whether the book came from the indexer or the chain, and is `null` before the first watch. `seedBlock` is the block the seed was consistent to. `seedTruncated` is true only when a chain seed reaches its own page budget and read a shallow book. `fillsLoaded` says whether fill history was loaded, which a chain seed does not load: `getLiveFills` returning an empty array now means "never loaded" when `fillsLoaded` is false, and "no fills in the loaded range" when it is true. A failed fill read reports `failure.operation` as `"fill-history"` and leaves the chain-seeded book intact. `getAllOpenOrdersOnchain` accepts `blockNumber`, so a multi-page snapshot of one side can pin every page to one block. - Add `client.getBookTopsOnchain(markets, opts?)` and give `fetchTicker` provenance fields. `getBookTopsOnchain` reads the top of book for many markets from pool state, at one pinned block. It is the chain-sourced sibling of `getBookTops`, which keeps its signature and its indexed source. Use the new read where a quote must not lag behind the indexer, such as a market board or a mark for open positions. Pass the market rows a view already holds; each supplies its own `poolAddress`. The result carries the block every top was read at, plus a map keyed by lowercased market id. A market with an empty book is absent, the same contract the indexed read documents, so the two are comparable key for key. Where the chain declares a Multicall3 the reads collapse into one aggregate call; elsewhere they fan out at two reads per market, so keep the market set to what a view shows. `UnifiedTicker` gains three fields. `lastSource` carries the time of the trade behind `last`, and its absence now means `last` fell back to cached market metadata that can be stale. `statsAsOf` carries the 24h statistics' own as-of, derived from the candle window rather than the response time; `timestamp` is unchanged and remains the time the snapshot was assembled. `perpState` reports one of `"not-applicable"`, `"ok"`, or `"degraded"`, so a missing `markPrice` on a perp whose chain read failed is no longer indistinguishable from a spot market. The perp enrichment still degrades to the 24h statistics rather than failing the whole call. `getOpenPositionsWithPnL` now marks positions from the chain-sourced tops. It previously marked from indexed tops while `getBinaryPositionPnL` marked from chain, so the same position could report two different `unrealizedPnl` values when the indexer lagged. A client configured without chain access still marks on last price, as before. - Retain collateral balance read failures by chain in `CollateralOnWrongChainError.readErrors` and its aggregate cause. Inspect `exchange.collateralReadErrors` after a successful funding operation to detect an incomplete sweep. Sort `unread` in the error constructor, including for directly constructed errors. - Add `CollateralOnWrongChainError.unread` to list chains whose balance read failed. The error message also names these chains, so callers can distinguish failed reads from zero balances. `elsewhere` keeps successfully read balances. `unread` is empty when all reads succeed. - BREAKING: `FillRow` gains two required fields, `takerRemainingQuantity` and `makerRemainingQuantity`. `getFills` and `getUserFills` now return the post-fill remainders — the two raw-unit amounts the `OrderFilled` event carries. A caller can now tell how much of each order was left after a fill directly from the tape, without a second read and without keeping a running total. `getFill`, `getOrderFills` and `getTradeContext` already selected them, so every fill read is now consistent. Migration: code that READS a fill row needs no change. Code that CONSTRUCTS one — a test fixture, a mock, or a synthetic row passed to `pnlEventsFor` or `binaryFillsFor` — must add the two fields. Both are decimal strings in raw base/outcome units, and `"0"` means the fill completed that side's order. - Populate the Hideki (50383) deployment manifest with the live CLOB family, deployed at the same CREATE3 addresses as testnet and mainnet. The `hideki-testnet` deployment resolves real addresses instead of the sentinel-zero template; the CollateralRouter stays absent on Hideki (no wSTT/Permit2 there), so router-dependent helpers keep reporting not-configured on that chain. - BREAKING: `hidekiTestnet` (50383) now points at the **v2 regenesis**, a different genesis reached through different endpoints. Chain id `50383` has changed meaning: anything you cached, indexed or hard-coded against Hideki before 2026-09-17 describes a chain this definition no longer reaches. **Why it is breaking even though the id is unchanged.** Hideki was rebuilt on 2026-09-17 on the SAME chain id with fresh state, and the deployer's nonces restarted at genesis. So an address is no longer a stable identifier across the two chains: most v1 addresses hold a *different* contract on v2, while a few — the whole binary/CLOB family, because it is deployed via CREATE3, and the bridged USDso synthetic — come back at the *same* address. That mixture is the hazard. A stale cache does not fail loudly; it silently answers with the other chain's history. **Migration.** - **To move to v2 (recommended):** take the new definition and **discard every piece of Hideki state you hold** — indexer databases, address caches, block-height watermarks, saved deployment manifests. Do not reconcile v1 addresses against v2 ones, and do not carry a v1 start block across: v1 is past 586M blocks while v2 is near 2.4M, so a v1 watermark parks you at a head v2 will not reach for a long time. - **To stay on v1:** pin `@somnia-chain/markets-sdk` to the previous minor, or construct the chain yourself with viem's `defineChain` using the v1 host `api.hideki.infra.testnet.somnia.network` and Multicall3 `0x540B091b608f54E603c5dC19F6b2d955e1d2D131`. Note v1's `/ws` already answers 502, so a websocket consumer is already broken there. - **Tell the two apart by height, never by chain id** — nothing in a signature, a wallet or this definition distinguishes them. **What changed in the definition.** The `api.hideki2…` HTTP and websocket endpoints, and the **canonical** Multicall3 at `0xcA11bde0…`, which v2 predeploys at block 1 — the reverse of v1, where the canonical route was unreachable and the bridge infra deployed the same runtime at `0x540B091b…` (which holds no code on v2). `net_version` moved `50000258` → `50000259` and still is not the chain id. **The bridge lane was redeployed with it.** All five **Shannon-side collateral routers** moved (STT, USDso, WBTC, WETH, HBTT); everything on the Hideki side — every synthetic and the whole core deployment (mailbox, ISM, merkle hook, validator announce, ICA router, proxy admin) — came back at its v1 address, because the same deployer replayed its sequence onto a chain whose nonces had restarted. All ten routers were re-read on chain and enroll their counterpart in both directions. Relayer delivery on v2 is not yet proven. **Scope.** This injects the **perps** plane only. The binary/CLOB family was the other half of the problem when this branch was cut — every one of its addresses was codeless on v2 — and that is now **resolved on `main` by TRAD-363**, which replayed the CREATE3 salt generations so the family came back at the same shared addresses; nothing here overlaps it. Spot is the remaining gap and it is a gap in coverage, not a stale record: dreamDEX spot **is** live on v2 as of 2026-09-18, but `spot-tokens.hideki-testnet-development.json` is still the empty sentinel it has always been, so those markets are simply not indexed yet. That is left for the plane's owners rather than guessed at here. - Add `getOrderHistoryPage` as the preferred name for paginated indexed order history while retaining `getOrdersPage` as a compatibility name. - Add opt-in indexer freshness and response-associated read observations through `client.getIndexerFreshness()` and `client.createObservedReads()`. The existing `getSyncStatus()` remains metadata-only and `fetchStatus()` remains local-only; `fetchDataStatus()` combines independent data-source measurements. Add precise per-asset delivery health through `getPriceHealth()` and `listPriceHealth()`, alongside unchanged legacy price status. Add `useWatchMarketResult`, `useWatchUserResult`, and `useWatchPriceResult` for typed acquisition errors while existing hooks retain their background warning behavior. - `listLiquidations` returns liquidation events with an optional `kind` filter, applied server-side. It replaces `getLiquidations`, which returned an array under a `get*` name. The old name forwards the filters verbatim and is deprecated, the same one-release compatibility path `getFundingRateHistory` took. Liquidation rows now come back in a stable total order: `timestamp`, then `blockNumber`, then the `id` primary key. Previously the query sorted by `timestamp` alone. Every row a block emits carries that block's timestamp, so ties had no defined order between requests and an `offset` page boundary landing inside one block could skip a row or repeat it — silently, in the skip case, and even against a table nobody was writing to. This fixes the tie ordering. It does not make offset paging snapshot-consistent: these are live rows, so an event indexed ahead of your offset still repeats a row and a reorg that removes one still skips a row. Paging the read is approximate; narrow with `account`, `pool` and `kind` when it must not be. This changes the order of rows that tie, so a caller that depended on the previous arbitrary tie order sees a different sequence. No row is added or removed. `LiquidationEvent` rows are stages of one mechanism, not repetitions of one event. A single cascade therefore emits many rows. Without the filter, a page can be consumed entirely by one account's summary and per-position legs, and a caller looking for a different kind concludes there were none. `kind` is matched exactly, in the schema's own casing. It is typed as `LiquidationKind`, a new exported union over the `LIQUIDATION_KIND` values. A misspelling is now a compile error rather than a silently empty page. `LiquidationEvent.kind` stays a `string`: a row carries whatever the deployed indexer wrote, which can outrun a pinned SDK. The exported `isLiquidationKind` guard bridges the two — narrow a row's kind to switch on it, or to pass it back into the filter. `getPerpFeedStatus` reads whether a perp pool's mark feed is live and how much open interest is riding on it. Prefer it to `getPerpState` for MONITORING a feed. `getPerpState` batches with `allowFailure: false` and one of its legs is a bare `IOracle.getPrice()`, so a dead or rotated oracle rejects the whole read — losing the mark verdict in the one case it matters most. `getPerpFeedStatus` reads the mark verdict and the open interest as a required pair that no oracle can revert, and takes the index timestamp best effort: a reverting index leg leaves `indexUpdatedAt` undefined instead of failing the call. It returns `PerpFeedStatus` and throws `SomniaMarketsClientGetPerpFeedStatusError`. Read `getPerpState` instead when you want the full pricing and funding picture and a dead oracle is a legitimate reason to fail. `listRegistryMarketsChecked` is `listRegistryMarkets` with the rows the SDK could not parse counted, as `{ markets, dropped }`. A malformed row is dropped rather than failing the page, so the plain read's length cannot tell "no markets" from "markets this SDK could not parse". `dropped > 0` says the registry holds markets the sweep did not return. Use it wherever absence from the sweep is treated as proof - a monitor publishing coverage over it, say. It returns `RegistrySweep` and throws `SomniaMarketsClientListRegistryMarketsCheckedError`. The two new options (`kind`, and `offset` on the new name) are additive. The ordering change is not: it is the one thing in this release an existing `getLiquidations` caller can observe, and only for rows that share a timestamp. - BREAKING: Order and fill reads gain the filters a client needs to find its own work, and the client can wait for the indexer to catch up. Consumers that construct `OpenOrder` or `OrderRow` values must add `userData`. Custom `SomniaMarketsClient` implementations must add `waitForIndexedBlock`. `getOpenOrders` and `getOrders` now return each row's `userData`, the opaque uint64 tag the placement carried, as a decimal string. `OrdersOptions.userData` filters on it, so a client correlates rows with the orders it sent instead of keeping its own map. `OrdersOptions.market`, `OrdersOptions.pools` and `OrdersOptions.markets` scope one read to a market, or to several venues or markets at once, so the order scope now mirrors the fill scope in both forms. An empty array matches nothing. Supplying a singular scope with a list intersects both constraints. A list is capped at 100 entries to bound the generated GraphQL predicate; pool entries also require classification reads. Fill `market`, `markets` and `pool` identifiers must be non-empty strings. Invalid runtime values now reject with `InvalidInputError` instead of reaching the indexer or leaking a JavaScript type error. `getOpenOrders`, `getOrders` and `countOrders` now require a non-empty owner string before normalization. `getUserFills` and `countUserFills` require a non-empty account string. `getOrderFills` also requires a non-negative bigint or canonical unsigned decimal order id. Invalid runtime inputs reject with `InvalidInputError` before network I/O. `SomniaMarketsClientGetOrderFillsError` exports the complete `InvalidInputError | IndexerError` contract for the one-order fill lookup. `sinceBlock` bounds order and fill reads by block. On fills it bounds `Fill.blockNumber`, which is the exact resume point after processing up to a known block; a bound in seconds cannot be exact, because blocks share timestamps. On orders it bounds the PLACEMENT block. It does not report a later amend, fill or cancel of an order placed before the bound. `client.waitForIndexedBlock(chainId, block, opts)` resolves once the indexer has processed a block, reporting the wait and the lag it started from. It rejects with the new `IndexerWaitTimeoutError` when the deadline passes, which is a different decision from a failed read. The wait ends when the client's configured signal, its own `signal`, or the owning client's live-read lifecycle closes. A later wait relinks to the replacement owner signal. Indexer request deadlines remain enforced while a successful HTTP response body is being parsed. Caller cancellation still keeps its exact reason; an SDK-owned deadline rejects with `IndexerError`. None of these columns is indexed. Pair a tag or block bound with a pool scope and a status to keep the scan small. - Write the perp linked-wallet rail, not just read it: `proposePerpWalletLink` / `acceptPerpWalletLink` / `cancelPerpWalletLinkProposal` / `unlinkPerpWallet` for the two-sided consent handshake, and `repayPerpMainFunding` / `recallPerpMainFunding` for both routes home. Isolated margin on perps is one wallet per position, and linking a sub-account was previously reachable only through raw viem. - Size a linked child's perp order off both funding wallets, the way the pool funds it. `previewPerpOrderMargin` and `getMaxPerpOrderSize` under `autoPull` now resolve the funding payer and add the main's wallet capacity as a second leg, judge a partial pull by the margin gates rather than requiring full top-up coverage, and withhold the main's leg while the child still owes a prior payer. New `fundingPayer`, `mainWalletCapacity`, `ownWalletPull`, `mainWalletPull` and `mainFundingBlocked` fields, plus `"mainWallet"` and `"mainFundingBlocked"` on `limitedBy`. `topUpRequired` is the total requested, not one wallet's debit. - Add a watchable perp plane, so liquidations and funding settlement can be streamed. `client.watchPerpMarkets()` hydrates the recent liquidation waterfall legs and per-account funding settlements from the indexer once, backfills the seam from chain, then streams both from MarginBank and LiquidationEngine — the same snapshot-then-live guarantee `watchMarket` gives a book, and a reconnect heals from chain with no second indexer touch. Read them with `listLiveLiquidations` / `listLiveFundingPayments`, or the `useLiveLiquidations` / `useLiveFundingPayments` / `useWatchPerpMarkets` hooks. Rows are the same `LiquidationEvent` and `FundingPayment` types the one-shot reads serve, in the same order, so a live page and a paged history merge by `id`. They overlap, because the live window is hydrated from the newest indexed rows. All seventeen waterfall kinds are produced. One scope covers the whole venue rather than one per pool: both sources are singletons, and the account-level legs carry no pool, so filtering is at read time. `getPerpPlaneStatus()` reports the watch state, and `TailStatus.watchCount` now counts the plane as one scope so a plane-only session no longer reports itself idle while streaming. On a deployment with no plane — no perp market indexed, or a MarginBank naming no liquidation engine — the scope registers, answers empty and reports `"live"` rather than waiting forever on a stream that has no source. The indexed `getFundingPayments` now orders by `(timestamp, id)` rather than by timestamp alone, matching what `listLiquidations` already does for liquidations with `(timestamp, blockNumber, id)`. Settlements share a block timestamp, so without a tie-break which rows a `limit` kept at a page boundary was undefined and the live and indexed halves of the same feed could disagree about which rows exist. The live store and the plane hydration sort on each row type's own total key, so all three paths page identically. React: `useWatchPerpMarkets(opts?)` takes one options object (`enabled`, `marginBank`), the two read hooks take the same options object as their client members, and `useWatchPerpMarketsResult` exposes the typed acquisition failure that the warning-only hooks otherwise turn into an empty feed. `TailStatus.watchCount` also counts a discovery-only `watchAllMarkets(true)` as one scope, and a socket drop on such a session is now healed: the reconnect guard and its recovery set were built from pools alone, so a venue with no market yet held the factory socket, reported an idle tail, and never backfilled a `MarketCreated` missed during the outage. A released all-markets watch now stays counted and healed through its release linger too. A block whose only logs are ones the tail does not fold (such as MarginBank's `PositionUpdated` or `FeeCharged`) no longer wakes store subscribers. After `stopLive()` the plane's last rows stay readable, like every other live read; `getPerpPlaneStatus()` then reports `"unwatched"`. - `getPerpPositionAnalytics` and `listPerpPositionAnalytics` now return the position's signed `size` on an unpriceable row, alongside `pool` and `asOfBlock`. Only the pool's price read fails in that case; the MarginBank position read succeeds at the same block, so the size was already known and was being discarded. A caller could not tell a position nobody can price from no position at all, and the bank's `activePerpPools` list covers pools the account has orders in as well as pools it holds a position in — so an order-only pool with a stale mark feed arrived indistinguishable from a real position and rendered as an empty row. Filter on `size !== 0n` to drop those. - `getOrderOnchain` accepts a trailing options object with `blockNumber`, so an order can be read as of the end of a past block rather than only at head. `SomniaMarketsClientGetOrderOnchainError` is exported alongside it. This recovers a maker order a fill already removed. A fill deletes its maker order in the same transaction, and `OrderFilled` names the maker only by id, so at head that order is gone; `fill.blockNumber - 1n` is the last height holding it. What comes back exactly is the maker's identity - `isBid`, `owner`, `userData`, `expireTimestampNs` - which no fill log carries and a consumer cannot otherwise resolve for an order that rested before its process started. Everything else is already in the event: `fillPrice` (a fill executes at the maker's resting price, so this IS the maker's price), `quantityFilled` and `makerRemainingQuantity`. Both quantities are block-level, not per-fill. A block read cannot see between transactions, and an earlier transaction in the fill's own block can move either one: a fill lowers `quantityRemaining`, and `reduceOrder` lowers `fullQuantity` and `quantityRemaining` together under the same id. Two cases answer plausibly rather than failing, so both are documented on the option: a partial fill leaves the maker order in place with a smaller `quantityRemaining`, so a read at the fill's own block succeeds with different numbers; and an order placed and filled inside one block is absent one block earlier, where the placement is in that same block's `OrderPlaced`. A pinned read far behind head needs a node with archive state, so this suits a live tape rather than a backfill. A negative block is rejected with `InvalidInputError`. - `getVaultBalance` accepts an optional `blockNumber`, so a vault balance can be read as of a past block rather than only at head. A caller answering one request from several reads needs them all at one height. The withdrawable balance is contract state behind an append-only payout history, so no indexed entity reconstructs it at a past height, and serving this half at head mixed heights inside one response. A pinned read far behind head needs a node with archive state; a recent block answers against a full node. - BREAKING — `pnlEventsFor` now rejects rows carrying a malformed number `pnlEventsFor` reads each row's `id` for the first time, to order events by chain position, and throws `InvalidInputError` when it cannot: an `id` that is not `${blockNumber}_${logIndex}`. Previously `id` was not read at all and ordering used the timestamp alone, so a malformed `id` was simply ignored, leaving that row wherever the input happened to put it. It now has to be well-formed, because a row that cannot be placed in chain order cannot be folded into an average-cost roll without silently changing the result. The same check now covers every number the fold reads: `FillRow.quantity`, `FillRow.fillPrice`, and a router action's `amount`. These went through a bare `BigInt` before, which threw a native `SyntaxError` on `"abc"` — an error outside the documented error union of this function and of both client methods that wrap it, so a corrupt row escaped as something no consumer was told to catch. **Migration:** rows from `getUserFills` and the router-action reads already carry well-formed ids, so callers passing indexed data through are unaffected. A caller assembling its own `FillRow`/`RouterActionRecord` values — test fixtures especially — must set `id` to `` `${blockNumber}_${logIndex}` ``, and must give `quantity`, `fillPrice` and `amount` as unsigned decimal strings. EVERY one of those positions is now checked the same way: a sign (`"+1"`, `"-1"`), an `0x`/`0o`/`0b` prefix (`"0x10"`), surrounding whitespace (`" 7 "`), or an empty string is REJECTED rather than coerced. `BigInt` accepted all of them, so a fixture that happened to use any of those forms parsed before and throws now — normalize those fields to plain decimal digits. `timestamp` is no longer read at all, so its value cannot affect the fold. The new `PnlEventsForError` export names the error union. `getBinaryPositionPnL` and `getOpenPositionsWithPnL` fetch their own rows, so the same failure means the INDEXED data is corrupt rather than that the call was wrong. Those two report it as `IndexerError` — the retry-or-escalate path — with the parse failure on `cause`. A consumer catching `InvalidInputError` around either method to surface "bad arguments" must add an `IndexerError` arm. `SomniaMarketsClientGetBinaryPositionPnLError` is now exported and names that method's full error union. ### Fixed — same-second PnL events are folded in chain order `pnlEventsFor` ordered events by their unix-second timestamp alone. Fills are fetched newest-first and the sort is stable, so two events sharing a second stayed in reverse chain order: a buy and a sell in the same second were folded sell-first, the sale was clamped against a leg the buy had not yet opened, and the realized profit disappeared. Events are now ordered by the (block, log) position their ids already encode, as exact integers, and by nothing else. The timestamp is metadata rather than a chain position: leading with it lets a wrong one override the position it disagrees with, and it can never break a tie the position cannot, since a chain's timestamps are monotonic in block height. Figures change only where that ordering actually mattered: an account with two events whose result depends on which came first — a buy and a sell of the same outcome, or a mint and a sell of what it created. Two buys, or events on independent legs, or input that already happened to be oldest-first, are unaffected. ### Fixed — closing an outcome leg now releases all of its cost basis `computePositionPnL` released cost basis through a rounded average cost, so closing a leg completely could leave a sliver of cost behind on a leg that held nothing. A leg of 7 raw outcome-token units costing 5 raw collateral units has an average that does not divide evenly, and a full sale released only 4 of those 5 units. Two consequences, both small per trade and neither self-correcting: - The realized PnL of that sale was overstated by the unreleased remainder. - The remainder stayed on the leg after its quantity reached zero. Because average cost is total cost divided by quantity, anything bought on that leg afterwards inherited the leftover, so its average cost read high for the rest of the position's life. A sale that takes a leg's whole quantity now releases the leg's whole remaining cost, leaving it genuinely empty. Partial sales are unchanged and still release cost proportionally through the floored average. The size of a single correction scales with the position: the released cost was short by up to one raw unit per whole outcome token on the leg. A five-token close was off by units, a five-thousand-token close by thousands of them - a few thousandths of a collateral unit at six decimals - and a five-million-token close by around five whole units. Corrections accumulate across repeated full closes of the same outcome, so an account that has opened and closed a leg many times sees the largest movement, and any figure cached from a previous version may differ by that accumulated drift. - BREAKING: a live price watch now requires `priceFeed.quote`. Without it `watchPrice` rejects with a `NotConfiguredError` naming the key. To migrate, pin the feed to one quote - `priceFeed: { url, quote: "USDC" }`, which is what `SOMNIA_TESTNET_PRICE_FEED` and `SOMNIA_MAINNET_PRICE_FEED` already do, so configurations built from those constants need no change. The one-shot reads (snapshot, history, candles, batch prices, feed catalog) are unaffected and still work without a quote. The reason is the tick tape below: it now streams on a `requestId` cursor, and one upstream request prices every symbol in a tick, so that id is unique within a single feed but not across a base that spans several quotes. Such a stream can carry two rows sharing an id, and a batch boundary falling between them would skip the second permanently. An unpinned base was already double-counting on this path; refusing it is the alternative to silently losing ticks. The live price tape now streams only the ticks recorded since the last one delivered. It subscribed with a fixed window and re-sent that whole window on every push, so a watcher paid for one hundred rows to learn about one new tick. The tape is now a Hasura stream cursored on `requestId`, seeded from the newest tick in the hydration snapshot and advanced on every push, so a reconnect resumes exactly where it stopped with no gap and no re-delivery. The current price feed is unchanged: it is full-state, and re-subscribing is all it needs. The cursor is carried as an exact decimal string and compared as a `bigint`. A `requestId` past 2^53 would otherwise round when it went through a JavaScript number, and a cursor that rounds up skips the tick it lands past. A row whose `requestId` is unusable can no longer corrupt the cursor; it is ignored, and the rest of the batch still advances it. `PricePoint.raw.price` and `PricePoint.raw.ema` now report `"0"` for a tick the feed recorded with no price, matching the `price` and `ema` numbers beside them. They previously reported `null` despite being typed as strings. A price subscription the server rejects is now reported instead of passing unnoticed. Only a dropped socket was surfaced before, so a rejected subscription left the tape silent while the feed still read as connected. Rows arriving from the feed are checked against the fields the parsers actually read. A row short of the selection set, or carrying a non-string where a price belongs, is skipped rather than parsed into a malformed tick. - Two new root exports align a raw on-chain value onto a venue's grid: `snapRawToGrid(raw, step, direction)` and `roundPriceToTick(price, tickSize, direction)`. Both take and return `bigint`. They serve the engine path. A caller who holds raw values and calls `Trader.placeOrder` directly had no exported helper for this, so each one re-derived tick and lot rounding by hand. The unified facade already snaps for itself, so `exchange.createOrder` callers do not need these. `direction` is `"down"` or `"up"` and belongs to the value, not to the order side. A resting limit rounds toward the caller. A crossing limit rounds away so it still sweeps the levels it was priced against. Pass the direction you mean. Use `roundPriceToTick` for a price. It never returns `0`, which is the one price the pool always rejects: a positive price below one tick comes back as one whole tick. `snapRawToGrid` floors a quantity to `0` instead, because an empty size is a real answer the caller must branch on. Both throw `InvalidInputError` on a non-positive step. Neither checks `minQuantity`, which the pool tests before lot alignment. - BREAKING: four reads no longer report a failed read as an absent or a zero value. A read that did not complete now throws `RpcError`. Each read keeps its own documented `null` for a real absence, and that meaning is now narrow and stated per read below. - `getClosingPrice` returns `null` only for a pool that does not declare `closingPrice()`. A transport failure throws `RpcError`. A revert that names an error or a reason throws `ContractRevertError`. Migration: keep treating `null` as "this pool predates the capture surface", and handle a thrown error as a failed read. - `tryGetPerpLeverageImSurcharge` returns `null` only for a revert from the view itself, which is the case it is named for. A read that never reached the chain throws, and so does a `marginBank` address that does not declare the view. Migration: in a health sweep, catch the error per account if the sweep must continue, and report that account as unknown rather than as having no surcharge. - `getSystemInfo` throws when any configured contract read fails. The one exception is `settlement()`: a pre-v2 module does not declare that view, so its absence still reports `settlement: null` and the configured fallback. It no longer resolves with `marketCount: 0n`, `operatorId: 0`, and a zero `venueId`, which a dashboard could not tell apart from a freshly deployed creator. Five leaf fields are no longer nullable: `MarketCreatorInfo.owner`, `SystemInfo.oracle.owner`, `SystemInfo.oracle.binaryModule`, `SystemInfo.usdc.symbol`, and `SystemInfo.usdc.decimals`. Migration: handle a thrown error where the call is made. Keep the checks on the `marketCreator`, `oracle`, and `usdc` objects themselves, because each is still `null` when its contract is not configured; only the checks on the five leaf fields inside them can go. - `getTransactionSummary` returns `null` for a malformed hash and for a transaction the node reports as not found. A read that did not complete throws. Migration: if the previous best-effort behavior is what you want, add `.catch(() => null)` at the call site. `PriceFeedStatus` gains an `"error"` member. It means the price-feed server rejected or terminated that asset's subscription. This was previously dropped in silence: the status stayed `"live"` while the price froze. Reads keep answering with the last values they hold, so check the status before rendering a price. The rejection is also emitted as a `warn` event on the client's debug channel. The subscription is torn down, so stopping the watch and starting a new one re-subscribes from a fresh snapshot. Migration: handle `"error"` wherever you switch on `getPriceStatus` or `useWatchPrice`. - BREAKING: `loadMarkets()` no longer throws when the market registry read fails. It contains that failure and reports it through the new `registryReadError` accessor. An unreadable indexer used to end the whole load. That also ended perp discovery, which reads the PerpPoolFactory and needs no indexer once a factory is configured. An empty indexer was worse: it returned an empty market list that no caller could tell apart from a venue with no markets. Both cases are now answerable. `registryReadError` is `null` when the read completed and holds the typed error when it did not — in practice an `IndexerError` carrying `operation` and `detail`, with the underlying failure in `cause`. So `registryReadError === null` together with an empty `symbols` is the unambiguous "this venue has no markets". The value is cleared on every load that runs, so it always describes the last one. Retry with `loadMarkets(true)`, because a bare `loadMarkets()` early-returns the cached registry. Migration: replace a `try`/`catch` around `loadMarkets()` with a `registryReadError` check after it. ```ts await exchange.loadMarkets(); if (exchange.registryReadError) throw exchange.registryReadError; ``` Discovery coverage per market kind is now stated on `loadMarkets`. Perp is chain-complete and survives an empty or unreachable indexer, but with no indexed perp row the factory is found only from a configured `addresses.perpPoolFactory`. Binary and spot still come from the indexer in this method; new binary markets are discovered from the chain by `watchMarkets({ discover: true })`. - BREAKING: `IndexedOperator` and `IndexedVenue` gain a required `updatedAtBlock` field. Reading rows is unaffected — `listOperators`, `getOperator`, `listVenues` and `getVenue` simply return more than before. But if you CONSTRUCT either type anywhere (a test fixture, a mock, an adapter that builds rows by hand), that object literal no longer compiles: ``` error TS2741: Property 'updatedAtBlock' is missing in type '{ … }' but required in type 'IndexedOperator'. ``` To migrate, add the field to each literal you own. It is a `bigint`, so `updatedAtBlock: 0n` is enough where the value is not meaningful to your test. Reach for it when you need to tell two writes apart. Somnia blocks are ~100ms, so roughly ten consecutive blocks carry the same `updatedAtTimestamp` — a value that changes and changes back inside one second leaves the timestamp unmoved. The block number moves whenever a tracked write lands in a later block, so it is the field to difference against when "was this row written?" matters more than "when, roughly?". **It tracks CONTROL-PLANE writes, not every write to the row.** The indexer stamps it on the registry events and deliberately not on denormalized rollups, so market counts, cumulative volume and collected fees rewrite the row with this field unchanged. Without that exclusion ordinary trading would move it constantly. The consequence for you: an unmoved `updatedAtBlock` means no tracked control-plane event landed, NOT that the row was never written. **The two rows move on different events, and the sets are not the same.** `IndexedOperator.updatedAtBlock` moves on `OperatorRegistered`, `OperatorUpdated`, `OperatorEnabledChanged`, the three ownership-transfer events, and `VenueCreated` — that last one because creating a venue bumps the parent operator's `venueCount`. `IndexedVenue.updatedAtBlock` moves on `VenueCreated`, `VenueUpdated` and `VenueEnabledChanged`, and on no operator event at all: an ownership transfer leaves every venue marker where it was. Do not difference a venue marker expecting to see one. **It distinguishes updates across blocks, and nothing narrower.** It is not a write counter and does not identify a write: two updates in the SAME block carry the same number, so differencing this field sees them as one. If you must not miss a write within a single block, read the events rather than this column. It is typed `bigint`, not the raw decimal string its neighbouring columns use, because a block number is a protocol integer and `SDK-TYPE-007` requires those to be exact at the boundary — the generated wire string is now mapped to `bigint` behind the four reads above rather than handed through. The strings beside it predate that seam and are unchanged. A row whose `updatedAtBlock` is not an unsigned decimal integer now fails those four reads with `IndexerError`, naming the GraphQL document, rather than escaping the SDK as a native `SyntaxError` a caller narrowing on `IndexerError` could not catch. The shape is checked before conversion rather than relying on `BigInt` to throw, because `BigInt` accepts more than the wire format allows: `""` and whitespace become `0n`, `"0x10"` becomes 16, and a leading minus is taken as a sign. Those are the malformed values likeliest to arrive, and every one of them would otherwise have surfaced as a plausible block number. **This rejects the whole read, not the row.** A single malformed `updatedAtBlock` fails `listOperators` / `getOperator` / `listVenues` / `getVenue` outright; there is no partial result that skips the bad row. - BREAKING: `UnsignedCall` now carries `chainId` (and `functionName`). Pluggable transaction signing: the executor seam. Migration: every `build*` verb already stamps it, so a consumer that only READS unsigned calls changes nothing. Code that CONSTRUCTS an `UnsignedCall` itself (a custom relayer or bundler feeding calls to an executor, a test fixture pinning the shape) must add `chainId: `; every built-in executor refuses a call without a matching one. `functionName` is optional on a hand-built call (it only feeds error messages) and is set on every call the SDK builds. `createTrader({ executor })` takes any `Executor` — who signs and sends, separated from what the write is. The built-ins come from `client.createExecutor(spec)`: a private key or local account, a wallet client, a Somnia session seed, or a safe driven by any inner executor (with optional `MultiSend` batching, so an approval and the order it enables land in one safe transaction). Any object implementing `Executor` works too. - The writer hands an executor one or more `UnsignedCall`s and decodes the result from the receipt the executor returns; it never fetches a receipt it already has. A safe's swallowed revert surfaces as `ContractRevertError`, exactly like a reverted receipt. - An approval or operator grant a write needs rides in the SAME executor call as the write (one safe transaction through MultiSend; one transaction each, in order, for an executor that cannot batch — which stops at the first revert and never sends the calls behind it). - Whatever a custom executor or signer throws crosses the boundary as an SDK error with the original as `cause`; a local signer's own failure now surfaces as `RpcError` rather than raw. - `UnsignedCall` now carries `chainId`. Every built-in executor refuses a call for another chain with `InvalidInputError` before anything is signed (`assertCallsOnChain` is exported for custom executors). - `decodePlaceOrder`, `decodeAmendOrder` and `decodeAmendOrders` are exported pure functions over a receipt, byte-for-byte what the sending verbs produce. - `Trader.executor` names who sends. Verbs that sign rather than send (`signRedeemAuth`) need an executor with `signTypedData`; a safe or a session key has none and those verbs throw `SignerRequiredError`. - Existing callers change nothing, with one observable exception: a `walletClient` trader's pre-send rejection now reports `RpcError.operation === "sendTransaction"` (the wallet executor sends the encoded call) where the removed path reported `"writeContract"`. Code branching on that field updates the string. `privateKey` / `account` / `walletClient` otherwise build the matching built-in executor on the engine's own nonce lane and send ordering. - One exchange over every chain the account trades on — Somnia L1 and Hideki — with a safe as a first-class trader `SomniaMarkets` accepts `chains: [...]` and builds one engine per chain. Reads merge across chains, writes route to the chain a market lives on, and every struct names its `chainId`. The single-chain config is the one-element case and behaves as before. ```ts const exchange = new SomniaMarkets({ chains: [l1, hideki], account: safeAccount }); const bal = await exchange.fetchBalance(); // bal.USDso.total, bal.USDso.byChain[id] await exchange.createOrder("BTC/USDso:USDso", "limit", "buy", 1, 60_000); // routed ``` - **Chain-qualified identity.** `Market`, `Tradable`, every `Unified*` struct and every `UnsignedCall` carry `chainId`. `ChainMarketRef` / `ChainOrderRef` (`{ chainId, id }`) are accepted wherever a bare id is; a bare id that two chains know throws `InvalidInputError` instead of guessing. Symbols stay chain-free and unique across the union. - **The account.** `account: { address, executors: { [chainId]: Executor } }` — one address on every chain (the safe factory guarantees it), one executor per chain, built with `engine.createExecutor(spec)` (the executor seam shipped separately). - **Collateral placement.** A market's collateral must sit on its chain. On a multi-chain exchange `createOrder` checks the escrow balance there and throws `CollateralOnWrongChainError` — chain, token, shortfall, where the funds are, and a ready bridge plan — unless `{ funding: "auto" }` (bridge, wait, place) or `{ funding: "skip" }`. `exchange.bridge` plans and executes transfers between the exchange's chains through the account's executors; `exchange.ensureFunds` is the helper behind auto-funding. - **Portfolio netting.** `netInternalTransfers` drops bridge legs between the exchange's own chains from a funding list; `fetchPortfolioAnalytics` applies it, so a rebalance never reads as a withdrawal plus a deposit. - **React.** ``; every hook takes a trailing `{ chainId }`. - **Per-engine nonce lanes.** Each engine owns a nonce manager; the module-level fallback is gone. - Smart accounts, end to end: the factory account model of `@somnia-chain/accounts-sdk` (new runtime dependency) is reachable through this SDK alone — sending trades AS an account, and the whole account lifecycle around it. - **The executor.** `client.createExecutor({ smartAccount, inner, through?, signer? })` builds an executor whose actor is a factory account, including an account owned by other accounts. The accounts SDK builds the safe transaction (batching through its own MultiSend batcher from committed manifests — no `multiSend` knob); the `inner` executor sends the outer transaction, so writes keep the engine's realtime send, nonce lane and retry stance. With no `signer` and no `through`, nothing signs and nothing is read (the pre-validated path — the session-key arrangement); a `signer` or a `through` chain of parents switches to one owner signature the accounts SDK nests level by level, at any depth. An explicit `gas` below the accounts SDK's execution floor (2,000,000) is raised to it. - **`client.accounts`** — the one-chain capability: `addressOf`, `find`, `nextFreeIndex`, `ownersOf`, `custodyChain`, `authorityPath` (yields the executor's `through`), `tree`, `holdings`, `health`, and the build verbs `buildCreateAccount`, `buildAccountAuthorization` + `buildCreateAccounts` (one signature, every covered chain), `buildAddOwner` / `buildSwapOwner` / `buildRemoveOwner` / `buildChangeThreshold`, `buildTransfer`. Reads ride the client's own chain transport; every write returns `UnsignedCall`s for any executor to send — owner management and transfers through the account's own smart-account executor, so the account administers itself. - **`exchange.accounts`** — the multi-chain surface: `scan` across every covered configured chain, `buildCreateAccounts` fanning one signed authorization out into one creation call per chain, and `accountFor(accountId, index, { sessionSeed })` building the `SomniaMarketsAccount` the exchange trades through — one line from seed to tradable multi-chain account. - **Named failures.** A revert while sending through an account is attributed to the account's own `execTransaction`, and a best-effort replay names the actual cause: the account's `GS` code as a sentence (via the accounts SDK's catalogue), or — accounts being Safe 1.5.0, which propagates inner revert data — the inner call's real revert, including this SDK's own contract errors. - **Refusals before anything signs**: a chain the accounts SDK has no deployment for (5031 / 50312 / 50383 are covered), an `inner` on another chain, a `through` chain with no way to sign — all `InvalidInputError` at construction. - **Sign now, send later.** `client.accounts.buildExecution({ account, calls, signer, through? })` prepares an execution whose signer is not the sender: the owner signs the returned payload, and `toCall(signature)` is a finished call ANY funded key may broadcast (send it with at least `gasFloor` gas) — the sponsorship flow, without importing the accounts SDK. Pass `nonce` when it is already known (`0n` prepares an undeployed account's first action, read-free). - **`indexerUrl` is now optional.** A chain-only client (smart accounts, executors, on-chain reads) constructs without one; every indexer read and live watch on such a client throws `NotConfiguredError` naming `config.indexerUrl`. Nothing changes for clients that pass it. - New root exports: `SmartAccountsClient`, `ExchangeSmartAccounts`, `SmartAccountSigner`, `SmartAccountInner`, `PreparedAccountAuthorization`, `AccountAuthorizationTypedData`, `UnsignedAccountCreation`, the read/build error unions, the pure `describeCoverage` helper, and the accounts-SDK result types the members hand back. New docs: `docs/ACCOUNTS.md` and `docs/how-to/trade-through-a-smart-account.md`. - `listSeriesLatestMarkets` returns the most recent market of every rolling series that has rolled at least once - one row per series, joined server-side. A series row says how often it should roll; a market row says when it was created but not which series it belongs to. This read is the join between them: the question "when did each series last roll", answered server-side rather than by fetching every market and grouping client-side. It is PAGINATED, like every list in this SDK — one request per page of at most `limit` rows (default 100), not one request for all series however many there are. A caller with more series than a page must cursor through with `offset` until a short page comes back. It takes `ListSeriesLatestMarketsOptions` (`limit`, `offset`), returns `SeriesLatestMarket` rows (`series`, `market`, `createdAtTimestamp`) and throws `SomniaMarketsClientListSeriesLatestMarketsError`. A series that has never rolled has no row. Absence means "no market yet", not "stalled"; nothing indexed says when a first roll is due, so a caller should report such a series as unjudged rather than anchor on its registration time. - Add partial offset pagination for authenticated unified order history. Each row now carries immutable market and owner identity, while unresolved rows remain observable. ### Patch Changes - `getBookTops` is documented as covering every market kind, not only binary. A spot or perp pool address and a binary market id are both valid, and may be mixed in one call. - The multi-chain collateral pre-check now requires what the pool will lock `createOrder` on a multi-chain exchange checks the escrow balance on the market's chain before it sends anything. That check sized a binary buy as the human `amount × price`, a float, with no builder-fee headroom. An order with a `builderFeeBpsTimes1k` could pass the check with exactly the principal and then revert at the pool. The check now uses the same integer commitment the writer and `BinaryPool` use: ceil principal plus the builder fee's ceil-rounded headroom, so `CollateralOnWrongChainError.needed` is the amount the pool pulls. A spot buy's principal is sized by integer math too. - ### Fixed — a complete set now records the collateral it actually cost `computePositionPnL` priced each leg of a complete-set mint or merge at half a collateral unit per token, then multiplied back out. That representation loses the cost in two ways. On a **zero-decimal collateral** one whole unit is `1`, so half of it floors to `0` and the entire set was recorded as costing nothing. Every later sale of those tokens then realized pure profit, and the position's cost basis read zero for its whole life. On any collateral, an **odd raw quantity** floored a unit away on each leg: seven raw units booked three and three against a set that cost seven. Both legs now split the set's own aggregate quantity, with the odd unit going to the NO leg, so the two shares always sum to exactly what the set cost. A mint followed by a merge of the same amount nets to precisely zero. Releasing cost on a **partial** sale had the same defect from the other direction: it scaled a per-unit average through one whole collateral unit, which rounds to zero whenever a leg's cost is smaller than its quantity. A leg of five tokens costing two released nothing at all when four were sold, reporting the whole proceeds as profit and stranding the cost on the one token left. Partial releases now take the aggregate ratio directly. That is more exact rather than merely equivalent: the per-unit form rounds twice, so it differs at ordinary decimals as well, by up to one raw unit per whole token released. A **partial** merge is also credited correctly now. Where a merge names more tokens than the position holds, the proceeds split the quantity actually released rather than pro-rating the event's own half, which floored on each leg independently: merging seven against a position of six credited two plus three for six whole pairs and reported a loss of one unit that never happened. The reported **cost basis of an open position** had the same defect in the other direction: it scaled the held balance through a rounded per-unit average, which is zero whenever a leg's cost is smaller than its quantity. A zero-decimal position of five tokens costing two therefore reported no cost basis at all, even once the fold recorded it correctly. It is now taken from the aggregate. That also removes a rounding loss at ordinary decimals: a leg holding three raw units costing two reported a basis of one. A **partial** merge after an odd mint is exact now too. Because an odd amount splits unevenly between the legs, releasing each one's cost independently floored twice and lost a unit: minting five and merging four released three against four of proceeds, inventing a unit of profit and stranding a unit of basis on the set still held. The two legs are settled together when they are a genuine pair, so the cost released always matches what was merged. A zero-quantity merge event no longer throws when the account holds an open leg. It is treated as the no-op it is, as it was before complete sets were split per leg. Figures for accounts that minted or merged complete sets will move, and the moves compound across a position's history rather than being bounded per action. On a six-decimal collateral each partial release was short by up to one raw unit per whole token it released: a leg minted at 10,000,001 raw units and then sold down by 10,000,000 released 4,999,990 where it should have released 4,999,999, so realized PnL moves by nine units on that one sale. Repeated partial sales and merges accumulate. On a zero-decimal collateral the previous cost basis was absent entirely, so realized PnL for those markets was overstated by the full cost of every set. - Document the built-in Safe executor's supported accounts: a direct owner of a threshold-1 safe or an enabled module. Nested Safes are supported when their address has the required authorization. Module mode does not depend on the threshold. Other authorization schemes need a custom `Executor`. The SDK does not check the owner set or threshold. - Wait for complete market watch initialization before resolving concurrent callers. Failed initialization now releases unused subscriptions and allows a fresh retry while preserving separately watched markets. - `useFundingRateSeries` now waits for the indexer before it re-reads a new funding settlement. A settlement reaches the live tail as soon as its block is confirmed, which is before the indexer has processed that block. The hook previously re-read the rollups immediately, so the response could still be the old series and nothing retried until the next settlement. The hook now reads the indexer sync status about once a second until the processed block reaches the settlement's block, then re-reads the rollups once. The wait is bounded at 4 seconds. At the bound the hook re-reads the rollups anyway. The wait stops on unmount and on a pool change. It survives a `from`/`to` window roll and then re-reads the rolled window. A sync-status failure stops the wait and appears on the new optional `catchUpError` field of `IndexerQueryState`, typed `IndexerError | InvalidInputError`; the hook never treats a failed read as coverage. - Re-pin the Hideki (50383) deployment manifest to the hideki2 regenesis (2026-09-17): the chain was rebuilt on the same chain id with fresh state, and the CLOB family was redeployed at the SAME shared CREATE3 addresses, so no resolved address changes — only the deployment's `startBlock` moves (566759489 → 840122) and venue 1 carries fresh MarketCreatorV2/policy/TestUSDC instances. Consumers that scan from `startBlock` must pick up the new floor; the old one predates the regenesis and does not exist on the new chain. - Liquidation history documents how to read `stageReached`, and corrects two claims about `BadDebtAbsorbed`. `stageReached` is a 0-indexed enum, while the published waterfall numbers its stages 1 to 6, so the two need a mapping table; `LiquidationEvent` and the perps guide now carry it. The number names the deepest stage that acted, not the deepest consulted, and `CLOBPartial` is a fall-through marker that does not prove stage 3 filled anything — read `positionsProcessed` with it. `BadDebtAbsorbed` fires when the engine asks the insurance fund to cover, not when the fund pays, and its `counterparty` names the fund that was asked; both are recorded even when `insuranceCovered` is 0. Documentation only; no runtime behaviour changes. - Fix wrong decimal scale on binary markets the live tail discovers itself. A market built from a `MarketCreated` event was stamped with the 6-decimal fallback regardless of its collateral, so on a venue settling in an 18-decimal token every derived quote amount on that market — cumulative quote volume, per-fill quote value, and anything formatted from `quoteDecimals` — was off by a factor of 10^12 until an indexer snapshot happened to overwrite the row. Discovered markets now carry their collateral's real `decimals()`, matching what the indexer stores for the same event. - Derive a live order book once per block instead of once per depth. Reading the same pool at two depths, as a trading page does when it shows a mid price and an order book together, now costs one pass over the resting orders. The full sorted ladder is computed once and each depth is a slice of it. Repeated status updates that change nothing no longer discard the derived books. Book contents are unchanged, and an expired order still leaves the book without a removal event. A book read keeps returning the same value until something it depends on moves, which now includes the one-second expiry cutoff as well as new blocks, so a level that expires is dropped without waiting for the next block. Watching a second pool now always publishes that pool's rows, even while a connection failure is pending and even when the new pool shares the first one's indexer snapshot block. - Fix `close()` and `stopLive()` leaving the chain WebSocket and a background timer running. Both now release every socket and timer the instance opened, so a Node script that has touched the chain exits on its own — the `process.exit(0)` the guides used to require is no longer needed. The instance stays usable afterwards: a later read reopens a connection, and a later `close()` releases that one too. Instances configured with the same `wsRpcUrl` share one chain socket, which closes when the last of them closes. A socket your own application already had open on that URL is left untouched. - Document the linked-wallet funding rail in the perps guide: what isolated margin on perps actually is, how a child's order draws on its main's wallet, which read answers which question, why a pending link proposal is only visible in the indexed log, and why the two funding ledgers must not be summed together. - Read each cross-margin account view from one chain block so its balances, health, and status describe the same state. - Check that the safe and any required MultiSend address have code before sending. Missing code raises `InvalidInputError` before signing. Failed reads raise `RpcError`; existing SDK errors pass through. Successful checks are cached. Single calls do not use or check MultiSend. - Preserve `NotConfiguredError` from Safe code checks through Trader writes. Include it in the executor error contract and document the missing-transport condition. - The package now carries its documentation, and the README links to pages a reader can open. The source repository is private, so every relative link out of the README resolved to a 404 for anyone outside the organisation, and npm derived the package homepage from that same private repository. - The tarball now contains the 32 hand-written guides under `docs/`. They are the only copy a consumer can read offline. The generated API reference stays out, so the tarball has the same contents whether or not TypeDoc has run. - The 13 documentation links in the README are now absolute URLs on the public documentation site. Each one was requested and returns 200. - `homepage` now points at the public documentation site instead of the private repository. - The publish gate now fails if the documentation is absent from the packed artifact, or if the generated API reference leaks into it. - Clarify SDK read sources, startup dependencies, freshness, and transport costs. Complete the Engine read inventory and explain separate price-feed connections and mixed-source reads. - `Order.cancelReason` is documented as `SelfMatch` on every pool type, not perps only. Spot and binary pools now tag their `OrderCancelledSelfMatch` removals the same way perps always did, so a spot order the protocol pulled during matching is distinguishable from one its owner cancelled. On spot this also covers the removals the indexer RECONSTRUCTS for blocks that predate the pool emitting the event at all (DEX-1236). Before the fix those makers stayed `Open` in the index forever — 673 of them on mainnet USDC.e/USDso, locking that book at 1.0000. Reconstructed and reported removals carry the same status and the same reason on purpose: on chain they are the same removal, only one of them reported itself. - ### Fixed — baked testnet venue-2 creator/policy reconciled with chain truth The testnet manifest carried a stale `marketCreator` (`0x138CfA6b…`) and `marketCreatorPolicy` (`0x191BBBDc…`) for venue 2. Ground truth on-chain (TRAD-223, re-verified): `MarketsCore.getVenue(2, 0x679795a0…)` returns policy `0xa24822b8d4adCC770c8B071e0Dc8e19c39991204`, which authorizes only creator `0x94D963B6670AB96E78C8d0C46ca35D196d606EFE`. The baked `SOMNIA_TESTNET_ADDRESSES` bundle now carries those live values. Mainnet is unaffected. ## 0.30.0 ### Minor Changes - Three new client reads answer block-scoped questions: `getBlockActivity` returns what one block traded grouped by market, `getLatestActiveBlock` names the newest block with markets activity, and `getAdjacentActiveBlocks` names the closest such block on either side. All three anchor on the indexed timestamp columns rather than a block column, none of which the indexer schema indexes. `getTransactionActivity` takes an optional `anchor` (the transaction's block and timestamp). Supplying it skips the `Order.placedTxHash` probe, which is not index-served and ran past the gateway timeout — so a transaction that produced no event, meaning one that only placed or cancelled orders, could not be read at all. - New `SOMNIA_MAINNET_PRICE_FEED` constant. It is the mainnet price feed, `https://price-feed.prd.oracle.somnia.host/v1/graphql`, pinned to the `USDC` quote. The SDK previously exported one price feed, `SOMNIA_TESTNET_PRICE_FEED`. A mainnet consumer had to write the endpoint by hand. The two feeds are separate deployments. Each one indexes the `PriceFeedScheduler` on its own chain. Use the feed that matches the chain the client runs on. The mainnet feed carries fewer symbols than the testnet feed. Code written for the testnet asset list can therefore fail on mainnet. Read the feed catalog to learn which bases exist. A base the feed does not carry returns no rows. It does not raise an error. Existing callers keep their behaviour. `SOMNIA_TESTNET_PRICE_FEED` is unchanged and remains correct for a testnet client. - Publish the perp event ABIs, so a consumer can decode perp logs from chain. `perpPoolEventsAbi` is now root-exported, and `marginBankEventsAbi` and `liquidationEngineEventsAbi` are new (18 and 13 events). Before this, `perpPoolWriteAbi` and `marginBankWriteAbi` exported no events and there was no MarginBank or LiquidationEngine event ABI at all, so funding settlement, positions, collateral flow and the liquidation waterfall were undecodable without a hand-copied ABI. Every signature is pinned by topic0 against the compiled artifacts. `docs/PERPS.md` has a new "Watch from chain" section. - Add `client.getPerpFundingPremium(pool)`, which reads the premium the next funding settlement will charge. Use `timeWeightedPremium` to project a funding rate. Do not use `lastObservedPremium` for that: the contract getter behind it kept its signature and changed its meaning, and it is now only the standing instantaneous sample. Check `armed` before calling the figure a time-weighted average, because a market that has not settled since the upgrade is still charging a point sample. This read is deliberately separate from `getPerpState`, whose batch would fail as a whole against a pool too old to serve these getters. Correct the funding documentation for the reworked premium and catch-up horizon. `FundingRateUpdate.intervalsAccrued` is no longer `min(intervalsSettled, n)`. A settlement now charges at most one interval, however long the gap, and the excess is forgiven. Compare `intervalsAccrued` against `intervalsSettled` to see whether anything was forgiven; `intervalsSettled` alone does not tell you. `intervalsPerWindow` is the per-interval divisor only. On a historical row that caught up over several intervals, one settlement's charge is `fundingRate * intervalsAccrued / n` rather than `fundingRate / n`. The premium driving the rate is the time-weighted impact-price premium, not a book midpoint, so `emaPremium` can be non-zero on a one-sided book. - Read the three perp ledgers the reindex made available: `listPerpInsuranceFundEvents` (the InsuranceFund's tier ledger behind `getInsuranceFundState`), `listPerpWalletLinkEvents` / `listPerpMarginPulls` / `listPerpMainFundingEvents` (the linked-wallet rail's consent graph and both funding sides), and `listPerpOrderRejections` (orders refused inside a batch placement). Two aggregation hazards are documented on the types: the insurance ledger's `amount` must be folded by `kind` rather than summed, and the two funding sides record the same wei — summing them double-counts every transfer. - `listPerpStopOrders` now returns `siblingOrderId` (the live OCO partner), `intent` and `cancelReason`, so a stops table no longer needs a chain read per row to show pairing or intent. `cancelReason` separates the three routes to `CANCELLED`, which refund differently: `"Owner"` returns the SOMI in the same transaction, while `"LinkedFill"` and `"Inert"` only credit `unclaimedSomi` for `claimSomi()`. - ### BREAKING — the portfolio trades legs default to the last seven days `getSpotPortfolio`, `getPerpPortfolio` and `getPortfolio` now apply `since = now − 7 days` to their trades leg unless the caller passes `since`. A caller that passed no `since` and expected the whole history gets the last week. Each result gains a required `tradesSince` (unix seconds): the bound that was applied, so a UI can label the list and a caller can page further back. **Migration.** To keep the previous unbounded read, pass `since: 0` (or the earliest time you need). Hand-built `Portfolio` / `SpotPortfolio` / `PerpPortfolio` values (fixtures, adapters) need a `tradesSince` field. A UI that renders `trades` should read `tradesSince` and say so when the list is empty — "no trades since " is true where "no trades yet" is not. Why a window: the type scope below is fast when a wallet's fills are dense in the requested type and slow when they are sparse — a spot market-maker asking for its binary fills walks every fill it has rejecting each. Measured on the development indexer for such a wallet: 24.8 s unbounded, 208 ms with a seven-day bound. A window is the only shape that is fast for every wallet without a schema change. Treat it as the SDK's standing position on wallet-scoped trade history, not as a stopgap: the composite indexes that would let it be dropped are a separate ticket, and removing a default later would be a second breaking change. ### Fixed — type- and pool-scoped reads no longer filter through the `market` relationship Every read that scoped `Fill`, `Order` or `StopOrder` by market type or by pool did so with `market: { marketType: { _eq } }` or `market: { poolAddress: { _eq } }`. Hasura compiles a relationship predicate to a correlated `EXISTS` on `Market` per candidate row, which stops Postgres using the `maker` / `taker` / `owner` indexes. Measured on the development indexer for one wallet's fills at `limit: 50`: `stream timeout` with the predicate, 102 ms without it. Three such reads every five seconds per open wallet page saturated the shared one-vCPU database and stalled ingestion on both indexer slots. These reads now scope on the direct, indexed columns instead: `pool` on `Fill`, `market_id` on `Order` and `StopOrder`. A market type resolves to its set of pools — `_in` for SPOT and PERP, whose `Market.id` is the pool address; `_nin` over spot ∪ perp for BINARY, whose pools are recycled across thousands of markets. A spot or perp pool is its own market id — a direct `_eq`, no query. A single **binary** pool keeps the `market: { poolAddress }` relationship form: a recycled pool has hosted ~2,000 markets, so an `_in` of its ids would be the worse shape, and every Order read that takes a pool also carries `owner`, which bounds that one EXISTS to the wallet's rows — no worse than before. Pool and type compose in one place (`marketScope`). The two type sets are memoized per indexer URL for a minute, so the extra hop is paid once, not once per poll. Affected: `getSpotPortfolio`, `getPerpPortfolio`, `getPortfolio`, `getOpenOrders`, `getOrders`, `countOrders`, `getSpotStopOrders`, `listPerpStopOrders`, `listPerpOrderHistory`, `listSweepableOrders`. Rows returned are unchanged for every read except the three portfolio trades legs, where the new default window applies. `getSpotStopOrders` in particular keeps returning every pending stop a wallet holds, spot or perp, as it did. - BREAKING for constructors — `PortfolioAnalytics` gains a required `holdings` series: what the traded book is worth over time The result's `equity` field is cumulative window PnL. It starts at zero, it is signed, and it is not the account's value. Consumers read the name and plotted it as a level, so a losing window drew a spot wallet below zero. `holdings` is the level that name promised. Each sample sums `qty × mark` over the open positions, on the same grid as `equity`, so a chart can draw both against one x axis: ```ts const p = await exchange.fetchPortfolioAnalytics("7d"); p.holdings.at(-1); // what the traded book is worth now p.equity.at(-1); // what it gained over the window ``` The first point is the carried-in book valued at the window start, not zero. The series sums signed position value. Every book the fold keeps today is long-only, so today the value cannot go below zero — but do not lock a chart axis to that, because a signed book marks negative and the perp plane is committed to joining this fold. The marks are the caller's and are not validated, so a negative price carries through as it already does for the PnL figures. A position the sample cannot price is left OUT of the value rather than valued at zero, and `HoldingsPoint.unpricedMarkets` counts what was left out. A market with no candle sample and no last price has no mark, and standing a zero in its place would drop a held position out of the level with nothing to say it had. Check the count before presenting a sample as the whole book. **Migration.** Reading the result needs no change: every existing field keeps its name, its meaning and its value. Anything that CONSTRUCTS a `PortfolioAnalytics` — a hand-written response fixture, a test mock, an adapter building the object for an HTTP layer — must add `holdings: HoldingsPoint[]` or it stops compiling. `HoldingsPoint` is exported from the package root. An adapter that forwards both series also serves roughly twice the series payload. The series measures the TRADED BOOK, not the wallet. A token that arrived without a fill — bridged in, transferred in, minted — is not in the book, so it is not in this value. Idle quote balance is not a position, so it is not included either. Funding events refine the capital base only, so a deposit inside the window does not step the curve. Read balances from the chain when you need what the wallet itself is worth. - BREAKING: `redeem` no longer guesses a leg before resolution, and unified leg selection now uses an options object `trader.redeem({ market, amount })` previously derived the winning leg as the argmax of the market's payout vector. A void pays BOTH legs, so that argmax was meaningless: it returned leg 0 on the uniform `[D/2, D/2]` vector, and the higher-priced leg on a `CLOB_SNAPSHOT` `[p, D−p]` one. A holder of only the NO leg got a confusing `InsufficientBalance` revert. A holder of both legs — what one `mintSet` call produces — redeemed YES, received half, and never attempted NO, with no error and a successful transaction. The collateral was stranded, not destroyed: it stays claimable from `BinarySettlement` with an explicit leg. The auto-lookup is now resolution-only. It checks the market's terminal state before reading the immutable payout vector. On a voided market `redeem` throws `InvalidInputError` naming both legs and pointing at `redeemMany`; on an unresolved market it asks the caller to wait for settlement. Resolved markets are unchanged: `[D,0]` still resolves to YES and `[0,D]` to NO. `exchange.redeem(ref, amount)` gains an optional trailing `RedeemOptions` bag, so a NO-holder can claim through the unified API instead of hitting a dead end. Existing two-argument calls behave as before. Migration: replace `exchange.redeem(ref, amount, outcomeIdx)` with `exchange.redeem(ref, amount, { outcomeIdx })`. If the market may be voided, pass the leg you hold. To claim both legs, use `redeemMany` with one entry per leg — they settle in one transaction. - Restore concurrent market-discovery coordination and stable user-fill pagination after their review withdrawal. Paginated fill reads include configured indexer headers, and indexer response-body cancellation preserves the caller's reason. This restoration supersedes the earlier withdrawal note. Dataset-reset coordination remains required for persisted fill cursors. - Add bounded user-fill pages with stable numeric continuation. Cursors preserve account and filter scope while newer fills arrive. Existing reads remain unchanged. Reindex, repair and endpoint cutover still require callers to discard cached pages and cursors. - Reject partially present void payout vectors, floor each raw payout leg from its stored numerator, and verify omitted unified redemption legs against on-chain terminal state. ### Patch Changes - Approval documentation now distinguishes cached unlimited allowances from finite allowances that each order must check again. - Traders from one configured client now coordinate local sends for each account. A failed signer cannot reset a nonce that another trader is still broadcasting. - Share concurrent initial market discovery within each exchange. Explicit registry reloads run in order, including after a failed read, so an older discovery cannot overwrite newer market metadata. - Withdraw the unreleased stable user-fill pagination API and concurrent market-discovery coordination pending maintainer review. This withdrawal supersedes the queued release notes announcing those additions; existing offset-based fill reads and the previous discovery behavior remain available. - Documentation: a documentation map plus tutorials, how-to guides, reference pages, and explanations organised by reader need. Two tutorials take a newcomer from an empty directory to a cancelled order on the Shannon testnet. Eight how-to guides cover network configuration, testnet funds, a quoting loop, fill detection, browser-wallet signing, the React hooks, error handling, and debugging. Six reference pages list configuration fields and defaults, networks and endpoints, the symbol grammar, units and scales, read tiers, and the error classes with the contract error names they decode. Every TypeScript example has a compile-checked public-import counterpart, and the tutorials were executed against the testnet. Corrections to the existing guides, verified against the source: the reactivity guide no longer claims the package is on GitHub Packages; the binary guide's cadence list, lifecycle (`Finalized`), `intervalSec` provenance, and builder-fee revert names are corrected; the exchange guide's verb table gains the ten verbs it omitted and notes that `close()` leaves the WebSocket open; the engine guide's API links now target the docs site; `isTailing()` is no longer presented as the price-feed status; the bridge guide names `sendBridgeStep` as its one sender; and the two `errors` TSDoc examples now match the real signatures of `createOrder` and `cancelExpiredOrders`. - Forward configured indexer headers to paginated user fill reads and preserve the caller's cancellation reason when an indexer response body is interrupted. - `/native`: a rejected `sendSessionTransaction` or `getSessionAddress` no longer carries the session seed in its error. viem builds a request failure's `message` and `cause` from the request body, so a mempool rejection or a transport error used to print the seed — a private key in another shape — in every log line that showed `error.message`. Both calls now throw `RpcError`. When the node answered, `cause` is its own `{ code, message, data? }` and `getSomniaRpcError` / `mempoolStatus` keep working on it; when the transport failed first, `cause` is `{ name, message, status? }` with the seed blanked out of the request text. `isMethodNotFound` also stops matching the node's genuine `account does not exist` and `Block does not exist` failures, which the documented degrade-to-`null` idiom used to swallow. - A live-tailed client no longer re-fetches every block it has already been handed. The tail took its chain head from viem's `watchBlocks`, which answers a pushed `newHeads` frame by issuing an `eth_getBlockByNumber` for the very block the frame already carried - nothing new, at double the per-block RPC cost. It now reads the height and timestamp straight off the pushed frame over the same socket. A frame is read only when both the height and the timestamp arrive as hex quantities; if either is missing, is not hex, or is the empty quantity `"0x"`, the frame is skipped whole rather than half-read. A skipped frame still counts as proof the stream is alive, so the heads watchdog behaves as before and the next head restores the timestamp. - Operational failures are no longer converted into success, zero, or a caller error at seven sites. Admin writes through `OperatorAdmin`, `GovernanceAdmin`, `MarketCreatorAdmin`, `OracleHubAdmin` and the lend `Lender` now throw `ContractRevertError` on a mined-but-reverted receipt (with the contract's error name when a replay at the receipt's block recovers it) instead of resolving as if confirmed, or misreporting the revert as `RpcError("no event")`. `SomniaMarkets.fetchBalance` throws when a balance read fails instead of reporting `0` or omitting the key. `getBinaryPositionPnL` falls back to `lastPrice` only when no chain client is configured, not when the book read fails. `cachedErc20Decimals` (and every read built on it) returns the fallback only for a token without `decimals()`, not on an RPC failure. `createStopOrder` surfaces a failed mark read as the indexer's error instead of `InvalidInputError("pass triggerDirection")`. `depositVaultNative` no longer broadcasts when its preflight read failed. The receipt wait used by external-signer and fallback confirms rejects after three consecutive receipt-read failures instead of pending forever; "receipt not found yet" still waits. - Decode three perps reverts that previously surfaced as opaque hex — `InvalidFundingCapDivergenceMargin`, `InvalidPremiumImpactNotional` and `InvalidLinkedWalletRegistry`, all added by the 2026-08-31 testnet upgrade. - `createOrder` and `createStopOrder` never send a larger quantity than requested. Quantities are truncated to the base token precision before applying the lot-size floor. `amountToPrecision` now truncates the decimal text instead of its binary floating-point expansion. Exact inputs such as `1.2` therefore remain exact for a `0.1` lot size. Local writes now serialize nonce consumption, signing, and broadcast acceptance. A signer or broadcast failure can reset nonce tracking without invalidating another in-flight write. - Live-tailed clients now receive binary settlement finalization. The SDK declared `MarketFinalized` with a stale trailing argument, so its topic0 did not match the emitted event and `liveTail` discarded every settlement finalize — leaving `netBacking` null for the settled lifetime of every binary market. Indexer-backed reads were never affected. - ### Fixed — a hydrated fill now names its taker A watch scope hydrated from a snapshot reported no taker on any of its fills. `taker`, `takerSide` and `kind` were missing from the snapshot's fill selection set and hardcoded `undefined` when the rows were parsed, on a comment claiming the indexer does not carry them. It does: they are real columns, stamped by the indexer's `PendingTakerFill` bridge once the taker's placement event lands. On a market-scoped watch this was permanent, not a live-tail race. The client-side back-join recovers taker fields from the local order map, but that scope hydrates resting orders only — and a taker order that filled completely is `Filled`, never `Open`, so it never enters the map to be joined against. Every market order and every IOC was affected, and a freshly loaded binary trade tape showed no taker side on any row it hydrated. `taker`, `takerSide` and `kind` now come through from the indexer, so: - A binary fill reports its taker's address, its four-way `BUY_YES`/`SELL_YES`/ `BUY_NO`/`SELL_NO` taker side, and its `DIRECT_YES`/`DIRECT_NO`/`MINT_A_PAIR`/ `BURN_A_PAIR` kind — the vocabulary `takerIsBid` cannot express, being one boolean covering two sides at a time and carrying no kind at all. - A spot or perp fill reports its taker. `takerSide` and `kind` stay undefined there, which is correct rather than a regression: outcome side is a binary-only concept and every spot and perp adapter leaves it unset. - A row the bridge has not stamped yet still reads `undefined`, and the existing back-join still fills in whatever is missing when the rows are selected. No type changed: the live-fill shape already declared all three as optional, and the user-scoped path already resolved them through the back-join. This closes the SDK half deferred by the binary trade tape's taker-colour fix. - Native-base spot sells now send the pool's exact vault shortfall as `msg.value`. This includes fee headroom and prevents `InvalidMsgValue` reverts on fee-bearing pools. Spot approval checks now use the pool's worst-case reserve. An allowance that covers only the principal is increased before the pull. Binary buy commitments now use the collateral token's exact scale. They also include the builder-fee headroom that the pool locks. - ### Fixed — a voided market now values against the payout vector it actually stored `estPayoutFor`, `computePositionPnL` and `computeBinaryPnl` returned a hardcoded half for every voided binary market. A void pays whatever payout vector the market stored. Under the `UNIFORM` void policy that vector is `[D/2, D/2]`, so the half was right. Under `CLOB_SNAPSHOT` a void that captures a two-sided close stores `[p, D−p]` at the closing YES price, and there the half was wrong on both legs: at a 0.80 close the YES leg was understated by 37.5% and the NO leg overstated by 150%. `estPayoutFor` quoted a claim settlement would not pay. All three now read `payoutNumerators` / `payoutDenominator`, which the indexer already carries and the market selection set already requested: - `estPayoutFor` returns `amount × payoutNumerators[outcomeIdx] / payoutDenominator` on a void. A void is never fee-charged, so no settlement fee applies on that branch. - `computePositionPnL` and `computeBinaryPnl` mark each leg from the same vector. `computePositionPnL` derives the NO leg by subtraction, as it already does while trading, so both legs still sum to exactly one collateral unit. - `ClaimableInput` accepts optional `payoutNumerators` and `payoutDenominator`, and `PortfolioMarket` carries them, so `getClaimable` and `getOpenPositionsWithPnL` value a void from the vector too. The payout comes from the vector and never from `voidPolicy`. A `CLOB_SNAPSHOT` market stores the uniform vector on every fallback — no capture-capable pool, a reverting `closingPrice()`, a one-sided or empty book, any overflow guard — so reading the policy instead of the vector would misreport exactly those markets. When a legacy voided market has no stored vector, all three keep returning the half, unchanged from previous behaviour. A present but invalid vector now raises `InvalidInputError` instead of silently turning corrupt indexer data into a plausible payout. The vector arrives from the indexer rather than the chain, so it is validated before use — as a whole vector, not one leg at a time. It must have both legs, both parseable and positive, a positive denominator, and a sum equal to that denominator. This is the shape `BinaryMarket` writes for a void: uniform or `[p, D−p]`, with `p` clamped to `[1, D−1]`. Rejecting any other present vector keeps corrupt data distinct from the legacy no-vector fallback. - Clarify voided-market rounding: `computePositionPnL` calculates each leg as `floor(oneCollateral * payoutNumerators[outcomeIdx] / payoutDenominator)`. It does not derive the voided NO mark by subtraction. Independent rounding can leave the two marks below one collateral unit in total. This supersedes the earlier queued payout-vector note's claim that the voided marks always sum to exactly one collateral unit; the implementation already follows settlement's independent rounding. ## 0.29.0 ### Minor Changes - ### Added — a market's whole history, one transaction, and one trade The tape and the fills list were the only ways in. A market page could show trades and nothing else; a transaction or a single fill had no read at all. - **`getMarketActivity(market, opts)` — one market's whole transaction history.** The mints, merges, redemptions, oracle resolutions and lifecycle transitions a market accumulates were all indexed and reachable only one entity at a time, in five different shapes. This returns them interleaved by time as one discriminated union on `kind` (`MarketActivity`), newest first, in a single round-trip. Every row carries its `txHash`, so a caller can follow any row to the chain. Select the streams with `kinds`, page backwards with `until`, and pass `pool` to let the fill read use its `(pool, timestamp)` index. A spot or perp market returns `TRADE` rows only — the other four streams read binary-only entities, so asking for them there is empty rather than an error. Pair it with `getLiveFills` for zero-latency trades: a trade's id is `TRADE:` followed by the fill id on both paths, so the two merge on `id` — but merge FIELD BY FIELD, preferring whichever source has a value. Neither is a superset of the other: the tail leaves `taker`/`takerSide` undefined on the fills it hydrates, and the indexer's `takerIsBid` is null until its taker bridge lands. Cache identity comes from the new `marketActivityKey`. **Known limit:** `until` has one-second resolution and is inclusive, so the boundary second is re-read between pages and a second holding `limit` or more rows cannot be paged past. A composite `(timestamp, blockNumber, logIndex)` cursor is the fix; it needs `logIndex` on the three non-fill streams, which this release adds to the indexer schema but which reaches a deployment only after a reindex. - **`getTransactionActivity(txHash)` — everything the protocol did in one transaction.** The transaction-scoped counterpart: the same `MarketActivity` union with the same row ids, but selected by transaction and returned in LOG order, plus the orders the transaction placed, the fees it paid and the market rows its events touched. One oracle callback settles every market on a question, so this is how a caller sees that a single transaction resolved four markets at once. A hash the indexer has nothing for returns empty collections and a null `blockNumber` rather than throwing — including a transaction that only rested a limit order, which emits no event and is anchored on the order table instead. New public types `TransactionActivity`, `TransactionActivityOptions` and `TransactionOrder`, and the `transactionActivityKey` cache key. - **`getTradeContext(id)` — one trade in full, for a trade detail view.** Returns the fill (with its block position), the market it executed in, BOTH sides' orders, the protocol and builder fees its transaction charged, and the other fills that transaction produced — enough to answer why a trade priced where it did. `null` for an unknown id, which is a stale link rather than a failure. New public types `TradeContext` and `FillOrder`, and the `tradeContextKey` cache key. Both transaction-scoped reads used to scan `Fill` to select by hash. The indexer schema now carries `@index` on `Fill.txHash`, so that scan goes away once a reindex has run. - ### Added — single-entity detail reads, a transaction summary, and the network tape The indexer surface was list-shaped throughout: orders, fills and markets could be enumerated, but nothing addressed ONE of them. An explorer drilling into a row had no read to call. - **`getOrder(pool, orderId)`, `getFill(id)`, `getOrderFills(pool, orderId)`** — the three reads a detail view runs on. Order ids never repeat (a monotonic per-pool counter), so `(pool, orderId)` names one order permanently; a fill is named by its `${blockNumber}_${logIndex}` id. All three embed a `MarketRef` (symbols, decimals, routing identity) so a page renders from one read instead of a second lookup per row. `null` for an unindexed id — a just-executed fill can lag by a beat, which is a stale link rather than a failure. The embedded market is `marketRef`, not `market`: `FillRow.market` is already the bytes32 marketId string, and GraphQL will not select a relationship alongside an alias of the same name. - **`listMarketsByPool(pool)`** — every market a pool has hosted, newest first. A binary pool is recycled across successive markets, so this is its full history rather than the one market `getMarketByPool` resolves. Plus **`getSeries(creator, seriesId)`**, the single-row sibling of `listSeries`. - **`getTransactionSummary(hash)`** — sender, gas used and limit, effective gas price, fee paid, status. Chain-direct rather than indexed, so it answers for any hash the node still has; `null` for an unknown one, never a throw. - **`createNetworkTape()`** — a network-wide order-flow firehose. One topics-only chain-log subscription sees `OrderPlaced` / `OrderFilled` from every pool, including pools created after it starts, with no indexer on the hot path. Not the live tail: no books and no snapshots, just three newest-first ring buffers (`bids` / `fills` / `asks`) plus a session `(pool, orderId) → owner` map that attributes fills. Takers always resolve; makers resolve when they were quoted while the tape ran. Rows carry RAW units — join to `listMarkets` for symbols and decimals. Nothing connects until the first `subscribe`, and reconnect plus stall detection for Somnia's silently-dying subscriptions is built in. The indexer also materializes the Market→Series edge from `MarketCreator.SeriesRolled` (`Market.series` / `Market.seriesKey`), replacing a heuristic join on asset + venue + cadence. That reaches a deployment only after a reindex, and the SDK does not read the field yet. - ### Added — read a pool's operator permissions registry from your own call `spotPoolOperatorRegistryReadAbi` is now exported from the package root. It is the ABI fragment for `getOperatorPermissionsRegistry()`, the view that tells you WHICH `OperatorPermissionsRegistry` a SpotPool consults when it gates `placeOrderFor`, `cancelOrderFor` and `reduceOrderFor`. `client.getOperatorPermissionsRegistry(pool)` already answered that question and still does. Reach for the fragment instead when the method does not fit: - **Multicall composition.** The method issues its own `readContract`, so it cannot be batched into a caller-built multicall. With the fragment the registry read joins the same batch as the rest of your pool reads. - **No instantiated client on that code path.** The method resolves a chain client lazily and needs one; the fragment is a static value and needs nothing. Previously the only route was a hand-copied fragment, since the `exports` map has no wildcard and no deep import could reach it — which is how a signature drifts in silence. ```ts import { spotPoolOperatorRegistryReadAbi } from "@somnia-chain/markets-sdk"; // `allowFailure: false` so a failed read throws instead of yielding a // `{ status, result }` wrapper. With the default (`true`) each element is that // wrapper, and comparing it to an address silently reports every pool as wired. const [registry] = await publicClient.multicall({ allowFailure: false, contracts: [{ address: pool, abi: spotPoolOperatorRegistryReadAbi, functionName: "getOperatorPermissionsRegistry" }], }); const wired = registry.toLowerCase() !== "0x0000000000000000000000000000000000000000"; ``` Two differences from the method, both of which matter for an authorization check: - **`address(0)` reaches you raw.** The method returns `null` for an unwired pool; a direct read returns the zero address, which is truthy. Compare it yourself, as above — such a pool denies every operator call, so a grant written anywhere will not make `placeOrderFor` succeed. The SDK's own grant reads and writes reject a zero registry with `NotConfiguredError` rather than acting on it. - **Read per pool.** Two pools on one deployment may name different registries, and the pool is the authority: a grant written to any other registry is inert. Do not cache one answer for all pools. The other read-side ABIs stay internal. - ### Added — a portfolio says when its trade history is incomplete `Portfolio`, `SpotPortfolio` and `PerpPortfolio` gain a `tradesTruncated` boolean. The three portfolio reads cap `trades` at 50 by default and page newest-first, so the cap drops the OLDEST fills. The returned shape carried no sign of this. A caller that folds `trades` into Net PnL, win rate, volume or a trade count got a total over the recent slice only, and read it as the whole history. This is the same signal `FundingRateSeries.truncated` already gives the funding chart. `tradesTruncated` is `trades.length >= tradesLimit`. A full page means older fills exist and were not returned. An empty page is not truncated, and neither is `tradesLimit: 0`, which asks for no trades at all. The default cap is unchanged, and raising `tradesLimit` moves the cap rather than removing it, so check the flag instead of assuming a large limit is enough. ### Changed (breaking) — perp markets are discovered from the chain, not only the indexer `loadMarkets()` now unions the indexer's perp rows with the PerpPoolFactory's and derives `active` from the live tradeability gates, so a close-only market no longer reads as tradeable. New `perpStatus` / `perpDiscoveryError` surface. **Breaking:** `indexed` is a required property on `UnifiedMarket`, so code that CONSTRUCTS one (fixtures, adapters) must set it; reading is unaffected. ### Added — the spot stop-order lifecycle is decodable, and the write ABIs are importable Protocol signatures were being hand-copied into consumer repositories, because this package held them and did not publish them. A transcription drifts in silence: it decodes nothing, or decodes wrong, and the failure looks like a missing trigger rather than an error. - **`spotStopRegistryEventsAbi` now carries the whole pending-order lifecycle.** It held `PendingOrderCreated` alone. It gains `PendingOrderTriggered(uint128 indexed pendingOrderId, bool success, uint128 indexed spotOrderId)`, `PendingOrderCancelled(uint128 indexed orderId)` and `InertOrderCancelled(uint128 indexed orderId, address indexed owner, uint256 somiCredited)` — so a consumer can decode a stop order firing, being cancelled by its owner, or being swept as inert, from a receipt. A new test checks every fragment's topic0 and argument shape against the compiled artifact `indexer/abis/SpotStopOrderRegistry.json`. That artifact carries no `PROVENANCE.json` entry, so the guard proves SDK-vs-artifact agreement, not SDK-vs-deployed-bytecode. Do not reuse the perp registry's shapes: its `PendingOrderTriggered` carries a drop reason the spot one does not have, and the test pins that divergence. - **`client.getOperatorPermissionsRegistry(pool)`** — the registry a SpotPool gates its operator calls through, at chain head, or `null` when the pool is unwired and denies every operator call. This is discovery for a caller who has not configured `addresses.operatorPermissionsRegistry`. The grant writes and the two grant reads need that address and otherwise throw `NotConfiguredError`, and no deployment manifest carries the key yet. A configured address still wins where it is used: this adds a path, it does not redirect one. - **Seven ABIs on the root barrel** — `erc20WriteAbi`, `erc20VaultWriteAbi`, `orderBookBatchWriteAbi`, `marginBankWriteAbi`, `spotStopRegistryWriteAbi`, `spotStopRegistryEventsAbi` and `operatorRegistryWriteAbi`. Token approvals, vault funding, batch order management, perp collateral, the stop-order lifecycle, and operator delegation are now encodable by hand from published surface. ```ts import { spotStopRegistryEventsAbi } from "@somnia-chain/markets-sdk"; import { decodeEventLog } from "viem"; for (const log of receipt.logs) { if (log.address.toLowerCase() !== registry.toLowerCase()) continue; const event = decodeEventLog({ abi: spotStopRegistryEventsAbi, ...log }); if (event.eventName === "PendingOrderTriggered") render(event.args); } ``` The read-side ABIs stay internal. A root export is permanent public surface, so the set is limited to what consumers have needed. ### Added — every placement path honours `selfMatchingOption` - **`selfMatchingOption` is now a caller input on all four placement paths**, so `CANCEL_MAKER` is reachable without leaving the SDK. It was pinned to `0` (`CANCEL_TAKER`) in each encoder, on a parameter the pools have always taken: `placeSpotOrder` / `buildPlaceSpotOrder` (`PlaceSpotOrderParams`), `placeSpotOrders` (`SpotOrderRequest`, per request), `placePerpOrder` / `buildPlacePerpOrder` (`PlacePerpOrderParams`), and `placeOrder` / `buildPlaceOrder` (`PlaceOrderParams`). `amendOrder` and `amendOrders` already took it, so every placement and amend verb now shares one vocabulary — the exported `SELF_MATCHING_OPTION`. Omitting the field encodes `CANCEL_TAKER`, exactly as before, so no existing call changes behaviour. Note that this default is the SDK's own: the pool reads the value out of every order request and has no default to fall back on. ```ts await trader.placeSpotOrder({ ...order, selfMatchingOption: SELF_MATCHING_OPTION.CANCEL_MAKER, // drop MY resting order }); ``` - **`userData` is settable on single spot placement** (`PlaceSpotOrderParams`), which the batch request shape already allowed. The single verb pinned the tag to `0`, so the same order encoded differently depending on which verb placed it. - **`placeSpotOrders` forwards each request's `builder` and `builderFeeBpsTimes1k`** instead of zeroing them. Choosing the batch verb silently dropped the routing attribution that `placeSpotOrder` honours. ### Added — a both-leg binary position can finally show either row - **`BinaryPositionPnL.outcomes`** — the same position split into its YES and NO books, as `{ yes, no }` of the new exported `BinaryOutcomePositionPnL` (`balance`, `costBasis`, `avgCost`, `markPrice`, `markValue`, `unrealizedPnl`, `realizedPnl`, all RAW). `OpenPositionPnL` extends `BinaryPositionPnL`, so `getBinaryPositionPnL` and `getOpenPositionsWithPnL` both carry it with no extra request. Every money field on the result is blended across both outcomes, which is unusable for a wallet holding both. Buy 10 YES at `0.20` and 10 NO at `0.80`, mark YES at `0.40`: the legs are `+2.00` and `-2.00` and the blended `unrealizedPnl` is `0.00`. Neither position row could show that zero as its own PnL, and consumers were falling back to local math for both-leg wallets. The fold already kept the two books separately in bigint space, mints and merges included — it computed each leg and then summed the values away. This publishes them. ```ts const [row] = await client.getOpenPositionsWithPnL(account); for (const leg of [row.outcomes.yes, row.outcomes.no]) { if (leg.balance > 0n) render(leg); // per-outcome, not blended } ``` Legs sum EXACTLY to the totals: `costBasis`, `markValue`, `unrealizedPnl` and `realizedPnl` are stored per leg and added up, so integer division cannot make a published leg disagree with the published total. `avgCost` and `markPrice` are per-token rates and do not sum — though while trading the two marks add up to one whole collateral unit. ### Added — the linked-wallet funding rail, and the margin surcharge that explains a refused order - **`getPerpLeverageImSurcharge(marginBank, account)`** and **`tryGetPerpLeverageImSurcharge`** — the EXTRA initial margin an account's own leverage settings demand, summed over every market where it both holds a position and has set a stricter-than-market cap. This closes a real gap rather than refining an existing read. `quotePerpOrderTopUp` funds ONE order and measures the account's *unlocked* balance, while the admission gate measures whole-account *equity* — so an order can be fully funded on its own market and still be refused `InsufficientMarginForOrder` because of an override on a different one. Nothing in the SDK could name that amount. Note the magnitude before dismissing it: the order lock reserves only the market's margin factor, so a 5x setting on a 2%-IMF market needs 20% of notional, not 2%. The strict read reverts when a market that is both positioned and overridden is unpriceable; the `try` variant reports that as `null`, never `0n` — zero would under-state the requirement, which is the direction that produces an order the bank then refuses. - **The linked-wallet read surface** — `quotePerpFundingPayer`, `getPerpMainFunding`, `getPerpWalletPullCapacity`, `getPerpLinkedWalletRegistry`, `getPerpWalletLinkage`, `listPerpLinkedChildren`, `getPerpMaxLinkedChildren`. A linked child's position-increasing order draws its shortfall from its MAIN's wallet, and none of that was readable from the SDK. **`quotePerpFundingPayer` returns a discriminated union, not an address**, because the contract's single zero collapses three situations a UI must not render alike: the rail is `dormant` (the bank holds no registry, so the feature is off for everyone and linking would not help), the wallet is `unlinked` (the one case the user can fix), or the wallet `isMain` (linked, but funding flows main→child only). The arming check runs first and short-circuits, so a deployment with the rail off costs one read and cannot report a misleading "unlinked". **`getPerpMainFunding().payer` is the payer snapshotted at funding time**, not whoever is linked now. Both routes home settle against it, so an unlink or re-link between the pull and the repayment cannot misroute the money — read it rather than `mainOf` when the question is "who gets it back". `principal` is what the child may trade but not withdraw (`withdraw` frees at most `balance - principal`), and it is not a segregated bucket: the claim clamps to `min(principal, balance)` at flat moments, so the child's own contribution is the junior tranche and a loss eats it first. **`getPerpWalletLinkage` derives `isChild` / `isMain`** because the raw encoding is a trap — a main resolves to ITSELF in `mainOf`, so the natural test `main !== zero` is true for mains and children alike. `maturesAt` gates ADL netting only; the funding rail reads the raw graph, so a link can be fundable and not yet mature. All chain tier. The rail's five events are live on chain but not yet subscribed, so HISTORY is not available — these answer "what is true right now". Writes (`proposeLink` / `acceptLink` / `repayFunding` / `recallFromChild`) are deliberately not in this release. ### Added — a count can now say whether it is the whole truth - **`client.countMarketsBounded` / `client.countBinaryMarketsBounded`** — return `CountResult` (`{ count, truncated }`) instead of a bare number. `truncated: true` means `count` is a LOWER BOUND (10,000 rows): render it as "10,000+", and do not gate pagination on `rows.length < count`, which goes false while rows remain. Without the server-only `_aggregate` header every count falls back to a bounded row scan that returned *the rows it fetched* — so a scan that filled its cap reported exactly `10000`, indistinguishable from a real total. The fallback now requests `cap + 1` and reads the extra row as the signal; the probe row is never counted. `Fill` and `Order` are already past the cap in production and `Market` crosses it during 2026. The six bare-number count helpers are unchanged, and each now documents the bound on its client declaration — past the cap they return a lower bound as if it were exact. `countOperators`/`countVenues` get no variant: those tables are orders of magnitude below the cap. `countOrders`/`countUserFills` have none yet, and `Order`/`Fill` are both already past it — copy `countMarketsBounded` when a caller needs the signal. ### Added — a binary market's resolution mode, served - **`BinaryMarket.mode`** — `"reference"` (an up/down market whose threshold is another question's answer) or `"fixed"` (a threshold set at creation). Derived from `strike`, so it costs no extra query, and stamped on the live-tail path too — a market built from logs before the indexer has it reports the same mode it will report after. Exported as `BinaryResolutionMode`, with `binaryResolutionMode(strike)` as the one place that reading happens — both construction paths call it, so they cannot drift. Consumers previously inferred this from a LOOKUP MISS — "no opening answer, so it must be fixed-strike" — which conflates "no reference question" with "the reference question has not been answered yet". That reads as working code until an oracle is slow. - **`boundaryPrice(market, openingPrices)`** — the level a market's outcome is measured against, taken from whichever source `mode` names, with `posted` saying which. Only a posted answer has an "answered at" instant, so only it may be labelled as one; returning that alongside the value keeps a label and the number it labels derived from one decision. Returns the raw oracle value — scale stays the caller's to apply. ### Changed - **`BinaryMarketFilter.intervalSec` now matches a BAND, not an exact value.** A rolled market's indexed `intervalSec` is `expiry − tradingStart`, and trading routinely opens a second or two late, so one 15m series is indexed at 898s and 899s as well as 900s. The filter matched exactly, so it returned a fraction of a cadence and called it the whole thing — 5m was missing a quarter of its own markets. `listBinaryMarkets`, `listLiveBinaryMarkets`, `listPastBinaryMarkets` and `countBinaryMarkets` all inherit this, so **row counts change** for any caller passing `intervalSec`. The band is `± CADENCE_TOLERANCE_SEC` (5s); rungs are far enough apart that bands never overlap. A caller that genuinely wants one exact window should filter the returned rows itself. - **A non-finite or non-positive `intervalSec` now THROWS `RangeError`** rather than silently matching nothing. Previously `{ intervalSec: 0 }` sent `_eq: "0"` and `{ intervalSec: NaN }` sent `_eq: "NaN"`, both yielding `[]`. A filter that silently matches nothing reads as an empty result set rather than as the caller error it is, so it is rejected at the boundary. Callers parsing user input (a URL param, a form field) should validate first — the same way `operatorId` is already expected to be a positive integer. - **`marketIntervalLabel` snaps to the cadence ladder**, so `BinaryMarket.interval` and the labels stamped on trade-history and portfolio rows now read `"1m"` where they read `"56s"`, `"15m"` where they read `"898s"`. A window matching no rung is unchanged. ### Added - `BaseMarket.createdAtBlock` — the block a market was created in, the counterpart to `resolvedAtBlock`. A market is bracketed by two reads of an off-chain feed and only a block identifies which print each one saw: a `"fixed"`-mode market's `strike` is the feed's spot at `createdAtBlock`, and that print lands before `tradingStart` far more often than on it, so `createdAtTimestamp` cannot find it. **The field is required**, so any code constructing a `Market` by hand must supply it; it is non-null on the wire, so every indexed market carries one. - `getResolutionPrices(marketIds)` — batch settlement prices, the counterpart to `getOpeningPrices`. Joins each market's OWN `oracleQuestionId`, so fixed-strike markets (which have no reference question) are covered. **Read its note on scale before consuming it**: the value is a raw integer and the indexer does not carry the answer's decimals. - `getOnchainResolutionPrice(marketId)` and the `OnchainResolutionPrice` type — a chain fallback for a settled market whose answer the indexer never saw, because its oracle adapter is not the one the indexer ingests. Resolves the market's bound adapter through the module, so it works for any adapter, and carries its own `decimals` (adapters differ: 18 on the price-feed adapter, 2 on OracleHub). Returns null while the question is not final; a failed read throws rather than reporting absence. - `CADENCE_LADDER_SEC`, `CADENCE_TOLERANCE_SEC`, `snapToCadence` and `cadenceBandSec` — the SDK-canonical cadence rules, so grouping and filtering read one source instead of each re-deriving a tolerance. See the note on `CADENCE_LADDER_SEC`: these exist only because the markets indexer derives `intervalSec` from a market's own window instead of reading the exact value `MarketCreator.MarketCreated` already emits. ### Breaking — the MWRR capital base is deposited capital `mwrr.return` previously divided the window's gain by net trade flow: the carried-in position's value, plus buys, minus the full proceeds of sells. Net trade flow is not capital the account put in, so the figure overstated the return for an account trading a small part of its balance. An account that funded 10,000 USD, traded 500 USD and gained 50 USD reported 10 percent instead of 0.5 percent. Supply the new `funding` events to measure against real deposited capital; without them the base remains a trades-only proxy, and `mwrr.capitalBasis` now says which one produced the number. `mwrr.depositedUsd` keeps its name and its meaning of net capital, with one correction: a sell now returns only the capital it matched against a tracked position. Proceeds of tokens the account never bought on the venue no longer reduce the base, so an account selling externally-sourced tokens reads zero rather than a negative base — and receives a return where it previously received none. Returns computed from funding events are time-weighted (Modified Dietz): each deposit or withdrawal counts for the fraction of the window it was invested, so capital that arrived late no longer claims a whole window's return. Trade flows are deliberately not weighted. A trade moves capital that is already in the account, and weighting a sale as capital returned and a later repurchase as capital re-deployed would collapse the base for an account that merely rearranged what it held. A return can exceed 100 percent in either direction on the funding basis, because capital deployed for a few hours of a window earns or loses at a large period rate. That is what a money-weighted rate states. Read the new `weightedCapitalUsd` to see how much capital the figure is measured against before presenting it as a headline. Every account's reported return changes. Read `mwrr.capitalBasis` to detect which definition a build implements, rather than inferring it from the package version. ### Fixed - **Binary PnL no longer folds a recycled pool's PREVIOUS markets into the current market's cost basis.** A binary pool is reused by successive markets, and the PnL reads keyed a wallet's fills by pool address, so an earlier market's fills landed on whichever market held that pool next. `getBinaryPositionPnL` and `getOpenPositionsWithPnL` could both report a wrong `avgCost`, `costBasis`, `unrealizedPnl` and `realizedPnl`. They now key by the stable `market_id` that `FillRow.market` has carried since 0.28.0. **Reported money values change** for any wallet that traded more than one market on the same pool; spot and perp are unaffected, since their market id IS the pool address. - `getOpenPositionsWithPnL` now asks the indexer only for the fills and router actions of the markets it is folding. Both reads are capped at 1000 rows and the cap drops the OLDEST rows first — the buys and mints that establish the cost basis — so a wallet with a long cross-market history could be priced off a partial book. ### Fixed — portfolio analytics reject a non-finite sampling bound `computePortfolioAnalytics` sampled its equity curve until the sample time reached `asOf`. A non-finite `asOf`, or a window start derived from a non-finite event timestamp, left that comparison false forever while every iteration appended another point, so the call exhausted memory instead of reporting a bad argument. The fold now validates `asOf`, every event timestamp, and the derived window and bucket bounds before it sorts, allocates, or samples. An invalid value throws `InvalidInputError` naming the field. Nothing is substituted and no event is dropped: an invalid time is the caller's to fix, and guessing one would misplace money on the curve. The new `ComputePortfolioAnalyticsError` type states the errors the function can throw. `fetchPortfolioAnalytics` now skips a fill whose indexed timestamp is unusable — nullish, blank, or non-numeric — the same way it already skips a fill whose direction it cannot determine. The check runs before the market is recorded and before a candle range is derived, so one unusable row cannot move an `all`-window start. Blank strings matter here specifically: `Number("")` is zero, which would have placed a fill in 1970 rather than failing. A finite bound is not automatically a sampleable one. A fixed timeframe subtracts a constant, so its span is its own definition, but the `all` timeframe opens at the earliest event — one funding event dated far enough in the past asked the fold for millions of points and exhausted the heap. The fold now rejects a span above 100,000 sample points, naming the implied count. That is roughly 11 years of hourly buckets or 270 years of daily ones, so a real portfolio never meets it: a twenty-year history samples about 7,300 points and is unaffected. The sampling loop itself stays uncapped. Capping it would turn a loud failure into silently truncated financial output; refusing an impossible span is the loud version. ### Added - `getUserFills` / `countUserFills` take `market` (one bytes32 market id) and `markets` (several) alongside the existing `pool`, as the exported `FillsScope`. `getRouterActions` takes `markets` as `RouterActionsOptions`. The predicates run at the indexer, so a `limit` applies to the rows you asked for. Prefer `market` over `pool` on binary: a pool selects every market that ever used it. ### Added — closing-price snapshot voids (TRAD-106) Venue-selectable void payouts: a `CLOB_SNAPSHOT` venue's markets pay `[p, D−p]` at their closing YES price when they void, instead of the uniform 0.50 refund. - **Venue params v3**: `BinaryVenueParams` gains optional `voidPolicy` (`"UNIFORM"` default | `"CLOB_SNAPSHOT"`; exported as `VenueVoidPolicy`). `encodeBinaryVenueFeeParams` encodes v3 through the module's on-chain encoder; `decodeBinaryVenueFeeParams` (and the BINARY_V1 plugin codec) dual-decodes — legacy 192-byte v2 payloads stay valid with an implied `UNIFORM`. - **`trader.captureClose({ pool, maxSteps? })`** — the permissionless closing-price capture that lifts the pool's closing-book lock. Sweep keepers: a `CloseNotCaptured` revert on a post-expiry cancel/sweep means "capture first, then retry"; after a normal resolution the lock lifts by itself and capture is never needed. - **Reads**: `client.getClosingPrice(pool)` (returns `ClosingPriceState` or `null` on pre-capture pools — the selector doubles as the capability probe), `closingTop` in the pool read ABI, and `voidPolicy` on `getMarketOnchain` (null on pre-policy clones) + the indexed `BinaryMarket` row. - **Errors**: the contract-error table now decodes the capture surface (`CloseNotCaptured`, `CloseAlreadyCaptured`, `CaptureTooEarly`, `CaptureStepsExhausted`, `InvalidVenueVoidPolicy`, `InvalidVoidPolicy`). ### Added — dead-oracle recovery without `cast send` `Trader` gains the two entry points the recovery path was missing, so the whole chain is SDK-callable (`syncSettlement` / `finalizeMarket` / `releasePool` were already there): ```ts // 1. Always try the real answer first — voiding pays 1/N, resolution pays winners. await exchange.trader.pokeOracle({ oracleQuestionId }); // 2. Only once expiry + settlementWindow has lapsed: await exchange.trader.voidExpired({ marketId }); await exchange.trader.syncSettlement({ marketId }); // void bypasses the module await exchange.trader.finalizeMarket({ marketId }); await exchange.trader.releasePool({ marketId }); ``` - `pokeOracle` is keyed by **oracle question**, not market: the module fans out to every market bound to that question and resolves the ones whose adapter answers. A success is not "all bound markets resolved". `OracleNotAnswered` (none answered) and `UnknownOracleQuestion` (nothing bound) arrive as `ContractRevertError`, so a keeper loop can branch on `errorName`. - `voidExpired` writes to the market contract, bypassing the module — hence the `syncSettlement` follow-up to release the hub earmark. Before sending, it reads the market's state and throws `InvalidInputError` naming the exact unix second the window lapses, because the on-chain `SettlementWindowOpen` revert carries no timestamp. The gate is compared against the chain's `block.timestamp` (what the contract itself uses), not the local clock. Pass `skipPreflight: true` to send blind. OPERATOR-GUIDE §5's recovery runbook now shows these calls instead of `cast send`. ### Added — funding-aware capital base `mwrr` carries two new fields. `weightedCapitalUsd` is the Modified Dietz denominator. `capitalBasis` names the definition that produced the figures: `"funding"` when external capital movements bearing on the window were supplied, `"trades"` for the fallback proxy that cannot see capital which never passed through a trade. `fetchPortfolioAnalytics` accepts a `funding` option, and the new `PortfolioFundingEvent` type describes a deposit or withdrawal. Funding events refine the capital base only — they never enter the equity curve, profit and loss, or volume. They are caller-supplied, because the indexer has no wallet token-transfer entity and the public RPC caps log queries at 1,000 blocks. Source them from application records, bridge history, or a private RPC scan, and exclude transfers whose counterparty is a venue contract or the same capital is counted twice. `PortfolioFlowEvent` is now a union of `PortfolioTradeEvent` and `PortfolioFundingEvent`. Code that constructs trade events with an explicit `kind: "trade"` is unaffected. ### Fixed — `balanceFloor` proves its guarantee against the write path's conversion `balanceFloor` returns the largest number that does not exceed a raw balance, so a caller can size a "max" order without it reverting for insufficient funds. It verified that by round-tripping its candidate through `candidate.toFixed(decimals)`, which is not the conversion a write performs. A number-to-raw conversion prefers the shortest string that round-trips to the same double, so `1.001` converts as `"1.001"`, while `(1.001).toFixed(18)` is the smaller `"1.000999999999999890"`. Checking the smaller value passed candidates that the write path then converted to more raw units than the wallet held. Over a deterministic sweep of 4,004 balances around a lot boundary at 18 decimals, 407 results converted above the balance and 110 still exceeded it after the venue's lot floor, by up to 110 wei. Six-decimal balances were unaffected, so this reached only 18-decimal venues — currently the only mainnet precision. The check now uses the same conversion as the write path. Results move by at most a few hundred wei, and after the venue's lot floor the placeable maximum is unchanged for every balance in that sweep, so no caller loses usable size. `floorRawBalance` inherits the fix on its fallback path. `ceilRawAmount` was never affected: it returns `bigint` and never round-trips through a double. - Read one account's stored perp leverage cap in a single call: `getPerpMaxLeverage`. `MarginBank.getMaxLeverage(account, pool)` is one storage read, but the only published route to it was `getPerpLeverage`, which walks the whole account and throws when any market the account is active in has a stale mark. A per-position badge or leverage dialog can now read the cap alone — it survives dead feeds on other markets, accepts `opts.blockNumber` for pinned rows, and returns `0` unchanged when no cap is set (that means "no account cap", not zero leverage). - Report a perp pool's aggregator oracle address on `getPerpState`. `PerpStateOnchain` gains an `oracle` field, read from the pool's own `oracle()` view. A consumer building a perp market description from `getPerpState` no longer has to omit the oracle or keep a parity read of its own against the pool. The read joins the existing pinned multicall, so it costs no extra round trip on that path and one parallel read on the `ChainDoesNotSupportContract` fan-out. - ### Added — name a revert from your own call `decodeRevert`, `contractErrorsAbi` and the `RevertContext` type are now exported from the package root. The SDK could already name a protocol revert: `decodeRevert` turns whatever a node threw into a `ContractRevertError` carrying the Solidity error name, decoding against `contractErrorsAbi` (500 custom-error entries). Neither symbol was on the barrel, and the `exports` map has no wildcard, so a deep import could not reach them either. A consumer holding revert data from its own call had no path to a name and had to hand-copy error fragments — which is how a signature drifts in silence. `ContractRevertError` alone is not a substitute: it is a passive holder that decodes nothing, so constructing one from raw revert data yields `errorName: undefined`. ```ts import { decodeRevert } from "@somnia-chain/markets-sdk"; try { await publicClient.simulateContract(request); } catch (caught) { const err = decodeRevert(caught, { address: pool, functionName: "placeOrder" }); console.log(err.errorName); // e.g. "InvalidTriggerPrice", not opaque hex } ``` `contractErrorsAbi` is a generated artifact (`pnpm errors:gen`, verified in CI by `pnpm errors:check`). Publishing it freezes that artifact as public API deliberately: the point is that a consumer's copy stops drifting when ours is regenerated. Both values are pure over caller-held data — no transport, no client, no owner — so they sit at the root under `SDK-API-003` alongside the other ABI data. `toSdkError` and `isRevert` remain internal; ask if you need them. - ### Breaking — `UnifiedOrder.type` may be `undefined` `fetchOrders`, `fetchOpenOrders` and `watchOrders` now omit `type` instead of reporting `"limit"`. That `"limit"` was never a read value. The pools do not emit the order type — `OrderPlaced` carries a `placedOrder` struct with no order-type member, and binary pools emit only the YES/NO side — so the indexer has nothing to store and the SDK had nothing to read. Four read paths wrote the literal anyway, which made **every market order the SDK returned claim to be a limit order**, with no field a consumer could check to tell the difference. Omitting it is the honest answer: absent means unknown, where before a wrong value was indistinguishable from a right one. The field is still present wherever the value is genuinely known: - `createOrder()` echoes the caller's own argument. - `fetchOpenStopOrders()` reads it from the registry row — `PendingOrderCreated` does carry `orderType`. - `UnifiedStopOrder.type` is unchanged and still required. ```diff - if (order.type === "limit") { /* true for every order, including market ones */ } + if (order.type === "limit") { /* now only where the type is actually known */ } ``` If you branch on `order.type` from a read path, that branch was reading a fabricated value. Handle `undefined` explicitly; the honest source for how an order was placed is your own `createOrder` result. Populating it on read paths needs the pools to emit the order type, which is a contract change. - BREAKING — a binary market that has never traded reports NO mark, instead of a mark of zero `computePositionPnL` and `computeBinaryPnl` valued an unpriced market at a YES price of zero. A binary market has no price until its first trade: the indexer creates the row with no `lastPrice`, and only a fill writes one. `markYesPrice` reports that correctly as `null`. Both PnL folds discarded the `null` and put a confident `0` in its place. The NO leg is derived as the complement of the YES mark. A YES mark of zero is therefore a NO mark of the FULL collateral unit. On a 10.00 basis, a wallet holding only NO read as a 5.00 gain, and a wallet holding only YES read as a 5.00 total loss. A wallet holding both legs cancelled to 0.00, which hid the fault in the blended total while both legs stayed wrong. Minting a complete set is the ordinary way to take a position in a market that has not traded, so this state is reachable. The unknown price now travels as `null` rather than a number: - `BinaryOutcomePositionPnL.markPrice`, `.markValue` and `.unrealizedPnl` are `bigint | null`. - `BinaryPositionPnL.markValue` and `.unrealizedPnl` are `bigint | null`. - `BinaryOutcomePnl.mark`, `.value` and `.unrealized` are `number | null`. - `BinaryPnl.unrealized` and `.total` are `number | null`. **Migration.** Handle `null` on those fields before you display or total them. `null` means the market has no price to mark against — show it as unknown, and do not treat it as zero. Every field that does not depend on a mark keeps its old type and value: `balance`, `costBasis`, `avgCost` and `realizedPnl` stay exact. Nothing else changes. A market with a last trade or a resting quote marks as before. A resolved market still marks the winner at one whole collateral unit and the loser at zero, and a voided market still marks both legs at half, because a settlement payout needs no price. While a market is unresolved and priced, its two legs still sum to exactly one collateral unit. ### Patch Changes - Document `StaleMark` in the `Order.cancelReason` vocabulary. The indexer writes five cancel reasons but both published vocabularies listed four, so the served GraphQL description and the SDK contract told a consumer that a value it can actually receive does not exist. No behaviour or type change: `cancelReason` remains an open `string | null`. - ### Fixed — pre-fill maker cancellations now leave the live order book Deployed perp pools cancel resting maker orders before any fill — negative equity, stale mark, exceeds position, self-match — and the SDK's live tail dropped those events undecoded. The cancelled order stayed `Open` in the local store, so the order book kept counting its quantity at a price level the chain had already cleared: phantom depth in every rendered book and market-maker view, for the whole life of the watch. `OrderCancelledPreFill` (the base event for every pre-fill removal) and the perp reason tags `MakerOrderCancelledNegativeEquity` and `MakerOrderCancelledStaleMark` are now declared and terminate the order; `MakerOrderCancelledExceedsPosition` and `OrderCancelledSelfMatch` were already declared and are now covered by tests. Termination only — no store shape change and no new fields. - Account-scoped fill reads match indexed columns instead of joining through the taker's order Three reads found the fills an account participated in by OR-ing a predicate on the taker ORDER's `owner` alongside the denormalized columns: `getUserFills`/`countUserFills`, the binary `getPortfolio`, and the user snapshot the live store hydrates from. That arm is a relationship predicate, and Hasura compiles it to a correlated `EXISTS` subquery. Postgres cannot combine such a subquery with a bitmap OR over the `maker` and `taker` indexes: the plan walks the `timestamp` index backwards testing each row, and every row it walks past costs a lookup into `Order`. The penalty therefore falls hardest on ordinary wallets, which are sparse in a table that market makers fill. A busy maker reaches `limit` in a few rows and barely notices; a wallet with a handful of fills scans a long way and pays the subquery the whole way down. On the development indexer, four real single-fill wallets took 2.78s, 4.50s, 8.75s and 10.93s to sweep their tape, against 0.04s, 0.41s, 0.26s and 0.27s once the arm was gone. The arm found nothing the other two missed. `backfillTakerFills` in the indexer stamps the taker address from `OrderPlaced` for SPOT, PERP and binary alike, and the taker's order is placed in the same transaction as the fill it crosses — a resting order occupies the maker seat by definition — so no committed row can lack it. `takerOrder: Order!` is non-null in the schema for the same reason. The docblock that defended the arm described binary as leaving `taker` null; that stopped being true when binary side attribution moved to `BinaryOrderPlaced`. Reads that page a wallet's whole tape gain the most, because they pay the penalty once per page. The three also compound: a trader portfolio sweeps its fill tape, reads its binary positions and hydrates its snapshot, so one light wallet paid the scan three times over. Measured together on the development indexer, one page of each took 13.89s before and 0.27s after. No signature, option or row shape changes, and the rows returned are the same rows. `takerOrder { owner side }` is still SELECTED: `side` is what makes a binary row mappable when the fill's own `takerSide` copy is still lagging, and selecting a non-null relationship is an ordinary join rather than a filter. The invariant holds structurally: the indexer writes `Fill.taker` and `Order.owner` from the same local in the same handler, so the two cannot disagree — delegated and operator-placed orders included. `sdk-e2e` also asserts it against a live indexer, though that suite is hand-run rather than a CI gate. ## 0.28.1 (2026-08-21) A single fix on top of 0.28.0. ### Fixed — five perp names the client-scoped move left unreachable 0.28.0 internalized the connection-bound free functions, but five names left the root barrel without arriving on `SomniaMarketsClient`. They were reachable by no route at all: absent from the root, absent from the client, and not deep-importable, since the package publishes only `.` and `./react`. Each is now where the client-scoped rule puts it. Two are connection-bound, so they are client members: | Name | Use | |---|---| | `getPerpStopOrder` | `exchange.client.getPerpStopOrder({ registry, orderId })` | | `getPerpStopOrderSomiPayment` | `exchange.client.getPerpStopOrderSomiPayment(registry)` | `listPerpStopOrders` did become a client member in 0.28.0, so listing was unaffected. But `getPerpStopOrder` is the only way to read a LIMIT stop's `limitPrice`, its linked `siblingOrderId` and its `intent`: no event carries them, so `PerpStopOrder` cannot, and nothing off-chain could tell an opening bracket from a reduce-only stop. Three are pure functions — sync, no client, no `Writer` — so they are client-independent utilities and are exported from the root again: - `perpLiquidationPrice` - `perpOrderMarginQuote` - `perpPositionAnalytics` Their input and output types were never removed (`PerpLiquidationPriceInputs`, `PerpPositionAnalyticsInputs`, `PerpPositionMetrics`, `PerpOrderMarginQuote`, `PerpOrderMarginQuoteInputs`), nor was `PerpStopOrderOnChain`, whose only producer is `getPerpStopOrder`. No migration is needed for 0.28.0 code: every name above was unreachable, so nothing can depend on its old shape. The roster in `test/rootExports.test.ts` now covers all five, so the same gap fails CI instead of shipping. ## 0.28.0 (2026-08-20) The API is now client-scoped — the one breaking item — and the published package can be imported again. The write path aligns prices and amounts to the venue's own tick and lot grids, and gains build-only order verbs (unsigned calldata) plus single and batch order amendment. Reads gain the stable market id on order and fill rows and the liquidation-keeper views. ### Breaking — client-scoped entrypoints (53 free functions + the `./lend` subpath removed) Anything that uses a connection (indexer reads, chain reads) is now reachable ONLY through the client facade — the root barrel no longer exports free-function duplicates of `SomniaMarketsClient` members. The migration is mechanical: drop the trailing `indexerUrl`/`client` argument and call the same name on `exchange.client` (every removed function already existed as a same-named member; none changed behavior). Types, pure kernels, constants, and ABIs stay importable from the root. `./react` is untouched. The `@somnia-chain/markets-sdk/lend` entrypoint is REMOVED for the same reason: the lend entry is client-scoped (`client.lend`). Its standalone surface moved to the root — change `from "@somnia-chain/markets-sdk/lend"` to `from "@somnia-chain/markets-sdk"` for the lend types (`LendReserve`, `LendAccount`, …), the `SOMNIA_MAINNET_LEND` / `SOMNIA_TESTNET_LEND` deployment constants, the ray-math helpers (`lendRayRateToApy`, `rayMul`, `accrueLinear`, `accrueCompounded`, `RAY`), and the lend ABIs. `createLendWithDeps` is no longer public — the client builds the lend entry itself. ```ts // before import { getBookTops } from "@somnia-chain/markets-sdk"; const tops = await getBookTops(marketIds, indexerUrl); // after const tops = await exchange.client.getBookTops(marketIds); ``` | Removed root export | Use instead | |---|---| | `countOrders` | `exchange.client.countOrders(…)` | | `countUserFills` | `exchange.client.countUserFills(…)` | | `creditOf` | `exchange.client.creditOf(…)` | | `earmarkedOf` | `exchange.client.earmarkedOf(…)` | | `getAccountHealth` | `exchange.client.getAccountHealth(…)` | | `getAllOpenOrdersOnchain` | `exchange.client.getAllOpenOrdersOnchain(…)` | | `getBinaryBookParams` | `exchange.client.getBinaryBookParams(…)` | | `getBookTops` | `exchange.client.getBookTops(…)` | | `getFreePools` | `exchange.client.getFreePools(…)` | | `getFundingPayments` | `exchange.client.getFundingPayments(…)` | | `getFundingRateHistory` | `exchange.client.getFundingRateHistory(…)` | | `getLiquidationPrice` | `exchange.client.getLiquidationPrice(…)` | | `getLiquidations` | `exchange.client.getLiquidations(…)` | | `getMarginEvents` | `exchange.client.getMarginEvents(…)` | | `getMarketByPool` | `exchange.client.getMarketByPool(…)` | | `getMarketCreator` | `exchange.client.getMarketCreator(…)` | | `getMarketResolution` | `exchange.client.getMarketResolution(…)` | | `getOpenInterestHistory` | `exchange.client.getOpenInterestHistory(…)` | | `getOpeningPrices` | `exchange.client.getOpeningPrices(…)` | | `getOperatorHubAccount` | `exchange.client.getOperatorHubAccount(…)` | | `getOracleAdapter` | `exchange.client.getOracleAdapter(…)` | | `getOracleQuestion` | `exchange.client.getOracleQuestion(…)` | | `getOrderOnchain` | `exchange.client.getOrderOnchain(…)` | | `getOwnOpenOrdersOnchain` | `exchange.client.getOwnOpenOrdersOnchain(…)` | | `getPool` | `exchange.client.getPool(…)` | | `getPoolBindings` | `exchange.client.getPoolBindings(…)` | | `getPoolCreator` | `exchange.client.getPoolCreator(…)` | | `getRouterActions` | `exchange.client.getRouterActions(…)` | | `getSchedulingCost` | `exchange.client.getSchedulingCost(…)` | | `getVaultBalance` | `exchange.client.getVaultBalance(…)` | | `getVaultPayoutFallbacks` | `exchange.client.getVaultPayoutFallbacks(…)` | | `listBuilderApprovals` | `exchange.client.listBuilderApprovals(…)` | | `listBuilderFees` | `exchange.client.listBuilderFees(…)` | | `listFundingRateCandles` | `exchange.client.listFundingRateCandles(…)` | | `listFundingRateHistory` | `exchange.client.listFundingRateHistory(…)` | | `listMarketCreators` | `exchange.client.listMarketCreators(…)` | | `listOperatorHubAccounts` | `exchange.client.listOperatorHubAccounts(…)` | | `listOracleAdapters` | `exchange.client.listOracleAdapters(…)` | | `listOracleBinds` | `exchange.client.listOracleBinds(…)` | | `listOracleCallbacks` | `exchange.client.listOracleCallbacks(…)` | | `listOracleQuestions` | `exchange.client.listOracleQuestions(…)` | | `listPerpFees` | `exchange.client.listPerpFees(…)` | | `listPerpOrderHistory` | `exchange.client.listPerpOrderHistory(…)` | | `listPerpPositions` | `exchange.client.listPerpPositions(…)` | | `listPerpStopOrders` | `exchange.client.listPerpStopOrders(…)` | | `listProtocolFees` | `exchange.client.listProtocolFees(…)` | | `listSeries` | `exchange.client.listSeries(…)` | | `listSettlementFees` | `exchange.client.listSettlementFees(…)` | | `listSweepableOrders` | `exchange.client.listSweepableOrders(…)` | | `outstandingOf` | `exchange.client.outstandingOf(…)` | | `quoteCreateMarketValue` | `exchange.client.quoteCreateMarketValue(…)` | | `resolveReserve` | `exchange.client.resolveReserve(…)` | | `withdrawableOf` | `exchange.client.withdrawableOf(…)` | | `createLendWithDeps` (from `/lend`) | `exchange.client.lend` (built by the client) | | any other `/lend` import | same name, `from "@somnia-chain/markets-sdk"` | ### Fixed — a scoped or windowed `fetchMyTrades` returns the rows it was asked for `fetchMyTrades` read a wallet's history through three venue portfolio functions and called all three with no options, so the indexer capped fills at 50 per venue BEFORE any scoping happened and `since`/`limit`/`ref` were applied afterwards in memory. The visible symptom was not truncation. A market-scoped call returned an EMPTY list over fills that exist: if a wallet's fills on the asked-for market were older than its 50 newest fills overall, the query never returned them and there was nothing left to filter. `since` failed the same way — "my trades since last week" returned whichever of the newest 50 fell in last week, a smaller and different set. It now reads the unified fill tape (`getUserFills`), so the scope, the window and the limit are applied by the indexer. `limit` counts rows the caller receives: unresolvable rows are skipped and the read pages until the limit is satisfied or the tape is exhausted. Two behavioural changes worth knowing: - **Ordering.** An unscoped call now returns rows newest-first across all venues. It previously returned them grouped binary → spot → perp, so "the newest 50 trades" was a venue-ordered window rather than the newest 50. - **`UnifiedTrade.info`** is now the `FillRow` the tape returned, where it was previously a venue portfolio trade row. It remains typed `unknown` and documented as the native fill row. `since` stays in MILLISECONDS on this surface, matching `UnifiedTrade.timestamp`; the conversion to the indexer's unix seconds happens internally. ### Added — `fetchOpenOrders` accepts a row limit It took only `(ref?)`, so a caller could not raise the 200-per-venue default. It now takes `(ref?, limit?)` and forwards it to the query. The limit is per venue, not a merged total — an unscoped call reads all three. Note the spot portfolio query binds one limit variable to both its open orders and its pending stop orders; that coupling is now documented on the verb. ### Added — the stable market id on order and fill reads Every row of `getOrders`, `getOpenOrders`, `listSweepableOrders`, `getFills` and `getUserFills` now carries **`market`** — the bytes32 market id, the stable identity of the market the row belongs to. A pool address is not a market identity: on binary event contracts one pool is recycled by successive markets, so the same pool names a different market depending on when the order was placed. Pass the id straight to `client.getMarket(id)`; no new API. Order rows additionally carry **`marketInfo`** (`asset`, `question`, `expiry`, `tradingStart`, `quoteDecimals`, `intervalSec`, plus the derived `interval` label), so a history view can label rows without a second round-trip. ### Fixed — the published package can be imported Every release from 0.20.0 through 0.27.0 shipped a `dist` in which no relative import specifier carried a file extension. Node's ESM resolver requires them, so `import "@somnia-chain/markets-sdk"` threw `ERR_MODULE_NOT_FOUND` before any user code ran, on every declared subpath. `./chains` failed differently, with `ERR_UNSUPPORTED_DIR_IMPORT`, because two specifiers named a directory. This was not limited to plain Node. webpack — and therefore Next.js — failed too, with "resolved as fully specified" errors; a consumer could only compile by setting `resolve.fullySpecified: false`. esbuild, Rollup, Vite and `tsx` worked only by legacy extension guessing. There was no CommonJS fallback, and `src` in the tarball was unreachable behind a strict `exports` map. The package now compiles with `moduleResolution: "nodenext"`, so every relative specifier carries its extension and the compiler rejects the form that caused this. The public API, the exports map and the module format are unchanged — imports that used to throw now resolve. Nothing caught this for seven releases because vitest and `sdk-e2e` consume the SDK through the workspace `exports` block pointing at `src/*.ts`, so the test surface never loaded `dist`. Publishing is now gated on `scripts/publish-import-gate.mjs`, which packs the tarball, installs it into a bare `{"type":"module"}` project with no bundler, and imports every subpath the published exports map declares. ### Fixed — the write path now applies the venue's tick and lot grids `createOrder` converted the caller's price to raw units and sent it without ever snapping it to the market's tick grid — it never called `priceToPrecision`. So the pool rejected the order with `InvalidPrice` even when nothing had been lost in conversion: `createOrder(sym, "limit", "buy", 1, 0.25)` on a market with a `0.1` tick sent an off-tick price, and `0.25` is exactly representable as a double. Market orders were worse, because the caller never supplies the price. The protective limit was `best * (1 ± slippage)` computed in float and sent unaligned. Its binary clamp also bounded at `1 / 10 ** decimals` — one *wei*, not one tick — so on any venue whose tick exceeds a single raw unit the clamp's own bound was a value the pool rejects. `createOrder`, `createStopOrder` and the computed crossing price now align in bigint space against the same grid the precision helpers read. Aligning a value that is already on the grid returns it unchanged, so a caller who pre-snaps with `priceToPrecision` / `amountToPrecision` sees no behavioural change at all. **Direction is side-aware, and never moves a value against the caller.** A buy price rounds down, a sell price rounds up, and a quantity always rounds down — so an order is never larger, nor worse priced, than what was asked for. Rounding a sell price down (which is what `priceToPrecision` does, for either side) would be a real loss, so the write path and that helper can now differ by one tick on a sell; the helper's own spec pins its floor-only behaviour and is left alone. The one exception is a protective limit the SDK computes for a market order: that rounds *away* from the caller, so the cushion survives alignment and the order still crosses the level it was priced against. This matches how the stake and sell quote builders in `derivedReads` have always done it. Two visible consequences: - `UnifiedOrder.price` / `.amount` (and the stop-order equivalents) report what was actually placed, which may differ from the arguments by up to one tick or lot. `remaining` and `status` are derived from the placed amount, so an order that aligned down no longer reports a remainder that does not exist. - A quantity below one whole lot now throws `InvalidInputError` naming the market's minimum, instead of sending a zero-quantity order. Not breaking: every affected call previously either reverted on-chain or was already being pre-aligned by the caller to the same value. ### Fixed — a float price could not be placed on an 18-decimal venue `fromHuman` formatted numbers with `toFixed(decimals)`, which prints the float's binary expansion rather than the number the caller typed: at 18 decimals `(0.05).toFixed(18)` is `"0.050000000000000003"`. Three wei is enough to miss the live binary venue's 1e15 tick, so the pool rejected the order with `InvalidPrice`. Measured against the mainnet USDso venue: of fifteen ordinary probabilities only 0.25, 0.5 and 0.75 could be placed, the ones binary floating point represents exactly. A 6-decimal venue never shows it, so testnet stayed clean. Numbers now convert through their shortest round-tripping form (`String(n)`, i.e. `"0.05"`) whenever it fits the token's scale. `toFixed` still covers what it was there for: exponent notation and mantissas longer than `decimals` (which it rounds to scale, now stated in `fromHuman`'s docs rather than left implicit). The string path is unchanged. The same defect had been hand-rolled at two more sites, both fixed here so the write path has one definition of "the value the caller typed": - `Structs.toRaw`, which `createOrder` uses via `toNativePrice` — so the ccxt-shaped surface was broken too, and a fix to `fromHuman` alone would have left it that way. - `exchange.priceToPrecision` / `amountToPrecision`, the helpers a caller is told to use to AVOID off-tick values. They aligned to the grid in float space and then re-printed with `toFixed`, putting the expansion back — off-tick 16 times out of 19 on the live venue's ladder. Alignment now happens in bigint space, the only space the grid is defined in. Note that this fixes conversion, not arithmetic done before it: a caller who computes `3 * 0.05` still hands over `0.15000000000000002`, a genuinely different number. Snapping a computed price onto the venue's grid is `priceToPrecision`'s job. `priceToPrecision` keeps treating a value a hair BELOW a grid point as sitting on it, which the old float path did with a `+1e-9` nudge. A book mid like `(0.001 + 0.009) / 2` is `0.004999999999999999`, and flooring that would quote a whole tick away from what the caller asked for. The tolerance is now relative (one part in `2 ** 52`, the double's own resolution) rather than a fixed `1e-9`, so it scales with the price instead of being meaningless at 1e6 and overwhelming at 1e-9. `amountToPrecision` deliberately does NOT get that nudge — it snaps strictly down. An amount is usually bounded by something the caller cannot exceed (a wallet balance, a budget), and because the tolerance is relative it grows with magnitude: a balance one wei under a lot boundary would be rounded past it, producing the "insufficient balance" revert that `balanceFloor` / `floorRawBalance` exist to prevent. A price has no such ceiling. `Structs.snapToGrid` takes a `strict` option for callers in the first category, and under it the conversion INTO raw units truncates past `decimals` rather than rounding to scale — otherwise an over-precise number arrives already inflated and the floor starts from the wrong value (`amountToPrecision(0.1234567)` on a 6-decimal base returned `0.123457`, above the caller's own number). `fromHuman` and `probabilityToPrice` now reject non-finite numbers with `InvalidInputError` instead of letting viem's `InvalidDecimalNumberError` escape. `probabilityToPrice(NaN)` previously slipped past its own range check, since `NaN < 0` and `NaN > 1` are both false. ### Fixed — raw → human scaling no longer divides floats `Structs.toHumanNum` scaled with `Number(raw) / 10 ** decimals`. The division is a float operation, so it could land a few wei off the value it was handed: `19000000000000000000000` came back as `19000.000000000004`, which is not on a 1e15 grid. That silently undid the bigint alignment `priceToPrecision` had just performed — about a quarter of ordinary prices above ~1000 were returned OFF the grid they had been snapped onto, and `createOrder` re-converts that number before sending it, so the result was `InvalidPrice` again. Spot and perp prices live at exactly those magnitudes; the binary probabilities under 1 that the rest of this entry is about never showed it. It now scales through the exact decimal string, like `toHumanString` already did. The result is still a `number`, so it is still display-grade past ~15 significant digits — but it is the closest double to the true value rather than the closest double to a lossy quotient. This affects every `toHumanNum` caller, and only ever in the direction of accuracy: the two differ solely where the division was wrong. ### Fixed — `getPerpState` reads every field at ONE block `getPerpState` fanned out with `Promise.all` over nine independent `readContract` calls, so its values could come from different blocks. A mark price from block N beside a funding rate from block N+2 describes a market state that never existed — and a price bar rendering the pair presents it as if it did. Every read is now pinned to a single block number. The pin, not the multicall, is what provides the guarantee: viem splits a batch into several `eth_call`s once the calldata exceeds `batchSize`, and those can straddle blocks. Where the client's chain declares a Multicall3 — `viem/chains`' `somnia` and `somniaTestnet` both do — the nine reads also batch into one `aggregate3`, so the call costs two round-trips instead of nine. A chain built with a bare `defineChain` declares no contracts, so it keeps the fan-out and costs one MORE round-trip than before (the block pin). Correctness is identical either way. No API change — `PerpStateOnchain` and the `getPerpState(pool)` signature are unchanged. `tryGetMarkPrice` is still the mark read, so a stale feed still returns `markPriceOk: false` rather than throwing. `withTypedReadErrors` now also wraps `multicall`. Viem binds `client.multicall` to the raw client, so the existing `readContract` wrapper never fired for batched reads — without this, a revert read through multicall escaped as a bare viem error while the identical read through `readContract` threw a typed SDK error. ### Added — caller-set expiry and builder attribution on spot and perp orders `placeSpotOrder` and `placePerpOrder` now accept the expiry and builder fields the binary `placeOrder` already threaded. They were hardcoded before, so a caller could not set a spot order's expiry at all and could not attribute a spot or perp order to a builder: ```ts await exchange.trader.placeSpotOrder({ pool, isBid: true, price, quantity, baseDecimals, quoteToken, baseToken, expireTimestampNs: 1_800_000_000_000_000_000n, // was pinned to ~50y (GTC) builder: "0xYourFrontend", // was pinned to the zero address builderFeeBpsTimes1k: 25_000n, // was pinned to 0 }); ``` - `PlaceSpotOrderParams` gains `expireTimestampNs`, `builder`, and `builderFeeBpsTimes1k`. `PlacePerpOrderParams` gains the two builder fields (it already had `expireTimestampNs`). - Every field is optional and defaults to the value that was hardcoded before (`farFutureNs()`, the zero address, `0n`), so existing callers are unaffected. - A nonzero builder fee still requires a prior `Trader.approveBuilder` on that pool — the approval is stored **per pool**. See `docs/SPOT.md` and `docs/PERPS.md` for the fee ceiling and the two spot-expiry traps (a past expiry places nothing silently; an expired order does not auto-return its escrow). ### Fixed — `SomniaMarkets.createOrder` dropped builder attribution on spot and perp `createOrder` accepted `builder` / `builderFeeBpsTimes1k` but only forwarded them on binary markets. A spot or perp order placed through the unified surface rested with the zero-address builder: the call reported success, and no fee was attributed. Both fields now reach all three branches, and they are no longer documented as "BINARY only". ### Added — liquidation-keeper reads: `getPerpSideHolders` + `getBankruptcyPrice` The two MarginBank views the agreed permissionless liquidation-keeper design consumes, from head state alone — no off-chain indexer: - **`getPerpSideHolders({ marginBank, pool, isLong }, opts?)`** — every account holding an open position on one side of one perp market. Pages through the bank's bounded slice view (`getSideHoldersPaginated`; many holders per round-trip, never one call per holder) with every page pinned to ONE block — `opts.blockNumber`, or the head sampled once — and returns `{ holders, asOfBlock }`. Feed `asOfBlock` into `getBankruptcyPrice`'s `blockNumber` option (and the other side's call) so a sweep describes one consistent state. - **`getBankruptcyPrice({ marginBank, account, pool }, { blockNumber? })`** — the bank's OWN price at which the position's allocated equity is exhausted, verbatim. A different quantity from the client-side `getLiquidationPrice` estimate (where liquidation *triggers*): keepers settle and bid against this one. Reverts arrive **named** — `ContractRevertError` with `errorName: "NoOpenPosition"` when the account is flat in that pool (and `"AdlZeroNotional"` in the dust degenerate) — even though the generated error table does not cover MarginBank yet: the module fills the name in from the ABI-declared selectors, and the seam is a structural no-op once the table grows to cover the submodule's perp contracts. New exports: `PerpSideHolders`, `PerpSideHoldersRef`, `GetPerpSideHoldersOptions` (types only — the reads live on the client, deliberately not as standalone connection-bound exports, matching the client-scoped API direction). ### Added — build-only order placement (unsigned calldata) `trader.buildPlaceOrder`, `buildPlaceSpotOrder`, and `buildPlacePerpOrder` take the same parameters as their sending twins but hand back the unsigned call instead of signing and broadcasting it: ```ts const { order, approval } = await trader.buildPlaceOrder({ pool, side: "BUY_YES", price, quantity }); if (approval) await walletClient.sendTransaction({ ...approval, account }); // `order` is {to, data, value} — pre-sign it, batch it, relay it, or simulate it. ``` For pre-signing an ERC-4337 UserOp off the form input, batching a placement into a multicall, handing it to a relayer, or simulating it. Ordinary "place this now" stays on `placeOrder`. The approval is **returned, not sent** — `placeOrder` approves as a side effect, which a build-only verb cannot do. Send `approval` first when it is present. It is absent when nothing needs approving (a native-base spot sell, every perp placement). Also newly exported from the root, so a caller can encode a placement by hand: `ORDER_KIND`, `binaryPoolWriteAbi`, `spotPoolWriteAbi`, `perpPoolWriteAbi`, and the `UnsignedCall` / `UnsignedOrder` types. (A returned `approval` is a standard ERC-20 `approve` or ERC-6909 `setOperator` — decode it with viem's own `erc20Abi` or the already-exported `erc6909Abi`.) ### Added — `ceilRawAmount` The SDK could round an amount DOWN in a controlled way but not UP. Flooring exists because a "max" one ULP above the wallet is an insufficient-balance revert; a **minimum** has the mirror failure, rejected as under the minimum. - **`ceilRawAmount(raw, decimals, quantum)`** — `raw` rounded UP to a whole multiple of `quantum`. The mirror of `floorRawBalance`, for sizing minimums. It returns a `bigint` rather than a `number` like the floors do: a lot boundary such as `0.1` at 18 decimals has no exact `double`, and the nearest one sits below the minimum. Convert at the edge with `Number(formatUnits(...))` if you need a number. ### Fixed — stop-order and SpotPool reverts have names instead of hex A failed `placeSpotStopOrder` or `cancelStopOrder` reported opaque hex. The generated revert-decoding table was extracted from this repo's Foundry artifacts only, and forge emits artifacts for just the DEX contracts our own contracts import — so `SpotStopOrderRegistry` and `SpotPool`, which nothing here imports, had no artifacts and no decodable errors at all. `Trader`'s docs promised `errorName` would carry the protocol's own error; for those paths it never could. `errors:gen` now builds the DEX submodule as its own forge project and merges its artifacts, so what the SDK can name no longer depends on what this repo happens to reference. Newly decodable: - **All 28 `ISpotStopOrderRegistry` errors** — including `InsufficientVaultBalance`, `InsufficientSomiPayment`, `NoActiveSubscription`, `LimitPriceIncompatibleWithTrigger` and `ExceedsWithdrawableBalance`. - **The `ISpotPool`-only errors** — `OrderIdMismatch` (cancelling an order that already filled) and the builder-code family (`BuilderNotApproved`, `BuilderFeeExceedsApproval`, `BuilderCodesNotSupported`). - **The parameterless `QuantityBelowMinimum()`** the registry declares, alongside the CLOB's existing `QuantityBelowMinimum(uint256,uint256)`. Different selectors, so both entries are needed; only the two-argument one was present before. `errors:check` is unchanged and still hermetic — it recomputes the stamp from this repo's files plus the submodule's pinned commit, with neither forge nor a submodule checkout, so CI needs no access to the private DEX clone. Only `errors:gen` now requires the submodule checked out, and it fails loudly rather than quietly writing a smaller table. ### Added — `trader.amendOrders`, cancel and replace N orders atomically Amending a quote one order at a time costs two transactions per rung and leaves the book briefly one-sided. `amendOrders` does the whole set in a single transaction: every old order is cancelled and its replacement placed, or the batch reverts and nothing moves. `alwaysPlace` handles the race where an order you meant to amend has already filled or been cancelled by the time the tx lands. False (the default, and the industry-standard posture) reverts `AmendOldOrderGone`; true skips the cancel leg and places the replacement anyway. It only tolerates a *gone* order — someone else's live order still reverts `IncorrectSender`. `newOrderIds` comes back index-aligned with the submitted amendments. The pool returns those ids on-chain, but a mined receipt exposes only logs, so they are reconstructed from `OrderPlaced` — which fires for every accepted order, including one that fills completely without ever resting. A rejected replacement reverts `AmendReplacementRejected(requestIndex, reason)`, which names both the rung and the `OrderRejectionReason` — the signal to branch on. Note the cancel-all-first phase shields replacements from the orders they replace but **not from each other**: a new bid crossing a new ask self-matches and, being all-or-nothing, takes the whole re-ladder with it. Unlike `placeSpotOrder`, this does not auto-approve escrow. On an auto-pull pool the cancel leg returns freed tokens to the wallet and the place leg pulls them back, so a trader whose first call is `amendOrders` needs an allowance already in place. **SpotPool and PerpPool only.** A BinaryPool reverts `UseBinaryPlacement` for the whole transaction: binary placement carries the YES/NO kind through a transient slot that only `placeBinaryOrder` sets, and there is no batch binary entry. ### Added — `trader.amendOrder`, the single-order re-quote The batch `amendOrders` landed without its singular sibling, so re-quoting ONE order meant either a two-transaction cancel-then-place (which opens a gap on the book — the thing amend exists to prevent) or a one-element batch with a worse error surface. `amendOrder({ pool, oldOrderId, alwaysPlace?, newOrder })` calls the pool's own `amendOrder`, so a rejected replacement raises its landing-time reason directly (`PostOnlyWouldCross`, `SelfMatchCancelTaker`, `ImmediateOrCancelNoFill`, `FillOrKillNotFillable`, `OrderAlreadyExpired`). The batch wraps the same failure as `AmendReplacementRejected(requestIndex, reason)`, which for a single order is an index the caller already knew and a reason they then have to unwrap. Everything else matches the batch verb: `alwaysPlace` defaults to false and reverts `AmendOldOrderGone` on a vanished order (true opts into an upsert, and never tolerates an ownership failure); the replacement gets a NEW id and loses queue priority — use `reduceOrder` to shrink in place; and the call is non-payable, so native replacements need a manual-vault balance rather than auto-pull. ### Added — claim the SOMI a perp stop registry owes you `trader.claimPerpStopSomi` and `client.getUnclaimedPerpStopSomi` — the registry holds SOMI for an account in two cases, and neither was reachable from the SDK: a cancel whose direct refund transfer failed (a contract owner with no payable receiver), and an operator winding a registry down, which credits **every** owner including EOAs. Read the balance first; the claim reverts `NothingToClaim` on zero. Deliberately not wrapped: `withdrawSomi` is owner-only and cannot touch unclaimed balances, and `poke()` — permissionless, but the caller subsidises every eligible trigger, the `somiPaid` is consumed rather than reimbursed, and below the gas reserve it breaks out and the transaction succeeds having done nothing. ### Changed — faster log decoding on the live tail and the write path `decodeEventLog` memoizes nothing: for every log it walks the ABI deriving each candidate selector, and a log the ABI does NOT carry costs a full scan plus a thrown error that the caller immediately swallows. Foreign logs are the common case — any ERC-20 `Transfer` from a token touched in the same transaction lands in the same receipt — and the live tail decodes every block. A topic0 membership check now runs first. Against `liveEventsAbi` (29 events) an unmatched log cost 223 µs and now costs 0.054 µs; on a realistic block carrying four pool events among forty foreign logs, decoding went from **9.00 ms to 0.10 ms**. Internal only — no API change, and the decoded type is unchanged: the full ABI still does the decoding, so the discriminated union callers rely on is intact. ### Added — `useIndexerQuery` aborts superseded requests + exported query-key factories `useIndexerQuery` now creates an `AbortController` per run, hands its signal to the fetch function (the `fn` signature widened to `(client, signal)`, an additive change), and aborts on dependency change, refetch and unmount — a late settle from a superseded run never reaches state, even when `fn` ignores the signal. The root entry also exports query-key factories for callers wiring client reads into their own query library: `marketsKey`, `portfolioKey`, `candlesKey`, `marketFeesKey`, `operatorsKey`, `marketCreatorsKey`, `oracleAdaptersKey`, `syncStatusKey`, `maxVenueFeeBpsKey` and `marketOnchainKey`. Plain functions, no query-library dependency, returning JSON-serializable, case-folded, scope-prefixed arrays. Client reads themselves still take no per-call `AbortSignal` — cancellation remains client-scoped via `ClientConfig.signal`; the hook's signal benefits fetch functions that do their own fetching. ## 0.27.0 (2026-08-14) The first release since 0.25.0. Three new entry points (`/chains`, `/reactivity`, `/native`), the perp trading surface filled in end to end, and batch order writes. One breaking item — the `somnia-dex-protocol` re-pin. ### Breaking - **`somnia-dex-protocol` re-pinned to `main` (DEX-1761).** Reinstall to pick up the corrected revert ABI. Four order rejections that used to be silent — post-only would cross, self-match cancel, IOC no-fill, already-expired — are now named reverts. ### Added — new entry points - **`/chains`** — every Somnia network as a viem `Chain` (mainnet, Shannon, Elwood, Hideki, local). The only place chain definitions live. - **`/chains` bridge** — the Hyperlane warp-route registry plus `createBridgeTransfer` / `sendBridgeStep`. Pure: no client, no RPC. - **`/reactivity`** — the upstream `@somnia-chain/reactivity` package re-exported, as an optional peer dependency. - **`/native`** — the node's `somnia_*` namespace: native ledger blocks, statistics, node public keys, reactivity subscription reads and session transactions. ### Added — perps - **Per-position analytics.** Unrealised PnL, accrued funding, position margin and return on margin, instead of account-level equity that folded them together and exposed neither. - **Leverage and a projected liquidation price.** `getPerpLeverage`, plus `previewPerpLiquidationPrice` for an order not yet placed. - **Max order size.** `getMaxPerpOrderSize` — what a Max button should call. It binary-searches the pool's own sizing rule rather than keeping a second copy, so the size it returns cannot be one the pool then rejects. - **Close preview.** `previewPerpClosePnl` for a full or partial close. Handles the two subtleties: size snaps down to a lot multiple before anything realises, and a close settles funding on the whole position rather than the closed share. - **Auto-pull.** Placement can now fund itself from the wallet, so opening a position is one transaction rather than approve + deposit + place. Both order-form previews take an `autoPull` flag, and `quotePerpOrderTopUp` exposes the bank's own sizing. See `docs/PERPS.md` — the flag is opt-in because the pool gates it on `msg.sender == order.owner`, so it must stay off for `placeOrderFor` and operator-grant flows. - **Stop orders (DEX-2154).** `placePerpStopOrder` with linked one-cancels-other TP/SL pairs and opening triggers, plus `listPerpStopOrders` / `getPerpStopOrder`. - **Build-only writes.** `buildPlacePerpStopOrder`, `buildCancelPerpStopOrder(s)`, `buildDepositMargin` and `buildWithdrawMargin` return the unsigned call instead of broadcasting it, so writes that are only safe together — an order with TP/SL attached, approve + deposit, withdraw + forward — fit in one UserOp, Safe batch or multicall. Approvals come back rather than going out and must execute first; ids come from your own receipt via `decodePerpStopOrderIds`. See `docs/PERPS.md`. - **Funding-rate series (DEX-2025).** `buildFundingRateSeries` and the matching React hook, for a chart — poll plus live nudge. ### Added — everything else - **Batch order writes (MAR2-95).** `placeSpotOrders` / `cancelOrders` / `reduceOrders` — a ladder in one transaction instead of a loop of single sends. - **Operator grants (TRAD-140).** Grant/revoke writes plus registry approval views. - **Dead-oracle recovery.** The two entry points the recovery path was missing, so it no longer needs `cast send`. - **Vault funding.** Deposits, and the auto-pull opt-out. - **SpotPool funding + lock reads** are public. ### Fixed - **Short-side liquidation price.** `getLiquidationPrice` reported the liquidation further away than it actually is on shorts. No call-site change, but the numbers move. - **CLOB reverts are named** rather than surfacing opaque hex. - **Perp reverts are named too.** A failed `PerpPool` / `MarginBank` / `PerpStopOrderRegistry` call now reports `ContractRevertError.errorName` — `InsufficientCollateral`, `MarketRestricted`, `InsufficientSomiPayment` — across 122 error names, so an app no longer needs a hand-copied list that goes stale. - **`stopRegistry` reaches perp market rows.** Every perp stop write takes the per-pool registry as a required argument, and the SDK gave no way to find that address. ### Changed - **`AsyncCache` (MAR2-80)** for promise-memoizing maps. ### Perp stop orders — linked (OCO) TP/SL and opening triggers `placePerpStopOrder` is now the single create entry point for perp stops, and it covers three registry functions that a caller no longer has to choose between: - **A linked (OCO) pair** — pass `pair` with the second leg. Both are created and linked atomically, at twice the SOMI (one payment funds one trigger). When one leg triggers **and fills**, the registry cancels the other and credits its SOMI back. Legs are routed by operator, not by argument order, so it does not matter which you pass first. The result carries `pairedStopOrderId` alongside `stopOrderId`, caller's own leg first. - **An opening (non-reduce-only) trigger** — pass `intent: "opening"` for a stop-entry or breakout, gated on initial margin at creation so an order that could never margin itself is refused rather than burning its SOMI at trigger. - **Unchanged by default.** A call passing neither `intent` nor `pair` still routes to `createPendingOrder` and produces byte-identical calldata to before. Also **`linkPerpStopOrders`** (pair two stops that already exist, moving no SOMI), **`cancelPerpStopOrders`** (batch teardown in one transaction with a single refund — the way to close a pair), and **`getPerpStopOrder`** (read one stop straight from the registry). That last one closes a gap this SDK previously recorded as permanent: a LIMIT stop's `limitPrice` never leaves calldata and private storage, so nothing off-chain could show the limit a trader chose. It also answers during an indexer outage, and is currently the only way to read a pair's `siblingOrderId` and an order's `intent`. Cancelling one leg of a pair yourself cancels **one order** — the other stays armed and becomes unlinked. That is the registry's behaviour, not a limitation here. `getPerpStopOrder().intent` is `null`, not `"reduceOnly"`, when the registry reports an intent this SDK version does not know. The registry appends to its enums (`DropReason` just gained `NoFill`), and defaulting an unrecognized member to reduce-only would assert that an order cannot increase a position when a newer member might let it. `listPerpStopOrders` decodes the new `NoFill` drop reason, and now breaks a `createdAt` tie with `id` so its `offset` paging cannot repeat or lose a row — two stops created in the same block share a timestamp, which left the boundary between two pages undefined. The listing does **not** yet carry pairing, intent, or a cancellation cause. Those are new indexer columns behind a from-scratch reindex, and selecting a column the deployed Hasura does not serve is a validation error rather than a null — it would take the whole read down for every caller. They arrive in a follow-up release once that reindex has cut over. ## 0.25.0 (2026-08-07) `getOpenPositionsWithPnL(account)` — reliable avg-cost PnL for ALL of an account's open binary positions in one batched call. ### Added - `client.getOpenPositionsWithPnL(account)` → `OpenPositionPnL[]`: each open position's market joined with its `costBasis` / `avgCost` / `markValue` / `unrealizedPnl` / `realizedPnl`, computed identically to `getBinaryPositionPnL` (weighted-average cost from the account's own fills, marked to the book-clamped price) but for every open market at once, in a bounded number of indexer round-trips (fills + router actions + top-of-book batched) instead of a per-position loop. Prefer this over deriving PnL from book stats. - Exported the pure `computeOpenPositionsPnL` fold + the `OpenPositionPnL` type. Additive; no breaking changes. ## 0.24.0 (2026-08-07) The perp read surface, in one release: discovery, positions, orders, risk, margin preview and protocol state. Plus order state at chain head for every market type. **Requires a reindex from scratch.** The perp stop registries are newly subscribed, so their history only exists after a full re-run. ### Breaking — `SpotStopOrder.spotOrderId` is now `placedOrderId` The field is the id of the order the stop PLACED when it triggered, and both the spot and perp registries now record it. Rename at the call site; type and meaning are unchanged. The chain event keeps its own name — this is the SDK/entity field only. ### Added — perp market discovery `listPerpPoolStatuses({ factory })`, `listTradeablePerpPools(…)`, `isPerpPoolRegistered(…)`. An on-chain source of truth, so a market deployed after the indexer's curated manifest is still visible. **"Deployed" is not "tradeable"** — two independent gates: `restricted` (close-only; position-increasing orders revert, and it is reversible) and `registered` (the MarginBank has activated the pool). `tradeable` folds both. `getPoolTier` is not a substitute — it is itself gated on registration. Do not build a market list from the factory's raw pool list; that is deployment history and lists wound-down markets as tradeable. Each row carries its pool's own `marginBank`, ready for the reads that follow. Feature-detected by ERC-165 on `IPerpPoolFactoryMarketStatus` (`0xa874fb70`, exported) with a per-pool fallback; on a chain old enough to need that fallback, `registered`/`tradeable` come back `null` rather than guessed, and `listTradeablePerpPools` throws instead of returning a short list that looks authoritative. Only a missing-selector revert is treated this way — an RPC failure still propagates. ### Added — `listPerpPositions` `listPerpPositions(account, opts?)` returns every pool's position from the indexer, replacing a chain-read-per-market fan-out. Additive; `getPerpPosition` remains the authority for a single pool. Three fields are translated at this boundary because the raw shape would produce plausible wrong numbers: `size` is **signed** (folded from the entity's absolute size + `isLong`), `entryPriceX18` is exported as `avgEntryPrice` (the column name is a misnomer — the value is raw quote units per whole base, not 1e18-scaled), and `realizedPnl` is exported as `lastUpdateRealizedPnl` (most recent update only, not cumulative, not summable). Fully-closed positions are excluded by default (`includeFlat: true` returns them). Nothing is marked to market — unrealized PnL, liquidation price and margin health remain chain reads. ### Added — `listPerpOrderHistory` `getPerpPortfolio` hard-filters `status = "Open"`, so finished perp orders were unreadable. This is the other half, most-recently-**ended** first — a long-resting order that just filled belongs at the top of a history view, not at its placement date. Note `Closed` is terminal, not transitional: an IOC that partially filled without resting stays `Closed` forever. ### Added — perp stop orders are listable `listPerpStopOrders` over the indexed `PerpStopOrderRegistry` set. The registry keeps pending orders in private storage with no getter, so before this there was no read — chain or otherwise — answering "what stops do I have"; a trader could create stops but not see or cancel them. `builderFeeBpsTimes1k` is captured now precisely because it cannot be captured later: the registry deletes a pending order on every fire, so `PendingOrderCreated` is the only record the fee ever existed. One field stays out of reach — a LIMIT stop's `limitPrice` never leaves calldata and private storage. ### Added — per-market risk parameters `getPerpRiskParams(pool)`, `getPerpHealthSnapshot(pool)`, `getEffectiveImfBps(pool)`. `maintenanceMarginBps` was exposed nowhere, so a projected liquidation price for an unplaced order was impossible. **Initial margin is not a constant; maintenance margin is.** `initialMarginBps` is the floor of the curve — with dynamic IMF the pool scales it with open interest, and `effectiveImfBps` is what an order is actually charged. Sizing off the static base under-margins whenever OI has pushed the curve up. Maintenance margin deliberately does not scale. On testnet today both are 500 bps (dynamic IMF off), which is why the distinction is documented rather than left to be discovered. `getPerpHealthSnapshot` returns a discriminated union: an unpriceable market surfaces as `{ priceable: false }` rather than an all-zero snapshot, where a `maintenanceMarginBps` of `0` would read as "can never be liquidated". ### Added — `previewPerpOrderMargin` Predicts what a perp order will lock and whether the pool will accept it, before sending. The two contract probes are also exposed verbatim: `quoteMeetsPerpImForOrder`, `meetsPerpImForFill`. **`quoteMeetsIMForOrder` looks like the pre-trade check and is not.** It runs with `baseImReserved = true`, mirroring the check that happens *after* `lockCollateral` has already reserved the order's base margin — so called cold it collapses to "does existing equity cover existing positions" and returned `true` for 10^18 base units against a live testnet account. It cannot gate an order form. The preview instead ports `PerpPool._computeLockAmount` and the `MarginBank` gate it feeds: the reducing/increasing split, **the adverse mark-to-entry reserve** (the usual reason a naively-sized "max" order is rejected, and a term a `notional × IMF` estimate misses entirely), the OI-scaled effective IMF, the per-market leverage cap, and the credit-voucher floor. Two gates are reported separately because they fail for different reasons: `hasCollateralForLock` means "deposit more", `meetsInitialMargin` means "close something". Every read is pinned to one block and `asOfBlock` is returned — composed across blocks these values tear. A purely reducing order trips neither gate, so a close is reported as accepted even from an account below initial margin. Not modelled: tick/lot quantization, position/OI caps, market restriction, the resting-order cap, isolated margin — all reject independently of margin. Verified against a live testnet account to the unit: the computed boundary is accepted at `q` and rejected at `q + 1`, matching the chain's own `meetsIMForFill`. ### Added — perp protocol state `getPerpSystemConfig`, `getInsuranceFundState`, `getLiquidationEngineConfig`, `tryGetPerpAccountEquity`, `getPerpCollateralBasis`. `getPerpSystemConfig` is the entry point — every other contract in the plane is reachable from it, as the bank's own view of them, so nothing is hardcoded per chain. Its `fullyWired` flag covers the factory, liquidation engine and insurance fund but **not** `feeRecipient`, so a go-live check must look at that separately. Insurance-fund tiers are indexed `0..maxTiers` **inclusive** — `maxTiers` is the maximum index, not a count, so the fund has `maxTiers + 1` buckets. `totalBalance` is deliberately not described as absorbable bad debt: it includes tier 0, which never absorbs anything. `liquidationEngine` is the proxy, and that distinction bites — an implementation address answers with unset defaults (zero bidders, zero penalty), which looks like a configured-but-idle engine rather than the wrong address; the returned `marginBank` is the cross-check. `bidderCount === 0n` is an operational signal: with no stage-4 backstop bidders the waterfall reaches ADL sooner than the configuration implies. `tryGetPerpAccountEquity` returns `null` where `getAccountHealth` would revert. Null is "not computable right now", never "zero equity" — the two mean opposite things. `getPerpCollateralBasis` is the complement: one storage pair, no oracle, cannot revert. ### Added — perp fields on `fetchTicker` `UnifiedTicker` gains `markPrice`, `indexPrice`, `fundingRate`, `fundingTimestamp` and `openInterest`, populated on perp symbols and `undefined` elsewhere, so one call answers a market header. A non-perp spends no chain round-trip. `fundingRate` is on the **same per-8h axis** as `fetchFundingRate` — a header reading one basis beside a chart reading another is a wrong number that looks right. It is not the per-settlement amount. `markPrice` is omitted rather than reported when the feed is stale: the contract's `0` sentinel reads as a real price, and an unguarded `markPrice - entryPrice` becomes a 100% loss on every open position. ### Added — order state at chain head `getOrderOnchain`, `getOwnOpenOrdersOnchain`, `getAllOpenOrdersOnchain` — so a caller can read its own writes instead of waiting for the indexer. All three work for binary, spot and perp pools; fields are raw `bigint` units. `getOrderOnchain` returns `null` for any id the pool has no **active** order for (unknown, filled, cancelled, or replaced by `reduceOrder`) — chain head knows what is open now, the indexed `getOrders` keeps the history. `getOwnOpenOrdersOnchain` takes the owner explicitly and needs no signer. `getAllOpenOrdersOnchain` never forwards a configured signer — the pool accepts that view only from the zero address — and surfaces the contract's own pagination as-is. ### Added — `listSweepableOrders` `listSweepableOrders({ pool?, marketType?, owner?, asOfSec? })` returns orders past expiry that are **still resting**, across the whole book — the work-list for a permissionless sweep. Each row carries `orderId` for `cancelExpiredOrders` and `isBid` + `price` for `sweepExpiredAtLevel`. **Deliberately not `status: "Expired"`.** That status is written when the chain emits `OrderExpired` — i.e. once an order has already been swept. A keeper needs the opposite: still `Open`, already past expiry. The cutoff is scaled to nanoseconds; comparing against unix seconds would make every order look unexpired by a factor of a billion. GTC excludes itself (written as now + 50 years). Longest-overdue first. ### Fixed — binary precision comes from the pool, not a one-token guess `amountToPrecision` returned `0` for any binary amount below a whole token. Binary rows arrive from the indexer with `tickSize` / `lotSize` / `minQuantity` undefined, so the helper fell back to a one-whole-token lot — while every deployed venue enforces a 0.001-token lot: ```ts // BEFORE — 0.005 outcome tokens, on a venue whose lot is 0.001 exchange.amountToPrecision("BTC-UP/USDC#YES", 0.005); // 0 ✗ // AFTER exchange.amountToPrecision("BTC-UP/USDC#YES", 0.005); // 0.005 ``` `loadMarkets()` now reads each distinct binary pool's `getOrderBookParameters` (pipelined, cached per pool, re-read on `loadMarkets(true)`), feeding `amountToPrecision`, `priceToPrecision` and `UnifiedMarket.limits.amount`. If a pool's parameters cannot be read the helpers throw `InvalidInputError` for that market rather than quantizing against the fallback — callers that treated `0` as "too small to trade" should catch it. Spot and perp precision is unchanged. ### Fixed — the baked mainnet `marketCreator` pointed at a retired venue `SOMNIA_MAINNET_ADDRESSES.marketCreator` was `0xfc4Ecc01…` (venue 3, `status: "retired"`); the active venue 5 creator is `0xfe81C4e8…`. The venue-5 recovery changed `venues.json` without rerunning `pnpm gen:addresses`, so the stale value shipped in 0.21.0–0.23.0. Mainnet consumers using the baked addresses were filtering the realtime tail (`liveTail`) on a dead contract's events. Testnet was unaffected. ## 0.23.0 (2026-08-06) Perp data corrections (open interest, mark staleness, liquidation accounting), funding-rate series reads, vault funding writes, and a type-tightening sweep across the client surface. ### Breaking — perp open interest is ONE counter `PerpMarket.longOpenInterest` / `shortOpenInterest` and the same pair on `PerpStateOnchain` and `OpenInterestSnapshot` are replaced by a single `openInterest`. Not a simplification — a correction. The contract emits `OpenInterestUpdated(uint256)` and exposes `getOpenInterest() -> uint256`, because in a matched CLOB the short side is provably equal. The two-field form never matched the deployed ABI, so the indexed pair was null on every row (its subscription's `topic0` could not match) and the chain read **threw on every call**. ```diff - const oi = BigInt(m.longOpenInterest ?? 0) + BigInt(m.shortOpenInterest ?? 0) + const oi = BigInt(m.openInterest ?? 0) ``` ### Breaking — `UnifiedFundingRate.markPrice` may be `undefined` `fetchFundingRate()` now reports `undefined` rather than a number when the pool's mark feed is stale. The pool signals staleness with a **0 price word** (`tryGetMarkPrice` returns `(ok, price)`; the event uses a 0 sentinel). That was being converted straight to a number, putting a mark of `0` on the wire as though it were a real price — and downstream, an unguarded `markPrice - entryPrice` reads as a 100% loss on every open position. `info.markPriceOk` carries the flag if you want to distinguish "stale" from "not a perp". For marking a position rather than reporting a reading, `perpMarkForPnl(state)` falls back to the index price and tells you which it used. ### Breaking — `LiquidationEvent.badDebt` is narrower, and there are three new columns `badDebt` used to receive five different quantities while being documented as "safe to SUM". It now carries **only** the uncovered, insolvent hole (`ResidualBadDebt`, `AdlPriceCapacityExhausted`). Alongside it: | column | source | aggregation | |---|---|---| | `badDebt` | `ResidualBadDebt`, `AdlPriceCapacityExhausted` | a LEVEL — never SUM | | `insuranceCovered` | `BadDebtAbsorbed.covered` | a FLOW — SUM is exact | | `deficit` | `BadDebtAbsorbed.badDebt`, `ResidualBackedByOpenPnl` | a LEVEL — never SUM | | `coverageDeclined` | `CoverageDeclinedByEquityCap` | a FLOW — SUM is exact | If you were summing `badDebt` for a bad-debt figure, that total was double-counting: the gross hole and its uncovered remainder both landed there, as did a PnL-backed hole that is explicitly *not* bad debt and a coverage amount the equity cap deliberately deferred. The correct point-in-time figure is the sum of the **latest** `badDebt` row per account — a residual is a state sample, so successive liquidations on one account re-report the same hole. `BadDebtAbsorbed.covered` and `absorbedBy` are now exposed at all (they were being dropped); `absorbedBy` arrives on `counterparty`. ### Changed — `getFundingRateHistory` → `listFundingRateHistory` Renamed for the `get*` = value-or-null / `list*` = array convention in CONVENTIONS.md. The old name forwards verbatim for one release cycle and is marked `@deprecated`. New in the same read: `order: "asc" | "desc"`. The default `"desc"` returns the newest page, so `from` is a window bound; pass `"asc"` to make it a forward **cursor**. `fetchFundingRateHistory(symbol, since, limit)` now ascends whenever `since` is given, which is what makes the ccxt pagination idiom (`since = last.timestamp + 1`) terminate instead of re-reading the tail. ### Added — funding as a series `listFundingRateCandles(pool, intervalSeconds, opts)` serves 1h / 4h / 1d rollups for ranges the raw series is too dense for, plus `densifyFundingBuckets` to fill the grid slots a sparse query legitimately omits. Rollup buckets are **absent** where no settlement's span reached them and **revised** when a catch-up settlement reaches backwards; both are properties of lazy settlement, and the TSDoc on each says so. Funding-rate normalization helpers (`fundingRate8h`, `fundingRatePerInterval`, `annualizedFundingRate`, `realizedFundingPerBase`, …) are exported. A perp funding rate is per **calculation window** (28800s), not per interval and not annual, and `fundingWindowSec / fundingIntervalSec` is 96 on testnet against an expected 8 on mainnet — so the same rate value means a 12× different per-interval accrual. Normalize with the row's own `fundingWindowSec`; a hardcoded denominator produces a plausible-looking wrong chart rather than an error. ### Breaking — market addresses and hashes are `Address` / `Hex`, not `string` Every address and hash on `Market` (and its `SpotMarket` / `PerpMarket` / `BinaryMarket` variants) is now typed with viem's `Address` or `Hex` instead of `string`: - **`Address`** — `poolAddress`, `baseToken`, `quoteToken`, `stopRegistry`, `marginBank`, `marketAddress`, `collateral`, `creator` - **`Hex`** — `marketId`, `createdByTx`, `venueId`, `context` The live-book types follow for the same reason — a field fed from a typed source but declared `string` widens it straight back and keeps the casts this change exists to remove: - `Tradable.pool` (always `market.poolAddress`) - `LiveFill.pool` / `.maker` / `.taker`, `LiveOrder.pool` / `.owner` - `DecodedEvent.address` (viem already types the log source; the SDK was casting the type away and then widening it with `.toLowerCase()`) **Lookup-key parameters stay `string`** and are not part of this change: `getLiveFills(pool, …)`, `getLiveMarketByPool(pool)`, `getLiveSpotOrderBook(pool, …)` and the other live reads take a pool address as a map KEY, which they lowercase before lookup. Tightening those would break callers holding a plain string for no safety gain — the value is being matched, not carried. ```ts // BEFORE — cast at every use await client.getBinaryOrderBook(market.poolAddress as `0x${string}`); await client.getMarketOnchain(market.marketAddress as Address); // AFTER — the type is already right await client.getBinaryOrderBook(market.poolAddress); await client.getMarketOnchain(market.marketAddress); ``` Most code needs no change at all. Existing `as Address` casts keep compiling (now no-ops), and reading a field into a `string` still works, because `Address` *is* a `0x`-prefixed string. What breaks is only the reverse direction — assigning a plain `string` INTO one of these fields, e.g. building a `Market`-shaped object from untyped data: ```ts const m: SpotMarket = { ...rest, poolAddress: someString }; // now an error const m: SpotMarket = { ...rest, poolAddress: someString as Address }; // fix ``` Values are unchanged: still lowercase, exactly as the indexer stores them. viem's `getAddress` is deliberately not used — it returns EIP-55 checksummed addresses, and the SDK's own store keys its pool/market lookup maps on the lowercase form. `Address` is a template-literal type that lowercase satisfies, so nothing is normalized at runtime and there is no per-row cost. Not retyped, because they only look hex-ish: `yesTokenId`, `noTokenId`, `strike` and `nonce` are **decimal** uint256 strings, and `id` is a bytes32 for binary markets but a pool address for spot/perp. ### Breaking — the viem escape hatch is explicit, and undecorated `SomniaMarketsClient.publicClient` is replaced by `getViemClient()`. The property was typed `PublicClient` and named `publicClient`, but it was the client the SDK had **decorated** — `readContract` / `call` rethrow as typed SDK errors. So a consumer reading their **own** contract through it lost viem's error types silently: `catch (e) { if (e instanceof ContractFunctionRevertedError) … }` simply stopped matching, no error, no warning. Worse on a foreign contract, where the decoder can't match the selector and produces a `ContractRevertError` with `errorName: undefined` — viem's typed error traded for nothing. `getViemClient()` returns the **undecorated** client, over the same WebSocket (no second connection). Reads through it keep viem's error contract. Everything reachable from the client interface still uses the decorated one, so protocol reverts arrive decoded as before. ```diff - await client.publicClient.getBalance({ address }) + await client.getViemClient().getBalance({ address }) ``` A method rather than a property, so reaching outside the SDK's error contract is a visible act — and because the call opens the socket, which a field read hid. ### Breaking — `createLend` is no longer exported `client.lend` (backed by `config.addresses.lend`) is the only entry to the lend surface. The factory took a whole `SomniaMarketsClient` to use two of its members, and let one chain's addresses be grafted onto another chain's socket — `createLend(mainnetClient, SOMNIA_TESTNET_LEND)` type-checked and silently read nothing, which the `*_MAINNET_*` / `*_TESTNET_*` constants make an easy mistake. A different deployment means a different client: ```diff - const lend = createLend(exchange.client, SOMNIA_MAINNET_LEND); + const exchange = new SomniaMarkets({ chain, wsRpcUrl, addresses: { lend: SOMNIA_MAINNET_LEND } }); + const lend = exchange.client.lend; ``` `@somnia-chain/markets-sdk/lend` still publishes the types, `SomniaLendClient`, both deployment constants, the ray-math helpers and the ABIs — only the factory is gone. ### Breaking — three-identifier reads take one params object Six methods keyed on three positional identifiers. All the perp/vault fields are `Address`, so any two swapped still compiled — and two siblings even ordered the **same** triple differently (`getPerpPosition(marginBank, account, pool)` vs `getLiquidationPrice(marginBank, pool, account)`), making the silent swap the easy mistake rather than the freak one. Each now takes a single object; the field names carry the order. On `SomniaMarketsClient`: ```diff - client.getPerpPosition(marginBank, account, pool) - client.getLiquidationPrice(marginBank, pool, account) + client.getPerpPosition({ marginBank, account, pool }) // PerpPositionRef + client.getLiquidationPrice({ marginBank, account, pool }) // PerpPositionRef (same shape, same order) - client.getVaultBalance(vault, owner, token) + client.getVaultBalance({ vault, owner, token }) // GetVaultBalanceParams - client.getOutcomeBalance(outcomeToken, account, id) + client.getOutcomeBalance({ outcomeToken, account, id }) // GetOutcomeBalanceParams - client.getBuilderApproval(pool, user, builder) - client.getEffectiveBuilderApproval(pool, user, builder) + client.getBuilderApproval({ pool, user, builder }) // BuilderApprovalRef + client.getEffectiveBuilderApproval({ pool, user, builder }) // BuilderApprovalRef ``` `Trader.getBuilderApproval` / `Trader.getEffectiveBuilderApproval` change the same way. The param types are exported from the package root. ### Changed — input/config failures throw the typed classes everywhere The last ten `throw new Error(...)` sites in the SDK now throw the documented classes — `InvalidInputError` (stop-order validation, the `quote*` methods' `{pool | marketId}` target), `NotConfiguredError` (missing `config.addresses.lend` entries), `ContractRevertError` (a lend write mined but reverted), and `RpcError` (`createStopOrder` receipt missing `PendingOrderCreated`). Messages are unchanged; only the classes (and their fields) are new. Code that caught plain `Error` still works — every class extends it. ## 0.22.0 (2026-08-05) `getPortfolio` now carries the binary contract's series cadence on every active position and open order, so a Positions / Trade History row can show whether a contract is a 15m / 1h / 4h / 24h event. ### Added - `PortfolioMarket.intervalSec` (raw seconds) + `PortfolioMarket.interval` (the derived `"15m"`/`"1h"`/… label), populated on `portfolio.positions[].market` and `portfolio.openOrders[].market`. `portfolio.trades[].market.interval` and `BinaryMarket.interval` already carried it — this closes the gap on active positions/orders. Additive; no breaking changes. ## 0.21.0 (2026-08-05) The typed error tier, and indexer reads regenerated from the schema the indexer actually serves. ### Added — the typed error tier Every SDK failure now has a class: `SomniaMarketsError` and its six subclasses (`InvalidInputError`, `NotConfiguredError`, `SignerRequiredError`, `IndexerError`, `RpcError`, `ContractRevertError`), exported from the package root. `ContractRevertError` decodes revert data against the protocol's custom errors (the generated `contractErrorsAbi`, kept current by the offline `errors:check` CI gate), so a failed call can report its Solidity error name. Pure addition in this release — the SDK's own call sites adopt the classes in the follow-up refactor; nothing thrown today changes class. Indexer reads are now typed against the GraphQL schema the indexer actually serves, instead of hand-written types kept in sync by memory. Internal change — the exported type surface, its TSDoc, and every method signature are unchanged apart from the nullability corrections below. ### Notes — why the indexer types are generated Queries were template strings with self-declared result types, so both halves could drift silently: a query could select a field Hasura no longer had (throws on every call), and a type could promise a field the wire never carried (`tsc` green, consumer reads `undefined`). `0.16.0` shipped both at once. A committed snapshot of the served schema now drives generation, so a renamed, removed, or retyped field fails `pnpm gql:codegen` / `pnpm typecheck` in the same PR that changes the schema. Public types stay hand-written; the mapping between wire and public is compiler-checked. ### Breaking — types corrected to match what the indexer actually returns Each of these promised non-null on a column the indexer genuinely leaves unset: `indexer/schema.graphql` declares them nullable, and the handlers carry `prior?.` forward, so an event arriving before the row's creation event leaves them empty. - `IndexerSyncStatus.numEventsProcessed` → `number | null` - `IndexedOracleAdapter.createdAtTimestamp` → `string | null` - `IndexedMarketCreator.createdAtTimestamp` / `.factory` → nullable; `.createdAtBlock` → `number | null` - `IndexedSeries.createdAtTimestamp` / `.updatedAtTimestamp` → `string | null` Migration: handle `null` where you read these (usually `?? "—"` at the render site). If you formatted them as timestamps, you were rendering January 1970 for the absent case. ### Notes - `schema:pull` now refuses to run against a Hasura that has not finished being configured. envio creates relationships ~25s after it starts tracking tables, and a snapshot pulled in that window is silently missing every relationship field — which then validates cleanly against every offline check. ## 0.20.0 (2026-08-04) **First public npm release.** The package now publishes to the public npm registry (`registry.npmjs.org`) — install is just `pnpm add @somnia-chain/markets-sdk viem`, no GitHub Packages registry config or token. Versions ≤ 0.19.0 remain on GitHub Packages. ### Breaking — token symbols preserve case - **Token symbols preserve case.** `sanitizePart` and `loadMarkets` no longer uppercase ERC-20 `symbol()` reads. Venue token symbols are mixed-case identities (`USDso`, `USDC.e`) and consumers key on them verbatim, so forcing uppercase was silently breaking lookups. If you persisted symbol strings from an earlier SDK version (e.g. `"SOMI/USDSO"`), they will no longer match the registry (`"SOMI/USDso"`) — re-derive stored symbols from `loadMarkets()` after upgrading. Symbols that were already all-uppercase are unaffected. ### Added — baked-in per-chain addresses New `SOMNIA_TESTNET_ADDRESSES` / `SOMNIA_MAINNET_ADDRESSES` constants — the full `SomniaMarketsAddresses` map per chain (including the SomniaLend wiring), generated from the canonical deployment manifests at release time (`pnpm gen:addresses` → `src/addresses.ts`). External consumers get a zero-setup `config.addresses` without the monorepo's private deployments hub. ### Added — book-clamped PnL marks PnL helpers used to mark unresolved positions to `lastPrice` alone. On a one-sided book that freezes the mark at a stale print — we saw a deep-ITM position showing +7.4% uPnL when it was really down 60%, because the losing side's makers had pulled their quotes and only a far-side bid remained. - **`markYesPrice(top, lastPrice)`** (new, exported): returns the two-sided mid, or the last trade clamped into the surviving side's bound. A resting quote beyond the last print is live, executable information and supersedes it; a last print inside the bound still wins (so a bid-ask spread doesn't flash as a loss right after a taker clears the top of the book). - `computePositionPnL` and `computeBinaryPnl` accept an optional **`opts.bookTop`** (`YesBookTop`, best YES bid/ask) and mark with the clamped price. Omit it and behaviour is unchanged (mark to `lastPrice`). - `client.getBinaryPositionPnL` now fetches top-of-book alongside the indexer fan-out (one extra `eth_call`) and passes it through. An indexer-only client or a failed read falls back to `lastPrice` alone — no breaking change for existing callers. - `BinaryPnl` legs (now named **`BinaryOutcomePnl`**) additionally report **`avgCost`**, **`mark`**, and **`value`**, so a per-leg positions UI can render entry/mark/value/uPnL% straight from the SDK instead of hand-rolling the fold. - **`binaryFillsFromPortfolio(trades, decimals)`** (new): derive `BinaryPnlFill`s from one market's slice of `getPortfolio().trades`, which already carries the account's own side per fill. - The unified `markYesPrice` replaces the simpler mid-or-last version that shipped unreleased with the presentation tier. Same name, now `(top: YesBookTop, lastPrice)` with the one-sided clamp, exported from the barrel. `midYesPrice` (odds display) is unchanged. ### Added — the unified presentation tier A unified exchange facade (`SomniaMarkets`) for presentation apps — the surface a frontend needs to render tickers, order books, and account state without reaching into the low-level client. - **`fetchTicker`**: ticker snapshots (last price, bid/ask, 24h volume). - **`fetchOrders`**: open and historical orders with a unified shape. - **Stop orders**: place and track stop orders through the same facade. - **Portfolio analytics**: `getPortfolio()` returns trades and positions with enough context to compute per-market PnL without extra calls. - **`takerIsBid`** on live fills: know which side of the book a fill took liquidity from. - **`txHash`** on `UnifiedTrade` and `UnifiedOrder`: link trades and orders back to their on-chain transaction. ### Added — stake-sized binary quotes - **`quoteBinaryStake`**: get a buy quote sized by stake (the amount you want to spend) rather than by quantity. - **`quoteBinarySell`**: get a sell quote that walks the crossable bids — like the buy side walks the asks — so a thin book surfaces as a partial unwind up front instead of a silent IOC cancel. - `BinarySellQuote` gains **`fillableQuantity`** and **`estProceeds`**: see how much of your position the book can actually absorb and what you'd get for it before you submit. ## 0.19.0 (2026-08-03) **Market timeframe served with markets & trade history** — the series cadence a binary market trades on (15m / 1h / 4h / 24h) is now a ready-to-render label on every market AND every trade-history row, so consumers stop re-deriving `expiry − tradingStart` and hand-formatting it. ### Added - **`BinaryMarket.interval`** — a new derived field on every market the SDK returns (all list + point reads flow through it): the timeframe label (`"15m"` / `"1h"` / `"4h"` / `"24h"`), computed from `intervalSec` (falling back to `expiry − tradingStart`). The label uses the largest unit up to hours that divides the cadence cleanly, so a 10-minute market reads `"10m"`. `null` on SPOT/PERP. - **Trade history carries the market's timeframe.** `FillRow` (from `getFills` / `getUserFills`) gains a joined **`market`** context — `{ asset, intervalSec, interval, tradingStart, expiry }` (new `FillMarketContext` type) — so a trade row can show which timeframe the order was for without a second query. `PortfolioTrade.market` (from `getPortfolio`) likewise gains `intervalSec`, `interval`, `tradingStart`, `expiry`. - **New canonical cadence helpers** (exported from the barrel): `resolveIntervalSec`, `snapIntervalSec`, `formatIntervalLabel`, `marketIntervalLabel`, and the `IntervalSource` type — the single `intervalSec → "15m"` mapping the explorer and other UIs now share instead of each re-implementing it. ## 0.18.0 (2026-08-03) **SomniaLend integration** — the SDK now wraps the third-party SomniaLend money market (an Aave v3.0 fork on Somnia mainnet 5031 + testnet 50312) so trading capital can earn while idle: supply USDso between sessions, post collateral, borrow working capital against it. ### Added - **New `client.lend` namespace** on `SomniaMarketsClient`: `lend.listReserves()` (every listed asset — config, caps, live ray rates, indexes, liquidity, oracle price, one aggregated eth_call), `lend.getAccount(address)` (health factor, borrowing power, and every non-empty position, balances accrued to head with Aave's own interest math), and `lend.createLender(signer)` — the write surface (`supply` / `withdraw` / `borrow` / `repay` / `setUseAsCollateral` plus native-SOMI gateway variants `supplyNative` / `withdrawNative` / `borrowNative` / `repayNative`). Auto-approval follows the trader doctrine (one allowance read, `maxUint256` grant, in-memory cache); `borrowNative` additionally auto-delegates credit on the WSOMI variable-debt token. Variable rate only. - **New subpath entry `@somnia-chain/markets-sdk/lend`** — the same module standalone: `createLend(client, addresses)`, all types, the ray-math helpers (`lendRayRateToApy`, `rayMul`, `accrueLinear`, `accrueCompounded`, `RAY`), and the verified minimal ABIs. - **`addresses.lend?: LendAddresses`** on `ClientConfig` wires the deployment; the published addresses ship as `SOMNIA_MAINNET_LEND` / `SOMNIA_TESTNET_LEND` (NOT in the deployments manifests — SomniaLend is third-party; the testnet addresses are undocumented upstream, extracted from the official app's testnet mode and verified on-chain). Lend methods throw a clear error when the address they need is unset. - **React**: `useLendReserves()` / `useLendAccount(address)` in `@somnia-chain/markets-sdk/react`. - Docs: `docs/LEND.md` guide; ABI shapes pinned against the verified deployed contracts (UiPoolDataProviderV3's v3.0 54-field reserve tuple — do not hand-edit). ## 0.17.0 (2026-07-29) Two related price-feed changes: reads are pinned to a **quote asset**, and the feed's **freshness surface** becomes readable. ### Changed — quote pinning The feed publishes more than one pair per base — `BTC/USDC` and `BTC/USDT` both carry `base: "BTC"` — so `base` alone stopped being a unique feed key and every read matched two rows. The oracle has migrated to USDC: the USDC rows are live, the USDT rows froze on 2026-07-21, and they have since drifted ~5% apart. `Feed(where: {base})` returned both and the SDK took `[0]`, so the current price was a coin-flip between a live value and a week-stale one. - `PriceFeedConfig` gains an optional **`quote`** (case-insensitive, e.g. `"USDC"`). When set, every read — snapshot, feed info, history, candles, the catalog, and both live subscriptions — adds a `quote: {_eq}` clause, so a base resolves to exactly one feed. `$quote` is passed as a GraphQL variable, never interpolated. - `SOMNIA_TESTNET_PRICE_FEED` is now pinned to **`quote: "USDC"`**. - Leaving `quote` unset preserves the old unfiltered behaviour (correct only where each base has a single quote). Beyond the wrong current price, an unpinned multi-quote base merged two series into one candle response, producing duplicate `bucketStart` values — a hard error in charting libraries that require strictly ascending, unique timestamps (observed at `H1` and `D1`; `M1` windows are currently short enough to miss it). **Behaviour change:** an unfiltered `listPriceFeeds()` against the testnet feed no longer returns bases that lack a USDC pair — today that is `BCH` (USDT-only), so the catalog goes 31 → 30 rows. Pass `quote: undefined` to opt out. ### Added — freshness The SDK previously selected no timestamp beyond the block, so a consumer could not distinguish a 1-second-old price from a day-old one — and since a stalled feed simply stops pushing, a live subscription looks identical to a healthy one. On 2026-07-28 `SOMI/USDC` was 26.8h stale while every consumer reported it live. - `PriceFeedInfo` gains **`updatedAtMs`** (when the oracle last wrote the feed), **`sourceUpdatedAtMs`** (when the underlying market data was timestamped), and **`resynced`**. All unix **milliseconds**, null when unknown. - New **`useLivePriceFeedInfo(asset)`** hook — `getLivePriceFeedInfo` already existed on the client but had no reactive React binding. Comparing the two timestamps separates the two distinct failures: a large `updatedAtMs - sourceUpdatedAtMs` gap means the oracle is still writing but with stale source data, whereas a growing `updatedAtMs` age means it stopped writing. Both fields ride the shared selection set, so they populate from the snapshot **and** the live `Feed` subscription. Note that neither re-renders as a price ages: age must be computed against a local clock on a timer, because a stalled asset delivers no event to react to. ## 0.16.0 (2026-07-24) `listBuilderApprovals` / `BuilderApproval` reconciled with the indexer entity, plus follow-ups from the docs pass. ### Breaking — `listBuilderApprovals` matches the indexer entity The old query selected `pool` and `updatedAt` and ordered by `updatedAt`, none of which exist on the `BuilderApproval` entity — every call threw `field 'updatedAt' not found in type: 'BuilderApproval_order_by'` against a live indexer. - `BuilderApproval.updatedAt` → **`timestamp`** (unix seconds of the last `BuilderApproved` upsert; also the sort key, newest first). - New fields mirroring the entity: **`market`** (market id), **`blockNumber`**, **`txHash`**. `pool` is kept, now joined via the market row. - Migration: `approval.updatedAt` → `approval.timestamp`; everything else is additive. ### Changed — follow-ups from the docs pass - **`exchange.fetchStatus()` gains `"connecting"`** (union widening): a watch whose WS handshake hasn't delivered a head yet reports `"connecting"` instead of a false `"error"` — `"error"` now means a previously-live socket was LOST. Callers switching exhaustively on `status` must handle the new member. - `claimableFrom` now enforces the lowercased `pool` its result type documents (previously true only via the indexer wiring). - Docs: `RegisterSeriesParams.asset` / `SeriesOnchain.asset` corrected to a plain display ticker (`"BTC"`, not `"BTC/USDT"`) per the MarketCreator natspec — it must match the source exchanges' spot listing for candle sources; `binaryPoolImpl` doc no longer claims it is unread (the explorer renders it). - Dead code: unused `PortfolioTrade` import (exchange.ts) and unused `resolved` local (derivedReads.ts) removed. ## 0.15.0 (2026-07-21) A1 — resolution surplus refunded to the reserve-PAYER (the market creator) instead of the operator, and the autonomous MarketCreator self-reclaims its own surplus. Additive to the 0.14.0 OracleHub surface (no breaking changes). ### Added — OracleHub payer credit - **ABI** (`machineryAbi.ts`): `payerCreditOf(address)`, `payerOf(bytes32)`, `withdrawMyCredit(uint256,address)`; events `PayerSurplusCredited(address indexed payer, bytes32 indexed marketId, uint256)` + `PayerCreditWithdrawn(address indexed payer, address indexed to, uint256)`. - **Reads**: `client.payerCreditOf(payer)`, `client.payerOf(marketId)`. - **Write**: `createOracleHubAdmin().withdrawMyCredit({ amountWei, to })` — msg.sender-gated (the connected signer draws only its own accrued payer surplus). `WithdrawMyCreditParams`. ### Added — MarketCreator self-reclaim + migration - **ABI**: `reclaimOracleCredit()`, `armFirstRoll(uint32,uint256)`, plus reads `firstRollArmed`/`latestExpiryBySeriesId`/`armedBoundary`/`marketCount` and `withdrawNative`/`cancelSubscription`. - **Admin**: `createMarketCreatorAdmin().reclaimOracleCredit({ creator })` (manual sweep of the leftover surplus; runs automatically each roll cycle on-chain) and `.armFirstRoll({ creator, seriesId, firesAtSec })` (deferred first roll for a seamless MarketCreator migration — start the new creator exactly at the old market's expiry). `ReclaimOracleCreditParams` / `ArmFirstRollParams`. ## 0.14.0 (2026-07-20) Oracle v2 + Settlement v3 for the binary CLOB, plus the operator "market machinery" management layer. This entry consolidates ALL work since 0.13.0 — the branch-internal 0.15–0.18.x iterations (escrow → prepaid → earmark) were never released, so only the final state is described here. BREAKING for the OracleHub surface and the binary settlement/resolution reads. ### Breaking — Oracle v2: earmark-at-creation resolution funding - Funding is now EARMARK-AT-CREATION: the per-market resolution reserve is attached to the market-creation value and LOCKED per-market at `onBind` (never withdrawable while the market is live). At resolution the exact metered gas cost is charged against the earmark and the surplus (`reserve − charged`) is credited to the operator's WITHDRAWABLE credit. No prepaid pool, no per-bind escrow. Bounded-drain resolution (batched callback + self-armed `Schedule` continuation) + content-addressed question dedup. - **OracleHub ABI** (`machineryAbi.ts`): `earmarkedOf`/`creditOf`/`outstandingOf`/ `withdrawableOf(uint32)`, `resolveReserve()`, `reservedFor(bytes32)`, `operatorOf(bytes32)`, `marketsForQuestion`, `pendingResolves`, `continuationSubId`, `setDrainParams`. `withdraw(uint32,uint256,address)` is credit-only. The prepaid/escrow surface is removed. - **Events**: `ReserveEarmarked`, `SurplusCredited`, `CreditWithdrawn`, `MarketBound`, `MarketResolveCharged`, `AnswerDelivered`, `CallbackAccounted`, `DrainContinuation` (indexed-ness byte-for-byte with `OracleHub.sol`). - **`quoteCreateMarketValue(def)` = `getSchedulingCost(def) + resolveReserve()`** (both attached to the create; excess refunded). - **`syncSettlement(marketId)`** (module write): permissionless earmark reconcile for a market voided via `BinaryMarket.voidExpired()` (which bypasses the module, so the hub's earmark release never fires). Idempotent; reverts `MarketNotSettled` while still live. - **Indexer reads** (`query.ts`, matching `indexer/schema.graphql`): `OperatorHubAccountRecord` (`earmarked`/`credit`/`outstanding`), `getOperatorHubAccount`/`listOperatorHubAccounts`; reshaped `OracleBindRecord`/`OracleCallbackRecord`. `preflight.ts` gates on the full create value. Client surface (`oracleHub.ts`/`createClient.ts`/`somniaMarketsClient.ts`) follows. ### Breaking — Settlement v3: payout vectors - Binary markets settle to a payout VECTOR (`payoutNumerators`, denominator 10_000_000); redemption pays `amount × num[idx] / D` — one formula for win / loss / void (a losing redeem pays 0 without reverting). Reusable pools + a permanent `BinarySettlement` singleton. - **`getSettlement`** (`readsAbi.ts`) returns `(…, uint256[] payoutNumerators)` — removed the `uint8 winningOutcome` slot. `SettlementRecord` exposes `payoutNumerators` + a derived `winningOutcome`. - **`winningOutcome()` was REMOVED from BinaryMarket** — the SDK derives the winner as the argmax of `payoutNumerators` in `getMarketOnchain`, the `redeem()` auto-winner lookup, and the `Resolved(uint32 payoutDenominator, uint256[] payoutNumerators)` live-tail decode. ### Added — the operator "market machinery" management layer - Machinery admins (same signer doctrine as `createOperatorAdmin`): `createOracleAdapterAdmin` (create/fund/enableReactivity/gas params + adapter status), `createGovernanceAdmin` (`setAdapterApproved`, module-owner gating), `createMarketCreatorAdmin` (create/fund/registerSeries/updateSeries/triggerRoll/gas params + creator & series reads). - Indexer machinery reads (`listMarketCreators`/`getMarketCreator`/`listOracleAdapters`/ `getOracleAdapter`/`listSeries` + `Indexed*` mirrors), the `MarketTypePlugin` registry (fee-codec + machinery step descriptor keyed off the bytes4 `marketType`), and per-step preflight validators. - Deployments hub + SDK config gain `marketCreatorFactory`/`oracleAdapterFactory`/ `sharedOracleAdapter` (all optional, degrade cleanly when unset). ## 0.13.0 (2026-07-18) Settlement-extraction v2 — the binary release. A BinaryPool is no longer the permanent redemption custodian: on finalize its backing + resolution snapshot sweep to the ONE `BinarySettlement` singleton (the redemption home, forever), and the pool is recycled onto the next market — the same pool address serves SUCCESSIVE markets. This release also lands the full trader write surface, the pool-reuse / binding reads, the recycle-safe live order book, and the derived analytics bundle a frontend needs for a full-lifecycle up/down prediction-market product. Requires a v2 deployment (BinarySettlement + v2 pool impl + v2 OutcomeToken6909) and the WS5 indexer schema. Supersedes the 0.12.x binary surface; carries all of `main` through 0.12.3 (price-feed `PriceFeedScheduler` realignment + `PricePoint.requestId`). ### Breaking - **Outcome-id encoding changed** — v2 wedges the pool's per-market `nonce` between the pool address and the outcome index: `id = (uint160(pool) << 72) | (nonce << 8) | idx`; `marketKey = id >> 8 = (pool << 64) | nonce` keys settlement records. The old `outcomeIdFor(pool, idx)` (`pool << 8 | idx`) is REMOVED — use the new exported helpers `outcomeId(pool, nonce, idx)` / `decodeOutcomeId(id)` / `marketKey(outcomeId)` from the package root. Any cached v1 ids are invalid. - **`kindOf(isBid, userData)` is REMOVED** — v2 stopped encoding the YES/NO side in `userData` (it is opaque market-maker bookkeeping now, forwarded verbatim). The side comes from the pool's new `BinaryOrderPlaced(orderId, kind)` event; map the enum with the new `sideOfKind(kind)` / `ORDER_KIND_SIDE`. Never decode `userData`. - **`getMarketOnchain(marketId)` replaces `getMarketOnchain(marketAddress)`** — market identity is the module's bytes32 `marketId` (pools/market contracts are recycled/per-market). Resolves through `BinaryMarketsModule.markets(marketId)`; requires `addresses.binaryModule`. A 20-byte address argument throws loudly. The result gains `marketAddress` / `nonce` / `finalized`, and `backing` falls back to the settlement record's NET backing once finalized (the pool-side `market.backing()` reads 0 from then on). - **`Trader.redeem` routes through the module, keyed by `marketId`** — `RedeemParams.marketId` (bytes32) is required; `market` (address) is now only an optional lookup aid for `outcomeIdx`/`outcomeToken`. The module pulls the winning tokens under an ERC-6909 operator grant to the MODULE (auto-approved), finalizes-if-needed, and redeems via settlement. The v1 pool `redeem` no longer exists on-chain. - **Pool write ABI**: `placeOrder` → `placeBinaryOrder(kind, price, quantity, expireTimestampNs, orderType, selfMatchingOption, builder, builderFeeBpsTimes1k, userData)` (+`placeBinaryOrderFor`). The generic `placeOrder`/`placeOrderFor`/`amendOrder` REVERT (`UseBinaryPlacement`) on binary pools. `redeem` is gone from `binaryPoolWriteAbi`. - **Order expiry must satisfy `0 < expireNs ≤ pool.marketExpiryNs`** — the pool rejects never-expiring / beyond-market orders (`OrderExpiryBeyondMarket`). `Trader.placeOrder` now DEFAULTS the expiry to the market's expiry (one `marketExpiryNs` read) instead of ~50y; an explicit `expireTimestampNs` is forwarded verbatim (no silent clamping). - **Live-tail events**: the pool `Redeemed` / `SettlementFeeCharged` events no longer exist (redemption + the one-time fee skim live on the settlement singleton). New events consumed: pool `BinaryOrderPlaced` / `PoolFinalized` / `PoolRecycled`; module `MarketFinalized` / `PoolReleased`; settlement `MarketFinalized` / `SettlementFeeCharged` / `Redeemed` / `PayoutOwed` / `OwedClaimed`. The module `MarketCreated` gained a `nonce` field. - **Pool address is a TIME-VARYING market binding** — never key a market by pool address. `getMarketByPool` now returns the pool's NEWEST (current) market and documents the caveat; `BinaryMarket` rows expose `nonce` for disambiguation. ### Added **Settlement + redemption** - **Trader methods**: `redeemDirect({ outcomeId, amount, to? })` (settlement redemption by raw id), `claimOwed({ token })` (push-fallback pull), `finalizeMarket({ marketId })` + `releasePool({ marketId })` (permissionless keeper entries), `getSettlement(marketId)` → `SettlementRecord | null`. - **`trader.signRedeemAuth(params)` + `trader.redeemFor(params)`** — the relayed (gasless) redeem pair. `signRedeemAuth` has the position OWNER sign an EIP-712 `RedeemAuthorization` over the module's `REDEEM_AUTH_TYPEHASH` in the `SomniaMarkets`/`1` domain (`verifyingContract` = the `binaryModule`); no tx is sent. A relayer then submits it via `redeemFor` — they pay the gas, the module pins the payout to `owner` (never the relayer). New types `RedeemAuthorization`, `SignRedeemAuthParams`, `RedeemForParams`. - **Config**: `addresses.binarySettlement` (and `@somnia-chain/deployments` maps the manifest's `BinarySettlement` proxy key onto it). **Pool reuse / bindings** - **`client.getPoolBindings(pool)` → `PoolBindingRecord[]`** — a pool's full pool→market binding history from the indexer (WS5 `PoolBinding`; newest nonce first; `toBlock === null` marks the current binding; `closedBy` is `"Released" | "Rotated"`). - **`client.getPool(address)` → `IndexedPool | null`** — the indexer's per-pool aggregate (creator, collateral, `currentMarketId`, `currentNonce`, `generationCount`). - **`client.getPoolCreator(pool)` / `client.getFreePools(creator, collateral)`** — the chain reads previously only reachable through the signer-bearing trader, now on the unsigned client tier (an unconnected explorer can render them). Standalone `getPoolCreator` / `getFreePools` are exported from the package root too; the Trader methods (`poolCreator(pool)`, `getFreePools(creator, collateral)`) remain. Pool "sponsor" is uniformly "creator" across the SDK, matching the on-chain `poolCreator()` view and the indexer `Pool.creator` field. - **`"Finalized"` in `BinaryMarketStatus`** — the indexer's `ClobMarketStatus` terminal state (set when the market's backing + resolution sweep to the BinarySettlement singleton; supersedes Resolved/Voided). Flows through every `status` filter (`listBinaryMarkets` / `listLiveBinaryMarkets` / `listPastBinaryMarkets` / `countBinaryMarkets`). The live-tail reducer now also sets it on the module/settlement `MarketFinalized` events. The on-chain `BINARY_MARKET_STATUS` index map is deliberately unchanged (no on-chain enum member exists). **Trader writes** - **`trader.reduceOrder(params)`** — shrink a resting order's remaining quantity IN PLACE, keeping its price-time queue priority (unlike an amend, which re-queues at the back). Works on spot AND binary pools — `BinaryPool` implements the `_onOrderReduced` → `_refundPartial` hook, so the freed escrow returns to the owner. New `ReduceOrderParams`; new `reduceOrder` entry on `binaryPoolWriteAbi`. - **`trader.cancelExpiredOrders(params)` / `trader.sweepExpiredAtLevel(params)`** — the permissionless keeper drains for the resting book (inherited from the OrderBook base, callable by anyone on a binary pool). `cancelExpiredOrders` cleans an explicit list of expired ids; `sweepExpiredAtLevel` walks one price level from the best order cleaning up to `maxCount`. Each returns locked escrow to the order owner (best-effort — non-expired / stale entries are skipped on-chain). New `CancelExpiredOrdersParams`, `SweepExpiredAtLevelParams`; new `cancelExpiredOrders` / `sweepExpiredAtLevel` entries on `binaryPoolWriteAbi`. - **`PlaceOrderParams.userData?: bigint`** — opaque MM bookkeeping tag, default `0n`, forwarded verbatim (the SDK never sets or interprets it). **Live order book (recycle-safe)** - **`store.bookLevels(pool)` filters by the pool's CURRENT `market_id`, structurally.** A `BinaryPool` is recycled across markets (one pool serves successive markets, never concurrently). The live book now requires `o.market_id` to equal the pool's current binding (`marketByPool(pool)?.id`), and returns an EMPTY book when the pool has no current binding — the exclusion of a prior market's orders is now structural, not reliant on expiry timing. - **`client.getLiveBinaryOrderBookByMarket(marketId, { depth? })`** + the **`useLiveBinaryOrderBookByMarket`** hook — resolve a binary book by `marketId` rather than pool address. If `marketId` is no longer the pool's current binding (stale/ended), returns an EMPTY book so a stale page can't render the successor market's orders. Backed by the new `store.bookLevelsByMarket`. **Reads & analytics (derived; no new indexer field)** - **`client.quoteBinaryOrder({ pool | marketId, side, quantity, depth? })`** — a market-order preview over the live book (`{ avgPrice, cost, filledQuantity, wouldRest, levelsConsumed, slippageVsMid }`). BUY consumes asks, SELL consumes bids, respecting the YES/NO price inversion. Also exported as the kernel `quoteBinaryOrderOverBook`. New type `BinaryOrderQuote`. - **`client.getMarketStats24h({ pool | marketId })`** — trailing-24h `{ volume24h, trades24h, priceChange24h, high24h, low24h, openPrice24h }` summed from 1h candle buckets. Kernel `marketStats24hFromCandles`; new type `MarketStats24h`. - **`BinaryMarketFilter.orderBy`** (`"newest" | "closingSoon" | "volume" | "tradeCount"`) threaded into `listBinaryMarkets` + `listLiveBinaryMarkets` as the Hasura `order_by` (server-side). `listBinaryMarkets` still defaults to newest, `listLiveBinaryMarkets` to closingSoon; an explicit `orderBy` overrides. New type `BinaryMarketOrderBy`. - **`client.getBinaryPositionPnL(account, marketId)`** — avg-cost position PnL (`{ balanceYes, balanceNo, costBasis, avgCost, markValue, unrealizedPnl, realizedPnl }`, RAW units) reconstructed from the account's order-book fills folded with complete-set mints/merges, marked to `lastPrice` (or the settlement payout once resolved). Kernels `pnlEventsFor` + `computePositionPnL`; new types `BinaryPositionPnL`, `PnLEvent`. - **`client.getClaimable(account)`** — redeemable positions across settled (resolved/voided) markets, each shaped to feed `trader.redeemMany({ entries })`: `{ marketId, pool, outcomeIdx, amount, estPayout, status }`. Winner payout skims the settlement fee; voided pays half both sides; losers omitted. Kernels `claimableFrom` + `estPayoutFor`; new types `ClaimablePosition`, `ClaimableInput`. - `RouterActionRecord` now surfaces the existing indexer `amount` field (each outcome's set size) so mint/merge cost basis folds in; `PortfolioMarket` now carries `id` (the bytes32 marketId). - **`getMarketResolution`** now returns **`openingAnswer`** (the reference-question oracle answer — a reference-mode market's OPENING price) and **`closingAnswer`** (its own resolution answer — the CLOSING price) alongside the outcome. `oracleAnswer` is kept as a deprecated alias of `closingAnswer`. Requires the deployment manifest to record `OracleCore` (its `AnswerPosted.numericValue` is the price) — the deploy script now writes it. - **`client.getOpeningPrices(marketIds)`** — batch opening (reference) prices for many markets in one pair of round-trips (map `marketId → raw numericValue`), for list views that show each up/down market's opening price without an N+1 fan-out. **Id helpers, ABIs, rows, live tail** - **Id helpers** (single source of truth, exported): `outcomeId(pool, nonce, idx)`, `decodeOutcomeId(id)`, `marketKey(outcomeId)`, types `DecodedOutcomeId` / `OutcomeIdx`. - **ABIs**: `binarySettlementAbi` (redeem / finalizeAndRedeem / finalize / claimOwed / getSettlement / isFinalized / owed / isPoolApproved / poolRegistrar / outcomeToken), `binaryModuleWriteAbi` / `binaryModuleReadAbi` (module redeem rails + finalizeMarket / releasePool + settlement / poolCreator / getFreePools / freePoolCount / marketNonce / markets), pool v2 reads on `binaryPoolReadAbi` (marketNonce / settlement / finalized / booksEmpty / marketExpiryNs / setBacking / getBinaryPoolParams), event ABIs `binaryPoolEventsAbi` / `binarySettlementEventsAbi`. - **`BinaryMarket` rows**: `nonce` / `finalized` / `netBacking` (WS5 indexer schema). `MarketOnchain`: `marketAddress` / `nonce` / `finalized`. - **Live tail**: watches the module + settlement whenever any market is watched; reducer implements the v2 binding model (`MarketCreated` opens/re-points a pool→market binding, `PoolReleased` closes it — order events attribute via the pool's CURRENT binding), takes sides from `BinaryOrderPlaced`, zeroes pool backing on `PoolFinalized`, and tracks the settlement-side `netBacking` via the settlement `MarketFinalized` / `Redeemed`. ### Migration 1. Regenerate/refresh the deployment manifest (v2 deploy adds `BinarySettlement`); `addresses.binarySettlement` flows through `@somnia-chain/deployments` automatically. 2. Replace `outcomeIdFor(pool, idx)` with `outcomeId(pool, nonce, idx)` — get the nonce from `BinaryMarket.nonce`, `MarketOnchain.nonce`, or `pool.marketNonce()`. Purge any cached v1 ids. 3. Replace `kindOf(isBid, userData)` with `sideOfKind(kind)` joined from `BinaryOrderPlaced` (indexer rows keep serving `side` precomputed). 4. `client.getMarketOnchain(...)`: pass the bytes32 `marketId` (from `listBinaryMarkets` / `BinaryMarket.marketId`), not the market address. 5. `trader.redeem(...)`: pass `marketId` (+ optionally `outcomeIdx` to skip a read). Native redemption (`redeemNative`) and complete-set methods are unchanged. 6. Market makers: tag orders with `userData` freely — it round-trips verbatim and appears on indexed orders; it no longer selects the book side. ## 0.12.3 (2026-07-17) Re-add `PricePoint.requestId` — the on-chain feed re-added `requestId` to `PriceUpdated` (as an indexed arg) and the indexer now exposes it again, so the SDK surfaces it once more. Additive; the field 0.12.2 dropped is back. ### Added - `PricePoint.requestId` (decimal string) — the Somnia-Agents batch request that produced a tick. One request prices every symbol in the tick, so all of a tick's rows share the same `requestId` (group by it for a whole batch / join to agent provenance). Read via `getPriceHistory` / the live tick tape. ## 0.12.2 (2026-07-17) Price-feed schema realignment — the price feed is now the on-chain `PriceFeedScheduler` (spot index + EMA mark) rather than the per-asset EMA oracles. The `Feed` / `PricePoint` / `Candle` reads and the live tail target the scheduler's fields. Requires the price-feed indexer at the PriceFeedScheduler schema (a full reindex — already live on dev). ### Changed - Price-feed GraphQL reads map the feed's new server fields onto the SDK's stable shape: `price` ← `spot` (median spot index), `ema` ← `mark` (the EMA-smoothed perpetual mark), `emaClose` ← `markClose`. The public `LivePrice` / `PricePoint` / `PriceCandle` field names are unchanged, so consumers need no code changes. ### Removed - `PricePoint.requestId` — the scheduler batches every symbol into one agent request, so there is no per-tick request id. ## 0.12.1 (2026-07-16) Docs-only release — no API, ABI, or behavior change. ### Docs - Completed guide coverage for 20 previously reference-only client methods: the batch price reads (`watchPrices` / `getLivePrices` / `fetchPrices`) + `isTailing` (PRICES), spot discovery (`listSpotMarkets` / `getSpotMarket`, SPOT), binary discovery (`listBinaryAssets` / `countBinaryMarkets`, BINARY), and the cross-cutting reads (`getBalances`, `getOutcomeBalance`, `getErc20Metadata`, `getErc20Allowance`, `getContractMeta`, `getMaxVenueFeeBps`, `getOrders`, `getUserFills`, `getMarketStatusHistory`, `countMarkets` / `countVenues` / `countOperators`, ENGINE). Every public method was already in the generated API reference; these are the narrative-guide additions. - Fixed three broken `{@link}` cross-references in TSDoc (`binaryFillsFor`, `computeBinaryPnl`, `listBuilderApprovals`) that rendered as dead links in the API reference. ## 0.12.0 (2026-07-16) Coverage-gaps wave — close the read/write/hook gaps against the coverage-gaps indexer schema (new perp-account, fee-stream, resolution, router, and vault-credit entities). Requires an indexer at that schema (a full reindex). ### Added - **Router action history** — `getRouterActions(account, opts?)` → `RouterActionRecord[]` (redeem / mint / merge, from the indexer `RouterActionRecord`). - **Resolution visibility** — `getMarketResolution(marketId)` → `{ events, reference, oracleAnswer }` joining `MarketResolutionEvent` / `MarketReferenceLink` / `OracleAnswer` (by `oracleQuestionId`). - **Fee-record streams** — `listProtocolFees` / `listBuilderFees` / `listSettlementFees` (the per-fill streams behind `getMarketFees`' running total; support a `payer` filter). - **Builder-approval directory** — `listBuilderApprovals({ user?, builder?, … })` → `BuilderApproval[]`, complementing the on-chain point read `getBuilderApproval`. `ApproveBuilderParams` is now exported. - **Markets-by-creator** — `BinaryMarketFilter.creator` (applied across `listBinaryMarkets` / `listLiveBinaryMarkets` / `listPastBinaryMarkets` / `countBinaryMarkets`). - **Vault credits** — `getVaultPayoutFallbacks(owner, opts?)` (append-only credit history), `client.getVaultBalance(vault, owner, token)` (live claimable, `ERC20Vault.getWithdrawableBalance`), and `trader.withdrawVault({ vault, token, amount })` (`ERC20Vault.withdraw`). - **Perp margin health + liquidation price** — `getMarginAccount` now also returns `imReq`/`mmReq`/`cmReq`/`marginStatus` (from `MarginBank.getAccountHealth` / `getMarginStatus`); new `client.getAccountHealth(marginBank, account)` and `client.getLiquidationPrice(marginBank, pool, account)`. `MarginStatus` / `MARGIN_STATUS` / `AccountHealth` are exported. The unified `fetchPositions` now populates `UnifiedPosition.liquidationPrice`. - **Perp/funding history reads** — `getFundingPayments`, `getMarginEvents`, `getLiquidations`, `getFundingRateHistory`, `getOpenInterestHistory` (the indexer's perp-account + funding/OI history). - **Lookups + pagination totals** — `getMarketByPool(pool)` (resolve a market by pool address), and `countOrders(owner, opts?)` / `countUserFills(account, opts?)` (history-page totals via the `_aggregate` fallback helper, now extended to `Order`/`Fill`). - **Unified balances** — `fetchBalance` now includes binary YES/NO ERC-6909 holdings (keyed by tradable symbol). - **Pure helpers + constants** — `CANDLE_INTERVALS` (in lockstep with `indexer/src/intervals.ts`), and `computeBinaryPnl(fills, balances, market)` / `binaryFillsFor(account, fills)` (avg-cost basis, no indexer/chain dependency). - **React hooks** (`@somnia-chain/markets-sdk/react`) — a generic `useIndexerQuery(fn, deps)` plus `usePortfolio`, `useMarkets`, `useCandles`, `useMarketFees`, `useOperators`, and the live-store `useLiveMarkets`. ## 0.11.1 (2026-07-16) ### Fixed - Count helpers (`countMarkets`/`countBinaryMarkets`/`countOperators`/`countVenues`) now fall back to a bounded row count when Hasura `_aggregate` is not exposed to the requesting role (public role, no admin-secret header) instead of throwing `field 'X_aggregate' not found`. The fast aggregate path still runs when the privileged header is present. Real query/network errors still surface. ## 0.11.0 (2026-07-16) Operator/venue + fee refactor follow-up — resync the SDK to the post-refactor contracts, deployment hub, and indexer schema. ### Added - **Per-venue collateral.** `SomniaMarketsAddresses` gains `collateral` (the per-venue collateral ERC-20). `testUsdc` remains as a legacy/fallback alias. `getSystemInfo`, `trader.faucet`, and collateral reads now resolve `collateral ?? testUsdc`, so hub-fed testnet clients (where the protocol `addresses.json` no longer carries TestUSDC) work correctly. - **Settlement-fee backing.** The live tail now consumes `SettlementFeeCharged(address indexed feeRecipient, uint256 winningBacking, uint256 fee)` and debits the market's `backing` running total, so the tail tracks on-chain `setBacking` after settlement instead of overstating it by the fee. - **Module-created market discovery.** `watchAllMarkets({ discover: true })` now also discovers markets created via `BinaryMarketsModule.createMarket` (the 19-field module `MarketCreated`), not just the `MarketCreator` rolling series. ### Fixed - `getSystemInfo.binaryMarketImpl` no longer falls back to the (different) `binaryPoolImpl` address when the live factory read fails. ### Notes - Addresses are provided entirely by `@somnia-chain/deployments` (the single source of truth). `SomniaMarketsAddresses` now carries `marketsCore` and `collateralRouter` first-class, so consumers feed the hub map straight into `new SomniaMarkets({ addresses })` with no hand-mapping. --- # /docs/typescript/tutorials/stream-a-live-order-book # Stream a live order book In this tutorial we install the SDK in an empty project, load the markets on the Somnia testnet, and read an order book and the latest trades. Then we follow the top of the book live for thirty seconds. At the end you will have a running script that prints a line each time the best bid or ask on `SOMI/USDso` changes. No wallet and no funds are needed. Everything in this tutorial reads public data. ## Before you start You need: - Node.js 22 or newer. Check with `node --version`. - npm, which ships with Node.js. - An empty directory to work in. - A network connection to the Somnia testnet endpoints. We run TypeScript directly with `tsx`, so there is no build step. ## 1. Create the project In your empty directory, run these three commands: ```sh npm init -y npm pkg set type=module npm install @somnia-chain/markets-sdk@0.29.0 viem@2.55.10 tsx@4.23.1 ``` The first creates `package.json`. The second lets Node.js load our files as ES modules, which the SDK requires. The third installs the versions used to verify this tutorial: SDK 0.29.0, viem 2.55.10, and tsx 4.23.1. `tsx` runs TypeScript files directly but does not check types, so no `tsconfig.json` is needed. Your editor may underline `process.env` in the next tutorial because Node's type definitions are not installed; the scripts still run. You should see npm report the added packages, and a `node_modules` directory should exist. ## 2. Create the exchange and load the markets Create a file named `watch.ts` with this content: ```ts import { SomniaMarkets, SOMNIA_TESTNET_ADDRESSES } from "@somnia-chain/markets-sdk"; import { somniaTestnet } from "viem/chains"; const exchange = new SomniaMarkets({ indexerUrl: "https://dev.smk.somnia.host/v1/graphql", chain: somniaTestnet, wsRpcUrl: "wss://api.infra.testnet.somnia.network/ws", addresses: SOMNIA_TESTNET_ADDRESSES, }); const markets = await exchange.loadMarkets(); const spot = Object.values(markets).filter((m) => m.type === "spot"); console.log( `${exchange.symbols.length} symbols, ${spot.length} spot markets:`, spot.map((m) => m.symbol), ); await exchange.close(); ``` `SomniaMarkets` is the SDK's single entry point. The three fields point it at the testnet: the indexer URL for history, the chain definition, and the deployed contract addresses. `loadMarkets` fetches every market and builds the symbol table. Run it: ```sh npx tsx watch.ts ``` You should see one line naming the spot markets. The counts change as markets are created and expire; the three spot symbols are stable: ```text 597 symbols, 3 spot markets: [ 'WBTC/USDso', 'SOMI/USDso', 'WETH/USDso' ] ``` Notice that most symbols are binary markets, short-lived questions about BTC and ETH prices. We work with the spot market `SOMI/USDso`. SOMI is the market's name for the chain's native token, which the testnet calls STT. USDso is a test stablecoin. ## 3. Read the order book and the last trades Replace the `await exchange.close();` line with this, so the new code runs before the exchange closes: ```ts const book = await exchange.fetchOrderBook("SOMI/USDso", 3); console.log("bids", book.bids); console.log("asks", book.asks); const trades = await exchange.fetchTrades("SOMI/USDso", undefined, 3); for (const t of trades) console.log(t.datetime, t.side, t.amount, "@", t.price); await exchange.close(); ``` The middle argument of `fetchTrades` is a `since` timestamp we do not need. Run the file again. You should see three levels per side and three trades: ```text 597 symbols, 3 spot markets: [ 'WBTC/USDso', 'SOMI/USDso', 'WETH/USDso' ] bids [ [ 0.1153, 445 ], [ 0.1152, 1222 ], [ 0.1151, 752 ] ] asks [ [ 0.1154, 530 ], [ 0.1155, 1378 ], [ 0.1156, 1810.46 ] ] 2026-09-03T21:40:52.000Z sell 25 @ 0.1153 2026-09-03T21:40:43.000Z sell 25 @ 0.1153 2026-09-03T21:40:33.000Z sell 25 @ 0.1153 ``` Notice the shapes. A book level is a `[price, amount]` pair in plain numbers: 445 SOMI bid at 0.1153 USDso each. Trades come newest first with an ISO timestamp. `fetchOrderBook` read the pool contract on the chain; `fetchTrades` read the indexer. Both are one-shot reads. Notice also the timestamps: on the testnet a market-making bot trades this market every few seconds. That activity is what we watch next. ## 4. Follow the top of the book live Replace the `await exchange.close();` line again, this time with a loop: ```ts // Follow the book for 30 seconds. Print a line whenever the best bid or ask changes. const stop = new Promise((resolve) => setTimeout(() => resolve(null), 30_000)); let last = ""; while (true) { const live = await Promise.race([exchange.watchOrderBook("SOMI/USDso", 1), stop]); if (!live) break; const top = `bid ${live.bids[0]?.[0]} × ${live.bids[0]?.[1]} / ask ${live.asks[0]?.[0]} × ${live.asks[0]?.[1]}`; if (top !== last) console.log(new Date().toISOString(), top); last = top; } await exchange.close(); console.log("done"); ``` `watchOrderBook` is different from `fetchOrderBook`. The first call opens a live watch on the market, and every later call resolves the next time the book changes, with no request to any server. [Read tiers](../reference/read-tiers.md) describes how the watch works. The `Promise.race` against a 30-second timer is only there to end the tutorial. `close()` releases the watch and the WebSocket to the node, so the script prints `done` and exits. Run the file one more time. The first live line prints at once. After that, a line appears only when the best level changes; the testnet bot usually moves it every few seconds, so expect several lines in thirty seconds. On a quiet market you see one live line and then `done`. This run looked like this: ```text 597 symbols, 3 spot markets: [ 'WBTC/USDso', 'SOMI/USDso', 'WETH/USDso' ] bids [ [ 0.1153, 445 ], [ 0.1152, 1222 ], [ 0.1151, 752 ] ] asks [ [ 0.1154, 530 ], [ 0.1155, 1378 ], [ 0.1156, 1810.46 ] ] 2026-09-03T21:40:52.000Z sell 25 @ 0.1153 2026-09-03T21:40:43.000Z sell 25 @ 0.1153 2026-09-03T21:40:33.000Z sell 25 @ 0.1153 2026-09-03T21:41:03.545Z bid 0.1153 × 445 / ask 0.1154 × 1165.4 2026-09-03T21:41:03.974Z bid 0.1153 × 420 / ask 0.1154 × 1165.4 2026-09-03T21:41:10.083Z bid 0.1153 × 420 / ask 0.1154 × 635.4 2026-09-03T21:41:10.084Z bid 0.1152 × 470.5 / ask 0.1154 × 635.4 2026-09-03T21:41:13.866Z bid 0.1152 × 1010.1 / ask 0.1154 × 1164.9 2026-09-03T21:41:22.768Z bid 0.1152 × 985.1 / ask 0.1154 × 1164.9 2026-09-03T21:41:30.078Z bid 0.1152 × 470.5 / ask 0.1153 × 529.5 done ``` Notice that in this run the bid size dropped by 25 a few seconds in: a trade of the same size as the ones from step 3, seen from the chain event rather than from the indexer. Two lines can carry almost the same timestamp when one block moves more than one level. Notice too that the book copy changes more often than its top. The `if (top !== last)` check keeps the output to what changed at the best level. ## What you can do now You can create an exchange for the Somnia testnet, load its markets, and read any spot market's book and trades on demand. You can open a live watch and react each time the book changes, without a polling loop. The same `fetchOrderBook`, `fetchTrades`, and `watchOrderBook` calls work on every symbol `loadMarkets` returned, including the binary markets. Next, [Place and cancel your first order](./place-and-cancel-your-first-order.md) adds a signer to this project and puts an order on this book. To see which reads are live, on-chain, or indexed, read [Read tiers](../reference/read-tiers.md). --- # /docs/typescript/tutorials/place-and-cancel-your-first-order # Place and cancel your first order In this tutorial we place a real limit order on the Somnia testnet, watch it appear in our open orders, and cancel it. At the end you will have sent two transactions through the SDK and seen how a resting order shows up in the live data. The order tries to sell 1 SOMI at four times the current price. We submit it as post-only, so the pool either rests it on the book or rejects it; nothing is bought or sold. Your balance still changes temporarily while a resting order reserves its funding requirement, and permanently by the testnet gas you spend. ## Before you start You need: - The project from [Stream a live order book](./stream-a-live-order-book.md). We add one file to it. - A private key, including its `0x` prefix, for an account on the Somnia testnet that holds at least 2 STT. The testnet is called Shannon; it is the `somniaTestnet` chain we already import from viem. Create a fresh key for this tutorial and never use a key that holds real funds. [Get testnet funds](../how-to/get-testnet-funds.md) lists the faucets. Why 2 STT: the pool's required reserve includes the 1 SOMI quantity and any configured fee headroom. A native sell sends only the part not already credited to your pool vault. The transaction also needs room under the SDK's gas ceiling; unused gas is not charged. Put the key in your shell for this session. Replace the value with your own key. ```sh export SOMNIA_PRIVATE_KEY=0x… ``` We run the file twice in this tutorial: once after step 1, to check the key, and once after step 5, to place and cancel the order. Steps 2 to 4 only add code. ## 1. Create the exchange with a signer Create `trade.ts` next to `watch.ts`: ```ts import { isHex } from "viem"; import { somniaTestnet } from "viem/chains"; import { SomniaMarkets, SOMNIA_TESTNET_ADDRESSES } from "@somnia-chain/markets-sdk"; const privateKey = process.env.SOMNIA_PRIVATE_KEY; if (!privateKey || !isHex(privateKey, { strict: true }) || privateKey.length !== 66) { throw new Error("set SOMNIA_PRIVATE_KEY to a 32-byte 0x-prefixed key"); } const exchange = new SomniaMarkets({ indexerUrl: "https://dev.smk.somnia.host/v1/graphql", chain: somniaTestnet, wsRpcUrl: "wss://api.infra.testnet.somnia.network/ws", addresses: SOMNIA_TESTNET_ADDRESSES, privateKey, }); await exchange.loadMarkets(); console.log("trading as", exchange.walletAddress); const before = await exchange.fetchBalance(); console.log("STT before:", before.STT?.total); await exchange.close(); ``` The one new field is `privateKey`. With it, the SDK signs transactions locally and every authenticated method knows whose data to return. The closing `close()` is the same ending as `watch.ts`. Run it: ```sh npx tsx trade.ts ``` You should see your own address and your STT balance: ```text trading as 0x0a9753f040E0cC077eB514c207F8ba2c14230b42 STT before: 19997.22114964 ``` Notice that `fetchBalance` took no address. It answers for the signer. If the balance is below 2, stop here and fund the account before you continue. ## 2. Open the live watch Replace the closing `close()` line of `trade.ts` with this: ```ts const book = await exchange.watchOrderBook("SOMI/USDso", 1); const bestAsk = book.asks[0]?.[0]; if (bestAsk === undefined) throw new Error("the ask side is empty right now; run again in a moment"); console.log("best ask:", bestAsk); ``` We open the live watch before placing the order. From now on the SDK keeps a local copy of this market current from the chain's events, so our own order will appear in that copy in the block it lands. No need to run yet; step 3 uses `bestAsk`. ## 3. Place the order Append: ```ts const order = await exchange.createOrder("SOMI/USDso", "limit", "sell", 1, bestAsk * 4, { postOnly: true }); console.log("placed:", order.id, order.status, `${order.amount} @ ${order.price}`); ``` The first five arguments are the symbol, the order type, the side, the amount in SOMI, and the price in USDso per SOMI. `{ postOnly: true }` guarantees the order cannot take liquidity. Four times the best ask should rest far above the market, but the book can move before the transaction lands. If that makes the order cross, `createOrder` throws a `ContractRevertError` named `PostOnlyWouldCross`; run the script again so step 2 reads a fresh book. `createOrder` resolves only after the transaction is mined; there is nothing to wait for afterwards. ## 4. See the order in your open orders Append: ```ts let orders = await exchange.watchOrders("SOMI/USDso"); while (!orders.some((o) => o.id === order.id)) orders = await exchange.watchOrders("SOMI/USDso"); console.log("in my open orders:", orders.find((o) => o.id === order.id)?.status); const during = await exchange.fetchBalance(); console.log("STT while resting:", during.STT?.total); ``` `watchOrders` returns your orders on this market from the local copy the watch keeps current, with no request to a server. Its first call returns what the copy holds now, and each later call resolves when the copy changes. The `while` loop covers the moment between the transaction being mined and its event reaching the copy, which is usually zero calls. ## 5. Cancel the order Append: ```ts const cancel = await exchange.cancelOrder(order.id, "SOMI/USDso"); console.log("cancel:", cancel.status); const after = await exchange.watchOrders("SOMI/USDso"); console.log("after cancel:", after.find((o) => o.id === order.id)?.status); const final = await exchange.fetchBalance(); console.log("STT after:", final.STT?.total); await exchange.close(); ``` Run the file. It takes a few seconds longer than the first run, because two transactions are mined. The output should look like this, with your own address, order id, price, and balances: ```text trading as 0x0a9753f040E0cC077eB514c207F8ba2c14230b42 STT before: 19997.… best ask: 0.1147 placed: 793209995169529057822 open 1 @ 0.4588 in my open orders: open STT while resting: 19996.… cancel: canceled after cancel: canceled STT after: 19997.… ``` Notice five things. - `status` is `open` after placement: the order rests on the book. The `id` is the pool's order id, a long decimal string. - The price prints as `0.4588`, four times `0.1147` rounded onto the market's allowed price steps, in the direction that favours you. - `STT while resting` is below `STT before`. The pool reserves enough for the 1 SOMI sale and its configured fee headroom, less any native balance you already had in the pool vault, and gas was paid. SOMI is the market's name for the chain's native token, which the testnet calls STT. - The second `watchOrders` call returned the same order with status `canceled`. The local copy saw the cancel event and updated. - `STT after` is `STT before` minus the gas for two transactions. The unused reserve came back; the exact difference depends on current gas fees and the pool's fee settings. `close()` releases everything the instance opened, including the WebSocket to the node, so the script ends on its own. ## If a run stops halfway A run that fails after `placed:` leaves that order resting with 1 STT locked. Cancel it by id with a one-line script, replacing the id with the one the run printed: ```ts await exchange.cancelOrder("793209995169529057822", "SOMI/USDso"); ``` Use the same construction lines as `trade.ts` above it, and the same two closing lines below it. Cancelling an order that is already gone throws a `ContractRevertError` named `IncorrectSender`; that means there is nothing left to cancel. ## What you can do now You can place a limit order on any spot market the SDK lists, read it back from the live data, and cancel it. The same `createOrder` call with `"buy"` and a price above the best ask fills immediately and returns `status: "closed"` with the fills in `order.info`. To run this as a bot, continue with [Run a quoting loop](../how-to/run-a-quoting-loop.md). To learn when a resting order fills, read [Detect when an order fills](../how-to/detect-fills.md). To see what the SDK did during each step, add a debug sink as shown in [Debug what the SDK is doing](../how-to/debug-the-sdk.md). --- # /docs/typescript/how-to/configure-for-a-network # How to configure the SDK for testnet, mainnet, or a local chain This guide shows you how to build a `SomniaMarkets` instance for each network the SDK supports. It assumes you can install an npm package and write a TypeScript module. The field-by-field reference is [Configuration](../reference/configuration.md); the values are in [Networks and endpoints](../reference/networks-and-endpoints.md). ## Shannon testnet Use the testnet for development. Markets exist, bots trade on them, and funds are free. ```ts import { somniaTestnet } from "viem/chains"; import { SomniaMarkets, SOMNIA_TESTNET_ADDRESSES } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ indexerUrl: "https://dev.smk.somnia.host/v1/graphql", chain: somniaTestnet, wsRpcUrl: "wss://api.infra.testnet.somnia.network/ws", addresses: SOMNIA_TESTNET_ADDRESSES, }); ``` The viem chain definition does not carry a WebSocket URL. Set `wsRpcUrl` to the Somnia endpoint that the SDK must use for chain reads, writes, and watches. ## Mainnet Swap the three network-specific values. ```ts import { somnia } from "viem/chains"; import { SomniaMarkets, SOMNIA_MAINNET_ADDRESSES } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ indexerUrl: "https://prd.smk.somnia.host/v1/graphql", chain: somnia, wsRpcUrl: "wss://api.infra.mainnet.somnia.network/ws", addresses: SOMNIA_MAINNET_ADDRESSES, }); ``` ## Local anvil stack Start the stack from the repository root with `./demo-clob.sh up`. It deploys the contracts to anvil on chain id 31337, runs the indexer, and writes the address manifest. ```ts import { selectDeployment } from "@somnia-chain/deployments/local"; import { SomniaMarkets } from "@somnia-chain/markets-sdk"; import { defineChain } from "viem"; const somniaLocal = defineChain({ id: 31337, name: "Somnia Local", nativeCurrency: { name: "Somnia Test Token", symbol: "STT", decimals: 18 }, rpcUrls: { default: { http: ["http://127.0.0.1:8545"], webSocket: ["ws://127.0.0.1:8545"] } }, }); const deployment = selectDeployment("my-bot", "local"); // reads the anvil manifest const exchange = new SomniaMarkets({ indexerUrl: "http://localhost:8085/v1/graphql", chain: somniaLocal, wsRpcUrl: "ws://127.0.0.1:8545", addresses: deployment.addresses, }); ``` `@somnia-chain/deployments` is the workspace package that reads the manifests; it is available to packages inside the repository. Outside the repository, copy the addresses from `smart-contracts/deployments/31337/local/addresses.json` into an object instead. A restarted anvil is a new chain under the same id: redeploy and reindex, or the indexer rows point at contracts that no longer exist. ## Add a signer Pass one of three signer fields to unlock writes and the authenticated reads. Keep the key out of source control; read it from the environment. Validate the environment value before construction. The `privateKey` variable below must be a 32-byte, `0x`-prefixed hex string. The tutorial [Place and cancel your first order](../tutorials/place-and-cancel-your-first-order.md#create-the-exchange-with-a-signer) shows the guard. ```ts const exchange = new SomniaMarkets({ ...config, privateKey, }); ``` For a browser wallet, see [Sign with a browser wallet](./sign-with-a-browser-wallet.md). ## Add the price feed The price methods need a separate endpoint. On testnet: ```ts import { SOMNIA_TESTNET_PRICE_FEED } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ ...config, priceFeed: SOMNIA_TESTNET_PRICE_FEED }); ``` ## Run indexer-only No extra field is needed. The WebSocket opens on the first chain read, write, or watch, so an instance that only calls `listMarkets`, `getCandles`, or `getPortfolio` never opens one. This suits server-side rendering. The examples above set `wsRpcUrl` explicitly. The first chain touch throws `NotConfiguredError` when neither this field nor `chain.rpcUrls.default.webSocket[0]` is present. ## Cancel indexer reads from a request scope Pass an `AbortSignal` to stop in-flight indexer reads when the caller goes away, for example on a server per request. ```ts const controller = new AbortController(); const exchange = new SomniaMarkets({ ...config, signal: controller.signal }); // later, when the request is abandoned: controller.abort(); ``` An abort re-throws your own reason. Chain reads are not covered by the signal; they time out after 4 seconds on their own. ## Check the result `await exchange.fetchOrderBook(symbol)` proves the chain transport. `await exchange.fetchBalance()` proves the signer. Each one throws the class named in [Errors](../reference/errors.md) when its input is wrong. `loadMarkets()` does not prove the indexer URL, because it does not throw when the registry read fails. It contains that failure so an indexer outage still returns the perp markets the chain can enumerate. Check the accessor instead: ```ts await exchange.loadMarkets(); if (exchange.registryReadError) throw exchange.registryReadError; // the indexer URL is wrong or the indexer is down ``` --- # /docs/typescript/how-to/get-testnet-funds # How to get testnet funds This guide shows you how to fund an account on the Shannon testnet for the three things trading needs: gas, spot and perp collateral, and binary collateral. It assumes you have a private key and know its address. ## Gas: STT Every transaction pays gas in STT. A write also needs the account to hold the SDK's gas ceiling times its fee ceiling on top of the transaction value: 0.6 STT at the defaults (see [Configuration](../reference/configuration.md#gas)). The chain refunds unused gas. Request STT from one of the faucets listed on the Somnia network page: the official faucet at `https://testnet.somnia.network/`, the Google Cloud faucet for Somnia Shannon, or the Stakely and Thirdweb faucets. Each faucet pays a fixed amount per request; repeat until the balance covers what you need. Some faucets require the requesting address to hold funds on another network first. If none works, ask in the `#dev-chat` channel of the Somnia Discord. Check the balance with a configured exchange: ```ts const balances = await exchange.fetchBalance(); console.log(balances.STT?.total); ``` `fetchBalance` needs a signer in the configuration. Without one, read `exchange.client.getNativeBalance(address)` instead; it returns wei as a `bigint`. ## Spot and perp collateral: USDso `USDso` is the quote token of the spot pairs and the settlement token of the perps. On Shannon it has a public `mint(address, uint256)` with 18 decimals. Mint it with viem: ```ts import { createWalletClient, http, parseUnits } from "viem"; import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(privateKey); const wallet = createWalletClient({ account, chain: exchange.client.config.chain, transport: http() }); const hash = await wallet.writeContract({ address: "0x9c32f3827a1a99f0cf9b213de8b53ec3d57bb171", // USDso on Shannon abi: [ { type: "function", name: "mint", stateMutability: "nonpayable", inputs: [ { name: "to", type: "address" }, { name: "amount", type: "uint256" }, ], outputs: [], }, ], functionName: "mint", args: [account.address, parseUnits("1000", 18)], gas: 500_000n, }); await exchange.client.getViemClient().waitForTransactionReceipt({ hash }); ``` The SDK does not wrap this call. USDso is a test token; the mainnet collateral has no mint. To sell SOMI on `SOMI/USDso`, no USDso is needed: the base of that pair is the native token, and a sell escrows STT. ## Binary collateral: tUSDC The binary markets on Shannon settle in `tUSDC`, a 6-decimal test token with a faucet. The SDK wraps it: ```ts await exchange.trader.faucet(); // mints 10,000 tUSDC to the signer ``` `faucet()` needs `addresses.collateral` (present in `SOMNIA_TESTNET_ADDRESSES`) and a signer. Pass `{ amount }` in raw units to mint less. The contract caps the amount per call; a larger request reverts with `FaucetCapExceeded`. ## Verify ```ts console.log(await exchange.fetchBalance()); ``` The result keys balances by currency code: `STT`, `USDso`, `tUSDC`, and one key per binary tradable you hold shares of, for example `BTC-0-04SEP26/tUSDC#YES`. ## Perps Perp orders draw margin from the MarginBank, not from the wallet. After minting USDso, deposit it: ```ts await exchange.depositMargin("BTC/USDso:USDso", 100); ``` See [Perps](../PERPS.md) for margin, leverage, and funding. --- # /docs/typescript/how-to/run-a-quoting-loop # How to run a quoting loop This guide shows you how to keep a two-sided quote on a spot market from a Node bot: read the live book, place a bid and an ask, re-quote when the market moves, and cancel everything on exit. It assumes a configured `SomniaMarkets` instance with a `privateKey` and funds on the market (see [Get testnet funds](./get-testnet-funds.md)). The example quotes `SOMI/USDso` on the Shannon testnet. ## Open the watch before you quote `watchOrderBook` opens the market watch on its first call and returns the current book. Every later call resolves when the book changes. Open it once before the loop so your own orders show up in `watchOrders` the moment they land. ```ts const symbol = "SOMI/USDso"; await exchange.loadMarkets(); let book = await exchange.watchOrderBook(symbol, 1); ``` ## Quote around the mid Use the exchange verbs for a simple loop. `createOrder` aligns price and amount to the market's tick and lot grids and echoes the aligned values, so compute freely and read the result. ```ts import { ContractRevertError } from "@somnia-chain/markets-sdk"; const size = 5; // SOMI per side const spread = 0.002; // 0.2 % each side let bidId: string | undefined; let askId: string | undefined; let running = true; function isPostOnlyWouldCross(error: unknown) { return error instanceof ContractRevertError && error.errorName === "PostOnlyWouldCross"; } async function cancelIfResting(orderId: string) { try { await exchange.cancelOrder(orderId, symbol); } catch (error) { if (error instanceof ContractRevertError && error.errorName === "IncorrectSender") return; throw error; } } async function requote(book: Awaited>) { const bestBid = book.bids[0]?.[0]; const bestAsk = book.asks[0]?.[0]; if (bestBid === undefined || bestAsk === undefined) return; // one-sided book: skip this tick const mid = (bestBid + bestAsk) / 2; if (bidId) { const previousBidId = bidId; await cancelIfResting(previousBidId); if (bidId === previousBidId) bidId = undefined; } if (askId) { const previousAskId = askId; await cancelIfResting(previousAskId); if (askId === previousAskId) askId = undefined; } if (!running) return; let bid: Awaited>; try { bid = await exchange.createOrder(symbol, "limit", "buy", size, mid * (1 - spread), { postOnly: true }); } catch (error) { if (isPostOnlyWouldCross(error)) return; throw error; } bidId = bid.status === "open" ? bid.id : undefined; if (!running) return; try { const ask = await exchange.createOrder(symbol, "limit", "sell", size, mid * (1 + spread), { postOnly: true }); askId = ask.status === "open" ? ask.id : undefined; } catch (error) { const failures: unknown[] = [error]; const placedBidId = bidId; if (placedBidId) { try { await cancelIfResting(placedBidId); if (bidId === placedBidId) bidId = undefined; } catch (cancelError) { failures.push(cancelError); } } if (failures.length > 1) throw new AggregateError(failures, "ask placement and bid cleanup failed"); if (isPostOnlyWouldCross(error)) return; throw error; } } ``` `postOnly: true` makes the pool reject a quote that would cross instead of taking liquidity; the rejection arrives as `ContractRevertError` with `errorName` `PostOnlyWouldCross`. This loop waits for the next book change after that outcome. If the ask fails after the bid rests, it cancels the bid before it continues. If that cancellation also fails, the loop preserves both errors and the bid id for final cleanup. See [Handle errors and reverts](./handle-errors.md). ## Re-quote on change Each `await exchange.watchOrderBook(symbol, 1)` resolves on the next change of the book. On a busy market that is every block, so compare the top of book and skip unchanged ticks. ```ts let requestStop: (() => void) | undefined; const stop = new Promise((resolve) => { requestStop = () => resolve(null); }); process.once("SIGINT", () => { running = false; requestStop?.(); }); async function cleanupQuotes() { const failures: unknown[] = []; if (bidId) { const orderId = bidId; try { await cancelIfResting(orderId); if (bidId === orderId) bidId = undefined; } catch (error) { failures.push(error); } } if (askId) { const orderId = askId; try { await cancelIfResting(orderId); if (askId === orderId) askId = undefined; } catch (error) { failures.push(error); } } try { await exchange.close(); } catch (error) { failures.push(error); } if (failures.length > 0) throw new AggregateError(failures, "quote cleanup failed"); } let lastTop = `${book.bids[0]?.[0]}/${book.asks[0]?.[0]}`; const failures: unknown[] = []; try { if (running) await requote(book); while (running) { const nextBook = await Promise.race([exchange.watchOrderBook(symbol, 1), stop]); if (nextBook === null || !running) break; book = nextBook; const top = `${book.bids[0]?.[0]}/${book.asks[0]?.[0]}`; if (top === lastTop) continue; lastTop = top; await requote(book); } } catch (error) { failures.push(error); } try { await cleanupQuotes(); } catch (error) { failures.push(error); } if (failures.length > 0) throw new AggregateError(failures, "quoting loop stopped with errors"); ``` Each `createOrder` and `cancelOrder` awaits its receipt. A full re-quote sends two cancellation transactions and two placement transactions. The SDK can also perform prerequisite reads: in particular, every native-base sell reads the pool's current funding requirement and vault shortfall before it sends. ## Re-quote in one transaction For lower latency, move to the engine and use the batch writes. `amendOrders` cancels and replaces several orders in one transaction, all or nothing. It works on spot and perp pools, not on binary pools. ```ts import { ORDER_TYPE, fromHuman, isSpotMarket } from "@somnia-chain/markets-sdk"; const t = exchange.market(symbol); if (!isSpotMarket(t.market)) throw new Error("spot only"); const { quoteDecimals, baseDecimals } = t.market; if (!bidId || !askId) throw new Error("place both quotes before amending them"); const bestBid = book.bids[0]?.[0]; const bestAsk = book.asks[0]?.[0]; if (bestBid === undefined || bestAsk === undefined) throw new Error("two-sided book required"); const mid = (bestBid + bestAsk) / 2; const newBid = exchange.priceToPrecision(symbol, mid * (1 - spread)); const newAsk = exchange.priceToPrecision(symbol, mid * (1 + spread)); const newSize = exchange.amountToPrecision(symbol, size); const result = await exchange.trader.amendOrders({ pool: t.pool, amendments: [ { oldOrderId: bidId, newOrder: { isBid: true, price: fromHuman(newBid, quoteDecimals), quantity: fromHuman(newSize, baseDecimals), orderType: ORDER_TYPE.POST_ONLY, }, }, { oldOrderId: askId, newOrder: { isBid: false, price: fromHuman(newAsk, quoteDecimals), quantity: fromHuman(newSize, baseDecimals), orderType: ORDER_TYPE.POST_ONLY, }, }, ], }); [bidId, askId] = result.newOrderIds.map(String); ``` Prices and quantities are raw `bigint` here; `fromHuman` scales the aligned values by the market's decimals. `ORDER_TYPE.POST_ONLY` preserves the quoting behavior of `createOrder(..., { postOnly: true })`. An unaligned value reverts with `PriceNotAlignedToTickSize` or `QuantityNotAlignedToLotSize`. An amendment whose old order is already gone fails the whole batch with `AmendOldOrderGone`; pass `alwaysPlace: true` on that amendment to place the new order anyway. To place a ladder, use `placeSpotOrders`; to pull one, use `cancelOrders`. To pull every quote you hold on a pool without tracking the ids, use `cancelAllOrders(pool)`. It reads the resting ids and cancels them in one call, which is what a restarted bot needs. Pass `{ source: "live" }` to take the ids from the live tail instead, so the cancel is the only round trip; that needs an active watch on the pool. An expired order that still rests is invisible to the chain source — clear that residue with `cancelExpiredOrders`. The live source does see it, forwards its id, and the cancel lands: the pool gates a best-effort cancel on owner and id, not on expiry, so the order is removed and reported `cancelled: true`. Batches are not payable, so on a market whose base is the native token a batched sell needs a vault balance deposited beforehand with `trader.depositVaultNative`. [Spot markets](../SPOT.md) covers the batch parameters and the vault. ## Set an expiry so a crashed bot's quotes die On the engine every order takes `expireTimestampNs`. Set it a few minutes ahead so a crashed bot's quotes die on their own. Expiry is lazy: an expired order stays on the book until a cancel or a fill attempt touches it, and a fill attempt reverts with `ExpiredOrderMustBeCancelled`. When unset, a spot or perp order expires in about 50 years and a binary order at its market's expiry. ```ts const inFiveMinutes = BigInt(Date.now() + 5 * 60_000) * 1_000_000n; ``` ## Stop cleanly The handler is installed before the first quote. The loop quotes once from the book already returned by the initial watch, then waits for later changes. The handler resolves a pending book read and stops new placements. If a placement is already in flight, the loop waits for its receipt and records its order id before cleanup starts. Cleanup preserves each id until its cancellation succeeds. It attempts both sides even if one cancellation fails. It closes the exchange and then reports every loop or cleanup failure. `cancelIfResting` contains only `IncorrectSender`, which means the known order is no longer cancellable. ## Know what filled Track fills with `watchMyTrades` or `watchOrders` in a second loop. See [Detect when an order fills](./detect-fills.md). --- # /docs/typescript/how-to/detect-fills # How to detect when an order fills This guide shows you how to learn that a resting order was filled, partially filled, or cancelled, with the least latency and without polling. It assumes a configured `SomniaMarkets` instance with a signer, and a market watch opened before the order was placed. ## Read the placement result first A `createOrder` that crosses the book fills in the same transaction. Its result already says so. ```ts const order = await exchange.createOrder("SOMI/USDso", "limit", "buy", 10, 0.116); if (order.status === "closed") { // fully filled in the placement transaction } else if (order.status === "open") { // resting: order.filled may still be > 0 for a partial fill } ``` `status` is `"closed"` when `remaining` is zero, `"open"` when a remainder rests, and `"canceled"` when an immediate-or-cancel or market order left an unfillable remainder. The raw fills are in `order.info.fills`. ## Wait for the status to flip `watchOrders(symbol)` returns your orders on the market from the live store. The first call returns the current list; each later call resolves when the list changes. Loop until your order is no longer open. ```ts let mine = order; while (mine.status === "open") { const orders = await exchange.watchOrders("SOMI/USDso"); mine = orders.find((o) => o.id === order.id) ?? mine; } console.log(mine.status, "filled", mine.filled, "of", mine.amount); ``` The list changes on every order event for your account on that market, including partial fills, so the loop also observes `filled` growing while `status` stays `"open"`. Open the market watch before placing. `watchOrderBook`, `watchTrades`, or `watchOrders` on the symbol all open it. The watch learns about an order placed after it opened from the chain event, in the block the order lands. It learns about an order placed before it opened from the indexer snapshot, which lags the chain by the indexing delay, typically a few seconds. ## Watch your trades `watchMyTrades(symbol)` returns your fills on the market, newest first, and resolves on each new one. Use it when you care about executions rather than order state, for example to update inventory. ```ts let seen = new Set(); while (true) { const trades = await exchange.watchMyTrades("SOMI/USDso", 20); for (const t of trades) { if (seen.has(t.id)) continue; seen.add(t.id); console.log(t.datetime, t.side, t.amount, "@", t.price, "cost", t.cost); } } ``` On spot and perp markets `side` is absent: the pools do not attribute a fill to a side in a way the SDK can map to you. Read `t.info.takerIsBid` and compare `t.info.maker` with your address instead. On binary markets `side` is your own side when the fill carries one. ## Use the engine for raw values `exchange.client.getLiveUserOrders(pool, owner)` and `getLiveUserFills(pool, owner)` are the synchronous views behind the two verbs. They return `LiveOrder` and `LiveFill` rows with exact raw values as decimal strings; wrap a value in `BigInt()` to compute with it. The API reference lists the fields. Subscribe to changes with `client.subscribeLive(listener)`. In React, `useLiveUserOrders` and `useLiveUserFills` re-render on the same changes. See [Use the React hooks](./use-the-react-hooks.md). ## Read your own writes at chain head When a write threw `RpcError` after sending, or when no watch is open, ask the pool directly. These reads answer from the contract in one round-trip and know only what is open now. ```ts const t = exchange.market("SOMI/USDso"); const owner = exchange.walletAddress; if (!owner) throw new Error("configure a signer before reading your open orders"); const openIds = await exchange.client.getOwnOpenOrdersOnchain(t.pool, owner); const stillOpen = openIds.some((id) => id.toString() === order.id); ``` `getOrderOnchain(pool, orderId)` returns one order's on-chain state. For history, including filled and cancelled orders, use the indexer reads `getOpenOrders`, `getOrders`, and `getOrderFills`; they lag the chain by the indexing delay. ## Read a maker order a fill already removed Decoding `OrderFilled` yourself gives you the fill's `fillPrice`, `quantityFilled` and `makerRemainingQuantity`, but names the maker only by id - and a fill removes the maker order in the same transaction, so at head it is gone. Pin the read one block earlier to recover the side the fill took: ```ts const maker = await exchange.client.getOrderOnchain(pool, makerOrderId, { blockNumber: fillBlock - 1n }); // `null` is an UNRESOLVED side, not a sell: an order placed and filled inside one // block has no state one block earlier, and its side is in that block's OrderPlaced. const takerBought = maker === null ? null : !maker.isBid; ``` What it answers, and what it does not: - The maker's identity - `isBid`, `owner`, `userData`, `expireTimestampNs` - cannot change under a given id, so the pinned read is exact for it, and no fill log carries it: `OrderFilled` names the maker by id alone. `OrderPlaced` carries it, but only a consumer that was already listening when the maker rested has that log, which is the case this read exists for. - **Not** the price. It is immutable too, but a fill executes at the maker's resting price and the book emits exactly that, so `OrderFilled.fillPrice` already is the maker's price. Reading for it is redundant work. - **Both** quantities are the values at the **block boundary**, not at your fill. `quantityRemaining` moves on every fill, and `reduceOrder` decrements `fullQuantity` and `quantityRemaining` together under the same id - so an earlier transaction in the fill's own block makes either value stale for your fill, and no block-level read can see between transactions. Take `quantityFilled` and `makerRemainingQuantity` from the event instead. Two edges answer plausibly rather than failing: - A **partial** fill leaves the maker order in place with a smaller `quantityRemaining`, so reading at the fill's own block succeeds with different numbers instead of returning `null`. - An order placed and filled inside **one** block does not exist at `fillBlock - 1n`. That read is `null`, and the placement is in the same block's `OrderPlaced`. A recent block answers against a full node. An older one needs archive state, so this suits a live tape rather than a backfill. ## Choose by need | Need | Use | Latency | | ----------------------------------------- | ------------------------------ | -------------- | | Did the placement itself fill | `createOrder` result | none | | Did a resting order change | `watchOrders` | next block | | What executed, for inventory | `watchMyTrades` | next block | | Is it still open, after a transport error | `getOwnOpenOrdersOnchain` | one round-trip | | Full history for a report | `getOrders`, `getOrderFills` | indexing delay | | Resume from where you stopped | `getUserFills({ sinceBlock })` | indexing delay | | Every fill of a kind in a block range | `getFillsPage` | indexing delay | ## Resume from a block `getUserFills`, `getFills`, `countUserFills` and `getUserFillsPage` take `sinceBlock` and `toBlock`, the source block of the fill. Both bounds include their block. Pass one more than the last block you processed to avoid reading it again. Do not resume with the `since` timestamp: two blocks can carry the same second, so a seconds bound repeats rows or skips them. `getOrderFills(pool, orderId, { limit })` is different: it returns the bounded whole fill history for one known order, accepts only `limit`, and does not take `sinceBlock`. Use `getFills` to resume a pool tape or `getUserFills` to resume an account tape. ```ts const page = await exchange.client.getUserFills(owner, { sinceBlock: BigInt(lastProcessedBlock) + 1n }); ``` ## Walk the whole venue by block range `getUserFills` and `getFills` resume ONE account or ONE pool. A published feed needs every fill of a market kind, across every pool, in a range of blocks. `getFillsPage` answers that, and `getLatestFillBlock` says how far the fill data reaches. ```ts const head = await exchange.client.getLatestFillBlock("SPOT"); if (head === null) return; // nothing traded yet if (head.blockNumber <= BigInt(lastProcessedBlock)) return; // caught up: no new range let cursor: string | undefined; do { const page = await exchange.client.getFillsPage({ marketType: "SPOT", sinceBlock: BigInt(lastProcessedBlock) + 1n, toBlock: head.blockNumber, cursor, }); for (const fill of page.fills) console.log(fill.blockNumber, fill.logIndex, fill.quantity); cursor = page.nextCursor ?? undefined; } while (cursor !== undefined); ``` Both bounds include their block, and rows arrive oldest first by `(blockNumber, logIndex)`. That pair is a total order over the fill table, so `[a, b]` followed by `[b + 1, c]` reads every fill exactly once. Pages hold 500 rows by default. Drain a range until `nextCursor` is null; a null cursor means this read saw no further row IN THE RANGE, not that indexing is complete. Take the upper bound from `getLatestFillBlock` rather than from the chain head. It reads the fill data itself, so it never names a block the range read cannot yet serve. It returns `null` while no fill of that kind is indexed. The cursor binds the chain, the endpoint, the kind and both bounds. A cursor from one range is refused by another, so a range cannot be continued into a different one by accident. All amount fields on `FillRow` stay as raw decimal strings. Do not route a published feed through the human-unit market reads: those convert through `Number()`. ## Bounds on the order reads `getOrders` and `getOpenOrders` take `sinceBlock` as well, but it bounds the block the order was PLACED in. A later fill, reduction or cancellation of an older order does not select that order. An amend places a replacement under a new id, so the replacement is selected when its placement block meets the bound; the older order is not. For an order placed before the bound, a fill read recovers only its executions. It does not report a reduction or cancellation that produced no fill. Keep `watchOrders` active for those changes. After reconnecting, use `getOrder(pool, orderId)` to reconcile the indexed lifecycle of each known order, or use `getOrderOnchain(pool, orderId)` when only current active state is required. Wait for the indexer to reach the block first with `client.waitForIndexedBlock(chainId, block)`; it resolves when the indexer has processed it. --- # /docs/typescript/how-to/sign-with-a-browser-wallet # How to sign with a browser wallet This guide shows you how to let a user trade through an injected wallet such as MetaMask instead of a private key held by your code. It assumes a React app with wagmi or another source of a viem `WalletClient`. For a Node process, use `privateKey` instead; see [Configure the SDK](./configure-for-a-network.md). ## Construct without a signer, bind on connect A browser app has no signer at boot. Construct the exchange for public reads, then bind the wallet when it connects and unbind it when it disconnects. ```tsx import { useEffect } from "react"; import { useWalletClient } from "wagmi"; import { exchange } from "./exchange.js"; // the module-scope SomniaMarkets instance export function SignerBinding() { const { data: walletClient } = useWalletClient(); useEffect(() => { exchange.setSigner(walletClient ? { walletClient } : {}); }, [walletClient]); return null; } ``` `setSigner` replaces the trader that every authenticated verb uses and updates `exchange.walletAddress`. Live watches and market data are unaffected. After binding, the exchange verbs work as they do with a private key: ```ts const order = await exchange.createOrder("SOMI/USDso", "limit", "buy", 10, 0.11); ``` ## What differs from a local key The wallet signs after a user prompt, sends through `eth_sendTransaction`, and the SDK reads the receipt on the next block heads instead of in one round-trip. The first order per token also prompts for an approval. Both paths resolve to the same result shape once the transaction is mined. The [Configuration reference](../reference/configuration.md#signer-paths) tabulates the differences. ## Make sure the wallet is on the right chain The SDK does not switch chains. Check `walletClient.chain?.id` against `exchange.client.config.chain.id` before a write, and ask the wallet to switch with wagmi's `useSwitchChain` when they differ. A write from the wrong chain is rejected by the wallet or the node, not by the SDK. ## Use the owner-derived trader with a wallet After `setSigner` binds the wallet, use the trader owned by the same exchange. It inherits the exchange's chain, read client, addresses, and lifecycle. ```ts await exchange.trader.faucet(); ``` ## Show the connected account's data `fetchBalance`, `fetchOpenOrders`, `watchOrders`, and `watchMyTrades` answer for `exchange.walletAddress`. In React, prefer the hooks with the account from wagmi's `useAccount`: `useWatchUser(address)` plus `useLiveUserOrders(pool, address)`. See [Use the React hooks](./use-the-react-hooks.md). ## Handle a rejected prompt A user who dismisses the wallet prompt produces an error from the wallet, not from the SDK. It does not extend `SomniaMarketsError`, so keep a final `throw` or a wallet-specific branch in your handler. See [Handle errors and reverts](./handle-errors.md). --- # /docs/typescript/how-to/use-the-react-hooks # How to use the React hooks This guide shows you how to wire `@somnia-chain/markets-sdk/react` into a React app: provide the client once, render live data that updates itself, and fetch indexer data with your own query library. It assumes you know React hooks and context. The hook signatures are in the API reference under "React hooks". ## Provide the client once Construct one exchange at module scope and pass its engine, `exchange.client`, to the provider near the root. Every hook reads the client from context. ```tsx import type React from "react"; import { SomniaMarkets, SOMNIA_TESTNET_ADDRESSES } from "@somnia-chain/markets-sdk"; import { SomniaMarketsProvider } from "@somnia-chain/markets-sdk/react"; import { somniaTestnet } from "viem/chains"; export const exchange = new SomniaMarkets({ indexerUrl: "https://dev.smk.somnia.host/v1/graphql", chain: somniaTestnet, wsRpcUrl: "wss://api.infra.testnet.somnia.network/ws", addresses: SOMNIA_TESTNET_ADDRESSES, }); export function App({ children }: { children: React.ReactNode }) { return {children}; } ``` Do not construct the exchange inside a component. A new instance per render means a new socket and a new store per render. ## Render a live order book The pool-keyed `useLive*` hooks open the market watch while the component is mounted and re-render on every change. Ten components on one pool share one watch. ```tsx import { toHuman } from "@somnia-chain/markets-sdk"; import { useLiveSpotOrderBook, useWatchMarket } from "@somnia-chain/markets-sdk/react"; export function SpotBook({ pool, baseDecimals, quoteDecimals, }: { pool: string; baseDecimals: number; quoteDecimals: number; }) { const status = useWatchMarket(pool); // "unwatched" | "hydrating" | "live" const book = useLiveSpotOrderBook(pool, 10); if (status !== "live") return

loading…

; return ( {book.asks.map((l) => ( ))} {book.bids.map((l) => ( ))}
{toHuman(l.price, quoteDecimals)} {toHuman(l.quantity, baseDecimals)}
{toHuman(l.price, quoteDecimals)} {toHuman(l.quantity, baseDecimals)}
); } ``` Live values are raw `bigint`. Convert at the edge with `toHuman` and the market's decimals. Read the decimals off the market row, from `useMarkets` or from `exchange.markets[symbol].info`. Pass `undefined` as the pool to render nothing and open no watch, for example while a route parameter loads. The other `useLive*` hooks follow the same pattern; the API reference under "React hooks" lists them. ## Show your own orders and fills Combine `useWatchUser` with the user-scoped hooks. `useWatchUser` hydrates the account's order and fill history; the pool watch keeps it current. ```tsx import { useLiveUserOrders, useWatchUser } from "@somnia-chain/markets-sdk/react"; export function MyOrders({ pool, account }: { pool: string; account: string }) { useWatchUser(account); const orders = useLiveUserOrders(pool, account, 50); return (
    {orders.map((o) => (
  • {o.orderId} {o.status}
  • ))}
); } ``` ## Fetch indexer data with TanStack Query or SWR The SDK ships no cache wrapper. Every client read is a promise, which is a ready-made `queryFn`, and the root entry exports one key factory per read so your keys never drift. ```tsx import { useQuery } from "@tanstack/react-query"; import { candlesKey } from "@somnia-chain/markets-sdk"; import { useSomniaMarketsClient } from "@somnia-chain/markets-sdk/react"; export function useCandles1h(pool: string) { const client = useSomniaMarketsClient(); return useQuery({ queryKey: candlesKey(pool, 3600, { limit: 500 }), queryFn: () => client.getCandles(pool, 3600, { limit: 500 }), refetchInterval: 15_000, }); } ``` After a write, invalidate with the same factory, for example `queryClient.invalidateQueries({ queryKey: portfolioKey(account) })`, or everything SDK-shaped with the `QUERY_KEY_SCOPE` prefix. On a multi-chain exchange, the same account or pool can exist on each chain. Give each key the chain of its read as the last argument: ```tsx export function useCandles1hOn(pool: string, chainId: number) { const client = useSomniaMarketsClient(chainId); return useQuery({ queryKey: candlesKey(pool, 3600, { limit: 500 }, { chainId }), queryFn: () => client.getCandles(pool, 3600, { limit: 500 }), }); } ``` A key without `chainId` is the same key a single-chain app uses. A key with a `chainId` is that key plus a last `{ chainId }` element. So `invalidateQueries` with a key without a chain matches the entries of every chain, because TanStack Query matches by prefix. A key with a `chainId` does not match an entry stored without one, even on the primary chain. So on a multi-chain exchange, pass `chainId` on every key you read with. Do not wrap the `useLive*` hooks in a query cache. They already read a shared, push-fed store. ## Fetch indexer data without a query library `useIndexerQuery(fn, deps)` re-runs `fn` when `deps` change and keeps `data`, `loading`, `error`, and `refetch`. It discards a superseded result. It also passes an `AbortSignal` to `fn`, but current client read methods do not accept a per-request signal, so the example below does not cancel its HTTP request. ```tsx import { useIndexerQuery } from "@somnia-chain/markets-sdk/react"; export function useOpenOrders(owner: string | undefined) { return useIndexerQuery((client) => (owner ? client.getOpenOrders(owner) : Promise.resolve([])), [owner]); } ``` The built-in indexer hooks such as `usePortfolio` and `useCandles` return the same shape. ## Write from a component Hooks read; writes go through the exchange or a trader. With a browser wallet, bind it first as shown in [Sign with a browser wallet](./sign-with-a-browser-wallet.md), then call `exchange.createOrder(...)` from an event handler. The live hooks pick up the resulting order and fills without any refetch. ## Render prices `useWatchPrice(asset)` opens the price watch; `useLivePrice(asset)` returns the latest `LivePrice` or `null`. Both need `priceFeed` in the configuration. `useLivePriceFeedInfo` does not re-render as a price ages; drive an age display from your own timer. --- # /docs/typescript/how-to/handle-errors # How to handle errors and reverts This guide shows you how to branch on the errors the SDK throws so a bot or a UI reacts correctly to a bad input, an outage, and a rejected transaction. It assumes you write `try`/`catch` in TypeScript. The complete list of classes and contract error names is in [Errors](../reference/errors.md). ## Branch on the class, not the message Every SDK error has a concrete class. Test with `instanceof`, most specific first, and keep a final `throw` for errors the SDK does not own. `InvariantError` is the class for an SDK defect; report it and rethrow it instead of using it for control flow. ```ts import { ContractRevertError, FillHistoryRestartRequiredError, FillHistoryUnavailableError, IndexerError, IndexerWaitTimeoutError, InvariantError, InvalidInputError, RpcError, SignerRequiredError, SomniaMarketsError, TransactionOutcomeUnknownError, } from "@somnia-chain/markets-sdk"; try { await exchange.createOrder("SOMI/USDso", "limit", "buy", 10, 0.11); } catch (e) { if (e instanceof TransactionOutcomeUnknownError) { // the order may be on chain: look up e.hash before placing it again } else if (e instanceof ContractRevertError) { // the chain rejected it: read e.errorName } else if (e instanceof InvalidInputError) { // the call is wrong: fix the arguments, do not retry } else if (e instanceof SignerRequiredError) { // configure a privateKey, account, or walletClient } else if (e instanceof FillHistoryRestartRequiredError) { // getUserFillsPage: discard accumulated pages and request page one without a cursor } else if (e instanceof FillHistoryUnavailableError) { // deploy and reindex a producer that initializes the fill dataset generation } else if (e instanceof RpcError || e instanceof IndexerError) { // the request did not complete: retry with backoff, or degrade } else if (e instanceof InvariantError) { console.error(e); // report the SDK defect throw e; } else if (e instanceof SomniaMarketsError) { // NotConfiguredError and anything else the SDK raised } else { throw e; // not ours: a wallet or an application bug } } ``` `IndexerWaitTimeoutError` comes from the indexer wait, not from the write. Wrap `waitForIndexedBlock` when you need to branch on that deadline: ```ts const targetBlock = 1_234_567n; // the confirmed transaction's block try { await exchange.client.waitForIndexedBlock(exchange.client.config.chain.id, targetBlock); } catch (e) { if (e instanceof IndexerWaitTimeoutError) { // the indexer answered but is still behind e.targetBlock } else if (e instanceof IndexerError) { // the metadata read did not complete: retry with backoff, or degrade } else { throw e; } } ``` Message text is not stable. `errorName`, `operation`, `what`, `cursorGeneration`, and `servingGeneration` are. ## Decide from a revert `ContractRevertError.errorName` is the contract's own error name when the revert data matched a known error. Branch on it with a fallback arm; `errorName` is `undefined` for a bare `require` string or unknown data. ```ts import { ContractRevertError } from "@somnia-chain/markets-sdk"; try { await exchange.trader.placeOrder(params); } catch (e) { if (!(e instanceof ContractRevertError)) throw e; switch (e.errorName) { case "ExpiredOrderMustBeCancelled": { // An expired maker sits in the way. Sweep the expired orders, then retry. const expired = await exchange.client.listSweepableOrders({ pool: params.pool }); await exchange.trader.cancelExpiredOrders({ pool: params.pool, orderIds: expired.map((o) => o.orderId) }); break; } case "InsufficientBalance": case "ERC20InsufficientBalance": // top up, then retry break; case "PostOnlyWouldCross": // re-quote one tick away break; case undefined: console.error("unrecognised revert", e.reason ?? e.data); break; default: throw e; } } ``` `e.args` holds the decoded arguments in order. `IncorrectSender(sender, expected)`, for example, is what a cancel of an already-cancelled order returns; `expected` is the zero address because the order no longer exists. ## Retry only what can succeed Retry a read that throws `RpcError` or `IndexerError` with backoff; the request never reached a conclusion. A write is different; see the next section. An `IndexerUnavailableError` is the SDK refusing locally. `breaker-open`, `breaker-trial`, and `queue-full` mean nothing was sent. `live-reset` can stop a retry backoff after an earlier attempt was sent. Branch on `reason` rather than waiting a fixed period, because `retryAfterMs` is meaningful only for `breaker-open`. Sleep `retryAfterMs` for `breaker-open`; retry shortly for `breaker-trial`, where a trial read is already deciding; back off on your own schedule for `queue-full`, since this client is saturated and retrying at once is just re-shed; and retry `live-reset` on the same client, which `stopLive()` leaves usable. Retrying sooner than the reason allows is what turns a slow indexer into an outage. An `IndexerWaitTimeoutError` means the indexer answered but did not reach `targetBlock` before the deadline: wait longer, or read the required state from chain. An `IncompleteHistoryError` means portfolio analytics stopped before reading every indexed fill: raise or omit `maxFillPages` when `reason` is `pageBudgetExceeded`, and investigate the indexer when it is `cursorCycle`; it never means an empty portfolio. A `FillHistoryUnavailableError` means the producer has not initialized its fill-dataset generation: deploy and reindex a compatible producer before trying again. A `FillHistoryRestartRequiredError` means a fill-page cursor belongs to a replaced serving dataset: discard the pages already read and restart from page one; retrying with the same cursor fails again. Retry a `ContractRevertError` only after the state that caused it changes; the same call reverts the same way. Never retry `InvalidInputError`, `NotConfiguredError`, or `SignerRequiredError`; fix the code or the configuration. A `CollateralOnWrongChainError` means the collateral is on another configured chain: bridge the shortfall — the error carries a plan when a route exists — and retry once it lands. A `BridgeLiquidityError` means a native bridge route's destination router holds less than the amount, so the SDK sent nothing: retry after the router is seeded, bridge at most `available` with `exchange.bridge.transfer`, or fund the destination another way. A `BridgeDeliveryTimeoutError` means the bridge leg was sent, but its message was not delivered within the timeout. Do not bridge again at once, or the funds move twice. Call `delivered(messageId)` on the destination Mailbox. When it returns `false`, wait longer: the message can still land. Two bridge `RpcError` operations also come after the origin leg was sent: `bridge message id` and `watch bridge delivery`. The funds may be in flight, so look up the origin transaction before you retry. ## Retry a write only after you know its outcome A write can fail after its signed transaction reached the node. The SDK then throws `TransactionOutcomeUnknownError`, a subclass of `RpcError`. The transaction can still mine, so sending the write again can place the order twice. Test for this class before `RpcError`. The error carries `chainId`, `operation` and `hash`. Look up `hash` before you send again: 1. Read the receipt for `hash`. If it exists, the transaction mined. Do not send it again. Its `status` tells you whether the write succeeded (`"success"`) or reverted (`"reverted"`). 2. If there is no receipt, or no `hash` (a session send gives none), read the state the write changes. For an order, read your open orders at chain head with `exchange.client.getOwnOpenOrdersOnchain(pool, owner)`; see [Detect when an order fills](./detect-fills.md). 3. Send again only when that state shows the write did not happen. ```ts import { TransactionOutcomeUnknownError } from "@somnia-chain/markets-sdk"; try { await exchange.trader.placeOrder(params); } catch (e) { if (!(e instanceof TransactionOutcomeUnknownError)) throw e; const viem = exchange.client.getViemClient(); const receipt = e.hash ? await viem.getTransactionReceipt({ hash: e.hash }).catch(() => null) : null; if (receipt === null) { // Unknown still: read your open orders at chain head before placing again. } } ``` From the local-signer and session-key executors, a plain `RpcError` from a write means the node refused the transaction or nothing was sent. Fix the cause (for example a stale nonce or an unfunded account), then send again. Other writes do not guarantee this. A wallet client can fail after it broadcast, and admin, lend and bridge writes do not make the distinction yet. After one of those throws `RpcError`, check the chain before you send again. ## Degrade an indexer read An indexer failure is never "no rows". Catch `IndexerError` deliberately when a page should render with stale or empty data rather than fail. ```ts import { IndexerError } from "@somnia-chain/markets-sdk"; const trades = await exchange .fetchTrades("SOMI/USDso", undefined, 50) .catch((e) => (e instanceof IndexerError ? [] : Promise.reject(e))); ``` Do not apply the same pattern to a chain read: a chain read throws only on real failure, and an empty fallback would hide it. ## Tell cancellation apart from failure When you pass `signal` in the configuration and abort it, in-flight indexer reads re-throw your abort reason, not an `IndexerError`. Check `e.name === "AbortError"` before the SDK classes. ## Decode a revert you sent yourself If you build a transaction with the exported ABIs and send it through your own client, `decodeRevert(caught)` turns the failure into a `ContractRevertError` with the same `errorName` decoding. It always returns an error and never throws. Call it only on failures you know are reverts; a transport error passed to it comes back without `errorName`. ```ts import { decodeRevert } from "@somnia-chain/markets-sdk"; try { await wallet.writeContract(request); } catch (caught) { const revert = decodeRevert(caught); console.error(revert.errorName ?? revert.reason); } ``` ## See the failure in context Pass a `debug` sink to see which span failed and with what arguments. See [Debug what the SDK is doing](./debug-the-sdk.md). --- # /docs/typescript/how-to/debug-the-sdk # How to debug what the SDK is doing This guide shows you how to see every trader call, the sign-and-send pipeline, and live-tail hydration as structured events, and how to capture them in tests. It assumes a working `SomniaMarkets` configuration. The SDK is silent by default. A `debug` sink in the configuration receives `DebugEvent` values: log lines, and span start, annotate, and end events with ids, parent ids, and durations. The sink owns filtering and formatting. ## Print an indented span tree `consoleDebugSink()` renders the stream to the console as a tree reconstructed from `parentId`. ```ts import { SomniaMarkets, consoleDebugSink } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets({ ...config, debug: consoleDebugSink() }); ``` A `createOrder` on a spot market printed these lines on the testnet: ```text [sdk] ▶ trader.placeSpotOrder { params: { pool: '0x259f…fff4', isBid: false, price: 459600000000000000n, … } } [sdk] ▶ trade.execute { functionName: 'placeOrder', address: '0x259f…fff4' } [sdk] ▶ trade.signCall [sdk] ◀ trade.signCall 224.2ms [sdk] ▶ trade.broadcast [sdk] ◀ trade.broadcast 948.4ms [sdk] · trade.execute { hash: '0xc164…b18a17' } [sdk] ◀ trade.execute 1173.2ms [sdk] ◀ trader.placeSpotOrder 1174.5ms ``` The trader span and the `trade.execute` span are both roots: a parent is only recorded where the SDK sets one explicitly, and `trade.signCall`, `trade.broadcast`, and `trade.confirm` are the spans that carry one. Pass `{ prefix }` to change the `[sdk]` label. A span that ended with an error prints through `console.warn`. ## Toggle it from your app The toggle belongs to the app, not the SDK. Two common shapes: ```ts // Browser: flip on from devtools with localStorage.setItem("sdk-debug", "1") and reload. const exchange = new SomniaMarkets({ ...config, debug: localStorage.getItem("sdk-debug") ? consoleDebugSink() : undefined, }); ``` ```ts // Node bot: JSON lines behind an environment variable. const exchange = new SomniaMarkets({ ...config, debug: process.env.SDK_DEBUG ? (e) => console.log(JSON.stringify(e, (_, v) => (typeof v === "bigint" ? v.toString() : v))) : undefined, }); ``` Events carry `bigint` values, so a plain `JSON.stringify` throws without the replacer. ## Capture events in a test `debugCollector()` returns a sink and typed filters over what it received. Each collector is independent, so parallel tests can each have their own. ```ts import { SomniaMarkets, debugCollector } from "@somnia-chain/markets-sdk"; const c = debugCollector(); const exchange = new SomniaMarkets({ ...config, debug: c.sink }); await exchange.trader.placeOrder(params); expect(c.starts("trade.execute").length).toBeGreaterThan(0); // 2 when a first order also sent an approve expect(c.ends("trade.execute").every((e) => e.error === undefined)).toBe(true); ``` `c.starts(name?)`, `c.ends(name?)`, `c.annotations(name?)`, and `c.logs(scope?)` filter `c.events`. ## Send spans to a tracer The span events map onto OpenTelemetry (`name`, `data` as attributes, `error` as status, `parentId` as parent). A sink that keeps a `Map` from span id to tracer span calls `startSpan` on `phase: "start"` and `end()` on `phase: "end"`; the tracer dependency stays in your app. ## What to look for | Symptom | Where it shows | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | A write is slow | `trade.execute` duration, split into `trade.signCall` and `trade.broadcast`; `trade.confirm` appears only on the external-wallet path, where the receipt is read separately | | A watch never goes live | The `liveTail.hydrate:` span ends with `error` set. In React, a `hooks` log line at level `warn` reads `watch failed for …` | | A first write does an extra round-trip | An `approve` transaction before the order: the allowance is cached per token and spender afterwards | The SDK swallows a sink that throws. A broken sink never breaks trading. --- # /docs/typescript/reference/configuration # Configuration This page lists every field a `SomniaMarkets` instance accepts, with its type, whether it is required, and its default. The same fields, minus the three signer fields, form `ClientConfig`, the configuration of the engine. For the values to put in these fields on each network, see [Networks and endpoints](./networks-and-endpoints.md). ```ts import { SomniaMarkets } from "@somnia-chain/markets-sdk"; const exchange = new SomniaMarkets(config); // config: SomniaMarketsConfig ``` ## `SomniaMarketsConfig` `SomniaMarketsConfig` is `ClientConfig` plus the signer fields `privateKey`, `account`, and `walletClient`. | Field | Type | Required | Default | Description | | ---------------- | ----------------------------- | -------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `indexerUrl` | `string` | no | none | Envio/Hasura GraphQL endpoint over HTTP. A same-origin relative path is accepted in a browser. Omit for a chain-only client (smart accounts, executors, on-chain reads): every indexer read and live watch then throws `NotConfiguredError` naming this field. | | `chain` | `Chain` (viem) | yes | none | The chain the markets live on. | | `wsRpcUrl` | `string` | no | `chain.rpcUrls.default.webSocket[0]` | The WebSocket RPC endpoint. It is the only chain transport: subscriptions, reads, and writes all use it. There is no HTTP fallback. Required when `chain` carries no WebSocket URL. | | `indexerHeaders` | `Record` | no | none | Extra headers on every indexer request, for example a Hasura admin secret. Server-side only. | | `signal` | `AbortSignal` | no | none | Aborts in-flight indexer reads. Client-wide, not per read. An abort re-throws the caller's own reason, not an `IndexerError`. Chain reads are not covered; they have a 4-second request timeout of their own. | | `fees` | `FixedFees` | no | `DEFAULT_FEES` | Fixed EIP-1559 fees for SDK-signed writes. | | `addresses` | `SomniaMarketsAddresses` | no | `{}` | Protocol contract addresses. Every entry is optional. A method that needs a missing address throws `NotConfiguredError` when it is called. | | `priceFeed` | `PriceFeedConfig` | no | none | The realtime price-feed endpoint. Required only by the price methods that fetch or watch (`watchPrice`, `fetchPrice`, `fetchPriceOHLCV`, and the client's `fetchPrice*` and `listPriceFeeds`). Its `quote` is mandatory to watch: an unpinned feed rejects `watchPrice`/`watchPrices` with `NotConfiguredError` because the tick tape's cursor is unique only within one quote; the one-shot reads still work unpinned. The `getLivePrice*` reads return `null` or `[]` until a watch is open. | | `debug` | `(event: DebugEvent) => void` | no | none | Receives structured debug events. When unset the SDK emits nothing and does no debug-only work. | | `privateKey` | `` `0x${string}` `` | no | none | A local signing key. The SDK signs locally and confirms in one round-trip. | | `account` | `Account \| Address` | no | none | A viem account, or a plain address to trade as through `walletClient`. | | `walletClient` | `WalletClient` | no | none | An external signer, for example an injected browser wallet. | ### Counts and `indexerHeaders` This section describes how the count methods (`countMarkets`, `countOrders` and the others) pick a query. A count first asks Hasura for `_aggregate`. Only a privileged role, such as the one an admin secret in `indexerHeaders` selects, has that field. On the public role Hasura rejects the field, and the count scans at most 10,001 ids instead. The client remembers that rejection for five minutes. The memory is per client, endpoint, header set and table. In that window a count of the same table sends only the scan. The first counts of a table that run at the same time share one probe. Only Hasura's exact `field '
_aggregate' not found in type: 'query_root'` error is remembered. Any other failure still throws and is not remembered. `stopLive()` clears the memory. After a role gains or loses the field, counts use the new permission within five minutes, or at once after `stopLive()`. ### Signer resolution A method that writes, or reads data scoped to the caller, resolves the caller's address in this order: `walletClient.account.address`, then `account.address`, then `account` when it is a string, then the address derived from `privateKey`. When none is set, `walletAddress` is `undefined` and every authenticated method throws `SignerRequiredError`. `setSigner(signer)` replaces the signer after construction. Passing `{}` removes it. Live watches and market data are unaffected. ### Signer paths | Aspect | `privateKey` or a signing `account` | `walletClient` | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | Who signs | The SDK, locally | The wallet, after a user prompt | | Fees and gas | The fixed values from `fees` and the gas ceiling | The same fixed values, passed to the wallet as `maxFeePerGas`, `maxPriorityFeePerGas`, and `gas` | | Send path | `eth_sendRawTransactionSync`: send and receipt in one round-trip; falls back to `eth_sendRawTransaction` when the node does not serve it | `eth_sendTransaction` through the wallet; the receipt is read on each new block head over the SDK's WebSocket | | Reverts | Decoded by replaying the failed call at the receipt's block | Surfaced by the wallet's simulation before the prompt, with revert data | | Approvals | One `approve(maxUint256)` per token and spender, on the first order that needs it, cached for the trader's lifetime | The same, as a second wallet prompt | | Nonce | Tracked locally after one fetch; reset on a rejected send | Managed by the wallet | ### Lazy connections The viem chain WebSocket opens on the first chain read, write, or watch. An instance that only performs indexer reads never opens one. The price-feed WebSocket opens on the first `watchPrice`. `close()` stops the watches and channels and closes every socket the instance opened, both the price-feed WebSockets and the viem chain transport, so a Node process exits on its own afterwards. Each instance owns its own chain socket, even when several use the same `wsRpcUrl`, so closing one never affects another. ## `FixedFees` | Field | Type | Description | | ---------------------- | -------- | ----------------------------------------------------------------------------------- | | `maxFeePerGas` | `bigint` | Fee ceiling in wei per gas. The unspent margin above base fee plus tip is refunded. | | `maxPriorityFeePerGas` | `bigint` | Tip in wei per gas. | `DEFAULT_FEES` is `{ maxFeePerGas: 60_000_000_000n, maxPriorityFeePerGas: 0n }`: a 60 gwei ceiling and no tip. ### Gas Every SDK-signed write uses a fixed gas ceiling of 10,000,000 gas. Gas is never estimated. Unused gas is not charged. The mempool accepts a transaction only when the account holds `gas × maxFeePerGas` on top of the transaction value: 0.6 STT or SOMI at the defaults. A lower-level write accepts a per-call `gas` override only when its public parameter type declares one. Unified exchange methods such as `createOrder` and `cancelOrder` do not expose that override. ## `SomniaMarketsAddresses` Every field is optional and typed `Address`, except `lend`. | Field | Used by | | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `collateral` | The venue's collateral ERC-20. `faucet()` mints it on test networks. | | `testUsdc` | Legacy alias for `collateral`. `collateral` takes precedence. | | `binaryModule` | Complete-set mint and redeem, market creation, hub-approval reads, system diagnostics. | | `marketCreator` | The live tail watches `MarketCreated` on it to discover new binary markets. | | `clobFactory` | System diagnostics fallback. | | `binaryPoolImpl`, `binaryPoolBeacon` | Surfaced to apps. Not read by the SDK. | | `binarySettlement` | `redeemDirect`, `claimOwed`, `getSettlement`. | | `operatorPermissionsRegistry` | Operator approval of a stop-order registry. Discoverable at runtime with `getOperatorPermissionsRegistry(pool)`. | | `marketsCore` | Operator and venue reads, `createOperatorAdmin`. | | `collateralRouter` | The native-token and Permit2 complete-set path (`mintSetNative`, `mintSetPermit2`, `redeemNative`). | | `marketCreatorFactory`, `marketCreatorFactoryV2` | `createMarketCreatorAdmin`. | | `oracleHub` | OracleHub reads and `createOracleHubAdmin`. | | `perpPoolFactory` | Perp discovery when the indexer has no perp rows. `loadMarkets` otherwise resolves the factory from `MarginBank.getSystemConfig()` on an indexed perp row, so this is needed only when there is no such row. Without it, discovery is SKIPPED and reports through `perpDiscoverySkipped`. When set it takes precedence. | | `lend` | `LendAddresses` for the third-party SomniaLend deployment. Backs `client.lend`. | | `fakeOracle` | `resolve` and `voidMarket` on demo stacks. | | `oracleAdapterFactory`, `sharedOracleAdapter` | Deprecated. Kept so old configurations type-check. Not read. | `SOMNIA_MAINNET_ADDRESSES`, `SOMNIA_TESTNET_ADDRESSES` and `SOMNIA_HIDEKI_TESTNET_ADDRESSES`, exported from the root entry, hold the current deployments. `SOMNIA_MAINNET_LEND` and `SOMNIA_TESTNET_LEND` hold the SomniaLend addresses and are already included in the mainnet and testnet constants. Hideki has no SomniaLend deployment, so its preset omits `lend`. ## `PriceFeedConfig` | Field | Type | Required | Default | Description | | ------- | -------- | -------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `url` | `string` | yes | none | HTTP GraphQL endpoint of the price-feed indexer. One endpoint serves every asset. | | `wsUrl` | `string` | no | `url` with `http` replaced by `ws` | WebSocket GraphQL endpoint for live subscriptions. | | `quote` | `string` | no | none | Quote asset to pin every read to, case-insensitive. When unset, a base that trades against two quotes is double-counted. | `SOMNIA_TESTNET_PRICE_FEED` is `{ url: "https://price-feed.dev.oracle.somnia.host/v1/graphql", quote: "USDC" }`. `SOMNIA_MAINNET_PRICE_FEED` is `{ url: "https://price-feed.prd.oracle.somnia.host/v1/graphql", quote: "USDC" }`. They index different chains; see [networks and endpoints](./networks-and-endpoints.md). ## Transport constants | Constant | Value | Where | | --------------------------- | ------------------------------ | ------------------------------------------------------------ | | WebSocket request timeout | 4,000 ms | Every chain read and write. | | Indexer request timeout | 30,000 ms | Every indexer read. | | Default gas ceiling | 10,000,000 | Every SDK-signed write. Not exported. | | `DEFAULT_FEES.maxFeePerGas` | 60 gwei | Exported from the root entry. | | Reconnect backoff | 500 ms, doubling to an 8 s cap | Live watches after a socket error. | | Watch linger | about 30 s | Time a scope stays materialised after its last handle stops. | --- # /docs/typescript/reference/networks-and-endpoints # Networks and endpoints This page lists the Somnia networks and the endpoint and address values that go into a [configuration](./configuration.md). The SDK accepts a viem `Chain`. The address constants come from the SDK root entry. ## Chains Use the chain definitions that `@somnia-chain/markets-sdk/chains` exports. Each one carries its WebSocket URL, so `wsRpcUrl` is optional with them. Do not define these networks by hand: a hand-written definition keeps old endpoints when a network moves, as Hideki did at its 2026-09-17 regenesis. viem's own `somnia` and `somniaTestnet` describe the mainnet and Shannon networks but carry no WebSocket URL. If you use them, set `wsRpcUrl`. ```ts import { hidekiTestnet, somniaMainnet, somniaShannon } from "@somnia-chain/markets-sdk/chains"; ``` | SDK export | Chain id | Name | Native currency | Block time | HTTP RPC | WebSocket RPC | | --------------- | -------- | --------------------- | --------------- | ---------- | -------------------------------------------------- | --------------------------------------------------- | | `somniaMainnet` | 5031 | Somnia | SOMI (18) | 100 ms | `https://api.infra.mainnet.somnia.network` | `wss://api.infra.mainnet.somnia.network/ws` | | `somniaShannon` | 50312 | Somnia Testnet | STT (18) | 100 ms | `https://api.infra.testnet.somnia.network` | `wss://api.infra.testnet.somnia.network/ws` | | `somniaElwood` | 50313 | Somnia Elwood Testnet | STT (18) | 100 ms | `https://api.elwood.infra.testnet.somnia.network` | `wss://api.elwood.infra.testnet.somnia.network/ws` | | `hidekiTestnet` | 50383 | Hideki Testnet | STT (18) | 10 ms | `https://api.hideki2.infra.testnet.somnia.network` | `wss://api.hideki2.infra.testnet.somnia.network/ws` | | `somniaLocal` | 31337 | Somnia Local | STT (18) | none | `http://127.0.0.1:8545` | `ws://127.0.0.1:8545` | Shannon also serves `https://dream-rpc.somnia.network` and `wss://dream-rpc.somnia.network/ws` as secondary RPC URLs for the same network. Block explorers: `https://explorer.somnia.network` (mainnet) and `https://shannon-explorer.somnia.network` (Shannon). Elwood, Hideki, and local carry no explorer. Multicall3: mainnet `0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11`, Shannon `0x841b8199E6d3Db3C6f264f6C2bd8848b3cA64223`, Hideki `0xcA11bde05977b3631167028862bE2a173976CA11` (the canonical address; v2 predeploys it). Elwood and local carry none. ## Somnia Markets deployments | Network | Indexer GraphQL | Address constant | | ----------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------- | | Mainnet (5031) | `https://prd.smk.somnia.host/v1/graphql` | `SOMNIA_MAINNET_ADDRESSES` | | Shannon testnet (50312) | `https://dev.smk.somnia.host/v1/graphql` | `SOMNIA_TESTNET_ADDRESSES` | | Hideki testnet (50383) | `https://hideki-dev.smk.somnia.host/v1/graphql` (development-grade) | `SOMNIA_HIDEKI_TESTNET_ADDRESSES` | | Local anvil (31337) | `http://localhost:8085/v1/graphql` when started with `demo-clob.sh up` | Resolved from the local manifest through `@somnia-chain/deployments/local` | The mainnet and Shannon testnet constants share the protocol contracts (`binaryModule`, `binaryPoolBeacon`, `binaryPoolImpl`, `marketsCore`, `oracleHub`, `binarySettlement`, `clobFactory`, `collateralRouter`, `marketCreatorFactory`) and differ in `collateral`, `marketCreator`, `lend`, and `perpPoolFactory`. The Hideki preset omits `collateralRouter` and `lend`. Hideki has no wSTT, Permit2, or SomniaLend deployment, so the corresponding helpers report not-configured. The Hideki indexer is development-grade. It runs in the development environment and has no alerting, so a stall can go unnoticed. It indexes the Hideki binary and perp markets. It does not index the Hideki spot pools yet. Omit `indexerUrl` for chain-only reads and writes; supply one for indexed discovery and history. Indexed reads without a configured URL fail with `NotConfiguredError`; requests to an unreachable indexer fail with `IndexerError`. The Shannon and Hideki presets set `perpPoolFactory`. `loadMarkets` therefore lists their perps from the chain, also when the binding has no `indexerUrl`. The mainnet preset has no `perpPoolFactory`. | Field | Mainnet | Shannon | | ------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------ | | `collateral` / `testUsdc` | `0x00000022dA000002656c64D9eA6011ea952D008A` | `0x70a86D8842FB63C4Ad2b7cdddF530eBf1BB25d8E` (tUSDC, 6 decimals, has `faucet`) | | `marketCreator` | `0xfe81C4e8EfFb7df27Eb21881f80AF2BF8DCF0c39` | `0x94D963B6670AB96E78C8d0C46ca35D196d606EFE` | | `lend` | `SOMNIA_MAINNET_LEND` | `SOMNIA_TESTNET_LEND` | Addresses change with deployments. The constants in the installed SDK version are the source of truth; the values above are the ones current at the time of writing. ## Testnet tokens | Token | Address on Shannon | Decimals | Role | How to obtain | | ----- | -------------------------------------------- | -------- | --------------------------------------------------- | --------------------------------------------------------------------- | | STT | native | 18 | Gas, and the base of `SOMI/USDso` | Faucets listed in [Get testnet funds](../how-to/get-testnet-funds.md) | | USDso | `0x9c32f3827a1a99f0cf9b213de8b53ec3d57bb171` | 18 | Quote of the spot pairs and settlement of the perps | Public `mint(address,uint256)` | | tUSDC | `0x70a86D8842FB63C4Ad2b7cdddF530eBf1BB25d8E` | 6 | Collateral of the binary markets | `exchange.trader.faucet()` | ## Price feed | Network | Endpoint | Constant | | --------------- | -------------------------------------------------------------------- | --------------------------- | | Somnia mainnet | `https://price-feed.prd.oracle.somnia.host/v1/graphql`, quote `USDC` | `SOMNIA_MAINNET_PRICE_FEED` | | Shannon testnet | `https://price-feed.dev.oracle.somnia.host/v1/graphql`, quote `USDC` | `SOMNIA_TESTNET_PRICE_FEED` | These are two separate deployments. Each one indexes the `PriceFeedScheduler` on its own chain. Use the feed that matches the chain the client runs on. A mainnet client that uses the testnet feed reads prices from chain 50312. The mainnet feed carries fewer symbols than the testnet feed. Code written for the testnet asset list can therefore fail on mainnet. Read the feed catalog to learn which bases exist. A base the feed does not carry returns no rows. It does not raise an error. ## Peer dependencies | Package | Range | Required | | -------------------------- | --------- | ----------------------------------------------- | | `viem` | `^2.18.5` | yes | | `react` | `>=18` | only for `@somnia-chain/markets-sdk/react` | | `@somnia-chain/reactivity` | `^0.2.1` | only for `@somnia-chain/markets-sdk/reactivity` | The package is published on the public npm registry from version 0.20.0. The chain transport uses the platform `WebSocket` where there is one, and the `ws` package on Node.js 20, which has none. --- # /docs/typescript/reference/symbols # Symbols This page describes the symbol grammar of the exchange API (`SomniaMarkets`). A symbol names a market; a tradable symbol names something an order can be placed on. Every method that takes a symbol also takes a raw chain reference. ## Grammar | Market kind | Market symbol | Tradable symbols | Example | | ---------------------- | --------------------------- | ----------------- | ---------------------------- | | Spot | `BASE/QUOTE` | the market symbol | `SOMI/USDso` | | Perp | `BASE/QUOTE:SETTLE` | the market symbol | `BTC/USDso:USDso` | | Binary | `ASSET-STRIKE-EXPIRY/QUOTE` | `…#YES`, `…#NO` | `BTC-95000-31DEC26/USDC#YES` | | Categorical (reserved) | `NAME/QUOTE` | `…#OUTCOME` | `US-ELECTION-28/USDC#TRUMP` | The part before `#` follows the conventions of exchange tooling such as ccxt. The `#OUTCOME` suffix is specific to this SDK. `UnifiedMarket.type` is `"spot"`, `"swap"` (a linear perp), `"binary"`, or `"categorical"` (reserved). ## Synthesis rules The SDK synthesises symbols from the indexed market row. - Token codes are the ERC-20 `symbol()` values, stripped to `[A-Za-z0-9.]`. Case is preserved: `USDso` and `USDC.e` keep their casing. - `STRIKE` is the strike as a decimal string with trailing zeros removed. A series market with strike `0` renders `0`, for example `ETH-0-04SEP26/tUSDC`. - `EXPIRY` is `DDMONYY` in UTC, for example `31DEC26`. An expiry that is not at 00:00 UTC appends `-HHMM`, for example `03JUL26-0930`. - A collision between two markets appends `-XXXX` to the base side, where `XXXX` is the last four hexadecimal digits of the market id, upper-cased. ## Raw references Every exchange-API method accepts, in place of a symbol: | Reference | Format | Resolves to | | -------------------- | ------------------------------------- | ----------------------- | | Pool address | 40 hexadecimal digits with `0x` | The market on that pool | | Market id | 40 or 64 hexadecimal digits with `0x` | The market | | BinaryMarket address | 40 hexadecimal digits with `0x` | The binary market | A binary market addressed without an outcome resolves to outcome 0, `YES`. ## Resolution `exchange.market(ref)` returns a `Tradable`: | Field | Type | Description | | -------------- | --------------------- | ------------------------------------------------ | | `market` | `Market` | The native market row. Narrow on `marketType`. | | `marketSymbol` | `string` | The market symbol, without outcome suffix. | | `symbol` | `string` | The tradable symbol. | | `outcome` | `string \| undefined` | `"YES"` or `"NO"` on binary markets. | | `outcomeIndex` | `number \| undefined` | `0` for YES, `1` for NO. | | `pool` | `Address` | The pool that receives orders for this tradable. | `market(ref)` throws `InvalidInputError` when: - a chain reference is unknown, including before `loadMarkets()` has run: `unknown market ref … — call loadMarkets() first`; - a symbol is unknown, including before `loadMarkets()` has run: `unknown symbol … — call loadMarkets() first`; - an outcome suffix is given on a spot or perp market: `… is a SPOT market — it has no outcomes`; - the outcome does not exist: `… has no outcome "X" (has: YES, NO)`. `exchange.symbols` lists every tradable symbol. `exchange.markets` maps market symbols to `UnifiedMarket` rows. Both are populated by `loadMarkets()`. ## Prices and sides per tradable Numbers are expressed in the tradable's own terms. - Spot and perp: price is quote per base; `buy` buys the base. - Binary `#YES`: price is the YES probability in `(0, 1)`; `buy` buys YES shares. - Binary `#NO`: price is the NO probability, `1 − YES`; `buy` buys NO shares. The conversion to the pool's YES-terms book is internal. `mintSet`, `burnSet`, and `redeem` take the market symbol or either tradable; they act on the market. --- # /docs/typescript/reference/units-and-scales # Units and scales This page lists every numeric convention the SDK uses, which surface uses it, and the helpers that convert between them. The exchange API (`SomniaMarkets`) speaks in human units. The engine (`SomniaMarketsClient`, the trader) and the indexer speak in raw integers. ## Amounts and prices | Convention | Type | Used by | Example | | --------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------------------------- | | Human units | `number` | Every `SomniaMarkets` method and struct | `10` shares, price `0.62` | | Raw token units | `bigint` on writes and chain reads; decimal `string` on indexer reads | `SomniaMarketsClient`, `Trader`, `Market` rows, every `info` payload | `620000n` for 0.62 with 6 decimals | A raw amount is scaled by the token's decimals. The scale differs per market kind: | Market kind | Quantity scale | Price scale | | ----------- | ----------------------------------------- | ------------------------------------------------------------------------------------------- | | Spot | `baseDecimals` of the pair | `quoteDecimals` of the pair (quote per one base) | | Perp | `baseDecimals` | `quoteDecimals` | | Binary | the selected market's collateral decimals | the same collateral decimals; one whole collateral unit prices a YES share at probability 1 | `SpotMarket.baseDecimals` and `quoteDecimals` come from the indexed row. Spot markets are not assumed to have 6 decimals: `SOMI/USDso` has 18 and 18, `WBTC/USDso` has 8 and 18. Binary collateral depends on the venue. The current deployment records show: | Network | Active binary venue collateral | Decimals | `oneCollateral` | | --------------- | ------------------------------ | -------- | --------------- | | Mainnet (5031) | USDso | 18 | `10n ** 18n` | | Shannon (50312) | tUSDC | 6 | `10n ** 6n` | | Hideki (50383) | tUSDC | 6 | `10n ** 6n` | These are current presets, not a rule for every market. A retired mainnet venue used six-decimal USDC.e. Custom venues may choose another token. Read the selected binary market's `quoteDecimals` from its indexed row; `baseDecimals` matches it. If only the `marketId` is available, `(await client.getMarketOnchain(marketId)).decimals` reads the collateral token scale. This method falls back to `DECIMALS` (6) only when the token lacks the `decimals()` view; other read failures throw. Verify a non-standard token's scale before writing. A binding without `indexerUrl` has no indexed `quoteDecimals`. With a known `marketId`, `getMarketOnchain(marketId)` supplies both `decimals` and `pool` for the chain-only order path. Omit `indexerUrl` for chain-only reads and writes; indexed discovery and history need an indexer. [Networks and endpoints](./networks-and-endpoints.md) lists the hosted indexers. Set `oneCollateral = 10n ** BigInt(decimals)`. Use `probabilityToPrice(0.62, decimals)` for a YES price and `fromHuman(10, decimals)` for an outcome quantity. `mintSet` and `burnSet` amounts also use raw collateral units. ### Grids | Field | Meaning | | ------------- | ---------------------------------------------------------------------------------------------- | | `tickSize` | Raw price step. `UnifiedMarket.precision.price` is the number of decimal places that step has. | | `lotSize` | Raw quantity step. `UnifiedMarket.precision.amount` is its decimal places. | | `minQuantity` | Raw minimum order quantity. `UnifiedMarket.limits.amount.min` is its human value. | `createOrder` aligns price and quantity to these grids before sending. A buy price rounds down, a sell price rounds up, a quantity rounds down. `priceToPrecision` and `amountToPrecision` round down for both sides. ### Conversion helpers All helpers are exported from the root entry and default `decimals` to `DECIMALS` (6). Pass the selected market's decimals for binary writes and displays. The default is only correct for a six-decimal market. | Helper | Signature | Behaviour | | ---------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `fromHuman` | `(human: number \| string, decimals?) => bigint` | Converts a human value to raw. A `number` with more fraction digits than `decimals` is rounded half away from zero: `fromHuman(0.1234567, 6)` is `123457n`. A `string` with at most `decimals` fraction digits is parsed exactly. Throws `InvalidInputError` on a non-finite number. | | `toHuman` | `(raw: bigint \| string, decimals?) => number` | Converts raw to a `number`. Not exact past about 15 significant digits; suitable for display. | | `toHumanString` | `(raw: bigint \| string, decimals?) => string` | Converts raw to an exact decimal string. | | `probabilityToPrice` | `(p: number, decimals?) => bigint` | A YES probability in `[0, 1]` to a raw YES price. Throws `InvalidInputError` outside the range, including `NaN`. | | `priceToProbability` | `(raw: bigint \| string, decimals?) => number` | A raw YES price to a probability. | | `balanceFloor` | `(raw: bigint, decimals?) => number` | The largest human value that converts back to at most `raw` through `fromHuman`. Spending `balanceFloor(raw)` never exceeds `raw`. | | `floorRawBalance`, `ceilRawAmount` | `(raw, decimals, quantum)` | Quantum-aligned floor and ceiling. | ## Basis points | Unit | Scale | Used by | | --------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Basis points (bps) | 1 bps = 0.01 % | Venue fees: `getMaxVenueFeeBps`, `MarketFees`, `getMaxLeverage` limits, `cexRateBps` in portfolio analytics | | Basis points × 1000 | 1,000 = 1 bps | Builder fees: `builderFeeBpsTimes1k` on order placement, `maxFeeBpsTimes1k` on `approveBuilder`, `getMaxBuilderFeeBpsTimes1k` | | Leverage in bps of 1× | 10,000 = 1.00×, 200,000 = 20× | Perp leverage: `getPerpLeverage`, `setPerpLeverage`, `getPerpMaxLeverage` | `5_000n` as `maxFeeBpsTimes1k` allows up to 5 bps. ## Fixed-point rates | Unit | Scale | Used by | | ---------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | Wad | 1e18 | SomniaLend health factor (`maxUint256` when the account has no debt); perp funding rates (`FUNDING_PRECISION`, `1_000_000_000_000_000_000n`) | | Ray | 1e27 | SomniaLend rates and indexes. `lendRayRateToApy(rateRay)` returns a `number` APY; `RAY` is `10n ** 27n`. | | Price feed | 1e18 (`PRICE_FEED_DECIMALS`) | Oracle index prices. `LivePrice.price` and `ema` are `number`; `raw` is the exact string. | A perp funding rate is a fraction per calculation window, 28,800 seconds (8 hours) on every live pool. `fundingRate8h`, `fundingRate1h`, `fundingRatePerInterval`, and `annualizedFundingRate` renormalise it. `UnifiedFundingRate.fundingRate` from `fetchFundingRate` is already per 8 hours as a `number`. ## Time | Unit | Used by | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unix seconds, as `string` | Indexer rows: `createdAt`, `lastTradeAt`, `placedAtTimestamp`, candle `bucketStart` | | Unix milliseconds, as `number` | Every `SomniaMarkets` struct (`timestamp`), `datetime` as ISO-8601; `since` parameters of `fetchTrades`, `fetchMyTrades`, `fetchOHLCV`; reactivity schedule timestamps | | Unix milliseconds, as `bigint` | Native `SomniaBlock` consensus timestamps | | Unix nanoseconds, as `bigint` | Order expiry: `expireTimestampNs` on `placeSpotOrder`, `placePerpOrder`, and the batch requests. The SDK default is about 50 years ahead. | Candle intervals: `CANDLE_INTERVALS` is `[60, 300, 900, 3600, 14400, 86400]` seconds. `TIMEFRAMES` maps the exchange strings `1m`, `5m`, `15m`, `1h`, `4h`, `1d` to those seconds. Price-feed candles use `1m`, `1h`, `1d` on the exchange and `M1`, `H1`, `D1` on the client. `UnifiedOHLCV` rows are `[ms, open, high, low, close, volume]`. On `fetchOHLCV` the last element is base volume. On `fetchPriceOHLCV` it is the number of oracle updates in the bucket, not volume. ## Struct conventions | Struct | Convention | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `UnifiedBalance` | `free === total` and `used` is `0` for spot and binary holdings. Funds locked in a resting order live in the pool, not the wallet, and do not appear. Perp collateral is locked in the MarginBank and does not appear either; `client.getMarginAccount(marginBank, account)` reads it. | | `UnifiedOrder.type` | Present only on the order `createOrder` returns. Absent on orders read from the indexer (`fetchOrders`, `fetchOpenOrders`, `watchOrders`): the pools do not emit the order type. | | `UnifiedStopOrder.type` | Always present: the stop registry emits it. | | `UnifiedOrder.id` | The pool's order id as a decimal string; the transaction hash when nothing rested. | | `info` | Structs that wrap a native row or write result carry the raw payload under `info`. Aggregate and tuple results such as `UnifiedBalance`, `UnifiedBalances`, and `UnifiedOHLCV` do not. | ## Identifiers | Identifier | Format | | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Order id | Decimal string on the exchange API (`UnifiedOrder.id`), on live-store rows, and on indexer rows; `bigint` on trader results and chain reads such as `getOwnOpenOrdersOnchain`. When nothing rested, `UnifiedOrder.id` falls back to the transaction hash. | | Fill id | `${blockNumber}_${logIndex}` | | Trade id in `MarketActivity` | `TRADE:` followed by the fill id | | ERC-6909 outcome id | `(pool << 72) \| (nonce << 8) \| outcomeIndex`; `outcomeId`, `decodeOutcomeId`, `marketKey` encode and decode it | | Market type tag | `bytes4`; `MARKET_TYPE_BINARY_V1` is `0x06c65d9f` | ## Order enumerations | Constant | Values | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `ORDER_TYPE` | `LIMIT: 0`, `FILL_OR_KILL: 1`, `MARKET: 2` (immediate-or-cancel), `POST_ONLY: 3` | | `SELF_MATCHING_OPTION` | `CANCEL_TAKER: 0` (SDK default), `CANCEL_MAKER: 1` | | `ORDER_KIND_SIDE` | `["BUY_YES", "SELL_YES", "BUY_NO", "SELL_NO"]`, indexed by the pool's `kind` | | `UnifiedOrderStatus` | `"open"`, `"closed"` (fully filled), `"canceled"` (explicit cancel, or an unfillable immediate-or-cancel remainder), `"expired"` | | `CreateOrderParams.timeInForce` | `"GTC"` (default), `"IOC"`, `"FOK"`, `"PO"` | --- # /docs/typescript/reference/read-tiers # Read tiers This reference lists the sources used by SDK reads, watches, and status accessors. Use it to budget startup dependencies and requests, and to decide whether a value is fresh enough for your application. [Architecture](../ARCHITECTURE.md) explains transport ownership. ## The tiers | Tier | Source and freshness | Startup requirements | Cost | | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Market live store | Main-indexer snapshot, or a chain seed on an opted-in watch, then applied chain events. Values reflect the last applied events, not a guarantee of the current head. | A market watch hydrates from the main indexer by default, and needs chain RPC for subscriptions and backfill. `watchMarket(pool, { seed: "chain", marketId })` seeds the book from the pool contract instead, so it starts with the main indexer unreachable. A user watch hydrates indexed history; live updates require watched markets. | Synchronous selectors make no requests. Cold hydration, backfill, ongoing subscriptions, and recovery have network cost. | | Chain | Chain RPC, normally over the owner's WebSocket. Reads reflect the blocks served by the node; a group of reads need not share one block. | A chain WebSocket endpoint and any method-specific contract addresses. | One or more RPC calls, sometimes cached or batched. Parallel calls do not guarantee one round-trip. | | Main indexer | Envio/Hasura GraphQL over HTTP. Values reflect indexed state and can lag the chain. | The main indexer endpoint; aggregate reads can require privileged headers. | One or more HTTP requests, depending on pagination and composition. No fixed freshness delay is guaranteed. | | Price-feed indexer and live price store | Separate price-feed Hasura service. HTTP reads and subscription updates reflect its indexed prices, not direct chain prices. | Price-feed HTTP configuration; watches also need its Hasura WebSocket endpoint. | Fetches make HTTP requests. Watches hydrate over HTTP in batched snapshot requests and share one Hasura socket per client and endpoint. Store selectors are synchronous and make no requests. | `indexerUrl` is optional: a caller that only uses chain reads (smart accounts included) constructs without one, and the main-indexer methods below then throw `NotConfiguredError`. Configuring it does not mean that every method requests the main indexer. The chain socket opens lazily on chain I/O. Price-feed transport and failures are separate from the market store. A result can combine tiers with different timestamps. The SDK does not generally compare indexed state with the current chain head to certify freshness. Check the method-specific inputs below before treating a derived value as current. ## Return contract - An indexer point read resolves to `null` when the row does not exist and throws `IndexerError` when the request fails. - An indexer list read resolves to `[]` when there are no rows and throws `IndexerError` when the request fails. - A chain read throws on failure. It never returns `null` in place of a failure. - A live-store read returns empty data for a market with no active watch. `getWatchStatus(pool)` is `"unwatched"` in that state. - The live store keeps market rows in bounded memory. It always keeps a market that a pool is bound to or that a retained fill or order names. It keeps up to 500 other market rows (released or replaced markets) and evicts the earliest-discovered ones first. An evicted market is absent from `getLiveMarkets` and `getLiveMarketByAddress`, and a late settlement event for it does not change the live store. Read it from the indexer (`getMarket`, `getBinaryMarket`). - A chain-seeded watch loads no fill history, so `getLiveFills` can be empty while the book is complete. `getLiveStatus().fillsLoaded` separates the two states: `false` means the history was never loaded, `true` means there are genuinely no fills in the loaded range. A failed fill read sets `failure.operation` to `"fill-history"` and does not empty the book. - Orders a chain seed writes carry an empty `createdAt` and `txHash`: placement history is indexer-only and the seed does not invent it. `userOrders` sorts on `createdAt`, so seeded orders sort LAST behind any order carrying a real placement timestamp. A chain-seeded pool is not re-snapshotted while the watch lives, so they stay undated for the store's lifetime; read placement history from the indexer. - The market row a chain seed writes carries only what the module answers. Indexer-only fields — `question`, `asset`, `oracleQuestion`, `strike`/`mode`, `tradingStart`, `intervalSec`/`interval`, `createdAtTimestamp`/`createdAtBlock`, `createdByTx`, the volume counters, and the origin attribution — are empty, `null` or zero and STAY that way: a seeded pool is not re-hydrated by a later watch, and the row outlives `stop()` until cold-market eviction drops it. Read the indexer directly (`getBinaryMarket`) when those fields are needed. `strike`/`mode` are `null` rather than `"0"`/`"reference"`, because a strike of 0 is the protocol's sentinel for an up/down market and would mislabel a fixed-strike one. - A chain seed never blanks a row the indexer already supplied. Inside the cold-market allowance the row outlives `stop()`, so a pool watched from the indexer first and chain-seeded later keeps each indexer-only field listed above, while every field the module answers — `status`, `backing`, `nonce`, `finalized`, `voided`, `winningOutcome`, `collateral`, the decimals and the token ids — takes the fresher chain value. - `getLiveStatus()` reports `seedSource` (`"indexer"`, `"chain"`, or `null` before the first watch), `seedBlock`, and `seedTruncated` for the MOST RECENT seed only. With several watched pools those values cannot be attributed to a pool: a later seed overwrites them, and `fillsLoaded` turns true when any pool's fill lane lands. Read `getSeedStatus(pool)` for one pool's own four fields; it is `null` when that pool has no hydrated watch. The indexer snapshot applies a PER-SCOPE order budget that is SHARED across the scope's pools, not a per-pool floor, and it drops the oldest resting orders first. A chain seed has no such cap; `seedTruncated` is `true` only when the drain reaches its own page budget. - `watchMarkets` selects markets by lifecycle, not by age. It hydrates every SPOT and PERP market and every BINARY market that is not finalized. A finalized BINARY market is left out of the watch. Read it with `getBinaryMarket(id)`. `watchMarket(pool)` applies no lifecycle filter, but it hydrates the market the pool serves now, so it hydrates a finalized market only until the pool is recycled. One snapshot hydrates at most 500 eligible markets, newest first. When more eligible markets exist, `getLiveStatus().allMarketsTruncated` is `true` while the all-markets watch is active, and the oldest eligible markets are not watched. Only the all-markets watch writes that field, so a later pool or chain seed does not reset it. - A live price read keeps answering with its last values after the server rejects the asset's subscription. `getPriceStatus(asset)` is `"error"` in that state, and the rejection is also emitted as a `warn` event on the debug channel. ## Exchange API (`SomniaMarkets`) | Method | Tier | | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `loadMarkets`, `fetchMarkets` | Indexer, plus chain reads for perp discovery and token symbols. Neither source's failure throws: the registry read reports through `registryReadError` and perp discovery through `perpDiscoveryError`, so one source being down still returns the other's markets. | | `fetchOrderBook` | Chain | | `fetchTrades`, `fetchOHLCV`, `fetchOpenOrders`, `fetchOrders`, `fetchMyTrades`, `fetchOpenStopOrders`, `fetchPortfolioAnalytics`, `fetchFundingRateHistory` | Indexer | | `fetchTicker` | Cached market metadata and main-indexer candles; on perps, also best-effort chain state. An EMPTY candle window falls `last` back to the cached market row, which stamps `lastSource` from that row's `lastTradeAt`; `lastSource` is absent only when `last` itself is absent or that timestamp is null. A candle request FAILURE is CONTAINED: `statsState` becomes `"unavailable"`, every 24h field is absent, and the call still resolves so the perp chain numbers survive. A market with `indexed: false` reports the same state and sends no candle request. `statsAsOf` carries the 24h window's own as-of; `timestamp` remains response time, not source freshness. A failed perp state read leaves candle-derived data and reports `perpState: "degraded"`. | | `fetchBalance` | Loads market/currency metadata through `loadMarkets`, then reads chain token/native balances and main-indexer binary holdings. Cost depends on currencies and metadata discovery. | | `fetchFundingRate` | Chain | | `fetchPositions` | Chain per position, but the call first awaits `loadMarkets`, so it depends on a loaded perp registry on the first call and on every call while the registry is empty. That registry is an INDEXER dependency only when no `addresses.perpPoolFactory` is configured: with one, `loadMarkets` discovers the perps from the factory on chain. Called with no refs, it returns positions only for the perps the registry loaded: a short perp set gives a silently short result, not an error. Explicit refs do not remove the dependency — `loadMarkets` is awaited either way — but they turn a silently short result into a loud `InvalidInputError` for a symbol the registry never loaded. | | `fetchPrice`, `fetchPriceOHLCV` | Separate price-feed Hasura HTTP | | `market`, `priceToPrecision`, `amountToPrecision` | Local | | `watchOrderBook`, `watchTrades`, `watchOrders`, `watchMyTrades` | Live store. The first call opens the market watch. | | `watchPrice` | Live price store. The first call opens the price watch. | A `watch*` call resolves with the current value on its first call and on every later call resolves when the channel's value changes. `unwatchMarket(symbol)` releases one market's watch and its channels. A pending `watch*` call on that market rejects with a `DOMException` named `AbortError`. The next `watch*` call opens a fresh watch. ## Engine (`SomniaMarketsClient`) The tables in this section are the canonical Engine inventory. Names refer to `exchange.client` (or `exchange.engineFor(chainId)` — `exchange.client` names no chain and throws `InvalidInputError` on an exchange spanning more than one), not similarly named Exchange methods. The inventory guard checks membership only; source and freshness claims require source review. Configuration, cleanup, escape hatches, and capability factories are outside this read inventory. ### Live store | Group | Methods | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Market selectors and status | `getLiveMarkets`, `getLiveMarketByPool`, `getLiveMarketByAddress`, `getLiveFills`, `getLiveUserFills`, `getLiveUserOrders`, `getLiveFundingUpdates`, `getLiveBinaryOrderBook`, `getLiveBinaryOrderBookByMarket`, `getLiveSpotOrderBook`, `getLiveStatus`, `getSeedStatus`, `getWatchStatus`, `isTailing`, `subscribeLive`, `listLiveLiquidations`, `listLiveFundingPayments`, `getPerpPlaneStatus` | | Price feed | `getLivePrice`, `getLivePrices`, `getLivePriceTicks`, `getLivePriceFeedInfo`, `getPriceStatus`, `subscribePrices` | | Watches | `watchMarket`, `watchMarkets`, `watchUser`, `watchPrice`, `watchPrices`, `watchPerpMarkets` | `getLiveUserOrders` keeps every unexpired open order, up to 400 recent unreferenced terminal orders per pool, and terminal orders needed by retained fills. Use `getOrders` for older order history. On-chain expiry emits no event, so each chain head is the retention checkpoint for expired orders. At the first head whose timestamp is strictly after an `Open` order's expiry, that order counts toward the 400-row cap. It keeps status `Open`: the chain holds its escrow until a cancel or a sweep, so removal from the live store does not mean a refund. An active `watchUser` keeps every expired open order of its user, including orders placed after the watch started, until the watch is released. A later cancel or sweep event for a removed order changes nothing. Accepted indexed `Closed` orders count toward the cap at hydration. Live `Closed` orders wait for a later block from the same pool so a delayed same-block `OrderRested` can still make them open. ### Chain | Group | Methods | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Books and orders | `getBinaryOrderBook`, `getSpotOrderBook`, `getOrderOnchain`, `getBookTopsOnchain`, `getOwnOpenOrdersOnchain`, `getOpenOrdersOnchain`, `getAllOpenOrdersOnchain` | | Markets and system | `getMarketOnchain`, `getPoolMarketBinding`, `getMarketIdOnchain`, `getContractMeta`, `getHeadBlock`, `getSystemInfo`, `getTransactionSummary`, `getPoolCreator`, `getFreePools`, `getOnchainResolutionPrice`, `getMaxVenueFeeBps`, `encodeBinaryVenueFeeParams` | | Balances and allowances | `getErc20Balance`, `getErc20Metadata`, `getErc20Allowance`, `getBalances`, `getNativeBalance`, `getOutcomeBalance`, `getVaultBalance`, `getOwnLockedBalance`, `getLockedTokenBreakdown` | | Operators and builders | `getOperatorPermissionsRegistry`, `isOperatorAuthorized`, `isGloballyApproved`, `isApprovedForPool`, `getMaxBuilderFeeBpsTimes1k`, `getBuilderApproval`, `getEffectiveBuilderApproval`, `getStopOrderSomiPayment`, `getPerpStopOrderSomiPayment`, `getPerpStopOrder`, `getPerpStopOrders`, `getUnclaimedPerpStopSomi`, `getManualVaultMode`, `getAutoPullRequirement`, `convertToQuoteAtPriceCeil` | | Perps | `getPerpState`, `getPerpFeedStatus`, `getPerpPosition`, `getMarginAccount`, `getAccountHealth`, `getLiquidationPrice`, `previewPerpLiquidationPrice`, `getPerpLeverage`, `getPerpPositionAnalytics`, `listPerpPositionAnalytics`, `getMaxPerpOrderSize`, `previewPerpOrderMargin`, `previewPerpClosePnl`, `getPerpSideHolders`, `getBankruptcyPrice`, `getPerpSystemConfig`, `getInsuranceFundState`, `getLiquidationEngineConfig`, `tryGetPerpAccountEquity`, `getPerpCollateralBasis`, `listPerpPoolStatuses`, `listTradeablePerpPools`, `isPerpPoolRegistered`, `getPerpRiskParams`, `getPerpHealthSnapshot`, `getEffectiveImfBps`, `getPerpMaxLeverage`, `getPerpLeverageImSurcharge`, `tryGetPerpLeverageImSurcharge`, `readPerpMarketFromChain`, `quotePerpFundingPayer`, `getPerpMainFunding`, `getPerpLinkedWalletRegistry`, `getPerpWalletPullCapacity`, `getPerpWalletLinkage`, `listPerpLinkedChildren`, `getPerpMaxLinkedChildren`, `getPerpVoucherCampaign`, `getPerpVoucherEligibility`, `getPerpVoucher`, `getPerpFundingPremium`, `meetsPerpImForFill`, `quoteMeetsPerpImForOrder`, `quotePerpOrderTopUp` | | Oracle hub | `getSchedulingCost`, `earmarkedOf`, `creditOf`, `outstandingOf`, `withdrawableOf`, `payerCreditOf`, `payerOf`, `resolveReserve`, `quoteCreateMarketValue` | | SomniaLend | `client.lend.listReserves`, `client.lend.getAccount` | | Smart accounts | `client.accounts.find`, `client.accounts.nextFreeIndex`, `client.accounts.ownersOf`, `client.accounts.custodyChain`, `client.accounts.authorityPath`, `client.accounts.tree`, `client.accounts.holdings`, `client.accounts.health`, `client.accounts.buildExecution` | ### Indexer | Group | Methods | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Markets | `listMarkets`, `listRegistryMarkets`, `listRegistryMarketsChecked`, `countMarkets`, `countMarketsBounded`, `getMarket`, `getMarketByPool`, `listMarketsByPool`, `listBinaryMarkets`, `listLiveBinaryMarkets`, `listPastBinaryMarkets`, `getBinaryMarket`, `getBinaryMarketByAddress`, `listBinaryVenueIds`, `listBinaryAssets`, `countBinaryMarkets`, `countBinaryMarketsBounded`, `listSpotMarkets`, `getSpotMarket`, `listPerpMarkets`, `getPerpMarket`, `getMarketFees`, `getMarketStatusHistory` | | History | `getCandles`, `getFills`, `getFill`, `getUserFills`, `countUserFills`, `getOrderFills`, `getOrder`, `getOrders`, `getOpenOrders`, `countOrders`, `getBookTops`, `listSweepableOrders`, `getMarketActivity`, `getTradeContext`, `getRouterActions`, [`getUserFillsPage`](fill-history-pages.md), `getFillsPage`, `getLatestFillBlock`, `getLatestActiveBlock` | | Portfolios | `getPortfolio`, `getSpotPortfolio`, `getPerpPortfolio`, `getOutcomeBalances`, `getSpotStopOrders`, `listPerpStopOrders`, `listPerpOrderHistory`, `listPerpPositions` | | Resolution | `getMarketResolution`, `listMarketResolutionEvents`, `listMarketReferenceLinks`, `getOpeningPrices`, `getResolutionPrices` | | Fees and perps history | `listProtocolFees`, `listBuilderFees`, `listSettlementFees`, `listBuilderApprovals`, `getVaultPayoutFallbacks`, `listVaultPayoutFallbacks`, `getFundingPayments`, `getMarginEvents`, `listLiquidations`, `getLiquidations`, `listFundingRateHistory`, `listFundingRateCandles`, `listPerpFees`, `getOpenInterestHistory`, `getFundingRateHistory`, `listPerpOrderRejections`, `listPerpInsuranceFundEvents`, `listPerpWalletLinkEvents`, `listPerpMarginPulls`, `listPerpMainFundingEvents` | | Control plane | `listOperators`, `getOperator`, `countOperators`, `listVenues`, `getVenue`, `countVenues`, `listMarketCreators`, `getMarketCreator`, `listOracleAdapters`, `getOracleAdapter`, `listSeries`, `listSeriesLatestMarkets`, `getSeries`, `getOracleQuestion`, `listOracleQuestions`, `getOperatorHubAccount`, `listOperatorHubAccounts`, `listOracleBinds`, `listOracleCallbacks`, `getSyncStatus`, `getPool`, `listPoolBindings` | ### Price-feed HTTP reads | Group | Methods | | -------------------------------- | ------------------------------------------------------------------- | | Current prices and feed metadata | `fetchPrice`, `fetchPrices`, `fetchPriceFeedInfo`, `listPriceFeeds` | | Price history | `fetchPriceHistory`, `fetchPriceCandles` | ### Mixed and derived reads | Inputs and behavior | Methods | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | | Main indexer plus a mandatory chain block timestamp lookup. The timestamp anchors indexed activity; it does not make indexed rows current. | `getBlockActivity`, `getAdjacentActiveBlocks` | | Main-indexer activity. Chain receipt and block lookups run only when no indexed event and no caller-supplied anchor place the transaction. Failure to obtain that anchor leaves the indexer order probe available. | `getTransactionActivity` | | Synchronous live binary book and stored market decimals. Needs a hydrated market watch for useful depth. | `quoteBinaryOrder` | | Live binary book plus cached chain tick/lot grid. A market-id target can add an indexer lookup when the store cannot resolve its pool. An empty live book is not replaced by an indexer book. | `quoteBinaryStake`, `quoteBinarySell` | | Chain grid read cached per pool for the client lifetime. Later administrative grid changes do not invalidate this cache. | `getBinaryBookParams` | | Chain closing-price view, including its capture state. | `getClosingPrice` | | Main-indexer candles; a market-id target also resolves its pool through the main indexer. | `getMarketStats24h` | | Main-indexer market metadata, fills, router actions, and outcome balances, plus chain book top for the mark clamp. Without configured chain access, uses indexed last price alone; an operational chain failure propagates. | `getBinaryPositionPnL` | | Main-indexer positions and market metadata, fills, and router actions, plus chain book tops for the mark, read at one pinned block. Without configured chain access, uses indexed last price alone; an operational chain failure propagates. This does not use the live book. | `getOpenPositionsWithPnL` | | Main-indexer positions and resolution data, plus indexed settlement fees for winning markets. This estimates claimable amounts from indexed state. | `getClaimable` | | Independent RPC head, then main-indexer metadata plus processed-block time. Raw measurements, no SDK stale threshold. An indexer more than 10,000 blocks past the head follows an earlier genesis of the chain id, so the read throws. | `getIndexerFreshness` | | Main-indexer metadata, polled until the target block. For the client's own chain, one RPC head read when the wait would resolve; an indexer more than 10,000 blocks past that head rejects the wait. Without configured chain access, the head read is skipped. | `waitForIndexedBlock` | | One independent head for response-associated reads, using the same owner. | `createObservedReads` | | Per-asset price watch lifecycle, without I/O. | `getPriceHealth`, `listPriceHealth` | ### Watch startup and updates Engine watches return a handle with `stop()`. Repeated handles for the same scope share its work. The scope normally remains for about 30 seconds after the last handle stops, so a quick remount can reuse it. After teardown, a new watch hydrates again. Market watches hydrate a main-indexer snapshot before chain backfill and live updates. `watchUser` hydrates the account's indexed order/fill history. It opens no subscription of its own. Subsequent account updates come only from market scopes watched by this client; it is not an account-wide chain subscription. Price watches hydrate metadata and recent prices from the separate price-feed HTTP service. Each asset key owns a Hasura socket for its price and tick subscriptions. A resolved watch means its snapshot landed, not that the socket has connected. Check `getPriceStatus` for state. Rejected subscriptions report `error`, while synchronous price reads retain stale values. These failures do not change market-watch status. ## React hooks | Hook family | Tier | | --------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `useLive*`, `useWatchMarket`, `useWatchUser`, `useLiveStatus`, `usePoolSeedStatus`, `useIsTailing` | Live store. The pool-keyed hooks open the market watch while mounted; `usePoolSeedStatus(pool)` reads one pool's seed state without opening a watch. | | `useLivePrice`, `useLivePriceTicks`, `useLivePriceFeedInfo`, `useWatchPrice` | Live price store | | `usePortfolio`, `useMarkets`, `useCandles`, `useFundingRateSeries`, `useMarketFees`, `useOperators`, `useMarketCreators`, `useOracleAdapters` | Indexer | | `useLendReserves`, `useLendAccount` | Chain | `useIndexerQuery` runs the supplied callback on mount, owner or dependency changes, and explicit `refetch`. It does not poll or automatically refresh on live events. The callback determines its source and freshness. The hook passes an abort signal and fences superseded responses; cancellation reaches the request only if the callback forwards that signal to an operation that supports it. Automatic hooks preserve background acquisition semantics: failures use the configured debug/console warning channel and do not throw during render. This includes `useFundingRateSeries`; its `state.error` still contains history query failures. Opt into `useWatchMarketResult`, `useWatchUserResult`, or `useWatchPriceResult` for a typed acquisition error, which a component may explicitly throw into an ErrorBoundary. Missing-provider validation still throws `InvalidInputError`. `SomniaMarketsProvider` accepts `chainSeedPools`, a fixed list of `{ chainId, pool }` for binary pools that must cold-start from chain. Every pool-watching React hook shares this choice, so effect order cannot choose the indexer seed first. The provider reads the current market binding via chain before opening a selected watch; the selected client must configure `addresses.binaryModule`. Remount the provider to change the list. Other pools use the normal indexer seed. The pool-specific `usePoolSeedStatus(pool, { chainId? })` returns `null` until that pool has seeded, then exposes `seedSource`, `seedBlock`, `seedTruncated`, and `fillsLoaded`. A chain-seeded book can be available with `fillsLoaded: false`; indexed history and market discovery still require the indexer. ## Response-associated indexer observations `client.createObservedReads()` observes one independent RPC head. Its `read` and `batch` methods accept the operations in `ObservedReadOperation`. The roster includes every ordinary main-indexer domain read, including mixed-tier derived reads. `getSyncStatus`, `waitForIndexedBlock` and `getIndexerFreshness` are source diagnostics, not row reads. Live-store reads, chain-only reads, write capabilities and the separate price service are excluded. The envelope keeps the domain value in `data`. `observation.latestProcessedBlock` is the minimum metadata watermark across successful contributing responses. Missing metadata in any response leaves it null. `startedAt`, `completedAt` and `responseCount` describe the observation span. The metadata is selected beside the rows in the same GraphQL request, without a separate metadata request. A rejected privileged aggregate attempt does not contribute; its successful fallback does. Observed portfolio reads refresh their scope inside the logical read so a cached pool set cannot hide an older contributing response. These are indexing watermarks. They do not claim each entity changed at that block, that the RPC itself is current, or that separate requests share an atomic historical snapshot. Keep an envelope with its value; later reads cannot update its observation. Create a new observed capability to refresh the shared head. Closing the owner cancels pending observations; a stopped capability cannot reopen transports. `fetchStatus()` remains a local-only three-field chain-tail snapshot. Opt into `fetchDataStatus()` to read RPC and the main indexer once. Its top-level `status` retains chain-tail meaning; `indexer` contains independent measurements and `prices` lists precise per-asset `health`. API-only monitors keep using `client.getSyncStatus(chainId)` with no RPC dependency. `client.waitForIndexedBlock(chainId, block)` polls the same metadata until the indexer has processed a block, so a caller can read its own write instead of guessing a delay. The concrete `exchange.client` exposes the additive `SomniaMarketsClientWithObservations` contract. `SomniaMarketsClient` includes `waitForIndexedBlock`, and order-list selections include `userData`. Custom `SomniaMarketsClient` implementations must provide the wait, and a serving indexer must expose `Order.userData`. Other ordinary reads retain their document selections and role permissions. Only observed reads select the response watermark. `stopLive()` invalidates observed capabilities and cancels pending indexed-block waits without aborting ordinary pending indexer reads; a later wait relinks to the replacement owner signal. Caller cancellation still reaches those reads. ### Consumer example Use the configured exchange in dreamDEX or another consumer. The downstream dreamDEX hook edit remains outside this repository. ```ts const observed = await exchange.client.createObservedReads(); const [markets, count] = await observed.batch([ { operation: "listMarkets", args: [{ limit: 20 }] }, { operation: "countMarkets", args: [] }, ]); console.log(markets.data, markets.observation.latestProcessedBlock); console.log(count.data, count.observation.independentHead.blockNumber); const freshness = await exchange.client.getIndexerFreshness(exchange.client.config.chain.id); console.log(freshness?.lagBlocks, freshness?.lagSeconds); ``` For a local end-to-end observation, start `./demo-clob.sh up`, construct the exchange with the local chain and deployment configuration used by the explorer, and run this example against `http://127.0.0.1:8085/v1/graphql` and `ws://127.0.0.1:8545`. Use chain id 31337. No production configuration or transaction is required. ## What still works when the main indexer is down This section tells you which SDK capabilities survive a main-indexer outage. Use it to plan degraded operation. It groups capabilities by what they need, not by method name. The tier tables above remain the per-method reference. Source-derived at `ebe97c4874b5394a3f9bc8cb2ccd9f46b1b1bda8`; no outage was induced. The scope is the main markets indexer. The price-feed service is a separate endpoint with its own configuration and its own failures, so a main-indexer outage does not stop `fetchPrice`, `fetchPriceOHLCV`, or the price watches. A chain RPC endpoint must still be reachable for everything in "Works on chain". ### Works on chain These reads need chain RPC only. They do not send a main-indexer request. One precondition applies to every UNIFIED verb below, the ones named `fetch*`. They take a symbol, and resolving a symbol reads the in-memory registry that `loadMarkets` fills from the indexer. So they answer during an outage only for markets loaded BEFORE it began; on a cold start they throw `InvalidInputError` for an unknown symbol. The Engine reads, which take a pool or market address, have no such precondition. | Capability | Methods | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | Order books | `getBinaryOrderBook`, `getSpotOrderBook`, `getBookTopsOnchain`; `fetchOrderBook` too, but only for a symbol the registry already loaded | | Own orders on chain | `getOwnOpenOrdersOnchain` (ids), `getOpenOrdersOnchain` (full rows, several pools, one block), `getOrderOnchain` (one order), `getAllOpenOrdersOnchain` | | Perp positions and state | `getPerpPosition`, `getPerpState`, `getMarginAccount`, `getAccountHealth`, `getLiquidationPrice` | | Balances | `getErc20Balance`, `getNativeBalance`, `getBalances`, `getOutcomeBalance`, `getVaultBalance` | | Markets and system by id | `getMarketOnchain`, `getSystemInfo`, `getHeadBlock`, `getContractMeta`, `getPoolCreator` | | Pool to market binding | `getPoolMarketBinding`, `getMarketIdOnchain` | | Settlement and provenance | `getSettlement`, `poolCreator` | | Cancel every resting order | `cancelAllOrders` (default `source: "chain"`) | `cancelAllOrders` is the kill switch. Its default source reads the caller's resting order ids from the pool contract, so it works with the main indexer down. Two limits apply. The method belongs to `Trader` and acts on one pool, and the unified facade has no equivalent verb. The caller must therefore already hold the pool address: spot pool discovery by symbol is indexer-only, so a cold start during an outage cannot resolve one. ### Works from the live store while a watch is live A hydrated watch keeps answering from its store, because its updates arrive over chain subscriptions. - `getLive*` selectors, including `getLiveUserOrders`, `getLiveFills`, and the live order books. - `cancelAllOrders({ source: "live" })`. This mode throws `NotConfiguredError` unless the watch covering the pool is live. A watch that is still hydrating or is reconnecting is not live. A binary watch can also START with the main indexer down. Call `watchMarket(pool, { seed: "chain", marketId })`, which seeds the book from the pool contract. It covers one pool per call, so N pools need N calls. Read the `marketId` that call needs with `getPoolMarketBinding(pool)`, which is also chain-only, so the whole cold start needs no main-indexer request. The discover-all watch cannot start, because it has no binding list to seed from. ### Unavailable by design These capabilities are main-indexer reads. They throw `IndexerError` while it is unreachable. Absence of data is never substituted for the failure. - All history: candles, fills, fees, funding payments, liquidations, and market activity. - `getOpenOrders` and the other indexed order reads. - Portfolios and PnL: `getPortfolio`, `getSpotPortfolio`, `getPerpPortfolio`, `getBinaryPositionPnL`, `getOpenPositionsWithPnL`, `getClaimable`. - The discover-all watch, `watchMarkets`. - Every freshness surface: `getSyncStatus`, `getIndexerFreshness`, and `fetchDataStatus`. `fetchStatus()` is local and still answers. - On an exchange with two or more chains, `fetchDataStatus` resolves when some chains fail. It reports each failed chain's error in `indexerErrorByChain`, and it throws only when every chain fails. ### One whole-call failure One unified method fails completely, although part of its result comes from chain. Use the substitute instead. `fetchTicker` used to belong here. Its candle read is now contained, so the call resolves with `statsState: "unavailable"` and still reports the perp chain numbers. | Method | Why it fails | Substitute | | -------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------- | | `fetchBalance` | `getPortfolio` runs inside `Promise.all` with no catch. | Use `getErc20Balance`, `getNativeBalance`, or `getBalances` for the chain-held balances. | --- # /docs/typescript/reference/errors # Errors This page lists the error classes the SDK throws, the fields each carries, and the contract error names the SDK decodes into `ContractRevertError`. For the decision logic that goes with them, see [Handle errors and reverts](../how-to/handle-errors.md). Every SDK error extends `SomniaMarketsError`, sets `name` to its class name, prefixes its message with `@somnia-chain/markets-sdk: `, and carries the underlying failure in `cause` when it wraps one. ## Classes All classes are exported from the root entry. `FillHistoryRestartRequiredError` is returned by `getUserFillsPage` when a continuation belongs to a replaced serving dataset or is a legacy cursor without a generation. Its readonly `cursorGeneration` and `servingGeneration` fields identify the mismatch; legacy cursors report `"legacy"` as `cursorGeneration`. Discard accumulated pages and [restart from page one](fill-history-pages.md); retrying the old cursor cannot succeed. `FillHistoryUnavailableError` means the serving indexer has not initialized `FillDataset/current`. Deploy and reindex a compatible producer. Retrying the same deployment cannot make the contract appear. | Class | Fields | Meaning | Retrying the same call | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SomniaMarketsError` | none | Base class. | depends on the subclass | | `InvalidInputError` | `chainIds?: readonly number[]` | The call cannot proceed: unknown symbol or reference, unknown timeframe, a method used on the wrong market kind, an amount below one lot, a limit order without a price, a market order against an empty opposite side, a probability outside `[0, 1]`, or a non-finite amount. Most cases are local validation. The empty-book market-order case follows a chain book read and depends on current liquidity. `chainIds` is set when a call names no chain on a multi-chain exchange (`exchange.client`, `exchange.trader`) and when `createReactivity` gets a wallet on another chain. | fails again, except an empty-book market order may succeed after liquidity appears | | `NotConfiguredError` | `what: string` | The client lacks a URL or address the feature needs: `indexerUrl`, `wsRpcUrl`, `priceFeed`, or an entry of `addresses`. Thrown at the first call that needs it, never at construction — a client built without an indexer still serves every chain-backed capability (smart accounts, executors, on-chain reads) and refuses indexer reads and live watches by feature. | fails again | | `SignerRequiredError` | `operation: string` | An authenticated method was called without a `privateKey`, `account`, `walletClient`, or `executor`. Authenticated methods include `fetchBalance`, `fetchOpenOrders`, `fetchOrders`, `fetchMyTrades`, `fetchPositions`, `watchOrders`, `watchMyTrades`, `exchange.trader`, and every write. | fails again | | `CollateralOnWrongChainError` | `chainId`, `code`, `needed`, `held`, `shortfall`, `elsewhere`, `plan?` | The order's collateral sits on another configured chain | Bridge the shortfall, then retry | | `BridgeLiquidityError` | `token`, `from`, `to`, `router`, `amount`, `available` | A native bridge route (STT) pays out of the destination router's own balance, and that balance is below the amount. `exchange.bridge.transfer`, `exchange.ensureFunds`, and `createOrder(…, { funding: "auto" })` read it first and send nothing. | Retry after seeding, bridge at most `available`, or fund another way | | `BridgeDeliveryTimeoutError` | `messageId`, `bridgeHash`, `from`, `to`, `token`, `amount` | `exchange.ensureFunds` or `createOrder(…, { funding: "auto" })` sent the bridge leg, but the destination Mailbox did not process its message within the delivery timeout. The funds are in flight. `exchange.bridge.transfer` resolves with `delivered: false` and the same `messageId` instead of throwing. | Call `delivered(messageId)` on the destination Mailbox before you bridge again | | `IndexerError` | `operation: string` | An indexer request did not complete: endpoint down, bad URL, HTTP error, GraphQL error, or the 30-second request timeout. Never means "no such row". | may succeed | | `IncompleteHistoryError` | `operation`, `reason`, `pagesRead`, `maxFillPages?` | Portfolio analytics could not traverse all indexed fills: the caller's page budget ended or the cursor cycled. No partial PnL is returned. | Increase or omit the budget; investigate a cursor cycle. | | `IndexerUnavailableError` | `reason: IndexerRefusalReason`, `retryAfterMs: number`, `consecutiveFailures: number` | The SDK refused the read locally. `reason` says which gate refused: `breaker-open` (repeated endpoint failures — timeouts or HTTP 429/502/503/504 — opened the breaker), `breaker-trial` (the cooling period ended and another read is the trial), `queue-full` (this client already has `maxQueued` reads waiting), or `live-reset` (`stopLive()` reset live reads while it queued or backed off). For the first three, nothing reached the network; if a gate refuses a retry after an earlier attempt was sent, the read fails with that attempt's `IndexerError` instead. `retryAfterMs` is meaningful only for `breaker-open` and is `0` for the rest. A subclass of `IndexerError`, so existing `instanceof IndexerError` handling still catches it. | Branch on `reason`: sleep `retryAfterMs` for `breaker-open`, retry shortly for `breaker-trial`, back off on your own schedule for `queue-full`, and retry `live-reset` on the same client | | `FillHistoryUnavailableError` | `operation: string` | The serving indexer has no initialized fill-dataset generation. | requires a compatible producer deployment and reindex | | `FillHistoryRestartRequiredError` | `cursorGeneration: string`, `servingGeneration: string` | A fill-page cursor belongs to a different serving generation or predates generation binding. | requires a fresh first page without the old cursor | | `IndexerWaitTimeoutError` | `targetBlock: number`, `latestProcessedBlock: number \| null`, `timeoutMs: number`, `waitedMs: number`, `polls: number` | The indexer did not reach the requested block before the wait deadline. The fields report the target, last observed processed block (or `null`), deadline, elapsed time and metadata polls; unlike `IndexerError`, the indexer answered but remained behind. | Retry with a longer deadline or handle the lag before reading. | | `RpcError` | `operation: string` | A JSON-RPC or WebSocket request did not complete: connection refused, 4-second request timeout, dropped subscription, unsupported method. From a write, it can also mean that the node refused the transaction (nonce too low, insufficient funds). Only the local-signer and session-key executors guarantee that nothing was sent otherwise; see [Handle errors](../how-to/handle-errors.md). | a read may succeed; a write may succeed after you fix the refusal | | `TransactionOutcomeUnknownError` | `chainId: number`, `operation: string`, `hash?` | A write signed a transaction that may have reached the node, and the SDK did not observe its receipt: the sync send timed out or its socket dropped, the receipt wait failed, or a session send lost its answer. The transaction can still mine. `hash` is absent only for a session send. A subclass of `RpcError`, so existing `instanceof RpcError` handling still catches it. | do not retry blindly: look up `hash` (or read the state the write changes) first, because a retry can execute the write twice | | `ContractRevertError` | `errorName?`, `args?`, `reason?`, `data?`, `address?`, `functionName?` | The chain rejected the call. Thrown on send-time rejection, pre-send simulation, a mined receipt with failed status, and `eth_call` reads. | fails again unless state changes | | `InvariantError` | none | The SDK contradicted an invariant that its own control flow had established. It indicates an SDK defect, not invalid caller input. | not applicable; report the SDK defect | Errors from code the SDK calls but does not own can surface unchanged. This includes a `walletClient` supplied by the app and the client returned by `getViemClient()`. Debug sink failures are different: the SDK contains them so diagnostic code cannot break an operation. ### `ContractRevertError` fields | Field | Type | Present when | | -------------- | -------------------- | -------------------------------------------------------------- | | `errorName` | `string` | The revert data matched a custom error in `contractErrorsAbi`. | | `args` | `readonly unknown[]` | `errorName` is set. Positional decoded arguments. | | `reason` | `string` | The revert carried a `require` or `revert` string. | | `data` | `string` | The node returned revert data. | | `address` | `string` | The reverting contract is known. | | `functionName` | `string` | The called function is known. | A mined transaction with `status: "reverted"` carries no revert data. The SDK replays the call as `eth_call` at the receipt's block to recover `errorName` or `reason`. When the replay yields nothing, the error is still a `ContractRevertError` and its message ends with `(no revert data recoverable)`. `decodeRevert(caught)` is exported for callers who send transactions themselves. It walks the `cause` chain, decodes the first revert data it finds against `contractErrorsAbi`, and always returns a `ContractRevertError`. It does not check that the input is a revert: a transport error passed to it returns a `ContractRevertError` without `errorName`. ## Absence versus failure | Outcome | Indexer point read (`get*`) | Indexer list read (`list*`) | Chain read | Live-store read | | -------------- | --------------------------- | --------------------------- | ------------------------------------------------------------------ | ------------------------------ | | Row exists | the row | the rows | the value | the value | | No such row | `null` | `[]` | throws `ContractRevertError` or returns the contract's empty value | `[]`, `null`, or an empty book | | Request failed | throws `IndexerError` | throws `IndexerError` | throws `RpcError` or `ContractRevertError` | not applicable | ## Contract error names `contractErrorsAbi`, exported from the root entry, is the generated ABI of every custom error the protocol contracts declare. `ContractRevertError.errorName` is one of its names. The names the exchange API and the trader raise most often: | Area | Error names | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Order validation | `InvalidPrice`, `InvalidQuantity`, `PriceNotAlignedToTickSize`, `QuantityNotAlignedToLotSize`, `QuantityBelowMinimum`, `PriceOutOfBounds`, `PriceTooLarge`, `TooManyRestingOrders` | | Market state | `TradingNotActive`, `UseBinaryPlacement`, `MarketRestricted`, `MarketNotSettled`, `NotFinalized`, `StaleMarketId` | | Order lifecycle | `OrderDoesNotExist`, `IncorrectSender` (a cancel of an order the caller does not own, including an order already cancelled), `OrderAlreadyExpired`, `ExpiredOrderMustBeCancelled`, `NotExpired`, `OrderExpiryBeyondMarket` | | Time in force | `PostOnlyWouldCross`, `FillOrKillNotFillable`, `ImmediateOrCancelNoFill`, `SelfMatchCancelTaker` | | Amend and batch | `AmendOldOrderGone`, `AmendReplacementRejected`, `EmptyOrderBatch`, `BatchTooLarge`, `LengthMismatch` | | Funds | `InsufficientBalance`, `InsufficientVaultBalance`, `ExceedsWithdrawableBalance`, `ERC20InsufficientAllowance`, `ERC20InsufficientBalance`, `InvalidMsgValue`, `NativeAmountMismatch` | | Builder fees | `BuilderNotApproved`, `BuilderFeeExceedsApproval`, `BuilderFeeExceedsCap`, `InvalidBuilder` | | Binary settlement | `NothingToClaim`, `AlreadyClaimed`, `NothingOwed`, `AlreadyFinalized`, `OracleNotAnswered`, `QuestionNotFinal` | | Perps | `NoOpenPosition`, `InsufficientMargin`, `InsufficientMarginForOrder`, `InsufficientMarginAfterWithdrawal`, `MaxPositionSizeExceeded`, `OpenInterestCapExceeded`, `InvalidLeverage`, `MarkPriceUnavailable`, `OraclePriceStale`, `NotLiquidatable`, `PerpPoolNotRegistered` | | Stop orders | `InvalidTriggerPrice`, `LimitPriceIncompatibleWithTrigger`, `InsufficientSomiPayment`, `TriggerTooCloseToEma`, `RefundFailed` | | Operators and venues | `OperatorDisabled`, `OperatorNotActive`, `UnknownOperator`, `UnknownVenue`, `VenuePolicyDenied`, `InsufficientPermission`, `Unauthorized`, `NotOwner` | | Test collateral | `FaucetCapExceeded` | The full list is longer and changes with the contracts. Read it from `contractErrorsAbi` in the installed version. --- # /docs/typescript/explanation/about-the-exchange-instance # About the exchange instance This page discusses why the SDK has one constructible object, `SomniaMarkets`, and what that decision buys and costs. It covers ownership of connections, state, and signers. It does not cover the internals of the live watches; those are in [Architecture](../ARCHITECTURE.md). ## One root, no globals Many chain SDKs expose a set of free functions and a global configuration step: set the RPC once, then call anything from anywhere. This SDK does not. `new SomniaMarkets(config)` creates an instance, and every capability hangs off it: the exchange verbs, the engine at `exchange.client`, the trader at `exchange.trader`, the SomniaLend namespace at `exchange.client.lend`. Nothing that needs a connection is reachable without an instance. The root entry exports only the class, types, pure helpers, constants, and ABIs. The reason is isolation. An instance owns its configuration, its WebSocket, its live store, its watches, its approval cache, its signer, and its local-send queue. Two instances share none of those execution resources. Nonce state is one of them. Each engine owns one nonce lane, and a multi-chain exchange has one engine per chain. Two exchanges that sign with the same key on the same chain keep separate lanes and do not coordinate, so their concurrent writes can take the same nonce. Share one long-lived exchange per signing account per chain. A multi-chain bot configures one exchange with `chains`. Each chain has its own socket, nonce lane, and fee settings. A server reuses one long-lived exchange. An indexer-only request may use a short-lived instance because it never opens a socket. A test suite runs cases in parallel with one exchange each. With module-level state, each of those needs a workaround. The cost is one line of plumbing. A React app constructs the exchange once at module scope and passes `exchange.client` to the provider. A script constructs it at the top. There is no `configure()` call to forget and no hidden singleton to reason about. ## Sockets opened late Each configured chain has an engine with an indexer HTTP endpoint and a chain WebSocket. That socket carries log and head subscriptions, `eth_call` reads, and transaction sends. Reads on the same engine share its socket. A configured price feed uses separate GraphQL HTTP and WebSocket connections. Each chain socket opens on that engine's first chain operation. Each price-feed socket opens on its first price watch. Construction and indexer-only reads do not open these sockets. A missing `wsRpcUrl` or chain WebSocket endpoint raises `NotConfiguredError` on the first chain operation. `close()` releases owned connections across all engines; see Lifecycle below. You can think of the instance as a small local node for the markets you care about. It hydrates a snapshot of a market from the indexer once, then follows the chain itself. After that the indexer is only asked for history. ## The signer belongs to the instance A signer is part of the configuration: `privateKey`, `account`, or `walletClient` — or, at the engine tier, any `Executor` (`createTrader({ executor })`), which is how a smart account trades. The instance derives `walletAddress` from it and uses it for every authenticated verb, read or write. `fetchBalance` and `watchOrders` are authenticated reads: they answer for the signer's address without taking an address parameter. That mirrors how exchange APIs behave, and it is why `SignerRequiredError` is thrown by reads as well as writes. Browser apps rarely have a signer at boot. `setSigner()` exists for them: construct the exchange for public reads, bind the wallet when the user connects, and pass `{}` on disconnect. Watches and market data are unaffected by a signer change; only the trader is rebuilt. An alternative would have been per-call signers, as in `createOrder(symbol, …, { signer })`. That design keeps the instance stateless but pushes the approval cache to the caller, and the cache needs to be per-signer to be correct. Holding the signer in the instance keeps it correct by construction. The trade-off is that one instance trades as one account; an app that trades as several accounts constructs several instances or calls `setSigner` between them. ## Lifecycle `close()` releases the watches, the streaming channels, and every socket and timer the instance opened, including the WebSocket to the node. That includes a socket that is still connecting: `close()` ends its handshake, and nothing retries it afterwards. A Node script that has touched the chain exits on its own once `close()` returns. The instance stays usable afterwards: a later read opens a new connection, and a later `close()` releases that one too. A viem client you took from `getViemClient()` belongs to the connection it came from. After `stopLive()` or `close()`, its requests reject with viem's `SocketClosedError`, so call `getViemClient()` again for a working one. `unwatchMarket(symbol)` releases one market and keeps the instance open. Use it when a consumer moves from one market to the next, for example in a rotating binary series. It stops that market's watch and drops its streaming channels. A pending `watch*` call on the market rejects with a `DOMException` named `AbortError`. The next `watch*` call on the market opens a fresh watch. The client keeps the market's live data for about 30 seconds after the release, then drops its orders and fills. Without this call, the instance holds every market it has watched until `close()`. Each instance owns its own socket, even when two instances use the same WebSocket URL. Closing one instance never affects another, and never affects a socket your own application opened through viem. Still prefer a long-lived instance over one per server request: each instance holds a socket, a market cache, and local order-book state. ## Where the design shows through - `exchange.client` is the engine, not a second client. It shares the store and the socket with the exchange, so a live book read through a hook and through `watchOrderBook` are the same data. - `exchange.client.getViemClient()` returns the underlying viem client for anything the SDK does not cover. It is deliberately undecorated: errors from it are viem's, not the SDK's, and it opens the socket if it is not open yet. --- # /docs/typescript/explanation/about-symbols-and-human-units # About symbols and human units This page discusses two choices in the exchange API: markets are addressed by symbols such as `SOMI/USDso`, and quantities are decimal numbers rather than integers scaled by token decimals. Both choices trade exactness for familiarity, and the SDK keeps the exact values within reach. The grammar itself is in the [Symbols reference](../reference/symbols.md) and the scales in [Units and scales](../reference/units-and-scales.md). ## Why symbols Spot and perp markets use a pool address as their identity. A binary market has a stable `marketId` and a `BinaryMarket` contract address; its pool address can be [reused by later markets](./binary-pool-recycling.md). These identifiers are exact, but they mean little to a human reading a log line or a config file. Exchange tooling answered this question years ago: a market is `BASE/QUOTE`, a derivative carries its settlement currency after a colon, and a bot's configuration lists symbols. The exchange API adopts that grammar so that code written against ccxt-style venues transfers with little change. The design intent is that the verbs never change again: a new market kind is new data (a `type`, an `outcomes` list), not a new API. Binary markets have no precedent in that grammar. Each market has two things you can trade, YES and NO, and each needs its own price and its own side of the book. The SDK's answer is the `#OUTCOME` suffix: `BTC-95000-31DEC26/USDC#YES` and `…#NO` are two tradables on one market. A market symbol without a suffix resolves to YES, so callers who only think in YES terms can ignore the suffix entirely. The cost of synthesised symbols is that they are derived, not stored. Two markets can render the same symbol, for example two series markets with the same asset and expiry. The SDK breaks the tie deterministically with a four-hex-digit suffix from the market id. That keeps the mapping one-to-one, but it means a symbol can carry a suffix a human did not expect. For that reason every method also accepts the raw pool address or market id in place of a symbol. ## Why human units On chain, a quantity is an integer scaled by the token's decimals, and a binary price of 0.62 is `620000` when the collateral has six decimals. Correct code must carry the decimals with every number, and most bugs in trading code are decimals bugs. The exchange API takes and returns JavaScript numbers in the tradable's own terms: 10 shares at 0.62, 1 SOMI at 0.5 USDso. The SDK converts at the boundary using the decimals it already knows from the market row. The caller never sees a raw integer unless they ask for one. A NO price is the NO probability. The pool keeps a single book in YES terms, and a NO bid at 0.38 is a YES ask at 0.62 on chain. The SDK presents each outcome's own view (prices, sides, and candles are outcome-relative) and performs the complement internally. A caller who buys NO at 0.38 reasons about NO at 0.38. ## What it costs, and how the SDK pays A JavaScript number holds about 15 significant digits. An 18-decimal token amount does not fit. The conversion helper used for display, `toHuman`, is documented as lossy for that reason, and `toHumanString` exists for exact rendering. On the way in, `fromHuman` rounds a value with too many fraction digits rather than throwing. We judged that a computed mid price almost always has too many digits and that rejecting it would hurt more than rounding. A caller who needs exactness passes a string. The exchange structs that wrap a native row or result carry that payload under `info`. An order's `info` is the placement result with the receipt and the decoded fills in bigint. A market's `info` is the indexed row with `tickSize`, `lotSize`, and the token addresses. Aggregate and tuple results such as `UnifiedBalance`, `UnifiedBalances`, and `UnifiedOHLCV` do not have `info`. The engine at `exchange.client` preserves each backend's exact representation: chain reads and writes use bigint, while indexer and live-store numeric fields such as prices and quantities are decimal strings. The SDK aligns prices and quantities to the venue's tick and lot grids before it sends an order, and never against the caller. A buy price rounds down, a sell price rounds up, a quantity rounds down. The returned order echoes the aligned values. This is where the human-unit design most visibly diverges from what the caller typed. It is why the reference says to read `price` and `amount` back from the result rather than assuming the inputs. ## The alternative we did not take A `bigint`-only exchange API would be exact and would match the engine's chain boundary. We judged that it would also reproduce the decimals bugs it exists to remove: every caller would carry `baseDecimals` and `quoteDecimals` through their own code, and the ccxt idiom the API borrows would be lost. A decimal library would be exact and readable, but it would make the SDK impose a number type on every consumer. The chosen design keeps the surface familiar and keeps exactness one property access away. ## Where the protocol shows through Two conventions in the structs are protocol facts that the human-unit layer cannot hide, and the [Units and scales reference](../reference/units-and-scales.md#struct-conventions) records them. Wallet balances report `free === total`, because locked funds sit in the pool rather than the wallet. Orders read back from the indexer have no `type`, because the pools do not emit it. In both cases the SDK reports what it knows rather than guessing. --- # /docs/contracts/raw-integration # Raw Smart-Contract Integration Somnia Markets runs three market families on one on-chain order-book engine: **spot** pairs (`SpotPool`), **binary markets** (`BinaryPool`), and **perps** (`PerpPool`). All three extend the same shared `OrderBook` core, so the placement surface, the order-lifecycle events, and the book-materialization technique are identical across every book; what differs per family is discovery, funding/escrow, and settlement. This guide is how to trade with nothing but an RPC node and the contract ABIs — any language, any stack. It covers the shared core first, then each family in turn, then [materializing a live local order book](#materialize-the-order-book-from-events) from the event stream. Pair it with [Market Making](./MarketMakingTips.md) if you are building a quoting system. (Building a JS/TypeScript app instead? The [SDK](../../../packages/sdk/README.md) wraps everything here.) What you need to start: contract addresses and signatures. Protocol contracts (the `BinaryMarketsModule` market registry, the `MarketsCore` control plane, the `OutcomeToken6909` singleton) are listed live per network on this explorer's [System page](/system); spot pairs and live binary markets are listed on the [markets page](/); per-market binary addresses are read from the module's registry on-chain ([below](#binary-markets)). The complete Solidity interfaces — everything needed to generate ABIs — are in the [interface reference](#interface-reference) at the end of this guide. ## The shared order-book core Binary books take orders through `placeBinaryOrder` instead (see [the order kind](#one-book-two-outcomes-the-order-kind)). Spot and perp books expose the same placement entrypoint, covering all order types (GTC / `NormalOrder`, `FillOrKill`, `ImmediateOrCancel`, `PostOnly`): ```solidity function placeOrder( bool isBid, uint64 userData, uint256 price, uint256 quantity, uint64 expireTimestampNs, OrderType orderType, SelfMatchingOption selfMatchingOption, address builder, uint96 builderFeeBpsTimes1k ) external payable returns (bool success, OrderId id); ``` - **`expireTimestampNs` is mandatory and nanoseconds** — a future unix-ns timestamp (`now_seconds * 1e9 + lifetime_ns`); zero or past values are rejected. There is no "no expiry" sentinel. - **A rejected order reverts.** A single-order placement does not return `success == false`; it reverts with a typed error. A `PostOnly` that would cross reverts `PostOnlyWouldCross`. A `FillOrKill` that cannot fill in full reverts `FillOrKillNotFillable`. An IOC that fills nothing reverts `ImmediateOrCancelNoFill`. A self-match under `CancelTaker` reverts `SelfMatchCancelTaker`. An expiry in the past reverts `OrderAlreadyExpired`. Decode the revert data to choose a recovery. The batch calls handle a rejection differently (see [Batch writes](#batch-writes)). - **Quantize in integers.** `getOrderBookParameters()` returns `tickSize`, `lotSize`, and `minQuantity` in raw token units; off-grid values revert `InvalidPrice` / `InvalidQuantity`. - **`builder` / `builderFeeBpsTimes1k`** attribute the order to a routing/builder frontend and pay it a per-order fee (basis-points × 1000). Pass `(address(0), 0)` for none. A non-zero fee requires the order owner to have opted the builder in first — `approveBuilder(builder, maxFeeBpsTimes1k)` on the pool (0 revokes) — and is capped by the pool's `getMaxBuilderFeeBpsTimes1k()`; charges emit `BuilderFeeCharged`. Spot, binary and perp pools all accept builder values; an unapproved non-zero fee reverts `BuilderNotApproved` (spot), `BuilderFeeExceedsCap` (binary) or `BuilderFeeExceedsApproval` (perp). - `cancelOrder(id)` / `reduceOrder(id, newQty)` manage resting orders; both revert (rather than no-op) on already-terminal orders — check your local book or `getOrder(id)` first. `cancelExpiredOrders(ids)` and `sweepExpiredAtLevel(isBid, price, maxCount)` are permissionless cleanup — the SDK's `client.listSweepableOrders({ pool?, marketType? })` is the work-list for both, returning `orderId` / `isBid` / `price` per row. Note it is **not** `status: "Expired"`: that status means the order was already swept, whereas a keeper wants orders still `Open` whose expiry has passed. - `OrderId`s are unique **per pool** — always key by `(pool, orderId)`. Reading any book on demand, via `eth_call`: | View | Returns | |---|---| | `getBookLevels(isBid, numLevels)` | Aggregated `(price, quantity)` levels, best first | | `getAllOpenOrdersOffChain(isBid, maxCount, startCursor)` | Full `Order` structs, paginated (`msg.sender` must be `address(0)` — the `eth_call` default) | | `getOrder(orderId)` / `getOwnOpenOrders()` | Single order / caller's open ids | Polling these is fine for a dashboard; a trading system should take one snapshot and apply event deltas — see [materialization](#materialize-the-order-book-from-events). ### Batch writes A quoting loop often changes several orders at once. Spot and perp pools accept these changes in one transaction. Binary pools reject `placeOrders` and `amendOrders` with `UseBinaryPlacement`. - `placeOrders(requests)` places each request in array order and returns `(successes, ids)`, aligned with `requests`. A request that the book rejects when it lands (a PostOnly that would cross, a FillOrKill or IOC that cannot fill, a self-match under `CancelTaker`, or an expiry in the past) does not revert the call: its flag is `false`, its id is `0`, and the other requests still apply. Any other failure reverts the whole batch, for example an off-grid price (`InvalidPrice`) or a request that the owner cannot fund. - `cancelOrders(orderIds)` returns one flag per id. It returns `false` for an order that is no longer live, where `cancelOrder` reverts. - `reduceOrders(requests)` applies one `(orderId, newQuantityRemaining)` reduction per request. - `amendOrder(request)` re-quotes the resting order `oldOrderId` with the terms in `newOrder`, in one transaction. Use the id that it returns: it can be different from `oldOrderId`. A failed amendment reverts with an error that names the reason, for example `PostOnlyWouldCross` or `AmendOldOrderGone`. - `amendOrders(requests)` amends several orders in one transaction. Deployed pools do not all report a failed request in the same way. Some pools revert the whole batch: `AmendReplacementRejected(requestIndex, reason)` for a rejected replacement, or `AmendOldOrderGone` for an old order that is no longer live. Other pools return id `0` for that request and apply the other requests. Handle both results: catch the revert, and check every returned id. On every pool, a failure that is not a rejection, for example an off-grid price, reverts the whole batch. - An empty array reverts `EmptyBatch`. - The batch calls are not `payable`. A native-token amount that a batch order needs must already be in your vault balance on that pool (`depositNative`). ### Operator keys A market maker often holds funds in one key and signs orders with a second key. Spot and perp pools support this split through an operator registry. Binary pools do not (see [Market Making](./MarketMakingTips.md)). 1. Read the registry address from the pool with `getOperatorPermissionsRegistry()`. 2. From the owner key, give the operator key the function selectors that it can call. `setOperatorApprovalForPool(pool, operator, selectors, true)` covers one pool. `setOperatorApprovalGlobal(operator, selectors, true)` covers every official pool. `setOperatorDenialForPool` removes one pool from a global grant. 3. From the operator key, call the `…For` entry points with the owner's address: `placeOrderFor(owner, …)`, `cancelOrderFor(owner, orderId)` and `reduceOrderFor(owner, orderId, newQuantityRemaining)`. The selector to grant is the selector of that function: `0x80054449` for `placeOrderFor`, `0xe37b444b` for `cancelOrderFor`, `0x364c2587` for `reduceOrderFor`. The batch and amend operator entry points use the same grants. `placeOrdersFor` needs the `placeOrderFor` grant, `cancelOrdersFor` needs the `cancelOrderFor` grant, and `reduceOrdersFor` needs the `reduceOrderFor` grant. `amendOrderFor` and `amendOrdersFor` need both the `placeOrderFor` and the `cancelOrderFor` grants. The order belongs to the owner, so its funds and its proceeds are the owner's. A call without a grant reverts `OnlyApprovedContracts`. Read a grant from the pool with `isOperatorAuthorized(owner, operator, selector)`. Two rules need care: - A global grant is broad. On the testnets it also covers every perp pool, so a global `placeOrderFor` grant lets the operator open leveraged positions for the owner. Grant per pool to keep an operator on one market. - On a perp pool, an order that the operator sends does not top up margin from the owner's wallet. Keep the owner's MarginBank balance funded (see [Perps](../../../packages/sdk/docs/PERPS.md)). ## Spot markets Each trading pair is its own `SpotPool` — live pairs are listed on the [markets page](/). `getPoolParams()` returns everything static in one call: `(baseToken, quoteToken, makerFeeBpsTimes1k, takerFeeBpsTimes1k, tickSize, minQuantity, lotSize)`. A native-token side is reported as a sentinel token address (not `address(0)`) — resolve it from `getPoolParams` rather than assuming. Spot semantics are the conventional ones: `isBid = true` buys base with quote, a fill is a base ↔ quote swap at the **maker's** resting price, and `userData` is a free 64-bit tag echoed back on the order struct and its `OrderPlaced` event. Use it for strategy/generation ids. **Funding.** By default the pool **auto-pulls** the required input from your wallet at placement (ERC-20 `transferFrom` after a one-time approval, or `msg.value` on native pools) and **auto-delivers** proceeds back on fill, cancel, or expiry. Size the pull with `getAutoPullRequirement(owner, isBid, price, quantity, builderFeeBpsTimes1k)`. High-churn integrations should opt out with `setManualVaultMode(true)`: `deposit` once, quote against the vault balance with no per-order token transfers, `withdraw` when rebalancing — for a loop that places and cancels constantly the gas savings compound. **Mark price.** Spot pools push `MarkPriceUpdated(asset, markPrice, rawMidpoint)` whenever the book midpoint advances — an EMA-smoothed midpoint plus the raw `(bestBid + bestAsk) / 2`, an on-chain fair-price feed with no extra infrastructure. ## Binary markets ### Discover markets `BinaryMarketsModule` is the market registry (the `MarketsCore` control plane holds only operators, venues, and module bindings — no markets). Each market is a `MarketRecord` (read via `module.markets(marketId)`): | Field | Use | |---|---| | `pool` | The `BinaryPool` — the order book you trade on | | `market` | The `BinaryMarket` — lifecycle + resolution state | | `collateral` | The ERC-20 quoted against (one per market) | | `originOperatorId` / `originVenueId` | Origin attribution: the uint32 operator id + opaque bytes32 venue id the market was created under | | `yesId` / `noId` | ERC-6909 ids of the outcome positions on the shared `OutcomeToken6909` singleton | | `tradingStart` / `expiry` | Trading window (unix seconds) | Watch the module's `MarketCreated` event to discover new markets — **every** market fires it, whether created directly via `createMarket` or rolled by a venue's `MarketCreator` (venues run rolling series — hourly up/down and similar — that create markets continuously), and it is the only creation event carrying the `(operatorId, venueId)` origin. `marketId` is a module-scoped counter (`bytes32(++marketSeq)`) that doubles as the CREATE2 salt — unique by construction, not precomputable before the create tx. `module.marketIdByAddress(addr)` is the reverse lookup. Every market carries an immutable kind tag, `IMarket.marketType()`. This section describes **`BINARY_SINGLE_BOOK`** — the only kind live today. Future kinds (dual-book, multi-outcome) will carry different tags and different book semantics: branch on the tag, never on assumptions. Lifecycle: `Listed → Trading → Locked → (Settling) → Resolved | Voided` (`BinaryMarket.StatusChanged`, plus `Resolved` / `Voided`). Orders are only accepted while the market reports Trading — placement reverts `TradingNotActive` otherwise. Cancellation stays open through `Locked`; `redeem` opens at `Resolved` / `Voided`. ### One book, two outcomes: the order kind Each `BinaryPool` runs a **single** order book. Place an order with `placeBinaryOrder` and name its kind: | `OrderKind` | Value | Book side | Locks at placement | |---|---|---|---| | `BUY_YES` | `0` | bid | collateral | | `SELL_YES` | `1` | ask | YES tokens | | `BUY_NO` | `2` | ask | collateral | | `SELL_NO` | `3` | bid | NO tokens | A binary pool rejects `placeOrder`, `placeOrders`, `amendOrder` and `amendOrders` with `UseBinaryPlacement`. `userData` is the last argument of `placeBinaryOrder` and is a free 64-bit tag, as on spot: the pool stores it and does not read it. `placeBinaryOrder` takes no native value; a non-zero `msg.value` reverts `UnexpectedNativeDeposit`. The NO book is price-inverted so the base matcher can cross the two books without knowing about outcomes: a NO order is submitted at the YES-side complement, `price = oneCollateral − noPrice`, where `oneCollateral = 10 ** collateral.decimals()`. All prices must satisfy `0 < price < oneCollateral`, because a share can never be worth more than one collateral unit. A price at or above `oneCollateral` reverts `PriceOutOfBounds`, and a zero price reverts `InvalidPrice`. ### Escrow and funding Placement escrows worst-case value up front: - **BUY orders** (`BUY_YES`, `BUY_NO`) lock collateral (ceil-rounded `price × quantity` in the order's own frame). The pull is **vault-first**: free vault balance is consumed before `transferFrom` on your wallet — so `collateral.approve(pool, …)` once per pool. (There is no auto-pull/manual-vault toggle here; this is the only mode.) - **SELL orders** (`SELL_YES`, `SELL_NO`) lock the outcome tokens themselves, pulled from your ERC-6909 balance on the singleton — call `outcomeToken.setOperator(pool, true)` once; it covers every market, since ids are namespaced by pool. Money flows back through two channels worth knowing: - **Refunds land in your vault balance** — taker surplus (you locked at your limit price, filled at a better maker price) and cancel/reduce/expiry refunds credit the pool vault, not your wallet. Because placement is vault-first, a quoting loop recycles these automatically; `withdraw(collateral, amount)` only when rebalancing. Read it with `getWithdrawableBalance(owner, collateral)`. - **Fill proceeds deliver wallet-first with vault fallback** — if the wallet transfer fails the pool credits the vault and emits `PayoutFallbackToVault`. Inventory comes from complete sets: `module.mintCompleteSet(operatorId, venueId, marketId, amount)` turns `amount` collateral into `amount` YES + `amount` NO (`setOperator(module, true)` once for the merge/redeem directions; `operatorId`/`venueId` are routing attribution only — pass `0` / `bytes32(0)` for none); `mergeCompleteSet(operatorId, venueId, marketId, amount)` is the inverse; `redeem(operatorId, venueId, marketId, outcomeIdx, amount)` burns the winning side 1:1 after resolution (or either side at 1/2 on void). You can also call the pool's `mintSet` / `burnSet` / `redeem` directly. Note you often need **no inventory at all** to quote — see the fill paths below. On a **resolved** market (never a voided one), the pool skims the venue's frozen `settlementFeeBpsTimes1k` ONCE from the whole winning backing when the first winning redeem lands (emitting `SettlementFeeCharged(feeRecipient, winningBacking, fee)`); every winner then redeems for `1 − fee` per token. Per-fill maker/taker fees (`ProtocolFeeCharged`) and the per-order builder fee (`BuilderFeeCharged`) are the other two fee rails — all rates are frozen into the pool at creation from the origin venue's config and readable via `getBinaryPoolParams()`. ### The four fill paths Two opposite-kind orders crossing settle by one of four paths (dispatched on the unordered pair of order kinds): | Crossing pair | Path | Settlement | |---|---|---| | `BUY_YES × SELL_YES` | DIRECT_YES | YES ↔ collateral swap | | `SELL_NO × BUY_NO` | DIRECT_NO | NO ↔ collateral swap | | `BUY_YES × BUY_NO` | MINT_A_PAIR | Both pay collateral; pool mints a fresh pair, one side each (emits `SetMinted`) | | `SELL_YES × SELL_NO` | BURN_A_PAIR | Both escrows burned as a pair; each seller paid their share (emits `SetBurned`) | The fill price on `OrderFilled` is always the **maker's** resting price, in the YES frame; the NO-side display price is `oneCollateral − fillPrice`. There is no on-chain "fill kind" field — consumers derive it from the two orders' kinds — the SDK exports [`sideOfKind`](/docs/typescript/api/index/functions/sideOfKind) (the YES/NO side of a resting order, from the pool's `BinaryOrderPlaced(orderId, kind)` event) and [`fillKind`](/docs/typescript/api/index/functions/fillKind) for exactly this derivation. `getOrderInfo(orderId)` exposes the binary-side escrow state per order (`lockedCollateral` / `lockedOutcome`, kind). ## Perps `PerpPool` extends the same `OrderBook` core, so everything in [the shared core](#the-shared-order-book-core) and [materialization](#materialize-the-order-book-from-events) carries over unchanged. On top it adds margin accounting, funding, and liquidations — with `FundingUpdated` / `OpenInterestUpdated` events, and a dedicated `MakerOrderCancelledExceedsPosition` removal event (a maker order erased pre-fill because it would breach the owner's position limit — treat it as a removal in a book reducer). Perp markets are live on testnet (see [Perps](../../../packages/sdk/docs/PERPS.md)). [Batch writes](#batch-writes) and [operator keys](#operator-keys) work on perp pools as on spot pools, with the differences listed in those sections. ## Materialize the order book from events Every book mutation emits an event, so one pinned snapshot plus the log stream reproduces the full book — for **any** of the three families. This is exactly how the protocol's own indexer and the SDK's live watches work — the reducer below is the same one they run (see [Architecture](../../../packages/sdk/docs/ARCHITECTURE.md) for the SDK's implementation of it). ### Snapshot, then stream 1. Pin a block `N` (`eth_blockNumber`). 2. Snapshot both sides with `getAllOpenOrdersOffChain` **at block `N`** (pass the block tag explicitly so pagination pages are mutually consistent). Drop orders whose `expireTimestampNs` has already passed. 3. Stream the pool's logs from `N + 1` (`eth_subscribe("logs")` over WSS, or an `eth_getLogs` loop) and apply them strictly in `(blockNumber, logIndex)` order. ### The event reducer Keep a map `orderId → Order` plus per-side level aggregates: | Event | Action | |---|---| | `OrderPlaced(orderId, placedOrder)` | Cache the struct; do **not** insert. Fires for every accepted order — `placedOrder.quantityRemaining` is already the **post-match residual** (the matcher runs before the event), so zero remaining means it fully filled on entry. | | `OrderRested(orderId)` | Insert the cached order into the book. This is the **only** insert signal. | | `OrderFilled(takerId, makerId, qty, takerRem, makerRem, fillPrice)` | Patch the **maker**: remaining = `makerRem`, remove at zero. Ignore the taker leg — its state arrives on its own `OrderPlaced`/`OrderRested` later in the same tx. | | `OrderReduced(orderId, newQuantity)` | Set remaining = `newQuantity` (not a fill). | | `OrderCancelled(orderId)` / `OrderExpired(orderId)` | Remove (idempotently). | | `OrderCancelledSelfMatch(orderId)` | Remove — a same-owner resting maker erased by a `CancelMaker` self-match. | | `OrderCancelledPreFill(orderId)` | Remove — a resting maker pulled by a pre-fill guard before it could fill. The matching loop emits it for **every** pre-fill removal, so handling it covers every present and future guard. | Family extras, none of which mutate book state: spot pools also emit `MarkPriceUpdated` (fair-price telemetry); binary pools emit `SetMinted` / `SetBurned` / `Redeemed` / `SettlementFeeCharged` (outcome-supply / settlement telemetry — mint-a-pair and burn-a-pair fills emit the first two alongside `OrderFilled`) and `BinaryMarket.StatusChanged` (leaves Trading → no new fills, only cancels from here); perp pools add `MakerOrderCancelledExceedsPosition`, `MakerOrderCancelledNegativeEquity` and `MakerOrderCancelledStaleMark`, which **do** mutate the book — treat all three as removals. They are reason tags emitted alongside the base `OrderCancelledPreFill`, so a reducer that handles the base event alone already removes the order. Ordering inside a placement tx: settlement hooks and one `OrderFilled` per matched maker fire **first**, then the taker's `OrderPlaced` (already residual-adjusted), then `OrderRested` iff the residual rested. A reducer that only inserts on `OrderRested` handles this for free. ### The sharp edges - **Self-match removals have their own event.** With `SelfMatchingOption.CancelMaker`, the matcher erases the same-owner resting maker and emits `OrderCancelledSelfMatch(orderId)` (on every book — spot, binary, perp). Handle it as a removal or your reducer carries a phantom order whenever *any* trader self-crosses with `CancelMaker`. With `CancelTaker` the incoming order is rejected instead: a single-order placement reverts `SelfMatchCancelTaker`, and `placeOrders` returns `false` for that request. - **Expiry is lazy.** Matching walks past expired makers without cleanup; `OrderExpired` only fires later (owner's next placement, or the permissionless sweeps). Prune locally the moment `expireTimestampNs` passes — an expired order can never fill — and treat the eventual event as a no-op. - **Make removals idempotent.** Between local pruning and the several removal paths, "remove an already-absent order" must be a no-op. - **Stream gaps.** On WSS reconnect, backfill the missed range with `eth_getLogs` before resuming. Somnia blocks have instant BFT finality, so a delivered log is final and no reorg handling is needed; the SDK's own live tail does none. If you still want a guard, treat a parent-hash discontinuity as a reason to re-snapshot rather than to unwind. ## Track your own orders and fills Both order-id parameters on `OrderFilled` are indexed topics, so you can filter your fills by the ids your `placeOrder` or `placeBinaryOrder` calls returned (or `getOwnOpenOrders()` after a restart). Alert on `PayoutFallbackToVault` — a delivery to your wallet failed and the proceeds are parked in your vault balance. Reconcile funds with `getWithdrawableBalance(owner, token)` and, on binary markets, `outcomeToken.balanceOf(owner, yesId | noId)` for positions. ## Interface reference ABI-faithful excerpts of every function and event used in this guide, taken from the deployed contracts. Admin/venue-governance entrypoints are omitted; external interface types (`IERC20`, adapters) are shown as `address` — the ABI encoding is identical. ### Shared order-book core (every pool) ```solidity type OrderId is uint128; enum OrderType { NormalOrder, FillOrKill, ImmediateOrCancel, PostOnly } enum SelfMatchingOption { CancelTaker, CancelMaker } struct Order { OrderId orderId; bool isBid; address owner; uint64 userData; uint256 price; uint256 fullQuantity; uint256 quantityRemaining; uint64 expireTimestampNs; } struct OrderBookLevel { uint256 price; uint256 quantity; } struct OrderBookParameters { uint256 tickSize; // min price increment, raw quote/collateral units uint256 minQuantity; // min order quantity, raw base units uint256 lotSize; // min quantity increment, raw base units } interface IOrderBook { event OrderPlaced(OrderId indexed orderId, Order placedOrder); event OrderRested(OrderId indexed orderId); event OrderFilled( OrderId indexed takerOrderId, OrderId indexed makerOrderId, uint256 quantityFilled, uint256 takerRemainingQuantity, uint256 makerRemainingQuantity, uint256 fillPrice ); event OrderCancelled(OrderId indexed orderId); event OrderCancelledSelfMatch(OrderId indexed orderId); event OrderExpired(OrderId indexed orderId); event OrderReduced(OrderId indexed orderId, uint256 newQuantity); event OrderBookParametersUpdated(OrderBookParameters newParameters); function placeOrder( bool isBid, uint64 userData, uint256 price, uint256 quantity, uint64 expireTimestampNs, OrderType orderType, SelfMatchingOption selfMatchingOption, address builder, uint96 builderFeeBpsTimes1k ) external payable returns (bool success, OrderId id); function cancelOrder(OrderId orderId) external; function reduceOrder(OrderId orderId, uint256 newQuantityRemaining) external; function cancelExpiredOrders(OrderId[] calldata orderIds) external; function sweepExpiredAtLevel(bool isBid, uint256 price, uint256 maxCount) external returns (uint256 cleaned); function getOrder(OrderId orderId) external view returns (Order memory); function getOwnOpenOrders() external view returns (OrderId[] memory); function getBookLevels(bool isBid, uint64 numLevels) external view returns (OrderBookLevel[] memory); function getOrderBookParameters() external view returns (OrderBookParameters memory); // eth_call only — msg.sender must be address(0) function getAllOpenOrdersOffChain(bool isBid, uint256 maxCount, uint64 startCursor) external view returns (Order[] memory orders, bool hasMoreOrders, uint64 nextCursor); } // The per-user vault, inherited by every pool. interface IVault { function deposit(address token, uint256 amount) external; function depositNative() external payable; function withdraw(address token, uint256 amount) external; function getWithdrawableBalance(address owner, address token) external view returns (uint256); } // Rejections of a single-order placement (every pool). error OrderAlreadyExpired(); error SelfMatchCancelTaker(); error PostOnlyWouldCross(); error FillOrKillNotFillable(); error ImmediateOrCancelNoFill(); ``` ### Batch writes and operator entry points (spot and perp pools) ```solidity struct PlaceOrderRequest { bool isBid; uint64 userData; uint256 price; uint256 quantity; uint64 expireTimestampNs; OrderType orderType; SelfMatchingOption selfMatchingOption; address builder; uint96 builderFeeBpsTimes1k; } struct ReduceOrderRequest { OrderId orderId; uint256 newQuantityRemaining; } struct AmendOrderRequest { OrderId oldOrderId; bool alwaysPlace; PlaceOrderRequest newOrder; } // IOrderBook, continued. interface IOrderBook { // Batch writes and amend. None of them is payable. function placeOrders(PlaceOrderRequest[] calldata requests) external returns (bool[] memory successes, OrderId[] memory ids); function cancelOrders(OrderId[] calldata orderIds) external returns (bool[] memory cancelled); function reduceOrders(ReduceOrderRequest[] calldata requests) external; function amendOrder(AmendOrderRequest calldata request) external returns (OrderId newOrderId); function amendOrders(AmendOrderRequest[] calldata requests) external returns (OrderId[] memory newOrderIds); // Called by an operator key for `owner`. function placeOrderFor( address owner, bool isBid, uint64 userData, uint256 price, uint256 quantity, uint64 expireTimestampNs, OrderType orderType, SelfMatchingOption selfMatchingOption, address builder, uint96 builderFeeBpsTimes1k ) external payable returns (bool success, OrderId id); function cancelOrderFor(address owner, OrderId orderId) external; function reduceOrderFor(address owner, OrderId orderId, uint256 newQuantityRemaining) external; function placeOrdersFor(address owner, PlaceOrderRequest[] calldata requests) external returns (bool[] memory successes, OrderId[] memory ids); function cancelOrdersFor(address owner, OrderId[] calldata orderIds) external returns (bool[] memory cancelled); function reduceOrdersFor(address owner, ReduceOrderRequest[] calldata requests) external; function amendOrderFor(address owner, AmendOrderRequest calldata request) external returns (OrderId newOrderId); function amendOrdersFor(address owner, AmendOrderRequest[] calldata requests) external returns (OrderId[] memory newOrderIds); } // Declared on both ISpotPool and IPerpPool. interface ISpotPool { function getOperatorPermissionsRegistry() external view returns (address); function isOperatorAuthorized(address owner, address operator, bytes4 selector) external view returns (bool); } interface IOperatorPermissionsRegistry { function setOperatorApprovalForPool(address pool, address operator, bytes4[] calldata selectors, bool approved) external; function setOperatorApprovalGlobal(address operator, bytes4[] calldata selectors, bool approved) external; function setOperatorDenialForPool(address pool, address operator, bytes4[] calldata selectors, bool denied) external; function isApproved(address owner, address operator, bytes4 selector, address pool) external view returns (bool); } error EmptyBatch(); error AmendOldOrderGone(OrderId oldOrderId); error AmendReplacementRejected(uint256 requestIndex, uint8 reason); // on pools where amendOrders reverts the whole batch error OnlyApprovedContracts(); error UseBinaryPlacement(); // a binary pool, on placeOrder, placeOrders and amend ``` ### SpotPool additions ```solidity interface ISpotPool /* is IOrderBook, IVault */ { event MarkPriceUpdated(address indexed asset, uint256 markPrice, uint256 rawMidpoint); event ManualVaultModeUpdated(address indexed user, bool enabled); event PayoutFallbackToVault(address indexed owner, address indexed token, uint256 amount); function setManualVaultMode(bool enabled) external; function getPoolParams() external view returns ( address baseToken, address quoteToken, uint256 makerFeeBpsTimes1k, uint256 takerFeeBpsTimes1k, uint256 tickSize, uint256 minQuantity, uint256 lotSize ); function getManualVaultMode(address user) external view returns (bool enabled); function getAutoPullRequirement( address owner, bool isBid, uint256 price, uint256 quantity, uint96 builderFeeBpsTimes1k ) external view returns (address inputToken, uint256 requiredAmount, uint256 delta); function getMidpointEmaState() external view returns (uint256 emaValue, uint64 lastUpdateNs); } ``` ### BinaryPool additions ```solidity enum OrderKind { BUY_YES, SELL_YES, BUY_NO, SELL_NO } struct BinaryPoolOrderInfo { OrderId orderId; uint256 lockedCollateral; // BUY escrow (mutually exclusive with lockedOutcome) uint256 lockedOutcome; // SELL escrow uint8 outcomeIdx; // 0 = YES, 1 = NO bool isBuy; address builder; uint96 builderFeeBpsTimes1k; } struct BinaryPoolInfo { address collateralToken; address market; address outcomeToken; uint256 yesId; uint256 noId; uint256 oneCollateral; // 10 ** collateral.decimals() uint256 setBacking; address feeRecipient; uint256 makerFeeBpsTimes1k; uint256 takerFeeBpsTimes1k; uint256 maxBuilderFeeBpsTimes1k; uint256 settlementFeeBpsTimes1k; } interface IBinaryPool /* is IOrderBook, IVault */ { event BinaryOrderPlaced(OrderId indexed orderId, OrderKind kind); event SetMinted(address indexed payer, address indexed yesTo, address indexed noTo, uint256 amount); event SetBurned(address indexed holder, uint256 amount); event Redeemed( address indexed holder, address indexed to, uint8 outcomeIdx, uint256 amountBurned, uint256 collateralOut ); // Fee rail: per-fill protocol fees, per-order builder fees (opt-in via // approveBuilder), and the one-time settlement fee on the winning backing. event ProtocolFeeCharged( OrderId indexed orderId, address indexed recipient, address indexed token, uint256 amount, bool isTakerSide ); event BuilderApproved(address indexed user, address indexed builder, uint256 maxFeeBpsTimes1k); event BuilderFeeCharged(OrderId indexed orderId, address indexed builder, address indexed token, uint256 amount); event SettlementFeeCharged(address indexed feeRecipient, uint256 winningBacking, uint256 fee); event PayoutFallbackToVault(address indexed owner, address indexed token, uint256 amount); // The placement entrypoint for binary pools. `price` is the YES-side price // for every kind. A non-zero msg.value reverts UnexpectedNativeDeposit. function placeBinaryOrder( OrderKind kind, uint256 price, uint256 quantity, uint64 expireTimestampNs, OrderType orderType, SelfMatchingOption selfMatchingOption, address builder, uint96 builderFeeBpsTimes1k, uint64 userData ) external payable returns (bool success, OrderId id); function approveBuilder(address builder, uint256 maxFeeBpsTimes1k) external; function getMaxBuilderFeeBpsTimes1k() external view returns (uint256 maxFeeBpsTimes1k); function getBuilderApproval(address user, address builder) external view returns (uint256 maxFeeBpsTimes1k); function getEffectiveBuilderApproval(address user, address builder) external view returns (uint256 maxFeeBpsTimes1k); function mintSet(address yesTo, address noTo, uint256 amount) external; function burnSet(uint256 amount) external; function redeem(uint256 amount, uint8 outcomeIdx, address to) external returns (uint256 collateralOut); function collateralToken() external view returns (address); function outcomeToken() external view returns (address); function outcomeId(uint8 outcomeIdx) external view returns (uint256); function market() external view returns (address); function setBacking() external view returns (uint256); function getBinaryPoolParams() external view returns (BinaryPoolInfo memory info); function getOrderInfo(OrderId orderId) external view returns (BinaryPoolOrderInfo memory info); } error UseBinaryPlacement(); // placeOrder, placeOrders or amend on a binary pool error UnexpectedNativeDeposit(); // msg.value on placeBinaryOrder error PriceOutOfBounds(); // price at or above oneCollateral ``` ### BinaryMarketsModule (the market registry) ```solidity enum VoidPolicy { UNIFORM, AMM_SNAPSHOT } // AMM_SNAPSHOT is a dead legacy slot enum MarketType { BINARY_SINGLE_BOOK, BINARY_DUAL_BOOK, NATIVE_MULTI } interface IBinaryMarketsModule { event MarketCreated( bytes32 indexed marketId, address indexed market, address indexed pool, uint256 oracleQuestionId, uint32 operatorId, bytes32 venueId, address creator, address collateral, uint256 yesId, uint256 noId, uint8 outcomeSlotCount, MarketType marketType, uint64 tradingStart, uint64 expiry, VoidPolicy voidPolicy, string asset, uint256 strike, // 0 for reference-mode markets (no fixed strike) string question, bytes context ); function markets(bytes32 marketId) external view returns ( uint256 oracleQuestionId, uint8 outcomeSlotCount, VoidPolicy voidPolicy, address collateral, uint32 originOperatorId, bytes32 originVenueId, address oracleAdapter, address creator, address market, address pool, uint256 yesId, uint256 noId, uint64 tradingStart, uint64 expiry ); function marketIdByAddress(address market) external view returns (bytes32 marketId); // operatorId / venueId are routing attribution only (0 / bytes32(0) = none). function mintCompleteSet(uint32 operatorId, bytes32 venueId, bytes32 marketId, uint256 amount) external; function mergeCompleteSet(uint32 operatorId, bytes32 venueId, bytes32 marketId, uint256 amount) external; function redeem(uint32 operatorId, bytes32 venueId, bytes32 marketId, uint8 outcomeIdx, uint256 amount) external; } ``` ### BinaryMarket (lifecycle) and the outcome-token singleton ```solidity enum MarketStatus { Listed, Trading, Locked, Settling, Resolved, Voided } interface IBinaryMarket { event StatusChanged(MarketStatus indexed oldStatus, MarketStatus indexed newStatus); event Resolved(uint8 indexed winningOutcome); event Voided(); function marketType() external view returns (MarketType); function tradingActive() external view returns (bool); function isResolved() external view returns (bool); function isVoided() external view returns (bool); function winningOutcome() external view returns (uint8); } // ERC-6909 subset. One singleton for all markets; id = (uint160(pool) << 8) | outcomeIdx. interface IOutcomeToken6909 { event Transfer( address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount ); function setOperator(address spender, bool approved) external returns (bool); function transferFrom(address from, address to, uint256 id, uint256 amount) external returns (bool); function balanceOf(address owner, uint256 id) external view returns (uint256); } ``` --- # /docs/contracts/market-making # Market Making on Somnia Markets What is different about quoting this venue. Somnia Markets runs **spot** order books, **binary** information markets, and **perps**, all on the same on-chain order-book engine; this guide covers quoting the **binary markets**. It assumes you already run market-making systems and skips the generalities — only the mechanics that will surprise you or cost you money if learned in production. Everything below is specific to binary markets (`marketType() == BINARY_SINGLE_BOOK`), which is every binary market live today; future kinds (multi-outcome, dual-book) carry a different `marketType()` and will not share these semantics — branch on the tag, never assume. Full contract mechanics are in [Raw Integration](./RawIntegration.md); the SDK (`@somnia-chain/markets-sdk`) wraps all of it if you're in a JS runtime. If you quote spot or perps, read the [batch writes](./RawIntegration.md#batch-writes) and [operator keys](./RawIntegration.md#operator-keys) sections there. Binary pools reject batch placement and amend with `UseBinaryPlacement`, and they have no per-user operator keys. ## One book per binary market; the order kind selects the side, and NO is price-inverted Each binary market runs a **single** order book crossing all four order kinds. Place orders with `placeBinaryOrder` and name the kind explicitly; the generic `placeOrder` reverts `UseBinaryPlacement`. `userData` is a free tag that the pool does not read, so you can use it for quote generations. NO orders are submitted at the YES complement: `price = oneCollateral − noPrice`, with `oneCollateral = 10 ** collateral.decimals()`. All prices must sit strictly inside `(0, oneCollateral)`, tick/lot/min from `getOrderBookParameters()` at runtime. The kind matrix. Because of the inversion, a NO buy rests on the ask side: | `OrderKind` | Value | Book side | |---|---|---| | `BUY_YES` | `0` | bid | | `SELL_YES` | `1` | ask | | `BUY_NO` | `2` | ask | | `SELL_NO` | `3` | bid | ## You can quote two-sided with zero inventory A resting BUY_YES at *p* and BUY_NO at *1 − p* is a full two-sided quote: when either crosses an incoming opposite buyer the pool **mints a fresh pair** (`MINT_A_PAIR`) — collateral in, one side to each buyer, no inventory required. `SELL_YES × SELL_NO` burns a pair symmetrically. This changes the standard outcome-market bootstrap: you never need to pre-mint outcome tokens to open a market, and your quoting book can stay entirely collateral-denominated. Deliberate inventory moves go through `mintCompleteSet` / `mergeCompleteSet` (1 collateral ⇄ 1 YES + 1 NO, always), and `redeem` pays the winning side 1:1 at resolution, less the venue's frozen settlement fee if it configured one (0.5 each on void, never fee'd). Price the venue's fees into your spread: maker/taker rates are **per-venue** and frozen into the pool at market creation — read them once per market from `getBinaryPoolParams()` (`makerFeeBpsTimes1k` / `takerFeeBpsTimes1k` / `settlementFeeBpsTimes1k`; basis-points × 1000). The per-order builder fee only applies if you opt a builder in with `approveBuilder` — as an MM placing your own orders you simply pass `(address(0), 0)` and never pay it. ## Escrow: BUYs lock collateral, SELLs lock tokens, refunds recycle via the vault Placement escrows worst-case value up front: BUYs lock collateral (vault-balance-first, then wallet `transferFrom` — one approval per pool), SELLs lock the ERC-6909 outcome tokens themselves (one `setOperator(pool, true)` on the singleton covers every market). Two flows matter for float accounting: - **Taker surplus and cancel/reduce refunds credit your pool vault balance**, not your wallet — and since placement is vault-first, a quoting loop recycles them automatically. `withdraw` only when rebalancing across pools. - **Fill proceeds deliver wallet-first with vault fallback.** Alert on `PayoutFallbackToVault` or your reconciliation will drift. ## Expiry is mandatory — make it your dead man's switch Every order carries `expireTimestampNs` (future unix-ns; there is no "no expiry" sentinel). Set it just past your requote interval rather than far-future: a crashed or partitioned quoter's ladder then ages off the book on its own. Note expired orders are unfillable **immediately**, but the `OrderExpired` event is lazy (fires on later cleanup, not at expiry) — prune your own book model on the timestamp, not the event. ## Self-match: pick your side, and handle `OrderCancelledSelfMatch` With `SelfMatchingOption.CancelMaker`, the matcher erases your same-owner resting maker and emits `OrderCancelledSelfMatch(orderId)` — an event-materialized book (yours, and every other participant's) must treat it as a removal or it carries a phantom order afterward. With `CancelTaker` the incoming order is rejected instead: the placement reverts `SelfMatchCancelTaker`. Details in [the sharp edges](./RawIntegration.md#the-sharp-edges). The protocol pulls your makers on other paths too. A pre-fill guard emits `OrderCancelledPreFill(orderId)` for every maker it removes before a fill. On a perp pool a reason tag rides alongside it — one of `MakerOrderCancelledExceedsPosition`, `MakerOrderCancelledNegativeEquity` or `MakerOrderCancelledStaleMark`. Treat all four as removals. Handling the base `OrderCancelledPreFill` alone covers every guard, present and future. ## Rejections revert A PostOnly that would cross reverts `PostOnlyWouldCross`. A FillOrKill that cannot fill in full reverts `FillOrKillNotFillable`. An IOC that fills nothing reverts `ImmediateOrCancelNoFill`. Binary pools have no batch placement, so every rejection reaches your loop as a revert. Decode the revert data to choose a recovery. `cancelOrder` / `reduceOrder` also revert on already-terminal orders. Check state before cancelling, or you burn a tx slot in your re-center path. ## Markets die on schedule — and respawn Every market has a hard `expiry`; venue rolling series (e.g. hourly up/down) spawn a successor each interval. Placement reverts `TradingNotActive` the moment the market leaves Trading; cancels keep working through `Locked`. Anything resting at lock is free option value to whoever knows the outcome first — pull quotes ahead of expiry, sweep after resolution (`redeem` winners — note a resolved market's winning payout is net of the venue's frozen settlement fee, if any — `mergeCompleteSet` balanced pairs), and watch `BinaryMarketsModule`'s `MarketCreated` to be resting in the successor the moment it opens. ## Infrastructure and latency The public Somnia RPC nodes — `https://api.infra.mainnet.somnia.network/` (mainnet) and `https://api.infra.testnet.somnia.network/` (testnet) — are hosted in **GCP `europe-west4` (Netherlands)** and have **no rate limit**: host your quoting infrastructure in or near that region and submit transactions / read state as fast as your strategy requires. There is no separate market-data service to rate-limit you on this venue — market data *is* the chain, materialized from the event stream ([Raw Integration](./RawIntegration.md#materialize-the-order-book-from-events)). A 24/7 operation should keep backup RPCs configured (the authoritative provider list, including WSS endpoints, is at [Somnia network-info](https://docs.somnia.network/developer/network-info)), fail over on repeated errors, and backfill any missed log range before trusting its book model again. ## No session keys — atomicity comes from owning a contract `BinaryPool` has no per-user operator approvals (the `*For` entrypoints are admin-allowlist only), so the operator/fund key split you may run elsewhere doesn't apply. The equivalent isolation *and* atomic multi-order operations come from making your own contract the order owner: it places a full ladder or cancel-and-replaces both sides in one all-or-nothing transaction, and the book never sees a half-updated ladder. --- # /docs/typescript/api **@somnia-chain/markets-sdk** *** # @somnia-chain/markets-sdk ## Modules - [chains](chains/README.md) - [index](index/README.md) - [native](native/README.md) - [react](react/README.md) - [reactivity](reactivity/README.md) --- # /docs/typescript/api/chains [**@somnia-chain/markets-sdk**](../README.md) *** [@somnia-chain/markets-sdk](../README.md) / chains # chains ## bridging - [warpRouterAbi](variables/warpRouterAbi.md) - [SOMNIA\_BRIDGE](variables/SOMNIA_BRIDGE.md) - [getBridgeToken](functions/getBridgeToken.md) - [listBridgeTokens](functions/listBridgeTokens.md) - [getBridgeNetwork](functions/getBridgeNetwork.md) - [listBridgeNetworks](functions/listBridgeNetworks.md) - [isBridgeNetwork](functions/isBridgeNetwork.md) - [getBridgeRoute](functions/getBridgeRoute.md) - [getBridgeRouter](functions/getBridgeRouter.md) - [SendBridgeStepOptions](interfaces/SendBridgeStepOptions.md) - [sendBridgeStep](functions/sendBridgeStep.md) - [CreateBridgeTransferParams](interfaces/CreateBridgeTransferParams.md) - [createBridgeTransfer](functions/createBridgeTransfer.md) - [toEip1193Transaction](functions/toEip1193Transaction.md) - [BridgeToken](variables/BridgeToken.md) - [BridgeToken](type-aliases/BridgeToken.md) - [BridgeTokenModel](type-aliases/BridgeTokenModel.md) - [BridgeTokenDetails](interfaces/BridgeTokenDetails.md) - [BridgeNetworkDetails](interfaces/BridgeNetworkDetails.md) - [BridgeRoute](interfaces/BridgeRoute.md) - [BridgeDetails](interfaces/BridgeDetails.md) - [BridgeTransaction](interfaces/BridgeTransaction.md) - [BridgeTransfer](interfaces/BridgeTransfer.md) ## networks - [ChainId](variables/ChainId.md) - [ChainId](type-aliases/ChainId.md) - [hidekiTestnet](variables/hidekiTestnet.md) - [somniaElwood](variables/somniaElwood.md) - [somniaLocal](variables/somniaLocal.md) - [somniaMainnet](variables/somniaMainnet.md) - [somniaShannon](variables/somniaShannon.md) - [somniaChains](variables/somniaChains.md) - [getSomniaChain](functions/getSomniaChain.md) - [isSomniaChainId](functions/isSomniaChainId.md) --- # /docs/typescript/api/chains/functions/createBridgeTransfer [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / createBridgeTransfer # Function: createBridgeTransfer() > **createBridgeTransfer**(`params`): [`BridgeTransfer`](../interfaces/BridgeTransfer.md) Defined in: packages/sdk/src/chains/bridge/transfer.ts:115 Build the unsigned transactions that bridge `amount` of `token` from one Somnia network to another. Returns a plan rather than a single transaction, because what it takes depends on the route: a **collateral** leg needs an ERC-20 `approve` before `transferRemote`, while **native** and **synthetic** legs need only the bridge call. `approveStep` is absent when there is nothing to approve — branch on it and it narrows, no non-null assertion needed: **Details** - `params`: Token, direction, amount, recipient, and the optional gas/approval knobs. - Returns: The transfer: `bridgeStep` (the `transferRemote` call), `approveStep` (the ERC-20 approval on a collateral route, absent otherwise), and both sides' token details. **Gotchas** - Throws If the amount is not positive, the recipient isn't an address, the two chains are the same, or that token has no route between them. The message names what IS supported. **Example** (Planning a bridge transfer) ```ts import { BridgeToken, ChainId, createBridgeTransfer } from "@somnia-chain/markets-sdk/chains"; const plan = createBridgeTransfer({ token: BridgeToken.WBTC, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: 100_000_000n, // 1 WBTC — 8 decimals, not 18 recipient: account.address, }); if (plan.approveStep) { const hash = await walletClient.sendTransaction({ ...plan.approveStep, account }); await publicClient.waitForTransactionReceipt({ hash }); // the approval must LAND first } const hash = await walletClient.sendTransaction({ ...plan.bridgeStep, account }); await publicClient.waitForTransactionReceipt({ hash }); ``` On a Somnia node, [sendBridgeStep](sendBridgeStep.md) does the same in one round-trip per transaction via `eth_sendRawTransactionSync`. Delivery is asynchronous: `transferRemote` only escrows and dispatches. The relayer delivers on the far side seconds later, and this bridge does not meter that gas — see [SOMNIA\_BRIDGE](../variables/SOMNIA_BRIDGE.md). ## Parameters ### params [`CreateBridgeTransferParams`](../interfaces/CreateBridgeTransferParams.md) ## Returns [`BridgeTransfer`](../interfaces/BridgeTransfer.md) --- # /docs/typescript/api/chains/functions/getBridgeNetwork [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / getBridgeNetwork # Function: getBridgeNetwork() > **getBridgeNetwork**(`chainId`): [`BridgeNetworkDetails`](../interfaces/BridgeNetworkDetails.md) \| `null` Defined in: packages/sdk/src/chains/bridge/registry.ts:360 The Hyperlane core deployment on one network — mailbox, ISM, hooks — plus the tokens it carries. **Details** - `chainId`: Chain id to look up. - Returns: The network's bridge deployment, or `null` if it isn't bridged. **Example** (Resolving a bridge network) ```ts import { ChainId, getBridgeNetwork } from "@somnia-chain/markets-sdk/chains"; getBridgeNetwork(ChainId.hidekiTestnet)?.mailbox; getBridgeNetwork(ChainId.somniaMainnet); // null — not bridged yet ``` ## Parameters ### chainId `number` ## Returns [`BridgeNetworkDetails`](../interfaces/BridgeNetworkDetails.md) \| `null` --- # /docs/typescript/api/chains/functions/getBridgeRoute [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / getBridgeRoute # Function: getBridgeRoute() > **getBridgeRoute**(`token`, `chainIdA`, `chainIdB`): [`BridgeRoute`](../interfaces/BridgeRoute.md) \| `null` Defined in: packages/sdk/src/chains/bridge/registry.ts:401 The route carrying one token between two networks, in either order. Bridging is **not transitive** — a chain must be a member of the token's route. **Details** - `token`: Token symbol. - `chainIdA`: One end of the lane. - `chainIdB`: The other end. - Returns: The route, or `null` if that token doesn't connect those two networks. ## Parameters ### token [`BridgeToken`](../type-aliases/BridgeToken.md) ### chainIdA `number` ### chainIdB `number` ## Returns [`BridgeRoute`](../interfaces/BridgeRoute.md) \| `null` --- # /docs/typescript/api/chains/functions/getBridgeRouter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / getBridgeRouter # Function: getBridgeRouter() > **getBridgeRouter**(`token`, `chainId`): `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/chains/bridge/registry.ts:415 The warp router that moves `token` on `chainId`, or `null`. ## Parameters ### token [`BridgeToken`](../type-aliases/BridgeToken.md) ### chainId `number` ## Returns `` `0x${string}` `` \| `null` --- # /docs/typescript/api/chains/functions/getBridgeToken [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / getBridgeToken # Function: getBridgeToken() > **getBridgeToken**(`token`, `chainId`): [`BridgeTokenDetails`](../interfaces/BridgeTokenDetails.md) \| `null` Defined in: packages/sdk/src/chains/bridge/registry.ts:322 Token details for one token on one network — the router to call, what the sender holds, its decimals, and where it can go. **Details** - `token`: Token symbol. - `chainId`: Chain id of the network (also the Hyperlane domain id). - Returns: The details, or `null` when that token has no route on that network. **Example** (Resolving a bridged token) ```ts import { BridgeToken, ChainId, getBridgeToken } from "@somnia-chain/markets-sdk/chains"; const wbtc = getBridgeToken(BridgeToken.WBTC, ChainId.somniaShannon); wbtc?.model; // "collateral" — approve `wbtc.address` to `wbtc.router` first wbtc?.decimals; // 8, NOT 18 ``` ## Parameters ### token [`BridgeToken`](../type-aliases/BridgeToken.md) ### chainId `number` ## Returns [`BridgeTokenDetails`](../interfaces/BridgeTokenDetails.md) \| `null` --- # /docs/typescript/api/chains/functions/getSomniaChain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / getSomniaChain # Function: getSomniaChain() > **getSomniaChain**(`chainId`): `Chain` \| `null` Defined in: packages/sdk/src/chains/index.ts:117 Resolve a chain id to its definition, or `null` when it isn't a Somnia network we ship. The `chainId` a deployment manifest carries is a plain `number`, so this is the bridge from "the env told me 50312" to a viem `Chain`. **Details** - `chainId`: Chain id to look up (e.g. `50312`). - Returns: The matching viem `Chain`, or `null` if it isn't one of ours. **Example** (Resolving a deployment chain) ```ts import { getSomniaChain, defineChain } from "@somnia-chain/markets-sdk/chains"; const chain = getSomniaChain(deployment.chainId) ?? defineChain({ id: deployment.chainId, name: "Somnia", nativeCurrency: { name: "STT", symbol: "STT", decimals: 18 }, rpcUrls: { default: { http: [rpcUrl] } }, }); ``` ## Parameters ### chainId `number` ## Returns `Chain` \| `null` --- # /docs/typescript/api/chains/functions/isBridgeNetwork [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / isBridgeNetwork # Function: isBridgeNetwork() > **isBridgeNetwork**(`chainId`): `boolean` Defined in: packages/sdk/src/chains/bridge/registry.ts:383 Is this chain id part of the bridge? A `true` here is what makes [getBridgeNetwork](getBridgeNetwork.md) non-null. **Details** - `chainId`: Chain id to test. ## Parameters ### chainId `number` ## Returns `boolean` --- # /docs/typescript/api/chains/functions/isSomniaChainId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / isSomniaChainId # Function: isSomniaChainId() > **isSomniaChainId**(`chainId`): `chainId is ChainId` Defined in: packages/sdk/src/chains/index.ts:132 Type guard: is this chain id one of the Somnia networks in [somniaChains](../variables/somniaChains.md)? Narrows a plain `number` to [ChainId](../variables/ChainId.md), so it can index `somniaChains` without a cast. **Details** - `chainId`: Chain id to test. ## Parameters ### chainId `number` ## Returns `chainId is ChainId` --- # /docs/typescript/api/chains/functions/listBridgeNetworks [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / listBridgeNetworks # Function: listBridgeNetworks() > **listBridgeNetworks**(): [`BridgeNetworkDetails`](../interfaces/BridgeNetworkDetails.md)[] Defined in: packages/sdk/src/chains/bridge/registry.ts:369 Every network with a bridge deployment. ## Returns [`BridgeNetworkDetails`](../interfaces/BridgeNetworkDetails.md)[] --- # /docs/typescript/api/chains/functions/listBridgeTokens [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / listBridgeTokens # Function: listBridgeTokens() > **listBridgeTokens**(`chainId?`): [`BridgeTokenDetails`](../interfaces/BridgeTokenDetails.md)[] Defined in: packages/sdk/src/chains/bridge/registry.ts:336 Every bridgeable token, optionally narrowed to one network. **Details** - `chainId`: Only tokens with a route on this network. Omit for all of them. - Returns: Matching token details; `[]` when the network isn't bridged. ## Parameters ### chainId? `number` ## Returns [`BridgeTokenDetails`](../interfaces/BridgeTokenDetails.md)[] --- # /docs/typescript/api/chains/functions/sendBridgeStep [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / sendBridgeStep # Function: sendBridgeStep() > **sendBridgeStep**(`client`, `step`, `options`): `Promise`\<`TransactionReceipt`\> Defined in: packages/sdk/src/chains/bridge/send.ts:94 Sign one planner transaction locally and send it via Somnia's **`eth_sendRawTransactionSync`** — the node blocks until the transaction is executed and answers with the receipt, so send + confirm is a single round-trip. On a node without the method (anvil, stock geth) it falls back to `eth_sendRawTransaction` + a receipt wait, so the same code runs against `somniaLocal`. **Details** - `client`: A public client for the transaction's chain (its `request` is the wire). - `step`: The planner transaction — `plan.approveStep` / `plan.bridgeStep`. - `options`: The local signer, plus optional gas/fee overrides. - Returns: The mined receipt, status `"success"`. **Gotchas** - Throws If the client is on a different chain than the step, if the node rejects the transaction, or if the receipt says `"reverted"` — the message names the step's `description`. **Example** (Sending a bridge transfer) ```ts import { BridgeToken, ChainId, createBridgeTransfer, sendBridgeStep } from "@somnia-chain/markets-sdk/chains"; const plan = createBridgeTransfer({ token: BridgeToken.WBTC, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: 100_000_000n, // 1 WBTC — 8 decimals, not 18 recipient: account.address, }); if (plan.approveStep) await sendBridgeStep(client, plan.approveStep, { account }); const receipt = await sendBridgeStep(client, plan.bridgeStep, { account }); receipt.status; // "success" — a reverted receipt throws instead ``` Each call resolves only once its transaction is CONFIRMED, so the approve-then-bridge ordering above is safe by construction. Fees and gas are fixed, never estimated — the same doctrine as the SDK's trading writes. ## Parameters ### client ### step [`BridgeTransaction`](../interfaces/BridgeTransaction.md) ### options [`SendBridgeStepOptions`](../interfaces/SendBridgeStepOptions.md) ## Returns `Promise`\<`TransactionReceipt`\> --- # /docs/typescript/api/chains/functions/toEip1193Transaction [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / toEip1193Transaction # Function: toEip1193Transaction() > **toEip1193Transaction**(`step`, `options?`): `RpcTransactionRequest` Defined in: packages/sdk/src/chains/bridge/transfer.ts:216 A [BridgeTransaction](../interfaces/BridgeTransaction.md) as the JSON-safe object a browser wallet's `eth_sendTransaction` takes — typed as viem's own `RpcTransactionRequest` (hex quantities throughout), with only `from`/`to`/`data`/`value` set. Every field is a hex string, so the result survives `JSON.stringify`, a server → browser boundary, or a `postMessage` — which a raw [BridgeTransaction](../interfaces/BridgeTransaction.md) does not: its `value` is a `bigint`, and `JSON.stringify` throws on bigints. What it deliberately DROPS is as important as what it converts: - **`chainId`** — `eth_sendTransaction` has no chain field; an EIP-1193 wallet signs on its **active** chain. Switch first with `wallet_switchEthereumChain` (using the transaction's `chainId`) or it goes out on whatever network the wallet happens to be on. - `description` — a UI label, not a transaction field; some wallets reject requests carrying unknown keys. No `gas`, no nonce, no fees, same as the input: the wallet estimates and fills those. Callers on viem don't need this at all — `walletClient.sendTransaction({ ...plan.bridgeStep, account })` takes it as-is; this exists for the raw `provider.request(...)` path and for moving a server-built plan across a JSON boundary. **Details** - `step`: The planner transaction (or anything with `to`/`data`/`value`) to convert. - `options`: `from` — the sender to pin; omit to let the wallet choose. - Returns: The `eth_sendTransaction` params object, JSON-safe by construction. **Example** (Preparing an EIP-1193 transaction) ```ts import { BridgeToken, ChainId, createBridgeTransfer, toEip1193Transaction } from "@somnia-chain/markets-sdk/chains"; import { numberToHex } from "viem"; const plan = createBridgeTransfer({ token: BridgeToken.STT, from: ChainId.somniaShannon, to: ChainId.hidekiTestnet, amount: 1_000_000_000_000_000_000n, // 1 STT recipient, }); const tx = toEip1193Transaction(plan.bridgeStep, { from: sender }); tx.value; // "0xde0b6b3a7640000" — hex wei, not a bigint JSON.stringify(tx); // safe: every field is a string // The wallet signs on its ACTIVE chain — put it on the step's chain first. await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: numberToHex(plan.bridgeStep.chainId) }], }); await provider.request({ method: "eth_sendTransaction", params: [tx] }); ``` ## Parameters ### step `Pick`\<[`BridgeTransaction`](../interfaces/BridgeTransaction.md), `"to"` \| `"data"` \| `"value"`\> ### options? #### from? `` `0x${string}` `` ## Returns `RpcTransactionRequest` --- # /docs/typescript/api/chains/interfaces/BridgeDetails [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeDetails # Interface: BridgeDetails Defined in: packages/sdk/src/chains/bridge/types.ts:157 The bridge as a whole: what it connects, what it carries, and how far to trust it. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:159 Lane id, e.g. `"somniatestnet-hideki2testnet"`. *** ### displayName > **displayName**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:161 Human name of the lane. *** ### chainIds > **chainIds**: `number`[] Defined in: packages/sdk/src/chains/bridge/types.ts:163 Chain ids the bridge connects. *** ### tokens > **tokens**: [`BridgeToken`](../type-aliases/BridgeToken.md)[] Defined in: packages/sdk/src/chains/bridge/types.ts:165 Tokens with at least one route. *** ### routes > **routes**: [`BridgeRoute`](BridgeRoute.md)[] Defined in: packages/sdk/src/chains/bridge/types.ts:167 Every token route on the lane. *** ### status > **status**: `"dev-test"` Defined in: packages/sdk/src/chains/bridge/types.ts:172 `"dev-test"` — a single validator, a threshold-1 ISM and EOA owners. One key is the entire bridge. **Do not put real funds behind it.** *** ### security > **security**: `object` Defined in: packages/sdk/src/chains/bridge/types.ts:174 Validators in the multisig ISM, and how many signatures it requires. #### validators > **validators**: `` `0x${string}` ``[] #### threshold > **threshold**: `number` *** ### relayerPaysDestinationGas > **relayerPaysDestinationGas**: `boolean` Defined in: packages/sdk/src/chains/bridge/types.ts:179 True when the relayer pays destination gas unmetered — so a sender attaches nothing for delivery, and delivery depends on the relayer staying funded. *** ### docs > **docs**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:181 Where the deployment record lives. --- # /docs/typescript/api/chains/interfaces/BridgeNetworkDetails [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeNetworkDetails # Interface: BridgeNetworkDetails Defined in: packages/sdk/src/chains/bridge/types.ts:108 The Hyperlane core deployment on one network, plus what it carries. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/chains/bridge/types.ts:110 Chain id. *** ### domainId > **domainId**: `number` Defined in: packages/sdk/src/chains/bridge/types.ts:112 Hyperlane domain id — equal to the chain id on this bridge. *** ### network > **network**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:114 Hyperlane registry name, e.g. `"hideki2testnet"`. *** ### displayName > **displayName**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:116 Human name, e.g. `"Hideki2 Testnet"`. *** ### mailbox > **mailbox**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:118 Dispatches and delivers interchain messages. *** ### interchainSecurityModule > **interchainSecurityModule**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:120 The default ISM messages are verified against (1-of-1 multisig on this lane). *** ### merkleTreeHook > **merkleTreeHook**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:122 Accumulates dispatched message ids into the tree validators sign. *** ### validatorAnnounce > **validatorAnnounce**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:124 Where validators announce their checkpoint storage. *** ### interchainAccountRouter > **interchainAccountRouter**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:126 Interchain account router (not used by token transfers). *** ### proxyAdmin > **proxyAdmin**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:128 Proxy admin owning the core proxies. *** ### interchainGasPaymaster > **interchainGasPaymaster**: `null` Defined in: packages/sdk/src/chains/bridge/types.ts:133 `null` — no InterchainGasPaymaster is deployed on this bridge, which is why `quoteGasPayment` is 0 and the relayer absorbs delivery gas. *** ### tokens > **tokens**: [`BridgeToken`](../type-aliases/BridgeToken.md)[] Defined in: packages/sdk/src/chains/bridge/types.ts:135 Tokens with a route on this network. --- # /docs/typescript/api/chains/interfaces/BridgeRoute [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeRoute # Interface: BridgeRoute Defined in: packages/sdk/src/chains/bridge/types.ts:143 A token route between exactly two networks. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:145 Hyperlane route id, e.g. `"WBTC/somniatestnet-hideki2testnet"`. *** ### token > **token**: [`BridgeToken`](../type-aliases/BridgeToken.md) Defined in: packages/sdk/src/chains/bridge/types.ts:147 The token this route carries. *** ### chainIds > **chainIds**: \[`number`, `number`\] Defined in: packages/sdk/src/chains/bridge/types.ts:149 The two chain ids it connects. Bridging is NOT transitive. --- # /docs/typescript/api/chains/interfaces/BridgeTokenDetails [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeTokenDetails # Interface: BridgeTokenDetails Defined in: packages/sdk/src/chains/bridge/types.ts:72 One token on one network: which router moves it, what the sender actually holds, and where it can go. ## Properties ### token > **token**: [`BridgeToken`](../type-aliases/BridgeToken.md) Defined in: packages/sdk/src/chains/bridge/types.ts:74 The token symbol. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/chains/bridge/types.ts:76 Chain id of the network these details describe (also the Hyperlane domain id). *** ### network > **network**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:78 Hyperlane registry name of that network, e.g. `"somniatestnet"`. *** ### model > **model**: [`BridgeTokenModel`](../type-aliases/BridgeTokenModel.md) Defined in: packages/sdk/src/chains/bridge/types.ts:80 How this side holds value — decides approvals and `msg.value`. *** ### router > **router**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:82 The warp router to call `transferRemote` on. *** ### address > **address**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/chains/bridge/types.ts:88 The ERC-20 the sender holds on this chain: the canonical token for `collateral`, the router itself for `synthetic` (a HypERC20 *is* its token), and `null` for `native` — where the balance is the chain's gas coin. *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/chains/bridge/types.ts:90 Decimals on this side. Amounts are base units of THIS number. *** ### name > **name**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:92 Human name of the token, e.g. `"Wrapped Bitcoin"`. *** ### destinations > **destinations**: `number`[] Defined in: packages/sdk/src/chains/bridge/types.ts:94 Chain ids this token can be bridged to from here. *** ### requiresDestinationLiquidity > **requiresDestinationLiquidity**: `boolean` Defined in: packages/sdk/src/chains/bridge/types.ts:100 True when delivery is paid out of the destination router's own balance rather than by minting — the `native` model. Such a route can stall if the destination router is drained, so check its balance before sending. --- # /docs/typescript/api/chains/interfaces/BridgeTransaction [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeTransaction # Interface: BridgeTransaction Defined in: packages/sdk/src/chains/bridge/types.ts:197 One unsigned transaction of a bridge transfer, ready for any signer: spread into viem's `sendTransaction`, hand to [sendBridgeStep](../functions/sendBridgeStep.md) for Somnia's one-round-trip sync path, or convert with [toEip1193Transaction](../functions/toEip1193Transaction.md) for a browser wallet. Its ROLE is the field it hangs off — `approveStep` or `bridgeStep` — so it carries no tag; `description` is the human label. Deliberately minimal and chain-tagged: no nonce, no fees, no gas — the signer's job. (No viem type requires exactly these fields, which is why this one exists; it is assignable to viem's `TransactionRequest`.) ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/chains/bridge/types.ts:199 Chain this must be sent on — always the ORIGIN chain. *** ### to > **to**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:201 Contract to call. *** ### data > **data**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:203 ABI-encoded calldata. *** ### value > **value**: `bigint` Defined in: packages/sdk/src/chains/bridge/types.ts:205 Native value to attach, in wei. `0n` unless the route is native. *** ### description > **description**: `string` Defined in: packages/sdk/src/chains/bridge/types.ts:207 What this transaction does, for a UI to label a confirmation with. --- # /docs/typescript/api/chains/interfaces/BridgeTransfer [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeTransfer # Interface: BridgeTransfer Defined in: packages/sdk/src/chains/bridge/types.ts:233 A bridge transfer, expanded into the transactions it actually takes. Two or one: a `collateral` transfer needs an ERC-20 `approve` before the bridge call; `native` and `synthetic` transfers do not. `approveStep` is simply absent when there is nothing to approve — branching on it narrows: **Example** (Sending an approval before a transfer) ```ts if (plan.approveStep) { await sendBridgeStep(client, plan.approveStep, { account }); // confirmed before the next line } await sendBridgeStep(client, plan.bridgeStep, { account }); ``` Everything protocol-derived lives on the transactions themselves or on `origin`/`destination` — e.g. a native route's destination-liquidity caveat is [BridgeTokenDetails.requiresDestinationLiquidity](BridgeTokenDetails.md#requiresdestinationliquidity) on `destination`, and an interchain gas payment is already folded into `bridgeStep.value`. ## Properties ### origin > **origin**: [`BridgeTokenDetails`](BridgeTokenDetails.md) Defined in: packages/sdk/src/chains/bridge/types.ts:235 The origin-side token being sent. *** ### destination > **destination**: [`BridgeTokenDetails`](BridgeTokenDetails.md) Defined in: packages/sdk/src/chains/bridge/types.ts:237 The destination-side token that will be received. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/chains/bridge/types.ts:239 Amount in base units of `origin.decimals`. *** ### recipient > **recipient**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/types.ts:241 Who receives it on the destination chain. *** ### approveStep? > `optional` **approveStep?**: [`BridgeTransaction`](BridgeTransaction.md) Defined in: packages/sdk/src/chains/bridge/types.ts:247 The ERC-20 approval a **collateral** route needs first — absent on native and synthetic routes. Confirm it before sending `bridgeStep`, which spends the allowance. *** ### bridgeStep > **bridgeStep**: [`BridgeTransaction`](BridgeTransaction.md) Defined in: packages/sdk/src/chains/bridge/types.ts:254 The `transferRemote` call on the origin router — the transaction that bridges. Always present, always sent last: it escrows or burns on the origin and dispatches the interchain message. Its `value` carries the amount on a native route (plus any `gasPayment` passed in), `0n` otherwise. --- # /docs/typescript/api/chains/interfaces/CreateBridgeTransferParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / CreateBridgeTransferParams # Interface: CreateBridgeTransferParams Defined in: packages/sdk/src/chains/bridge/transfer.ts:37 Parameters for [createBridgeTransfer](../functions/createBridgeTransfer.md). ## Properties ### token > **token**: [`BridgeToken`](../type-aliases/BridgeToken.md) Defined in: packages/sdk/src/chains/bridge/transfer.ts:39 Token to bridge. *** ### from > **from**: `number` Defined in: packages/sdk/src/chains/bridge/transfer.ts:41 Chain id to send FROM. *** ### to > **to**: `number` Defined in: packages/sdk/src/chains/bridge/transfer.ts:43 Chain id to send TO. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/chains/bridge/transfer.ts:48 Amount in **base units of the origin side's decimals** — read them off [BridgeTokenDetails.decimals](BridgeTokenDetails.md#decimals) rather than assuming 18 (WBTC is 8). *** ### recipient > **recipient**: `` `0x${string}` `` Defined in: packages/sdk/src/chains/bridge/transfer.ts:50 Who receives the tokens on the destination chain. *** ### gasPayment? > `optional` **gasPayment?**: `bigint` Defined in: packages/sdk/src/chains/bridge/transfer.ts:57 Interchain gas payment to attach, added to the transfer's `value`. Defaults to `0n`, which is correct for this bridge — it has no InterchainGasPaymaster and every router quotes 0. Pass the result of `quoteGasPayment(destinationDomain)` if that ever changes. *** ### approveAmount? > `optional` **approveAmount?**: `bigint` Defined in: packages/sdk/src/chains/bridge/transfer.ts:63 Amount to approve on a `collateral` route. Defaults to `amount` (exact approval). Pass a larger value to approve once for several transfers, or `0n` to skip the approval step entirely when an allowance is already in place. --- # /docs/typescript/api/chains/interfaces/SendBridgeStepOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / SendBridgeStepOptions # Interface: SendBridgeStepOptions Defined in: packages/sdk/src/chains/bridge/send.ts:30 Options for [sendBridgeStep](../functions/sendBridgeStep.md). ## Properties ### account > **account**: `object` Defined in: packages/sdk/src/chains/bridge/send.ts:43 The signer. Must be a LOCAL account (viem's `privateKeyToAccount`, a derived session account, a mnemonic account…) — raw-transaction sending needs `signTransaction`, which injected browser wallets do not expose. Its balance must cover the full FEE ENVELOPE — `gas × maxFeePerGas`, 0.6 STT at the defaults — on top of the transaction's `value`: Somnia's mempool admits a transaction only when the ceiling is funded, even though unused gas is never charged (measured live: a 0.05 STT account is rejected "insufficient balance"). Fund small accounts accordingly, or lower `gas`. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/chains/bridge/send.ts:45 Gas ceiling (default 10,000,000 — the SDK-wide fixed ceiling). Never estimated. *** ### maxFeePerGas? > `optional` **maxFeePerGas?**: `bigint` Defined in: packages/sdk/src/chains/bridge/send.ts:47 Fixed fees (default the SDK-wide `DEFAULT_FEES`: 60 gwei max, 0 priority). *** ### maxPriorityFeePerGas? > `optional` **maxPriorityFeePerGas?**: `bigint` Defined in: packages/sdk/src/chains/bridge/send.ts:48 --- # /docs/typescript/api/chains/type-aliases/BridgeToken [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeToken # Type Alias: BridgeToken > **BridgeToken** = *typeof* [`BridgeToken`](../variables/BridgeToken.md)\[keyof *typeof* [`BridgeToken`](../variables/BridgeToken.md)\] Defined in: packages/sdk/src/chains/bridge/types.ts:31 One of the [BridgeToken](../variables/BridgeToken.md) symbols. --- # /docs/typescript/api/chains/type-aliases/BridgeTokenModel [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeTokenModel # Type Alias: BridgeTokenModel > **BridgeTokenModel** = `"native"` \| `"collateral"` \| `"synthetic"` Defined in: packages/sdk/src/chains/bridge/types.ts:64 How a warp route holds value on one side. - `native` — the router escrows the chain's own gas coin and delivery pays out of the destination router's balance. No wrapped token exists. Needs seeded liquidity on each side (see [BridgeTokenDetails.requiresDestinationLiquidity](../interfaces/BridgeTokenDetails.md#requiresdestinationliquidity)). - `collateral` — the token's home chain: the router escrows the canonical ERC-20, which the sender must `approve` first. - `synthetic` — the router *is* an ERC-20 it mints and burns 1:1 against the collateral held on the home chain. No approval needed to send back. --- # /docs/typescript/api/chains/type-aliases/ChainId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / ChainId # Type Alias: ChainId > **ChainId** = *typeof* [`ChainId`](../variables/ChainId.md)\[keyof *typeof* [`ChainId`](../variables/ChainId.md)\] Defined in: packages/sdk/src/chains/chainId.ts:39 Chain id of one of the Somnia networks — the union behind `somniaChains`. --- # /docs/typescript/api/chains/variables/BridgeToken [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / BridgeToken # Variable: BridgeToken > `const` **BridgeToken**: `object` Defined in: packages/sdk/src/chains/bridge/types.ts:31 The tokens with a live warp route, by symbol. `BridgeToken.WBTC` is the value; `BridgeToken` is also the type of every such value. Adding a token is a registry change, not a code change. **Example** (Naming a bridge token) ```ts import { BridgeToken } from "@somnia-chain/markets-sdk/chains"; const symbol: BridgeToken = BridgeToken.WBTC; // "WBTC" ``` ## Type Declaration ### STT > `readonly` **STT**: `"STT"` = `"STT"` Native gas coin of every Somnia network. Native on BOTH sides of its route. ### USDso > `readonly` **USDso**: `"USDso"` = `"USDso"` Somnia USD test stable, 18 decimals. ### WBTC > `readonly` **WBTC**: `"WBTC"` = `"WBTC"` Wrapped Bitcoin — **8 decimals**, on the canonical token AND the synthetic. ### WETH > `readonly` **WETH**: `"WETH"` = `"WETH"` Wrapped ETH, 18 decimals. ### HBTT > `readonly` **HBTT**: `"HBTT"` = `"HBTT"` Hyperlane Bridge Test Token — a throwaway used to verify the lane. --- # /docs/typescript/api/chains/variables/ChainId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / ChainId # Variable: ChainId > `const` **ChainId**: `object` Defined in: packages/sdk/src/chains/chainId.ts:39 Every Somnia network's chain id, keyed by its chain definition's export name — `ChainId.somniaShannon === somniaShannon.id` by construction, so the constant and the definition can never disagree. The id is the value because that is what wallets, deployment manifests and viem all speak — and on the bridge the Hyperlane **domain id equals the chain id**, so one number identifies a network everywhere. A `const` object with a matching type, not a TS `enum` — the pattern this package uses everywhere (`BridgeToken`, `BinarySide`, …): `ChainId.somniaShannon` is the value, `ChainId` is also the type of every such value, and plain number literals still assign. Not every network is bridged — `listBridgeNetworks()` is the live set. **Example** (Indexing a chain definition) ```ts import { ChainId, somniaChains } from "@somnia-chain/markets-sdk/chains"; somniaChains[ChainId.hidekiTestnet].name; // "Hideki Testnet" ``` ## Type Declaration ### somniaMainnet > `readonly` **somniaMainnet**: `5031` = `somniaMainnet.id` Somnia mainnet (`5031`). Not bridged yet. ### somniaShannon > `readonly` **somniaShannon**: `50312` = `somniaShannon.id` Somnia Testnet — Shannon (`50312`), the general-purpose testnet. Bridged. ### somniaElwood > `readonly` **somniaElwood**: `50313` = `somniaElwood.id` Somnia Testnet — Elwood (`50313`), the testnet regenesis. Not bridged yet. ### hidekiTestnet > `readonly` **hidekiTestnet**: `50383` = `hidekiTestnet.id` Hideki Testnet (`50383`) — the low-latency Tokyo network. Bridged. ### somniaLocal > `readonly` **somniaLocal**: `31337` = `somniaLocal.id` The local anvil stack (`31337`). Never bridged. --- # /docs/typescript/api/chains/variables/SOMNIA_BRIDGE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / SOMNIA\_BRIDGE # Variable: SOMNIA\_BRIDGE > `const` **SOMNIA\_BRIDGE**: [`BridgeDetails`](../interfaces/BridgeDetails.md) Defined in: packages/sdk/src/chains/bridge/registry.ts:288 The Somnia token bridge: one Hyperlane lane, **Somnia Testnet ↔ Hideki2 Testnet**, carrying five token routes. Hideki2 is the 2026-09-17 regenesis of Hideki. [ChainId.hidekiTestnet](ChainId.md#hidekitestnet) (50383) resolves to it. Hideki 1 still runs on its own lane. This SDK does not ship that lane. Both chains use chain id 50383. Both use Hyperlane domain 50383. No id therefore tells the two lanes apart. Their Somnia-side core contracts differ, and that difference is the only way to identify a lane. > ⚠️ **`status: "dev-test"`.** A single validator, a threshold-1 ISM and EOA > owners — one key is the entire bridge. Do not put real funds behind it. Delivery gas is paid by the relayer, unmetered ([BridgeDetails.relayerPaysDestinationGas](../interfaces/BridgeDetails.md#relayerpaysdestinationgas)): a sender attaches nothing for it, and a drained relayer means transfers are accepted on the origin but not delivered until it is refunded — escrowed, not lost. **Example** (Inspecting the registry) ```ts import { SOMNIA_BRIDGE } from "@somnia-chain/markets-sdk/chains"; SOMNIA_BRIDGE.tokens; // ["STT", "USDso", "WBTC", "WETH", "HBTT"] SOMNIA_BRIDGE.chainIds; // [50312, 50383] SOMNIA_BRIDGE.id; // "somniatestnet-hideki2testnet" ``` --- # /docs/typescript/api/chains/variables/hidekiTestnet [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / hidekiTestnet # Variable: hidekiTestnet > `const` **hidekiTestnet**: `object` Defined in: packages/sdk/src/chains/definitions/hidekiTestnet.ts:42 **Hideki** testnet (chain id `50383`) — the low-latency Tokyo network. Validators sit in one region to keep validator-to-validator latency low, so blocks land every **10 ms** (~100 blocks/s) instead of Shannon's 100 ms. Native token is **STT**. **REGENESISED 2026-09-17 ("hideki v2"), ON THE SAME CHAIN ID.** The endpoints below are v2's (`api.hideki2…`); v1 lives on at `api.hideki…` but is superseded, and its `/ws` already answers 502. The shared chain id is worth stating plainly: nothing in a signature, a wallet or this definition distinguishes the two chains, so a transaction signed for one is valid on the other, and the same address holds DIFFERENT contracts on each — deployer nonces restarted at genesis. Tell the chains apart by height, not by chain id (v2 was ~293k blocks old when this was written; v1 was past 586M). One live-verified oddity, so nobody "fixes" it: Hideki's **network id is not its chain id**. `eth_chainId` answers `0xc4cf` (50383) — the value here, the one wallets and signatures use — while `net_version` answers `50000259` (v1 answered `50000258`; the regenesis moved it by one). Shannon's and mainnet's two ids are equal; Hideki's are not. The 10 ms cadence is what makes this the interesting target for latency work: a `blockTime` of 10 is what viem uses to size its own polling/waiting heuristics, and the SDK's live tail sees ~10x the block rate of Shannon. Multicall3 is at the **canonical** `0xcA11bde0…` on v2, holding code from block 1 — predeployed, not sent as a transaction. That reverses v1's situation and the reasoning that went with it: there the canonical route was unreachable (Somnia charges ~4,928 gas per deployed byte, so the presigned "Nick's method" transaction's fixed 500k limit cannot deploy Multicall3's 3,808-byte runtime, and the presigned deployers' nonce-0 transactions were already burned), so the bridge infra deployed the same runtime bytes at `0x540B091b…` instead. v2's canonical deployment is byte-identical to that one — verified by code hash — and `0x540B091b…` holds NO code on v2. No public block explorer is known for Hideki, so that field stays unset. ## Type Declaration ### blockTime > **blockTime**: `10` Block time in milliseconds. ### contracts > **contracts**: `object` Collection of contracts #### contracts.multicall3 > `readonly` **multicall3**: `object` #### contracts.multicall3.address > `readonly` **address**: `"0xcA11bde05977b3631167028862bE2a173976CA11"` = `"0xcA11bde05977b3631167028862bE2a173976CA11"` #### contracts.multicall3.blockCreated > `readonly` **blockCreated**: `1` = `1` ### id > **id**: `50383` ID in number form ### name > **name**: `"Hideki Testnet"` Human-readable name ### nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` ### rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### rpcUrls.default > `readonly` **default**: `object` #### rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.hideki2.infra.testnet.somnia.network"`\] #### rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.hideki2.infra.testnet.somnia.network/ws"`\] ### testnet > **testnet**: `true` Flag for test networks --- # /docs/typescript/api/chains/variables/somniaChains [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / somniaChains # Variable: somniaChains > `const` **somniaChains**: `object` Defined in: packages/sdk/src/chains/index.ts:82 Every Somnia network this module ships, keyed by chain id — the lookup table behind [getSomniaChain](../functions/getSomniaChain.md). Iterate it to build a network switcher; index it when you already know the id is one of ours. ## Type Declaration ### 5031 > `readonly` **5031**: `object` = `somniaMainnet` #### 5031.blockExplorers > **blockExplorers**: `object` Collection of block explorers #### 5031.blockExplorers.default > `readonly` **default**: `object` #### 5031.blockExplorers.default.name > `readonly` **name**: `"Somnia Explorer"` = `"Somnia Explorer"` #### 5031.blockExplorers.default.url > `readonly` **url**: `"https://explorer.somnia.network"` = `"https://explorer.somnia.network"` #### 5031.blockExplorers.default.apiUrl > `readonly` **apiUrl**: `"https://explorer.somnia.network/api"` = `"https://explorer.somnia.network/api"` #### 5031.blockTime > **blockTime**: `100` Block time in milliseconds. #### 5031.contracts > **contracts**: `object` Collection of contracts #### 5031.contracts.multicall3 > `readonly` **multicall3**: `object` #### 5031.contracts.multicall3.address > `readonly` **address**: `"0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11"` = `"0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11"` #### 5031.contracts.multicall3.blockCreated > `readonly` **blockCreated**: `38516341` = `38516341` #### 5031.id > **id**: `5031` ID in number form #### 5031.name > **name**: `"Somnia"` Human-readable name #### 5031.nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### 5031.nativeCurrency.name > `readonly` **name**: `"Somnia"` = `"Somnia"` #### 5031.nativeCurrency.symbol > `readonly` **symbol**: `"SOMI"` = `"SOMI"` #### 5031.nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` #### 5031.rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### 5031.rpcUrls.default > `readonly` **default**: `object` #### 5031.rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.infra.mainnet.somnia.network"`\] #### 5031.rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.infra.mainnet.somnia.network/ws"`\] #### 5031.testnet > **testnet**: `false` Flag for test networks ### 50312 > `readonly` **50312**: `object` = `somniaShannon` #### 50312.blockExplorers > **blockExplorers**: `object` Collection of block explorers #### 50312.blockExplorers.default > `readonly` **default**: `object` #### 50312.blockExplorers.default.name > `readonly` **name**: `"Somnia Testnet Explorer"` = `"Somnia Testnet Explorer"` #### 50312.blockExplorers.default.url > `readonly` **url**: `"https://shannon-explorer.somnia.network"` = `"https://shannon-explorer.somnia.network"` #### 50312.blockExplorers.default.apiUrl > `readonly` **apiUrl**: `"https://shannon-explorer.somnia.network/api"` = `"https://shannon-explorer.somnia.network/api"` #### 50312.blockTime > **blockTime**: `100` Block time in milliseconds. #### 50312.contracts > **contracts**: `object` Collection of contracts #### 50312.contracts.multicall3 > `readonly` **multicall3**: `object` #### 50312.contracts.multicall3.address > `readonly` **address**: `"0x841b8199E6d3Db3C6f264f6C2bd8848b3cA64223"` = `"0x841b8199E6d3Db3C6f264f6C2bd8848b3cA64223"` #### 50312.contracts.multicall3.blockCreated > `readonly` **blockCreated**: `71314235` = `71314235` #### 50312.id > **id**: `50312` ID in number form #### 50312.name > **name**: `"Somnia Testnet"` Human-readable name #### 50312.nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### 50312.nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### 50312.nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### 50312.nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` #### 50312.rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### 50312.rpcUrls.default > `readonly` **default**: `object` #### 50312.rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.infra.testnet.somnia.network"`, `"https://dream-rpc.somnia.network"`\] #### 50312.rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.infra.testnet.somnia.network/ws"`, `"wss://dream-rpc.somnia.network/ws"`\] #### 50312.testnet > **testnet**: `true` Flag for test networks ### 50313 > `readonly` **50313**: `object` = `somniaElwood` #### 50313.blockTime > **blockTime**: `100` Block time in milliseconds. #### 50313.id > **id**: `50313` ID in number form #### 50313.name > **name**: `"Somnia Elwood Testnet"` Human-readable name #### 50313.nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### 50313.nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### 50313.nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### 50313.nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` #### 50313.rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### 50313.rpcUrls.default > `readonly` **default**: `object` #### 50313.rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.elwood.infra.testnet.somnia.network"`\] #### 50313.rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.elwood.infra.testnet.somnia.network/ws"`\] #### 50313.testnet > **testnet**: `true` Flag for test networks ### 50383 > `readonly` **50383**: `object` = `hidekiTestnet` #### 50383.blockTime > **blockTime**: `10` Block time in milliseconds. #### 50383.contracts > **contracts**: `object` Collection of contracts #### 50383.contracts.multicall3 > `readonly` **multicall3**: `object` #### 50383.contracts.multicall3.address > `readonly` **address**: `"0xcA11bde05977b3631167028862bE2a173976CA11"` = `"0xcA11bde05977b3631167028862bE2a173976CA11"` #### 50383.contracts.multicall3.blockCreated > `readonly` **blockCreated**: `1` = `1` #### 50383.id > **id**: `50383` ID in number form #### 50383.name > **name**: `"Hideki Testnet"` Human-readable name #### 50383.nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### 50383.nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### 50383.nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### 50383.nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` #### 50383.rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### 50383.rpcUrls.default > `readonly` **default**: `object` #### 50383.rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.hideki2.infra.testnet.somnia.network"`\] #### 50383.rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.hideki2.infra.testnet.somnia.network/ws"`\] #### 50383.testnet > **testnet**: `true` Flag for test networks ### 31337 > `readonly` **31337**: `object` = `somniaLocal` #### 31337.id > **id**: `31337` ID in number form #### 31337.name > **name**: `"Somnia Local"` Human-readable name #### 31337.nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### 31337.nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### 31337.nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### 31337.nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` #### 31337.rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### 31337.rpcUrls.default > `readonly` **default**: `object` #### 31337.rpcUrls.default.http > `readonly` **http**: readonly \[`"http://127.0.0.1:8545"`\] #### 31337.rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"ws://127.0.0.1:8545"`\] #### 31337.testnet > **testnet**: `true` Flag for test networks --- # /docs/typescript/api/chains/variables/somniaElwood [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / somniaElwood # Variable: somniaElwood > `const` **somniaElwood**: `object` Defined in: packages/sdk/src/chains/definitions/somniaElwood.ts:14 Somnia testnet — **Elwood** (chain id `50313`, network id `50313`), the regenesis of the public testnet. Its own cluster, DNS zone and genesis; 100 ms blocks and **STT** as the native token, same as Shannon. No public block explorer and no Multicall3 deployment are known for Elwood, so neither field is set — a `multicall: true` read against this chain falls back to individual `eth_call`s instead of pointing at an address that has no code. ## Type Declaration ### blockTime > **blockTime**: `100` Block time in milliseconds. ### id > **id**: `50313` ID in number form ### name > **name**: `"Somnia Elwood Testnet"` Human-readable name ### nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` ### rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### rpcUrls.default > `readonly` **default**: `object` #### rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.elwood.infra.testnet.somnia.network"`\] #### rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.elwood.infra.testnet.somnia.network/ws"`\] ### testnet > **testnet**: `true` Flag for test networks --- # /docs/typescript/api/chains/variables/somniaLocal [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / somniaLocal # Variable: somniaLocal > `const` **somniaLocal**: `object` Defined in: packages/sdk/src/chains/definitions/somniaLocal.ts:21 The local Somnia dev chain (chain id `31337`) — an Anvil node, as brought up by `demo-clob.sh up` / `DEPLOY_ENV=local`. Anvil is a first-class environment for this protocol: the deploy scripts, the indexer, the deployments hub and the explorer all run against it, so it gets a definition here instead of borrowing viem's `foundry`. Deliberately presented as **Somnia** with **STT** rather than "Foundry"/"Ether": the agent-facing docs read the chain name and native symbol straight out of this object, and a local stack should still read as Somnia there. Two things a local chain does *not* have: the Somnia reactivity precompile at `0x…0100` (`isLocalPrecompileUnavailable` returns true here — anything that pings it, such as `enableReactivity` or `triggerRoll`, is testnet/mainnet only) and a Multicall3 deployment, unless you deployed one yourself. ## Type Declaration ### id > **id**: `31337` ID in number form ### name > **name**: `"Somnia Local"` Human-readable name ### nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` ### rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### rpcUrls.default > `readonly` **default**: `object` #### rpcUrls.default.http > `readonly` **http**: readonly \[`"http://127.0.0.1:8545"`\] #### rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"ws://127.0.0.1:8545"`\] ### testnet > **testnet**: `true` Flag for test networks --- # /docs/typescript/api/chains/variables/somniaMainnet [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / somniaMainnet # Variable: somniaMainnet > `const` **somniaMainnet**: `object` Defined in: packages/sdk/src/chains/definitions/somniaMainnet.ts:11 Somnia mainnet (chain id `5031`) — the production network. Native token is **SOMI**; blocks land roughly every 100 ms. Same content as viem's `somnia`, under the name the runbooks use. ## Type Declaration ### blockExplorers > **blockExplorers**: `object` Collection of block explorers #### blockExplorers.default > `readonly` **default**: `object` #### blockExplorers.default.name > `readonly` **name**: `"Somnia Explorer"` = `"Somnia Explorer"` #### blockExplorers.default.url > `readonly` **url**: `"https://explorer.somnia.network"` = `"https://explorer.somnia.network"` #### blockExplorers.default.apiUrl > `readonly` **apiUrl**: `"https://explorer.somnia.network/api"` = `"https://explorer.somnia.network/api"` ### blockTime > **blockTime**: `100` Block time in milliseconds. ### contracts > **contracts**: `object` Collection of contracts #### contracts.multicall3 > `readonly` **multicall3**: `object` #### contracts.multicall3.address > `readonly` **address**: `"0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11"` = `"0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11"` #### contracts.multicall3.blockCreated > `readonly` **blockCreated**: `38516341` = `38516341` ### id > **id**: `5031` ID in number form ### name > **name**: `"Somnia"` Human-readable name ### nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### nativeCurrency.name > `readonly` **name**: `"Somnia"` = `"Somnia"` #### nativeCurrency.symbol > `readonly` **symbol**: `"SOMI"` = `"SOMI"` #### nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` ### rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### rpcUrls.default > `readonly` **default**: `object` #### rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.infra.mainnet.somnia.network"`\] #### rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.infra.mainnet.somnia.network/ws"`\] ### testnet > **testnet**: `false` Flag for test networks --- # /docs/typescript/api/chains/variables/somniaShannon [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / somniaShannon # Variable: somniaShannon > `const` **somniaShannon**: `object` Defined in: packages/sdk/src/chains/definitions/somniaShannon.ts:13 Somnia testnet — **Shannon** (chain id `50312`), the public testnet and the default target for Somnia Markets development. Native token is **STT**; blocks land roughly every 100 ms. `https://dream-rpc.somnia.network` is a public alias for the same network and is listed as a secondary HTTP/WebSocket endpoint. ## Type Declaration ### blockExplorers > **blockExplorers**: `object` Collection of block explorers #### blockExplorers.default > `readonly` **default**: `object` #### blockExplorers.default.name > `readonly` **name**: `"Somnia Testnet Explorer"` = `"Somnia Testnet Explorer"` #### blockExplorers.default.url > `readonly` **url**: `"https://shannon-explorer.somnia.network"` = `"https://shannon-explorer.somnia.network"` #### blockExplorers.default.apiUrl > `readonly` **apiUrl**: `"https://shannon-explorer.somnia.network/api"` = `"https://shannon-explorer.somnia.network/api"` ### blockTime > **blockTime**: `100` Block time in milliseconds. ### contracts > **contracts**: `object` Collection of contracts #### contracts.multicall3 > `readonly` **multicall3**: `object` #### contracts.multicall3.address > `readonly` **address**: `"0x841b8199E6d3Db3C6f264f6C2bd8848b3cA64223"` = `"0x841b8199E6d3Db3C6f264f6C2bd8848b3cA64223"` #### contracts.multicall3.blockCreated > `readonly` **blockCreated**: `71314235` = `71314235` ### id > **id**: `50312` ID in number form ### name > **name**: `"Somnia Testnet"` Human-readable name ### nativeCurrency > **nativeCurrency**: `object` Currency used by chain #### nativeCurrency.name > `readonly` **name**: `"STT"` = `"STT"` #### nativeCurrency.symbol > `readonly` **symbol**: `"STT"` = `"STT"` #### nativeCurrency.decimals > `readonly` **decimals**: `18` = `18` ### rpcUrls > **rpcUrls**: `object` Collection of RPC endpoints #### rpcUrls.default > `readonly` **default**: `object` #### rpcUrls.default.http > `readonly` **http**: readonly \[`"https://api.infra.testnet.somnia.network"`, `"https://dream-rpc.somnia.network"`\] #### rpcUrls.default.webSocket > `readonly` **webSocket**: readonly \[`"wss://api.infra.testnet.somnia.network/ws"`, `"wss://dream-rpc.somnia.network/ws"`\] ### testnet > **testnet**: `true` Flag for test networks --- # /docs/typescript/api/chains/variables/warpRouterAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [chains](../README.md) / warpRouterAbi # Variable: warpRouterAbi > `const` **warpRouterAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/chains/bridge/abi.ts:28 The Warp Route router surface used to bridge and to preflight a bridge. `transferRemote` is the one write: selector `0x81b4e8b4`, payable, returns the dispatched message id. On a **native** route the amount rides in `msg.value`; on a **collateral** route the router pulls a pre-approved ERC-20 and `msg.value` carries only the (currently zero) interchain gas payment; on a **synthetic** route the router burns the sender's balance, no approval needed. --- # /docs/typescript/api/index [**@somnia-chain/markets-sdk**](../README.md) *** [@somnia-chain/markets-sdk](../README.md) / index # index ## ABIs - [orderBookEventsAbi](variables/orderBookEventsAbi.md) - [marginBankEventsAbi](variables/marginBankEventsAbi.md) - [liquidationEngineEventsAbi](variables/liquidationEngineEventsAbi.md) - [oracleHubAbi](variables/oracleHubAbi.md) - [oracleHubEventsAbi](variables/oracleHubEventsAbi.md) - [binaryModuleWriteAbi](variables/binaryModuleWriteAbi.md) - [binaryModuleReadAbi](variables/binaryModuleReadAbi.md) - [binarySettlementAbi](variables/binarySettlementAbi.md) - [erc6909Abi](variables/erc6909Abi.md) - [binaryPoolWriteAbi](variables/binaryPoolWriteAbi.md) - [spotPoolWriteAbi](variables/spotPoolWriteAbi.md) - [perpPoolWriteAbi](variables/perpPoolWriteAbi.md) ## accounts - [AccountAuthorizationTypedData](type-aliases/AccountAuthorizationTypedData.md) - [PreparedAccountAuthorization](interfaces/PreparedAccountAuthorization.md) - [UnsignedAccountCreation](interfaces/UnsignedAccountCreation.md) - [PreparedAccountExecution](interfaces/PreparedAccountExecution.md) - [SmartAccountsClient](interfaces/SmartAccountsClient.md) - [SmartAccountInner](type-aliases/SmartAccountInner.md) - [ExchangeSmartAccounts](interfaces/ExchangeSmartAccounts.md) ## activity - [byNewestFirst](functions/byNewestFirst.md) ## administration ### GovernanceAdminConfig Renames and re-exports [OracleHubAdminConfig](interfaces/OracleHubAdminConfig.md) *** ### MarketCreatorAdminConfig Renames and re-exports [OracleHubAdminConfig](interfaces/OracleHubAdminConfig.md) ## analytics - [BinaryOrderQuote](interfaces/BinaryOrderQuote.md) - [quoteBinaryOrderOverBook](functions/quoteBinaryOrderOverBook.md) - [MarketStats24h](interfaces/MarketStats24h.md) - [marketStats24hFromCandles](functions/marketStats24hFromCandles.md) - [BinaryOutcomePositionPnL](interfaces/BinaryOutcomePositionPnL.md) - [BinaryPositionPnL](interfaces/BinaryPositionPnL.md) - [PnLEvent](interfaces/PnLEvent.md) - [pnlEventsFor](functions/pnlEventsFor.md) - [computePositionPnL](functions/computePositionPnL.md) - [ClaimablePosition](interfaces/ClaimablePosition.md) - [ClaimableInput](interfaces/ClaimableInput.md) - [estPayoutFor](functions/estPayoutFor.md) - [claimableFrom](functions/claimableFrom.md) - [DEFAULT\_SLIPPAGE\_BPS](variables/DEFAULT_SLIPPAGE_BPS.md) - [DEFAULT\_SLIPPAGE\_MIN\_TICKS](variables/DEFAULT_SLIPPAGE_MIN_TICKS.md) - [BinaryCrossingParams](interfaces/BinaryCrossingParams.md) - [slippageForCrossing](functions/slippageForCrossing.md) - [BinaryBuySide](type-aliases/BinaryBuySide.md) - [BinarySellSide](type-aliases/BinarySellSide.md) - [BinaryStakeQuote](interfaces/BinaryStakeQuote.md) - [quoteBinaryStakeOverBook](functions/quoteBinaryStakeOverBook.md) - [BinarySellQuote](interfaces/BinarySellQuote.md) - [quoteBinarySellOverBook](functions/quoteBinarySellOverBook.md) - [midYesPrice](functions/midYesPrice.md) - [EntryTrade](interfaces/EntryTrade.md) - [averageEntryPrice](functions/averageEntryPrice.md) - [outcomeMarkPrice](functions/outcomeMarkPrice.md) - [OutcomePositionMark](interfaces/OutcomePositionMark.md) - [markOutcomePosition](functions/markOutcomePosition.md) - [PositionMarkState](type-aliases/PositionMarkState.md) - [positionMarkState](functions/positionMarkState.md) - [PortfolioTimeframe](type-aliases/PortfolioTimeframe.md) - [PortfolioTradeEvent](interfaces/PortfolioTradeEvent.md) - [PortfolioFundingEvent](interfaces/PortfolioFundingEvent.md) - [netInternalTransfers](functions/netInternalTransfers.md) - [PortfolioFlowEvent](type-aliases/PortfolioFlowEvent.md) - [MarkSeries](type-aliases/MarkSeries.md) - [MarkSources](interfaces/MarkSources.md) - [EquityPoint](interfaces/EquityPoint.md) - [HoldingsPoint](interfaces/HoldingsPoint.md) - [PnlBucket](interfaces/PnlBucket.md) - [PortfolioAnalytics](interfaces/PortfolioAnalytics.md) - [DEFAULT\_CEX\_RATE\_BPS](variables/DEFAULT_CEX_RATE_BPS.md) - [PortfolioAnalyticsOptions](interfaces/PortfolioAnalyticsOptions.md) - [ComputePortfolioAnalyticsError](type-aliases/ComputePortfolioAnalyticsError.md) - [computePortfolioAnalytics](functions/computePortfolioAnalytics.md) ## balances - [Erc20Metadata](interfaces/Erc20Metadata.md) - [BalanceQuery](interfaces/BalanceQuery.md) ## binary markets - [binaryMarketTypePlugin](variables/binaryMarketTypePlugin.md) - [OutcomeBalances](type-aliases/OutcomeBalances.md) - [PortfolioMarket](type-aliases/PortfolioMarket.md) - [PortfolioPosition](type-aliases/PortfolioPosition.md) - [OpenPositionPnL](type-aliases/OpenPositionPnL.md) - [PortfolioOrder](type-aliases/PortfolioOrder.md) - [PortfolioTrade](type-aliases/PortfolioTrade.md) - [Portfolio](type-aliases/Portfolio.md) - [PortfolioOptions](type-aliases/PortfolioOptions.md) - [GetVaultBalanceParams](interfaces/GetVaultBalanceParams.md) - [GetOutcomeBalanceParams](interfaces/GetOutcomeBalanceParams.md) - [VaultPayoutFallback](type-aliases/VaultPayoutFallback.md) - [ListVaultPayoutFallbacksOptions](interfaces/ListVaultPayoutFallbacksOptions.md) - [MarketResolutionEvent](type-aliases/MarketResolutionEvent.md) - [MarketReferenceLink](type-aliases/MarketReferenceLink.md) - [OracleAnswer](type-aliases/OracleAnswer.md) - [MarketResolutionKind](type-aliases/MarketResolutionKind.md) - [ListMarketResolutionEventsOptions](interfaces/ListMarketResolutionEventsOptions.md) - [ListMarketReferenceLinksOptions](interfaces/ListMarketReferenceLinksOptions.md) ## bridging - [ExchangeBridgeParams](interfaces/ExchangeBridgeParams.md) - [BridgeStepEvent](interfaces/BridgeStepEvent.md) - [ExchangeBridgeTransferOptions](interfaces/ExchangeBridgeTransferOptions.md) - [ExchangeBridgeResult](interfaces/ExchangeBridgeResult.md) - [ExchangeBridge](interfaces/ExchangeBridge.md) ## caching - [QUERY\_KEY\_SCOPE](variables/QUERY_KEY_SCOPE.md) - [QueryKeyElement](type-aliases/QueryKeyElement.md) - [ClientQueryKey](type-aliases/ClientQueryKey.md) - [QueryKeyChainOptions](interfaces/QueryKeyChainOptions.md) - [marketsKey](functions/marketsKey.md) - [portfolioKey](functions/portfolioKey.md) - [candlesKey](functions/candlesKey.md) - [marketActivityKey](functions/marketActivityKey.md) - [tradeContextKey](functions/tradeContextKey.md) - [transactionActivityKey](functions/transactionActivityKey.md) - [blockActivityKey](functions/blockActivityKey.md) - [marketFeesKey](functions/marketFeesKey.md) - [operatorsKey](functions/operatorsKey.md) - [marketCreatorsKey](functions/marketCreatorsKey.md) - [oracleAdaptersKey](functions/oracleAdaptersKey.md) - [syncStatusKey](functions/syncStatusKey.md) - [maxVenueFeeBpsKey](functions/maxVenueFeeBpsKey.md) - [marketOnchainKey](functions/marketOnchainKey.md) ## clients - [SomniaMarketsAccount](interfaces/SomniaMarketsAccount.md) - [SomniaMarketsClient](interfaces/SomniaMarketsClient.md) - [SomniaMarketsSignerConfig](interfaces/SomniaMarketsSignerConfig.md) - [SomniaMarketsChainsConfig](interfaces/SomniaMarketsChainsConfig.md) - [SomniaMarketsConfig](type-aliases/SomniaMarketsConfig.md) - [FetchOrderBookOptions](interfaces/FetchOrderBookOptions.md) - [SomniaMarketsFetchPortfolioAnalyticsOptions](interfaces/SomniaMarketsFetchPortfolioAnalyticsOptions.md) - [SomniaMarketsChainFilter](interfaces/SomniaMarketsChainFilter.md) - [SomniaMarketsGetOrdersPageOptions](type-aliases/SomniaMarketsGetOrdersPageOptions.md) - [SomniaMarketsGetOrderHistoryPageOptions](type-aliases/SomniaMarketsGetOrderHistoryPageOptions.md) - [CreateOrderParams](interfaces/CreateOrderParams.md) - [RedeemOptions](interfaces/RedeemOptions.md) ## configuration - [SOMNIA\_TESTNET\_ADDRESSES](variables/SOMNIA_TESTNET_ADDRESSES.md) - [SOMNIA\_MAINNET\_ADDRESSES](variables/SOMNIA_MAINNET_ADDRESSES.md) - [SOMNIA\_HIDEKI\_TESTNET\_ADDRESSES](variables/SOMNIA_HIDEKI_TESTNET_ADDRESSES.md) - [SomniaMarketsAddresses](interfaces/SomniaMarketsAddresses.md) - [PriceFeedConfig](interfaces/PriceFeedConfig.md) - [SOMNIA\_TESTNET\_PRICE\_FEED](variables/SOMNIA_TESTNET_PRICE_FEED.md) - [SOMNIA\_MAINNET\_PRICE\_FEED](variables/SOMNIA_MAINNET_PRICE_FEED.md) - [FixedFees](interfaces/FixedFees.md) - [DEFAULT\_FEES](variables/DEFAULT_FEES.md) - [IndexerLimits](interfaces/IndexerLimits.md) - [DEFAULT\_INDEXER\_LIMITS](variables/DEFAULT_INDEXER_LIMITS.md) - [nextBackoffDelayMs](functions/nextBackoffDelayMs.md) - [ClientConfig](interfaces/ClientConfig.md) - [ChainBinding](type-aliases/ChainBinding.md) - [TailReconciliationConfig](interfaces/TailReconciliationConfig.md) ## converting - [IntervalSource](type-aliases/IntervalSource.md) - [resolveIntervalSec](functions/resolveIntervalSec.md) - [snapIntervalSec](functions/snapIntervalSec.md) - [CADENCE\_LADDER\_SEC](variables/CADENCE_LADDER_SEC.md) - [CADENCE\_TOLERANCE\_SEC](variables/CADENCE_TOLERANCE_SEC.md) - [snapToCadence](functions/snapToCadence.md) - [cadenceBandSec](functions/cadenceBandSec.md) - [formatIntervalLabel](functions/formatIntervalLabel.md) - [marketIntervalLabel](functions/marketIntervalLabel.md) - [toHuman](functions/toHuman.md) - [toHumanString](functions/toHumanString.md) - [fromHuman](functions/fromHuman.md) - [priceToProbability](functions/priceToProbability.md) - [probabilityToPrice](functions/probabilityToPrice.md) - [YesBookTop](interfaces/YesBookTop.md) - [markYesPrice](functions/markYesPrice.md) - [BinaryOutcomePnl](interfaces/BinaryOutcomePnl.md) - [BinaryPnl](interfaces/BinaryPnl.md) - [BinaryPnlFill](interfaces/BinaryPnlFill.md) - [binaryFillsFor](functions/binaryFillsFor.md) - [binaryFillsFromPortfolio](functions/binaryFillsFromPortfolio.md) - [computeBinaryPnl](functions/computeBinaryPnl.md) - [balanceFloor](functions/balanceFloor.md) - [floorRawBalance](functions/floorRawBalance.md) - [ceilRawAmount](functions/ceilRawAmount.md) - [snapRawToGrid](functions/snapRawToGrid.md) - [roundPriceToTick](functions/roundPriceToTick.md) - [upProbability](functions/upProbability.md) - [upPercent](functions/upPercent.md) ## encoding - [OutcomeIdx](type-aliases/OutcomeIdx.md) - [outcomeId](functions/outcomeId.md) - [DecodedOutcomeId](interfaces/DecodedOutcomeId.md) - [decodeOutcomeId](functions/decodeOutcomeId.md) - [marketKey](functions/marketKey.md) ## errors - [DecodeAmendOrdersError](type-aliases/DecodeAmendOrdersError.md) - [SomniaMarketsError](classes/SomniaMarketsError.md) - [InvalidInputError](classes/InvalidInputError.md) - [FillHistoryRestartRequiredError](classes/FillHistoryRestartRequiredError.md) - [FillHistoryUnavailableError](classes/FillHistoryUnavailableError.md) - [NotConfiguredError](classes/NotConfiguredError.md) - [SignerRequiredError](classes/SignerRequiredError.md) - [IndexerError](classes/IndexerError.md) - [IncompleteHistoryError](classes/IncompleteHistoryError.md) - [IndexerWaitTimeoutError](classes/IndexerWaitTimeoutError.md) - [RpcError](classes/RpcError.md) - [TransactionOutcomeUnknownError](classes/TransactionOutcomeUnknownError.md) - [ContractRevertError](classes/ContractRevertError.md) - [CollateralReadError](type-aliases/CollateralReadError.md) - [IndexerRefusalReason](type-aliases/IndexerRefusalReason.md) - [IndexerUnavailableError](classes/IndexerUnavailableError.md) - [CollateralOnWrongChainError](classes/CollateralOnWrongChainError.md) - [BridgeLiquidityError](classes/BridgeLiquidityError.md) - [BridgeDeliveryTimeoutError](classes/BridgeDeliveryTimeoutError.md) - [AssertCallsOnChainError](type-aliases/AssertCallsOnChainError.md) - [ExecutorExecuteError](type-aliases/ExecutorExecuteError.md) - [ExecutorSignTypedDataError](type-aliases/ExecutorSignTypedDataError.md) - [SmartAccountsReadError](type-aliases/SmartAccountsReadError.md) - [SmartAccountsBuildError](type-aliases/SmartAccountsBuildError.md) - [SomniaMarketsClientGetBinaryOrderBookError](type-aliases/SomniaMarketsClientGetBinaryOrderBookError.md) - [SomniaMarketsClientGetSpotOrderBookError](type-aliases/SomniaMarketsClientGetSpotOrderBookError.md) - [SomniaMarketsClientGetOrderOnchainError](type-aliases/SomniaMarketsClientGetOrderOnchainError.md) - [ExchangeBridgeTransferError](type-aliases/ExchangeBridgeTransferError.md) - [SomniaMarketsFetchOrderBookError](type-aliases/SomniaMarketsFetchOrderBookError.md) - [SomniaMarketsConstructorError](type-aliases/SomniaMarketsConstructorError.md) - [SomniaMarketsClientError](type-aliases/SomniaMarketsClientError.md) - [SomniaMarketsTraderForError](type-aliases/SomniaMarketsTraderForError.md) - [SomniaMarketsTraderError](type-aliases/SomniaMarketsTraderError.md) - [SomniaMarketsSetSignerError](type-aliases/SomniaMarketsSetSignerError.md) - [SomniaMarketsLoadMarketsError](type-aliases/SomniaMarketsLoadMarketsError.md) - [SomniaMarketsFetchTradesError](type-aliases/SomniaMarketsFetchTradesError.md) - [SomniaMarketsFetchMyTradesError](type-aliases/SomniaMarketsFetchMyTradesError.md) - [SomniaMarketsFetchPortfolioAnalyticsError](type-aliases/SomniaMarketsFetchPortfolioAnalyticsError.md) - [SomniaMarketsWatchTradesError](type-aliases/SomniaMarketsWatchTradesError.md) - [SomniaMarketsWatchMyTradesError](type-aliases/SomniaMarketsWatchMyTradesError.md) - [SomniaMarketsWatchOrderBookError](type-aliases/SomniaMarketsWatchOrderBookError.md) - [SomniaMarketsGetOrdersPageError](type-aliases/SomniaMarketsGetOrdersPageError.md) - [SomniaMarketsGetOrderHistoryPageError](type-aliases/SomniaMarketsGetOrderHistoryPageError.md) ## fees - [ProtocolFeeRecord](type-aliases/ProtocolFeeRecord.md) - [BuilderFeeRecord](type-aliases/BuilderFeeRecord.md) - [SettlementFeeRecord](type-aliases/SettlementFeeRecord.md) - [BuilderApproval](type-aliases/BuilderApproval.md) - [BuilderApprovalRef](interfaces/BuilderApprovalRef.md) ## fills - [FillsOptions](type-aliases/FillsOptions.md) - [FillsScope](type-aliases/FillsScope.md) - [FillsPageOptions](type-aliases/FillsPageOptions.md) - [FillsPage](type-aliases/FillsPage.md) - [LatestFillBlock](type-aliases/LatestFillBlock.md) - [FillRow](type-aliases/FillRow.md) ## funding - [FUNDING\_PRECISION](variables/FUNDING_PRECISION.md) - [EIGHT\_HOURS\_SEC](variables/EIGHT_HOURS_SEC.md) - [ONE\_HOUR\_SEC](variables/ONE_HOUR_SEC.md) - [ONE\_YEAR\_SEC](variables/ONE_YEAR_SEC.md) - [normalizeFundingRate](functions/normalizeFundingRate.md) - [fundingRate8h](functions/fundingRate8h.md) - [fundingRate1h](functions/fundingRate1h.md) - [fundingRatePerInterval](functions/fundingRatePerInterval.md) - [annualizedFundingRate](functions/annualizedFundingRate.md) - [intervalsPerWindow](functions/intervalsPerWindow.md) - [realizedFundingPerBase](functions/realizedFundingPerBase.md) - [isFundingStale](functions/isFundingStale.md) - [FundingBucketLike](interfaces/FundingBucketLike.md) - [densifyFundingBuckets](functions/densifyFundingBuckets.md) - [FundingSeriesBucket](type-aliases/FundingSeriesBucket.md) - [FundingRateSeries](type-aliases/FundingRateSeries.md) - [buildFundingRateSeries](functions/buildFundingRateSeries.md) - [NATIVE\_TOKEN\_SENTINEL](variables/NATIVE_TOKEN_SENTINEL.md) ## indexing - [CountResult](type-aliases/CountResult.md) - [IndexerSyncStatus](type-aliases/IndexerSyncStatus.md) - [WaitForIndexedBlockOptions](type-aliases/WaitForIndexedBlockOptions.md) - [IndexedBlockWait](type-aliases/IndexedBlockWait.md) ## lending - [SomniaLendClient](interfaces/SomniaLendClient.md) - [SOMNIA\_MAINNET\_LEND](variables/SOMNIA_MAINNET_LEND.md) - [SOMNIA\_TESTNET\_LEND](variables/SOMNIA_TESTNET_LEND.md) - [lendPoolAbi](variables/lendPoolAbi.md) - [lendUiPoolDataProviderAbi](variables/lendUiPoolDataProviderAbi.md) - [lendGatewayAbi](variables/lendGatewayAbi.md) - [lendDebtTokenAbi](variables/lendDebtTokenAbi.md) - [LenderConfig](type-aliases/LenderConfig.md) - [LendWriteOptions](interfaces/LendWriteOptions.md) - [LendSupplyOptions](interfaces/LendSupplyOptions.md) - [LendWithdrawOptions](interfaces/LendWithdrawOptions.md) - [LendRepayOptions](interfaces/LendRepayOptions.md) - [Lender](interfaces/Lender.md) - [RAY](variables/RAY.md) - [rayMul](functions/rayMul.md) - [accrueLinear](functions/accrueLinear.md) - [accrueCompounded](functions/accrueCompounded.md) - [lendRayRateToApy](functions/lendRayRateToApy.md) - [LendAddresses](interfaces/LendAddresses.md) - [LendReserve](interfaces/LendReserve.md) - [LendPosition](interfaces/LendPosition.md) - [LendAccount](interfaces/LendAccount.md) ## live - [PoolSeedStatus](interfaces/PoolSeedStatus.md) ## live data - [SeedOptions](interfaces/SeedOptions.md) - [WatchHandle](interfaces/WatchHandle.md) - [WatchStatus](type-aliases/WatchStatus.md) - [WatchPerpMarketsOptions](interfaces/WatchPerpMarketsOptions.md) - [ListLiveLiquidationsOptions](interfaces/ListLiveLiquidationsOptions.md) - [ListLiveFundingPaymentsOptions](interfaces/ListLiveFundingPaymentsOptions.md) - [TailMode](type-aliases/TailMode.md) - [SeedSource](type-aliases/SeedSource.md) - [BinarySide](type-aliases/BinarySide.md) - [BinaryFillKind](type-aliases/BinaryFillKind.md) - [OrderStatus](type-aliases/OrderStatus.md) - [BinaryMarketStatus](type-aliases/BinaryMarketStatus.md) - [TailStatus](interfaces/TailStatus.md) - [TailFailure](interfaces/TailFailure.md) - [TailDivergence](interfaces/TailDivergence.md) - [LiveMarket](type-aliases/LiveMarket.md) - [LiveFundingUpdate](interfaces/LiveFundingUpdate.md) - [LiveFill](interfaces/LiveFill.md) - [LiveOrder](interfaces/LiveOrder.md) - [BookLevel](interfaces/BookLevel.md) - [DECIMALS](variables/DECIMALS.md) - [ORDER\_KIND\_SIDE](variables/ORDER_KIND_SIDE.md) - [sideOfKind](functions/sideOfKind.md) - [fillKind](functions/fillKind.md) ## logging - [DebugEvent](type-aliases/DebugEvent.md) - [Span](interfaces/Span.md) - [consoleDebugSink](functions/consoleDebugSink.md) - [DebugCollector](interfaces/DebugCollector.md) - [debugCollector](functions/debugCollector.md) ## market types - [MARKET\_TYPE\_PLUGINS](variables/MARKET_TYPE_PLUGINS.md) - [getMarketTypePlugin](functions/getMarketTypePlugin.md) - [listMarketTypePlugins](functions/listMarketTypePlugins.md) - [MachineryStep](interfaces/MachineryStep.md) - [MarketTypePlugin](interfaces/MarketTypePlugin.md) ## markets - [MarketType](type-aliases/MarketType.md) - [BaseMarket](type-aliases/BaseMarket.md) - [SpotMarket](type-aliases/SpotMarket.md) - [PerpMarket](type-aliases/PerpMarket.md) - [BinaryMarket](type-aliases/BinaryMarket.md) - [Market](type-aliases/Market.md) - [isBinaryMarket](functions/isBinaryMarket.md) - [isSpotMarket](functions/isSpotMarket.md) - [isPerpMarket](functions/isPerpMarket.md) - [BinaryResolutionMode](type-aliases/BinaryResolutionMode.md) - [binaryResolutionMode](functions/binaryResolutionMode.md) - [BinaryMarketFilter](type-aliases/BinaryMarketFilter.md) - [BinaryMarketOrderBy](type-aliases/BinaryMarketOrderBy.md) - [RegistrySweep](interfaces/RegistrySweep.md) - [BinaryMarketCountOptions](type-aliases/BinaryMarketCountOptions.md) - [MarketFees](type-aliases/MarketFees.md) - [SpotMarketFilter](type-aliases/SpotMarketFilter.md) - [MarketStatusUpdate](type-aliases/MarketStatusUpdate.md) - [PerpMarketFilter](type-aliases/PerpMarketFilter.md) - [LiveBinaryMarketsFilter](type-aliases/LiveBinaryMarketsFilter.md) - [PastBinaryMarketsOptions](type-aliases/PastBinaryMarketsOptions.md) - [boundaryPrice](functions/boundaryPrice.md) - [MarketOnchain](interfaces/MarketOnchain.md) - [OnchainResolutionPrice](interfaces/OnchainResolutionPrice.md) - [MarketOnchainSources](interfaces/MarketOnchainSources.md) - [PoolMarketBinding](interfaces/PoolMarketBinding.md) - [GetPoolMarketBindingOptions](interfaces/GetPoolMarketBindingOptions.md) - [ContractMeta](interfaces/ContractMeta.md) ## models - [Candle](type-aliases/Candle.md) - [CANDLE\_INTERVALS](variables/CANDLE_INTERVALS.md) - [ChainMarketRef](interfaces/ChainMarketRef.md) - [ChainOrderRef](interfaces/ChainOrderRef.md) - [MarketHandle](type-aliases/MarketHandle.md) - [OracleHubAdminConfig](interfaces/OracleHubAdminConfig.md) - [UnifiedOrderIdentity](type-aliases/UnifiedOrderIdentity.md) - [UnifiedOrderPageItem](type-aliases/UnifiedOrderPageItem.md) - [UnifiedOrdersPage](type-aliases/UnifiedOrdersPage.md) - [UnifiedMarketType](type-aliases/UnifiedMarketType.md) - [UnifiedMarket](interfaces/UnifiedMarket.md) - [UnifiedOrderBook](interfaces/UnifiedOrderBook.md) - [UnifiedTrade](interfaces/UnifiedTrade.md) - [UnifiedOrderStatus](type-aliases/UnifiedOrderStatus.md) - [UnifiedOrder](interfaces/UnifiedOrder.md) - [UnifiedStopOrderStatus](type-aliases/UnifiedStopOrderStatus.md) - [UnifiedStopOrder](interfaces/UnifiedStopOrder.md) - [UnifiedBalance](interfaces/UnifiedBalance.md) - [UnifiedChainBalance](interfaces/UnifiedChainBalance.md) - [UnifiedBalances](interfaces/UnifiedBalances.md) - [UnifiedOHLCV](type-aliases/UnifiedOHLCV.md) - [UnifiedTicker](interfaces/UnifiedTicker.md) - [UnifiedFundingRate](interfaces/UnifiedFundingRate.md) - [UnifiedPosition](interfaces/UnifiedPosition.md) - [UnifiedPrice](interfaces/UnifiedPrice.md) - [TIMEFRAMES](variables/TIMEFRAMES.md) - [Tradable](interfaces/Tradable.md) ## oracles - [QUESTION\_SOURCE\_TYPE](variables/QUESTION_SOURCE_TYPE.md) - [ANSWER\_TYPE](variables/ANSWER_TYPE.md) - [QuestionSourceInput](interfaces/QuestionSourceInput.md) - [QuestionIntervalInput](interfaces/QuestionIntervalInput.md) - [ValidAnswersInput](interfaces/ValidAnswersInput.md) - [QuestionDefinitionInput](interfaces/QuestionDefinitionInput.md) - [HubQuestionState](interfaces/HubQuestionState.md) - [HubStatus](interfaces/HubStatus.md) - [ScheduleQuestionParams](interfaces/ScheduleQuestionParams.md) - [ScheduleQuestionResult](interfaces/ScheduleQuestionResult.md) - [WithdrawParams](interfaces/WithdrawParams.md) - [WithdrawMyCreditParams](interfaces/WithdrawMyCreditParams.md) - [FundHubParams](interfaces/FundHubParams.md) - [SetHubGasParams](interfaces/SetHubGasParams.md) - [SetHubDrainParams](interfaces/SetHubDrainParams.md) - [EnableHubReactivityParams](interfaces/EnableHubReactivityParams.md) - [OracleHubAdmin](interfaces/OracleHubAdmin.md) - [OracleQuestionRecord](type-aliases/OracleQuestionRecord.md) - [OperatorHubAccountRecord](type-aliases/OperatorHubAccountRecord.md) - [OracleBindRecord](type-aliases/OracleBindRecord.md) - [OracleCallbackRecord](type-aliases/OracleCallbackRecord.md) ## orders - [OrderMarket](type-aliases/OrderMarket.md) - [OpenOrder](type-aliases/OpenOrder.md) - [OrdersOptions](type-aliases/OrdersOptions.md) - [OrderRow](type-aliases/OrderRow.md) - [BookTop](type-aliases/BookTop.md) - [GetBookTopsOnchainOptions](interfaces/GetBookTopsOnchainOptions.md) - [BookTopsOnchain](interfaces/BookTopsOnchain.md) - [BinaryOrderBook](interfaces/BinaryOrderBook.md) - [BinaryBookParams](interfaces/BinaryBookParams.md) - [ClosingPriceState](interfaces/ClosingPriceState.md) - [OnchainOrder](interfaces/OnchainOrder.md) - [GetOrderOnchainOptions](interfaces/GetOrderOnchainOptions.md) - [OpenOrdersOnchain](interfaces/OpenOrdersOnchain.md) - [GetOwnOpenOrdersOnchainOptions](interfaces/GetOwnOpenOrdersOnchainOptions.md) - [OPEN\_ORDERS\_ONCHAIN\_MAX\_POOLS](variables/OPEN_ORDERS_ONCHAIN_MAX_POOLS.md) - [GetOpenOrdersOnchainOptions](interfaces/GetOpenOrdersOnchainOptions.md) - [GetBinaryOrderBookOptions](interfaces/GetBinaryOrderBookOptions.md) - [GetSpotOrderBookOptions](interfaces/GetSpotOrderBookOptions.md) - [SpotOrderBook](interfaces/SpotOrderBook.md) - [SweepableOrder](type-aliases/SweepableOrder.md) ## Other - [isSomniaMarketsAccount](functions/isSomniaMarketsAccount.md) - [MarketActivityKind](type-aliases/MarketActivityKind.md) - [MarketActivityBase](type-aliases/MarketActivityBase.md) - [MarketTradeActivity](type-aliases/MarketTradeActivity.md) - [MarketSupplyActivity](type-aliases/MarketSupplyActivity.md) - [MarketResolutionActivity](type-aliases/MarketResolutionActivity.md) - [MarketStatusActivity](type-aliases/MarketStatusActivity.md) - [MarketActivity](type-aliases/MarketActivity.md) - [MarketActivityOptions](type-aliases/MarketActivityOptions.md) - [TransactionOrder](type-aliases/TransactionOrder.md) - [TransactionActivity](type-aliases/TransactionActivity.md) - [TransactionActivityOptions](type-aliases/TransactionActivityOptions.md) - [BlockTimestampResolver](type-aliases/BlockTimestampResolver.md) - [BlockOrderTouch](type-aliases/BlockOrderTouch.md) - [BlockOrder](type-aliases/BlockOrder.md) - [BlockMarketActivity](type-aliases/BlockMarketActivity.md) - [BlockActivity](type-aliases/BlockActivity.md) - [BlockActivityOptions](type-aliases/BlockActivityOptions.md) - [isChainMarketRef](functions/isChainMarketRef.md) - [isChainOrderRef](functions/isChainOrderRef.md) - [chainMarketRef](functions/chainMarketRef.md) - [chainOrderRef](functions/chainOrderRef.md) - [contractErrorsAbi](variables/contractErrorsAbi.md) - [PnlEventsForError](type-aliases/PnlEventsForError.md) - [ComputePositionPnLError](type-aliases/ComputePositionPnLError.md) - [EstPayoutForError](type-aliases/EstPayoutForError.md) - [ClaimableFromError](type-aliases/ClaimableFromError.md) - [perpPoolEventsAbi](variables/perpPoolEventsAbi.md) - [GetUserFillsPageOptions](type-aliases/GetUserFillsPageOptions.md) - [UserFillsPage](type-aliases/UserFillsPage.md) - [OrderFillRow](type-aliases/OrderFillRow.md) - [MarketRef](type-aliases/MarketRef.md) - [FillDetail](type-aliases/FillDetail.md) - [FillOrder](type-aliases/FillOrder.md) - [TradeContext](type-aliases/TradeContext.md) - [NetworkTapeOptions](interfaces/NetworkTapeOptions.md) - [TapeOrder](interfaces/TapeOrder.md) - [TapeFill](interfaces/TapeFill.md) - [NetworkTapeStatus](interfaces/NetworkTapeStatus.md) - [NetworkTape](classes/NetworkTape.md) - [ObservedReadOperation](type-aliases/ObservedReadOperation.md) - [ObservedReadMethods](type-aliases/ObservedReadMethods.md) - [ObservedReadRequest](type-aliases/ObservedReadRequest.md) - [IndexerObservation](interfaces/IndexerObservation.md) - [ObservedReadResult](interfaces/ObservedReadResult.md) - [ObservedReadsReadError](type-aliases/ObservedReadsReadError.md) - [ObservedReadsBatchError](type-aliases/ObservedReadsBatchError.md) - [SomniaMarketsClientCreateObservedReadsError](type-aliases/SomniaMarketsClientCreateObservedReadsError.md) - [SomniaMarketsClientGetIndexerFreshnessError](type-aliases/SomniaMarketsClientGetIndexerFreshnessError.md) - [SomniaMarketsClientGetSyncStatusError](type-aliases/SomniaMarketsClientGetSyncStatusError.md) - [ObservedReads](interfaces/ObservedReads.md) - [OrderDetail](type-aliases/OrderDetail.md) - [~~GetLiquidationsOptions~~](type-aliases/GetLiquidationsOptions.md) - [PerpStopOrderRef](type-aliases/PerpStopOrderRef.md) - [PerpStopOrderReadError](type-aliases/PerpStopOrderReadError.md) - [PerpStopOrderRead](type-aliases/PerpStopOrderRead.md) - [InvariantError](classes/InvariantError.md) - [spotPoolOperatorRegistryReadAbi](variables/spotPoolOperatorRegistryReadAbi.md) - [RevertContext](interfaces/RevertContext.md) - [decodeRevert](functions/decodeRevert.md) - [SomniaMarketsClientGetBinaryPositionPnLError](type-aliases/SomniaMarketsClientGetBinaryPositionPnLError.md) - [SomniaMarketsClientGetOpenPositionsWithPnLError](type-aliases/SomniaMarketsClientGetOpenPositionsWithPnLError.md) - [SomniaMarketsClientCreateTraderError](type-aliases/SomniaMarketsClientCreateTraderError.md) - [SomniaMarketsClientCreateExecutorError](type-aliases/SomniaMarketsClientCreateExecutorError.md) - [SomniaMarketsClientGetClaimableError](type-aliases/SomniaMarketsClientGetClaimableError.md) - [SomniaMarketsClientGetUserFillsPageError](type-aliases/SomniaMarketsClientGetUserFillsPageError.md) - [SomniaMarketsClientGetPerpStopOrderError](type-aliases/SomniaMarketsClientGetPerpStopOrderError.md) - [SomniaMarketsClientGetPerpStopOrdersError](type-aliases/SomniaMarketsClientGetPerpStopOrdersError.md) - [SomniaMarketsClientListLiquidationsError](type-aliases/SomniaMarketsClientListLiquidationsError.md) - [SomniaMarketsClientListVaultPayoutFallbacksError](type-aliases/SomniaMarketsClientListVaultPayoutFallbacksError.md) - [~~SomniaMarketsClientGetLiquidationsError~~](type-aliases/SomniaMarketsClientGetLiquidationsError.md) - [SomniaMarketsClientListRegistryMarketsCheckedError](type-aliases/SomniaMarketsClientListRegistryMarketsCheckedError.md) - [SomniaMarketsClientListPoolBindingsError](type-aliases/SomniaMarketsClientListPoolBindingsError.md) - [SomniaMarketsClientListSeriesLatestMarketsError](type-aliases/SomniaMarketsClientListSeriesLatestMarketsError.md) - [SomniaMarketsClientGetPerpFeedStatusError](type-aliases/SomniaMarketsClientGetPerpFeedStatusError.md) - [SomniaMarketsClientGetPerpVoucherCampaignError](type-aliases/SomniaMarketsClientGetPerpVoucherCampaignError.md) - [SomniaMarketsClientGetPerpVoucherEligibilityError](type-aliases/SomniaMarketsClientGetPerpVoucherEligibilityError.md) - [SomniaMarketsClientGetPerpVoucherError](type-aliases/SomniaMarketsClientGetPerpVoucherError.md) - [SomniaMarketsClientGetOpenOrdersError](type-aliases/SomniaMarketsClientGetOpenOrdersError.md) - [SomniaMarketsClientGetOrdersError](type-aliases/SomniaMarketsClientGetOrdersError.md) - [SomniaMarketsClientCountOrdersError](type-aliases/SomniaMarketsClientCountOrdersError.md) - [SomniaMarketsClientGetFillsError](type-aliases/SomniaMarketsClientGetFillsError.md) - [SomniaMarketsClientGetOrderFillsError](type-aliases/SomniaMarketsClientGetOrderFillsError.md) - [SomniaMarketsClientGetUserFillsError](type-aliases/SomniaMarketsClientGetUserFillsError.md) - [SomniaMarketsClientGetFillsPageError](type-aliases/SomniaMarketsClientGetFillsPageError.md) - [SomniaMarketsClientGetLatestFillBlockError](type-aliases/SomniaMarketsClientGetLatestFillBlockError.md) - [SomniaMarketsClientCountUserFillsError](type-aliases/SomniaMarketsClientCountUserFillsError.md) - [SomniaMarketsClientWaitForIndexedBlockError](type-aliases/SomniaMarketsClientWaitForIndexedBlockError.md) - [SomniaMarketsClientWatchPerpMarketsError](type-aliases/SomniaMarketsClientWatchPerpMarketsError.md) - [SomniaMarketsClientWithObservations](interfaces/SomniaMarketsClientWithObservations.md) - [IndependentHead](interfaces/IndependentHead.md) - [IndexerFreshness](type-aliases/IndexerFreshness.md) - [TransactionSummary](interfaces/TransactionSummary.md) - [erc20WriteAbi](variables/erc20WriteAbi.md) - [orderBookBatchWriteAbi](variables/orderBookBatchWriteAbi.md) - [marginBankWriteAbi](variables/marginBankWriteAbi.md) - [erc20VaultWriteAbi](variables/erc20VaultWriteAbi.md) - [spotStopRegistryWriteAbi](variables/spotStopRegistryWriteAbi.md) - [spotStopRegistryEventsAbi](variables/spotStopRegistryEventsAbi.md) - [operatorRegistryWriteAbi](variables/operatorRegistryWriteAbi.md) - [ExchangeStatus](interfaces/ExchangeStatus.md) - [ExchangeDataStatus](interfaces/ExchangeDataStatus.md) - [SomniaMarketsFetchDataStatusError](type-aliases/SomniaMarketsFetchDataStatusError.md) - [SomniaMarketsUnwatchMarketError](type-aliases/SomniaMarketsUnwatchMarketError.md) - [SomniaMarketsRedeemError](type-aliases/SomniaMarketsRedeemError.md) - [SomniaMarkets](classes/SomniaMarkets.md) - [ComputeBinaryPnlError](type-aliases/ComputeBinaryPnlError.md) - [RawGridDirection](type-aliases/RawGridDirection.md) ## perpetual markets - [FundingPayment](type-aliases/FundingPayment.md) - [MarginEvent](type-aliases/MarginEvent.md) - [LIQUIDATION\_KIND](variables/LIQUIDATION_KIND.md) - [LiquidationKind](type-aliases/LiquidationKind.md) - [isLiquidationKind](functions/isLiquidationKind.md) - [LiquidationEvent](type-aliases/LiquidationEvent.md) - [FundingRateUpdate](type-aliases/FundingRateUpdate.md) - [FundingRateCandle](type-aliases/FundingRateCandle.md) - [PerpFeeRecord](type-aliases/PerpFeeRecord.md) - [OpenInterestSnapshot](type-aliases/OpenInterestSnapshot.md) - [ListLiquidationsOptions](interfaces/ListLiquidationsOptions.md) - [PERP\_ORDER\_REJECTION\_REASON](variables/PERP_ORDER_REJECTION_REASON.md) - [PerpOrderRejectionReason](type-aliases/PerpOrderRejectionReason.md) - [PerpOrderRejection](type-aliases/PerpOrderRejection.md) - [PerpFundingPayer](type-aliases/PerpFundingPayer.md) - [PerpMainFunding](interfaces/PerpMainFunding.md) - [PerpWalletLinkage](interfaces/PerpWalletLinkage.md) - [PerpWalletLinkEvent](type-aliases/PerpWalletLinkEvent.md) - [PerpMarginPull](type-aliases/PerpMarginPull.md) - [PerpMainFundingEvent](type-aliases/PerpMainFundingEvent.md) - [MarginStatus](type-aliases/MarginStatus.md) - [MARGIN\_STATUS](variables/MARGIN_STATUS.md) - [MarginAccount](interfaces/MarginAccount.md) - [AccountHealth](interfaces/AccountHealth.md) - [PerpRiskParams](interfaces/PerpRiskParams.md) - [PerpHealthSnapshot](type-aliases/PerpHealthSnapshot.md) - [PerpLiquidationPriceInputs](interfaces/PerpLiquidationPriceInputs.md) - [perpLiquidationPrice](functions/perpLiquidationPrice.md) - [PerpLeverage](interfaces/PerpLeverage.md) - [PerpPositionAnalyticsInputs](interfaces/PerpPositionAnalyticsInputs.md) - [PerpPositionMetrics](interfaces/PerpPositionMetrics.md) - [perpPositionAnalytics](functions/perpPositionAnalytics.md) - [PerpPositionAnalytics](type-aliases/PerpPositionAnalytics.md) - [PerpSideHoldersRef](interfaces/PerpSideHoldersRef.md) - [GetPerpSideHoldersOptions](interfaces/GetPerpSideHoldersOptions.md) - [PerpSideHolders](interfaces/PerpSideHolders.md) - [GetBankruptcyPriceOptions](interfaces/GetBankruptcyPriceOptions.md) - [UnsignedMarginDeposit](interfaces/UnsignedMarginDeposit.md) - [PerpOrderMarginPreview](type-aliases/PerpOrderMarginPreview.md) - [PerpOrderMarginQuoteInputs](interfaces/PerpOrderMarginQuoteInputs.md) - [PerpOrderMarginQuote](interfaces/PerpOrderMarginQuote.md) - [perpOrderMarginQuote](functions/perpOrderMarginQuote.md) - [PerpMaxOrderSizeLimit](type-aliases/PerpMaxOrderSizeLimit.md) - [PerpMaxOrderSize](type-aliases/PerpMaxOrderSize.md) - [GetPerpMaxLeverageOptions](interfaces/GetPerpMaxLeverageOptions.md) - [PerpLiquidationPreview](type-aliases/PerpLiquidationPreview.md) - [PerpClosePreview](type-aliases/PerpClosePreview.md) - [PerpPortfolioMarket](type-aliases/PerpPortfolioMarket.md) - [PerpPortfolioOrder](type-aliases/PerpPortfolioOrder.md) - [PerpPortfolioTrade](type-aliases/PerpPortfolioTrade.md) - [PerpPortfolio](type-aliases/PerpPortfolio.md) - [TerminalOrderStatus](type-aliases/TerminalOrderStatus.md) - [PerpOrderHistoryRow](type-aliases/PerpOrderHistoryRow.md) - [PERP\_POOL\_FACTORY\_MARKET\_STATUS\_INTERFACE\_ID](variables/PERP_POOL_FACTORY_MARKET_STATUS_INTERFACE_ID.md) - [PerpPoolStatus](type-aliases/PerpPoolStatus.md) - [PerpStateOnchain](interfaces/PerpStateOnchain.md) - [perpMarkForPnl](functions/perpMarkForPnl.md) - [PerpFeedStatus](interfaces/PerpFeedStatus.md) - [PerpFundingPremium](interfaces/PerpFundingPremium.md) - [PerpPosition](interfaces/PerpPosition.md) - [PerpPositionRef](interfaces/PerpPositionRef.md) - [IndexedPerpPosition](type-aliases/IndexedPerpPosition.md) - [PERP\_STOP\_DROP\_REASON](variables/PERP_STOP_DROP_REASON.md) - [PerpStopDropReason](type-aliases/PerpStopDropReason.md) - [PerpStopOrderMarket](type-aliases/PerpStopOrderMarket.md) - [PerpStopOrder](type-aliases/PerpStopOrder.md) - [PerpStopOrderOnChain](type-aliases/PerpStopOrderOnChain.md) - [decodePerpStopOrderIds](functions/decodePerpStopOrderIds.md) - [UnsignedPerpStopOrder](interfaces/UnsignedPerpStopOrder.md) - [PerpSystemConfig](interfaces/PerpSystemConfig.md) - [InsuranceFundTier](interfaces/InsuranceFundTier.md) - [InsuranceFundState](interfaces/InsuranceFundState.md) - [LiquidationEngineConfig](interfaces/LiquidationEngineConfig.md) - [PerpInsuranceFundEvent](type-aliases/PerpInsuranceFundEvent.md) - [PerpVoucherCampaign](interfaces/PerpVoucherCampaign.md) - [PerpVoucherIneligibleReason](type-aliases/PerpVoucherIneligibleReason.md) - [PerpVoucherEligibility](type-aliases/PerpVoucherEligibility.md) - [PerpVoucher](interfaces/PerpVoucher.md) ## pools - [PoolBindingRecord](interfaces/PoolBindingRecord.md) - [ListPoolBindingsOptions](interfaces/ListPoolBindingsOptions.md) - [IndexedPool](interfaces/IndexedPool.md) ## price feeds - [PriceWatchHandle](interfaces/PriceWatchHandle.md) - [PRICE\_FEED\_DECIMALS](variables/PRICE_FEED_DECIMALS.md) - [PriceCandleResolution](type-aliases/PriceCandleResolution.md) - [PRICE\_RESOLUTION\_SECONDS](variables/PRICE_RESOLUTION_SECONDS.md) - [LivePrice](interfaces/LivePrice.md) - [PricePoint](interfaces/PricePoint.md) - [PriceCandle](interfaces/PriceCandle.md) - [PriceFeedInfo](interfaces/PriceFeedInfo.md) - [PriceFeedStatus](type-aliases/PriceFeedStatus.md) - [PriceFeedHealth](type-aliases/PriceFeedHealth.md) ## quoting - [UnifiedBookLevels](type-aliases/UnifiedBookLevels.md) - [QuoteDenomination](type-aliases/QuoteDenomination.md) - [MarketOrderEstimate](interfaces/MarketOrderEstimate.md) - [estimateMarketOrder](functions/estimateMarketOrder.md) - [bookMidPrice](functions/bookMidPrice.md) - [fillsWithinSlippage](functions/fillsWithinSlippage.md) ## routing - [RouterActionKind](type-aliases/RouterActionKind.md) - [RouterActionRecord](type-aliases/RouterActionRecord.md) - [RouterActionsOptions](type-aliases/RouterActionsOptions.md) ## spot markets - [PLACE\_ORDER\_FOR\_SELECTOR](variables/PLACE_ORDER_FOR_SELECTOR.md) - [CANCEL\_ORDER\_FOR\_SELECTOR](variables/CANCEL_ORDER_FOR_SELECTOR.md) - [IsGloballyApprovedParams](interfaces/IsGloballyApprovedParams.md) - [IsApprovedForPoolParams](interfaces/IsApprovedForPoolParams.md) - [GetAutoPullRequirementParams](interfaces/GetAutoPullRequirementParams.md) - [AutoPullRequirement](interfaces/AutoPullRequirement.md) - [IsOperatorAuthorizedParams](interfaces/IsOperatorAuthorizedParams.md) - [LockedBalance](interfaces/LockedBalance.md) - [TokenLockBreakdown](interfaces/TokenLockBreakdown.md) - [LockedTokenBreakdown](interfaces/LockedTokenBreakdown.md) - [SpotPortfolioMarket](type-aliases/SpotPortfolioMarket.md) - [SpotPortfolioOrder](type-aliases/SpotPortfolioOrder.md) - [SpotPortfolioTrade](type-aliases/SpotPortfolioTrade.md) - [SpotPortfolio](type-aliases/SpotPortfolio.md) - [StopOrderStatus](type-aliases/StopOrderStatus.md) - [SpotStopOrder](type-aliases/SpotStopOrder.md) - [GetManualVaultModeParams](interfaces/GetManualVaultModeParams.md) ## system - [MarketCreatorInfo](interfaces/MarketCreatorInfo.md) - [SystemInfo](interfaces/SystemInfo.md) ## trading - [DecodedPlacement](interfaces/DecodedPlacement.md) - [decodePlaceOrder](functions/decodePlaceOrder.md) - [DecodedAmendment](interfaces/DecodedAmendment.md) - [decodeAmendOrder](functions/decodeAmendOrder.md) - [DecodedBatchAmendment](interfaces/DecodedBatchAmendment.md) - [decodeAmendOrders](functions/decodeAmendOrders.md) - [asExecuteError](functions/asExecuteError.md) - [asSignTypedDataError](functions/asSignTypedDataError.md) - [ExecutorSpec](type-aliases/ExecutorSpec.md) - [assertCallsOnChain](functions/assertCallsOnChain.md) - [SmartAccountSigner](interfaces/SmartAccountSigner.md) - [ExecuteOptions](interfaces/ExecuteOptions.md) - [Executed](interfaces/Executed.md) - [TypedDataSigner](type-aliases/TypedDataSigner.md) - [Executor](interfaces/Executor.md) - [TraderConfig](interfaces/TraderConfig.md) - [TxResult](interfaces/TxResult.md) - [OrderFill](interfaces/OrderFill.md) - [PlaceStopOrderResult](interfaces/PlaceStopOrderResult.md) - [PlacePerpStopOrderResult](interfaces/PlacePerpStopOrderResult.md) - [PlaceOrderResult](interfaces/PlaceOrderResult.md) - [PlaceOrderParams](interfaces/PlaceOrderParams.md) - [ApproveBuilderParams](interfaces/ApproveBuilderParams.md) - [CancelOrderParams](interfaces/CancelOrderParams.md) - [ReduceOrderParams](interfaces/ReduceOrderParams.md) - [CancelExpiredOrdersParams](interfaces/CancelExpiredOrdersParams.md) - [SweepExpiredAtLevelParams](interfaces/SweepExpiredAtLevelParams.md) - [CaptureCloseParams](interfaces/CaptureCloseParams.md) - [ORDER\_TYPE](variables/ORDER_TYPE.md) - [PlaceSpotOrderParams](interfaces/PlaceSpotOrderParams.md) - [SpotOrderRequest](interfaces/SpotOrderRequest.md) - [PlaceSpotOrdersParams](interfaces/PlaceSpotOrdersParams.md) - [BatchPlaceOutcome](interfaces/BatchPlaceOutcome.md) - [PlaceSpotOrdersResult](interfaces/PlaceSpotOrdersResult.md) - [CancelOrdersParams](interfaces/CancelOrdersParams.md) - [BatchCancelOutcome](interfaces/BatchCancelOutcome.md) - [CancelOrdersResult](interfaces/CancelOrdersResult.md) - [CancelAllOrdersOptions](interfaces/CancelAllOrdersOptions.md) - [CancelAllOrdersEmpty](interfaces/CancelAllOrdersEmpty.md) - [CancelAllOrdersSent](interfaces/CancelAllOrdersSent.md) - [CancelAllOrdersResult](type-aliases/CancelAllOrdersResult.md) - [ReduceOrderRequest](interfaces/ReduceOrderRequest.md) - [ReduceOrdersParams](interfaces/ReduceOrdersParams.md) - [PlacePerpOrderParams](interfaces/PlacePerpOrderParams.md) - [SELF\_MATCHING\_OPTION](variables/SELF_MATCHING_OPTION.md) - [BatchOrderRequest](interfaces/BatchOrderRequest.md) - [AmendOrdersParams](interfaces/AmendOrdersParams.md) - [AmendOrdersResult](interfaces/AmendOrdersResult.md) - [AmendOrderParams](interfaces/AmendOrderParams.md) - [AmendOrderResult](interfaces/AmendOrderResult.md) - [DepositMarginParams](interfaces/DepositMarginParams.md) - [WithdrawMarginParams](interfaces/WithdrawMarginParams.md) - [PerpWalletLinkTarget](interfaces/PerpWalletLinkTarget.md) - [ProposePerpWalletLinkParams](interfaces/ProposePerpWalletLinkParams.md) - [AcceptPerpWalletLinkParams](interfaces/AcceptPerpWalletLinkParams.md) - [CancelPerpWalletLinkProposalParams](interfaces/CancelPerpWalletLinkProposalParams.md) - [UnlinkPerpWalletParams](interfaces/UnlinkPerpWalletParams.md) - [RepayPerpMainFundingParams](interfaces/RepayPerpMainFundingParams.md) - [RecallPerpMainFundingParams](interfaces/RecallPerpMainFundingParams.md) - [ClaimPerpVoucherParams](interfaces/ClaimPerpVoucherParams.md) - [WithdrawVaultParams](interfaces/WithdrawVaultParams.md) - [DepositVaultParams](interfaces/DepositVaultParams.md) - [DepositVaultNativeParams](interfaces/DepositVaultNativeParams.md) - [SetManualVaultModeParams](interfaces/SetManualVaultModeParams.md) - [SetOperatorApprovalGlobalParams](interfaces/SetOperatorApprovalGlobalParams.md) - [SetOperatorApprovalForPoolParams](interfaces/SetOperatorApprovalForPoolParams.md) - [SetPerpLeverageParams](interfaces/SetPerpLeverageParams.md) - [PlaceSpotStopOrderParams](interfaces/PlaceSpotStopOrderParams.md) - [CancelStopOrderParams](interfaces/CancelStopOrderParams.md) - [ClaimPerpStopSomiParams](interfaces/ClaimPerpStopSomiParams.md) - [PerpStopIntent](type-aliases/PerpStopIntent.md) - [PerpStopOrderLeg](interfaces/PerpStopOrderLeg.md) - [PlacePerpStopOrderParams](interfaces/PlacePerpStopOrderParams.md) - [LinkPerpStopOrdersParams](interfaces/LinkPerpStopOrdersParams.md) - [CancelPerpStopOrdersParams](interfaces/CancelPerpStopOrdersParams.md) - [MintSetParams](interfaces/MintSetParams.md) - [BurnSetParams](interfaces/BurnSetParams.md) - [RedeemParams](interfaces/RedeemParams.md) - [RedeemManyParams](interfaces/RedeemManyParams.md) - [RedeemAuthorization](interfaces/RedeemAuthorization.md) - [SignRedeemAuthParams](interfaces/SignRedeemAuthParams.md) - [RedeemForParams](interfaces/RedeemForParams.md) - [RedeemDirectParams](interfaces/RedeemDirectParams.md) - [ClaimOwedParams](interfaces/ClaimOwedParams.md) - [FinalizeMarketParams](interfaces/FinalizeMarketParams.md) - [SyncSettlementParams](interfaces/SyncSettlementParams.md) - [ReleasePoolParams](interfaces/ReleasePoolParams.md) - [PokeOracleParams](interfaces/PokeOracleParams.md) - [VoidExpiredParams](interfaces/VoidExpiredParams.md) - [SettlementRecord](interfaces/SettlementRecord.md) - [Permit2TransferFrom](interfaces/Permit2TransferFrom.md) - [RouterMintBase](interfaces/RouterMintBase.md) - [MintSetNativeParams](interfaces/MintSetNativeParams.md) - [MintSetPermit2Params](interfaces/MintSetPermit2Params.md) - [RedeemNativeParams](interfaces/RedeemNativeParams.md) - [FaucetParams](interfaces/FaucetParams.md) - [ResolveParams](interfaces/ResolveParams.md) - [VoidMarketParams](interfaces/VoidMarketParams.md) - [TraderBuildPlaceSpotOrderError](type-aliases/TraderBuildPlaceSpotOrderError.md) - [TraderCancelAllOrdersError](type-aliases/TraderCancelAllOrdersError.md) - [TraderBuildCancelOrdersError](type-aliases/TraderBuildCancelOrdersError.md) - [TraderBuildReduceOrdersError](type-aliases/TraderBuildReduceOrdersError.md) - [TraderSignRedeemAuthError](type-aliases/TraderSignRedeemAuthError.md) - [TraderClaimPerpVoucherError](type-aliases/TraderClaimPerpVoucherError.md) - [TraderBuildClaimPerpVoucherError](type-aliases/TraderBuildClaimPerpVoucherError.md) - [Trader](interfaces/Trader.md) - [ORDER\_KIND](variables/ORDER_KIND.md) - [UnsignedCall](interfaces/UnsignedCall.md) - [UnsignedOrder](interfaces/UnsignedOrder.md) ## validation - [PreflightResult](interfaces/PreflightResult.md) - [ZERO\_ADDRESS](variables/ZERO_ADDRESS.md) - [HUB\_MIN\_FREE\_BALANCE\_WEI](variables/HUB_MIN_FREE_BALANCE_WEI.md) - [MIN\_SERIES\_INTERVAL\_SEC](variables/MIN_SERIES_INTERVAL_SEC.md) - [OperatorPreflightInput](interfaces/OperatorPreflightInput.md) - [preflightOperator](functions/preflightOperator.md) - [VenuePreflightInput](interfaces/VenuePreflightInput.md) - [preflightVenue](functions/preflightVenue.md) - [HubPreflightInput](interfaces/HubPreflightInput.md) - [preflightHub](functions/preflightHub.md) - [CreateQuotePreflightInput](interfaces/CreateQuotePreflightInput.md) - [preflightCreateQuote](functions/preflightCreateQuote.md) - [MarketCreatorPreflightInput](interfaces/MarketCreatorPreflightInput.md) - [preflightMarketCreator](functions/preflightMarketCreator.md) - [SeriesPreflightInput](interfaces/SeriesPreflightInput.md) - [preflightSeries](functions/preflightSeries.md) - [RollPreflightInput](interfaces/RollPreflightInput.md) - [preflightRoll](functions/preflightRoll.md) - [preflightChain](functions/preflightChain.md) - [isLocalPrecompileUnavailable](functions/isLocalPrecompileUnavailable.md) --- # /docs/typescript/api/index/classes/BridgeDeliveryTimeoutError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BridgeDeliveryTimeoutError # Class: BridgeDeliveryTimeoutError Defined in: packages/sdk/src/errors.ts:917 A bridge transfer was sent, but its message was not delivered on the destination within the delivery timeout. The funds are in flight, not lost. **Details** `exchange.ensureFunds` and `createOrder(…, { funding: "auto" })` throw this error. `exchange.bridge.transfer` does not throw it: it resolves with `delivered: false` and the same `messageId`. - `messageId`: the Hyperlane message id, decoded from the origin receipt. - `bridgeHash`: the origin transaction that dispatched the message. - `token`, `from`, `to`: the route. - `amount`: raw units sent, in the origin side's decimals. **Gotchas** Do not send the transfer again before you check the message. Call `delivered(messageId)` on the destination chain's Mailbox (the `mailbox` of `getBridgeNetwork(to)`). When it returns `false`, the message can still land. A second transfer moves the funds twice. A later `ensureFunds` or auto-funded order on the same exchange does this for you: it waits for the pending message and sends no new leg for it. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new BridgeDeliveryTimeoutError**(`fields`): `BridgeDeliveryTimeoutError` Defined in: packages/sdk/src/errors.ts:931 #### Parameters ##### fields ###### messageId `` `0x${string}` `` ###### bridgeHash `` `0x${string}` `` ###### from `number` ###### to `number` ###### token [`BridgeToken`](../../chains/type-aliases/BridgeToken.md) ###### amount `bigint` #### Returns `BridgeDeliveryTimeoutError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### messageId > `readonly` **messageId**: `` `0x${string}` `` Defined in: packages/sdk/src/errors.ts:919 The Hyperlane message id of the transfer. *** ### bridgeHash > `readonly` **bridgeHash**: `` `0x${string}` `` Defined in: packages/sdk/src/errors.ts:921 Hash of the origin transaction that dispatched the message. *** ### from > `readonly` **from**: `number` Defined in: packages/sdk/src/errors.ts:923 Origin chain id. *** ### to > `readonly` **to**: `number` Defined in: packages/sdk/src/errors.ts:925 Destination chain id. *** ### token > `readonly` **token**: [`BridgeToken`](../../chains/type-aliases/BridgeToken.md) Defined in: packages/sdk/src/errors.ts:927 The bridged token. *** ### amount > `readonly` **amount**: `bigint` Defined in: packages/sdk/src/errors.ts:929 Raw units sent, in the origin side's decimals. --- # /docs/typescript/api/index/classes/BridgeLiquidityError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BridgeLiquidityError # Class: BridgeLiquidityError Defined in: packages/sdk/src/errors.ts:855 A native bridge route cannot deliver: the destination router holds less than the transfer amount. The SDK refused the transfer, and nothing was sent. **Details** A `native` route (STT) pays out of the destination router's own balance instead of minting. When that balance is below the amount, the relayer's delivery reverts, and the funds stay in escrow on the origin until someone seeds the router. `exchange.bridge.transfer`, `exchange.ensureFunds` and `createOrder(…, { funding: "auto" })` read the router balance first and throw this error instead of sending. - `token`, `from`, `to`: the route. - `router`: the destination router whose balance was read. - `amount`: raw units the transfer would deliver. - `available`: raw units the router held when the SDK read it. **Gotchas** Retry after the router is seeded, bridge at most `available`, or fund the destination another way. The check is a read, not a reservation: another transfer can still drain the router after the check passes. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new BridgeLiquidityError**(`fields`): `BridgeLiquidityError` Defined in: packages/sdk/src/errors.ts:869 #### Parameters ##### fields ###### token [`BridgeToken`](../../chains/type-aliases/BridgeToken.md) ###### from `number` ###### to `number` ###### router `` `0x${string}` `` ###### amount `bigint` ###### available `bigint` #### Returns `BridgeLiquidityError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### token > `readonly` **token**: [`BridgeToken`](../../chains/type-aliases/BridgeToken.md) Defined in: packages/sdk/src/errors.ts:857 The bridged token. *** ### from > `readonly` **from**: `number` Defined in: packages/sdk/src/errors.ts:859 Origin chain id. *** ### to > `readonly` **to**: `number` Defined in: packages/sdk/src/errors.ts:861 Destination chain id. *** ### router > `readonly` **router**: `` `0x${string}` `` Defined in: packages/sdk/src/errors.ts:863 The destination router that pays out the delivery. *** ### amount > `readonly` **amount**: `bigint` Defined in: packages/sdk/src/errors.ts:865 Raw units the transfer would deliver, in the origin side's decimals (equal to the destination's on every native route). *** ### available > `readonly` **available**: `bigint` Defined in: packages/sdk/src/errors.ts:867 Raw units the destination router held. --- # /docs/typescript/api/index/classes/CollateralOnWrongChainError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CollateralOnWrongChainError # Class: CollateralOnWrongChainError Defined in: packages/sdk/src/errors.ts:748 A write needs collateral on the market's chain, and the account does not hold enough of it THERE — though it may hold it on another chain the exchange spans. **Details** A market is unique to one chain and its collateral must sit on that chain. The exchange checks the escrow token's balance on the market's chain before encoding an order and throws this instead of letting the pool revert, so the caller learns WHERE the funds are and gets a ready bridge plan. Nothing was sent on any chain. - `chainId`, `token`, `code`: the chain and the escrow token (address, and its currency code) the order needs. - `needed`, `held`, `shortfall`: raw token units on that chain. - `elsewhere`: the raw balance of the same bridge token on every other configured chain the bridge registry lists it on. The bridge token is found by the escrow token's address in the registry, not by `code`. A token the registry does not list has no route, so `elsewhere` is empty. - `unread`: chains whose balance could not be read, so their absence from `elsewhere` is not a zero balance. A chain listed here may hold the shortfall. - `readErrors`: the original typed errors, keyed by chain and retained in `cause`. - `plan`: a [BridgeTransfer](../../chains/interfaces/BridgeTransfer.md) from the richest other chain covering the shortfall, when the token has a bridge route; absent when it does not. On a spot order, `needed` is the pool's own requirement net of the account's pool vault balance (`getAutoPullRequirement(...).delta`), and `held` is the wallet balance. Under the pool's manual vault mode, `needed` is the full requirement, `held` is the vault balance, `elsewhere` is empty, and there is no `plan`: the pool does not pull from the wallet, so only a vault deposit funds the order. **Gotchas** Explicit by design: the exchange never bridges on its own. Execute `plan` through `exchange.bridge.transfer(...)`, or ask for it with `createOrder(…, { funding: "auto" })`, or pass `{ funding: "skip" }` to bypass the check on a hot path you fund yourself. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new CollateralOnWrongChainError**(`fields`): `CollateralOnWrongChainError` Defined in: packages/sdk/src/errors.ts:780 #### Parameters ##### fields ###### chainId `number` ###### token `string` ###### code `string` ###### needed `bigint` ###### held `bigint` ###### elsewhere `Record`\<`number`, `bigint`\> ###### unread? readonly `number`[] ###### readErrors? `Readonly`\<`Record`\<`number`, [`CollateralReadError`](../type-aliases/CollateralReadError.md)\>\> ###### plan? [`BridgeTransfer`](../../chains/interfaces/BridgeTransfer.md) ###### symbol `string` #### Returns `CollateralOnWrongChainError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### chainId > `readonly` **chainId**: `number` Defined in: packages/sdk/src/errors.ts:750 Numeric chain id the market — and so the collateral — lives on. *** ### token > `readonly` **token**: `string` Defined in: packages/sdk/src/errors.ts:752 The escrow token's address on that chain, lowercased (the zero address for the native coin). *** ### code > `readonly` **code**: `string` Defined in: packages/sdk/src/errors.ts:754 The escrow token's currency code, the key [UnifiedBalances](../interfaces/UnifiedBalances.md) uses. *** ### needed > `readonly` **needed**: `bigint` Defined in: packages/sdk/src/errors.ts:760 Raw units the order needs on `chainId`. On a spot order this is the pool's requirement net of the pool vault balance, or the full requirement under manual vault mode. *** ### held > `readonly` **held**: `bigint` Defined in: packages/sdk/src/errors.ts:765 Raw units the account holds on `chainId` toward `needed`: the wallet balance, or the pool vault balance under manual vault mode. *** ### shortfall > `readonly` **shortfall**: `bigint` Defined in: packages/sdk/src/errors.ts:767 `needed − held`, raw units. *** ### elsewhere > `readonly` **elsewhere**: `Record`\<`number`, `bigint`\> Defined in: packages/sdk/src/errors.ts:769 The same bridge token's raw balance on every OTHER configured chain the bridge registry lists it on, keyed by chain id. *** ### unread > `readonly` **unread**: readonly `number`[] Defined in: packages/sdk/src/errors.ts:774 Chains whose balance read failed. Empty when all reads succeed. Retry these chains before concluding that no bridge route covers the shortfall. *** ### readErrors > `readonly` **readErrors**: `Readonly`\<`Record`\<`number`, [`CollateralReadError`](../type-aliases/CollateralReadError.md)\>\> Defined in: packages/sdk/src/errors.ts:776 Failed balance reads by chain. The same errors are retained in the aggregate cause. *** ### plan? > `readonly` `optional` **plan?**: [`BridgeTransfer`](../../chains/interfaces/BridgeTransfer.md) Defined in: packages/sdk/src/errors.ts:778 A bridge plan covering the shortfall from the richest other chain, when a route exists. --- # /docs/typescript/api/index/classes/ContractRevertError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ContractRevertError # Class: ContractRevertError Defined in: packages/sdk/src/errors.ts:546 A contract rejected the call — the SDK decodes the revert against the protocol's custom-error ABIs so the failure reads as its Solidity name. **Details** `errorName` is the contract's own error (e.g. `"InsufficientBalance"`, `"MarketNotSettled"`, `"ExpiredOrderMustBeCancelled"`) and `args` its decoded parameters — that pair is what a caller branches on to decide whether to cancel-then-retry, top up collateral, or give up. Thrown on every revert path: send-time rejection, pre-send simulation, a mined receipt with failed status, and `eth_call` reads. **Gotchas** `errorName` is not always populated. When the revert data doesn't match any known error (a bare `require` string, an unknown selector, or no data at all) it is `undefined` and `reason`/`data` carry whatever the node returned — so branch with a fallback arm rather than assuming a name. The error is still this class either way, so callers never face a raw viem error. **Example** (Handling a decoded revert) ```ts import { ContractRevertError } from "@somnia-chain/markets-sdk"; try { await trader.placeOrder(params); } catch (e) { if (e instanceof ContractRevertError && e.errorName === "ExpiredOrderMustBeCancelled") { await trader.cancelExpiredOrders({ pool, orderIds: [orderId] }); } else throw e; } ``` ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new ContractRevertError**(`fields`, `options?`): `ContractRevertError` Defined in: packages/sdk/src/errors.ts:560 #### Parameters ##### fields ###### errorName? `string` ###### args? readonly `unknown`[] ###### reason? `string` ###### data? `string` ###### address? `string` ###### functionName? `string` ##### options? `ErrorOptions` #### Returns `ContractRevertError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### errorName? > `readonly` `optional` **errorName?**: `string` Defined in: packages/sdk/src/errors.ts:548 The decoded Solidity error name, or `undefined` when the revert didn't match a known error. *** ### args? > `readonly` `optional` **args?**: readonly `unknown`[] Defined in: packages/sdk/src/errors.ts:550 Decoded arguments of the custom error, positionally, when `errorName` is set. *** ### reason? > `readonly` `optional` **reason?**: `string` Defined in: packages/sdk/src/errors.ts:552 A plain `require`/`revert` string reason, when the revert carried one instead of a custom error. *** ### data? > `readonly` `optional` **data?**: `string` Defined in: packages/sdk/src/errors.ts:554 Raw revert data as returned by the node, when present. *** ### address? > `readonly` `optional` **address?**: `string` Defined in: packages/sdk/src/errors.ts:556 The contract that reverted, when known. *** ### functionName? > `readonly` `optional` **functionName?**: `string` Defined in: packages/sdk/src/errors.ts:558 The function that was called, when known. --- # /docs/typescript/api/index/classes/FillHistoryRestartRequiredError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillHistoryRestartRequiredError # Class: FillHistoryRestartRequiredError Defined in: packages/sdk/src/errors.ts:118 A fill continuation belongs to a different serving dataset. Discard all accumulated pages and call `getUserFillsPage` again without a cursor. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new FillHistoryRestartRequiredError**(`cursorGeneration`, `servingGeneration`): `FillHistoryRestartRequiredError` Defined in: packages/sdk/src/errors.ts:119 #### Parameters ##### cursorGeneration `string` ##### servingGeneration `string` #### Returns `FillHistoryRestartRequiredError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### cursorGeneration > `readonly` **cursorGeneration**: `string` Defined in: packages/sdk/src/errors.ts:120 *** ### servingGeneration > `readonly` **servingGeneration**: `string` Defined in: packages/sdk/src/errors.ts:121 --- # /docs/typescript/api/index/classes/FillHistoryUnavailableError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillHistoryUnavailableError # Class: FillHistoryUnavailableError Defined in: packages/sdk/src/errors.ts:136 The serving indexer has not initialized its fill-history dataset contract. Deploy and reindex a compatible producer before reading historical pages. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new FillHistoryUnavailableError**(`operation`, `options?`): `FillHistoryUnavailableError` Defined in: packages/sdk/src/errors.ts:137 #### Parameters ##### operation `string` ##### options? `ErrorOptions` #### Returns `FillHistoryUnavailableError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:138 --- # /docs/typescript/api/index/classes/IncompleteHistoryError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IncompleteHistoryError # Class: IncompleteHistoryError Defined in: packages/sdk/src/errors.ts:286 Indexed history was not fully traversed, so portfolio analytics cannot be computed without a misleading cost basis. Increase or omit `maxFillPages` for `pageBudgetExceeded`. A `cursorCycle` means the indexer's pagination did not advance; retry or investigate its dataset before displaying analytics. Neither outcome is an empty portfolio. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new IncompleteHistoryError**(`operation`, `reason`, `pagesRead`, `maxFillPages?`): `IncompleteHistoryError` Defined in: packages/sdk/src/errors.ts:296 #### Parameters ##### operation `string` ##### reason `"pageBudgetExceeded"` \| `"cursorCycle"` ##### pagesRead `number` ##### maxFillPages? `number` #### Returns `IncompleteHistoryError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:288 The owner method that requires complete indexed history. *** ### reason > `readonly` **reason**: `"pageBudgetExceeded"` \| `"cursorCycle"` Defined in: packages/sdk/src/errors.ts:290 The action a caller must take before analytics can be trusted. *** ### pagesRead > `readonly` **pagesRead**: `number` Defined in: packages/sdk/src/errors.ts:292 Successful fill pages read before rejecting the incomplete result. *** ### maxFillPages? > `readonly` `optional` **maxFillPages?**: `number` Defined in: packages/sdk/src/errors.ts:294 Configured page budget, when the caller supplied one. --- # /docs/typescript/api/index/classes/IndexerError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerError # Class: IndexerError Defined in: packages/sdk/src/errors.ts:242 An indexer (Hasura/Envio GraphQL) request did not complete. **When to use** Use when opting into graceful degradation — this is the error to catch to serve stale or empty UI instead of failing a page. It is safe to treat as transient-or-misconfigured: endpoint down, bad URL, schema drift, timeout. **Gotchas** This ALWAYS means "the read didn't happen" — never "there is no such row". A point read that finds nothing resolves to `null` and a list read to `[]`; both are successful reads. Treating this as "not found" will hide an outage behind an empty state. **Example** (Falling back after an indexer failure) ```ts import { IndexerError } from "@somnia-chain/markets-sdk"; const markets = await exchange.client .listBinaryMarkets() .catch((e) => { if (e instanceof IndexerError) return []; throw e; }); ``` ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Extended by - [`IndexerUnavailableError`](IndexerUnavailableError.md) ## Constructors ### Constructor > **new IndexerError**(`operation`, `detail`, `options?`): `IndexerError` Defined in: packages/sdk/src/errors.ts:264 Creates an indexer error with operation context and an optional cause. **Details** - `operation`: GraphQL operation name that failed (e.g. `"listBinaryMarkets"`). - `detail`: Why it failed (HTTP status, GraphQL error message, "empty response"). - `options`: Standard `cause` passthrough — the underlying fetch/GraphQL failure — plus `chainId` when the failing chain is known. #### Parameters ##### operation `string` ##### detail `string` ##### options? `ErrorOptions` & `object` #### Returns `IndexerError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### chainId? > `readonly` `optional` **chainId?**: `number` Defined in: packages/sdk/src/errors.ts:253 The chain whose read failed. Set only on an exchange with two or more chains, in two cases. The account reads of `SomniaMarkets` (`fetchBalance`, `fetchOpenOrders`, `fetchOrders`, `getOrdersPage`, `getOrderHistoryPage`, `fetchMyTrades`, `fetchPositions`, `fetchOpenStopOrders`, `watchUser`) set it when the read spans more than one chain, or when the read has no market and no chain filter, also if it then touches only one chain. `fetchDataStatus` sets it on the error it throws when every chain fails. Absent on every other indexer error. *** ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:265 --- # /docs/typescript/api/index/classes/IndexerUnavailableError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerUnavailableError # Class: IndexerUnavailableError Defined in: packages/sdk/src/errors.ts:674 The SDK stopped an indexer read locally. **Details** A `breaker-open`, `breaker-trial`, or `queue-full` refusal leaves no request on the wire and returns at once instead of after a 30 s timeout. A `live-reset` can stop a retry backoff after an earlier attempt was sent. The breaker opens after [IndexerLimits.breakerThreshold](../interfaces/IndexerLimits.md#breakerthreshold) consecutive endpoint failures (timeouts or HTTP 429/502/503/504) and stays open for [IndexerLimits.breakerCooldownMs](../interfaces/IndexerLimits.md#breakercooldownms). **When to use** Catch it to show "the indexer is not answering" at once rather than spinning a skeleton. `retryAfterMs` says how much cooling period is left, so a poller can sleep exactly that long. **Gotchas** A subclass of [IndexerError](IndexerError.md), so existing `instanceof IndexerError` handling is unaffected. A gate refusal (`breaker-open`, `breaker-trial`, `queue-full`) means nothing reached the network: if a gate refuses a retry after an earlier attempt was sent, the read fails with that attempt's [IndexerError](IndexerError.md) instead. `live-reset` can end a retry's backoff, so an earlier attempt may have been sent. Never retry it in a tight loop — that is the storm the breaker exists to stop. Branch on `reason`; the four cases want different things, and only `breaker-open` carries a meaningful `retryAfterMs`: | `reason` | Means | Your move | | --- | --- | --- | | `breaker-open` | Consecutive endpoint failures opened the breaker | Sleep `retryAfterMs`, then retry | | `breaker-trial` | The cooling period ended and another read is the trial | Retry shortly; the trial decides | | `queue-full` | This client already has `maxQueued` reads waiting for a slot | Back off on your own schedule ([nextBackoffDelayMs](../functions/nextBackoffDelayMs.md)) or send less | | `live-reset` | `stopLive()` reset the live-read lifecycle while this read queued or backed off | Retry on the SAME client; it stays usable | **Example** (Sleeping for exactly the cooling period) ```ts import { IndexerUnavailableError } from "@somnia-chain/markets-sdk"; try { await exchange.client.listBinaryMarkets(); } catch (e) { if (!(e instanceof IndexerUnavailableError)) throw e; // Only `breaker-open` carries a cooling period; the rest retry sooner. await new Promise((r) => setTimeout(r, e.retryAfterMs || 1_000)); } ``` ## Extends - [`IndexerError`](IndexerError.md) ## Constructors ### Constructor > **new IndexerUnavailableError**(`operation`, `reason`, `detail`, `retryAfterMs`, `consecutiveFailures`): `IndexerUnavailableError` Defined in: packages/sdk/src/errors.ts:689 Creates a locally-refused indexer error. **Details** - `operation`: GraphQL operation name that was refused. - `reason`: Which gate refused, and so what the caller should do next. - `detail`: Why the SDK refused, in prose. - `retryAfterMs`: Cooling period remaining. Meaningful only for `breaker-open`; `0` for every other reason, where the wait is the caller's own backoff rather than a period the SDK knows. - `consecutiveFailures`: Endpoint failures in a row recorded so far: timeouts and overload responses (HTTP 429, 502, 503, 504). #### Parameters ##### operation `string` ##### reason [`IndexerRefusalReason`](../type-aliases/IndexerRefusalReason.md) ##### detail `string` ##### retryAfterMs `number` ##### consecutiveFailures `number` #### Returns `IndexerUnavailableError` #### Overrides [`IndexerError`](IndexerError.md).[`constructor`](IndexerError.md#constructor) ## Properties ### chainId? > `readonly` `optional` **chainId?**: `number` Defined in: packages/sdk/src/errors.ts:253 The chain whose read failed. Set only on an exchange with two or more chains, in two cases. The account reads of `SomniaMarkets` (`fetchBalance`, `fetchOpenOrders`, `fetchOrders`, `getOrdersPage`, `getOrderHistoryPage`, `fetchMyTrades`, `fetchPositions`, `fetchOpenStopOrders`, `watchUser`) set it when the read spans more than one chain, or when the read has no market and no chain filter, also if it then touches only one chain. `fetchDataStatus` sets it on the error it throws when every chain fails. Absent on every other indexer error. #### Inherited from [`IndexerError`](IndexerError.md).[`chainId`](IndexerError.md#chainid) *** ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:265 #### Inherited from [`IndexerError`](IndexerError.md).[`operation`](IndexerError.md#operation) *** ### reason > `readonly` **reason**: [`IndexerRefusalReason`](../type-aliases/IndexerRefusalReason.md) Defined in: packages/sdk/src/errors.ts:691 *** ### retryAfterMs > `readonly` **retryAfterMs**: `number` Defined in: packages/sdk/src/errors.ts:693 *** ### consecutiveFailures > `readonly` **consecutiveFailures**: `number` Defined in: packages/sdk/src/errors.ts:694 --- # /docs/typescript/api/index/classes/IndexerWaitTimeoutError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerWaitTimeoutError # Class: IndexerWaitTimeoutError Defined in: packages/sdk/src/errors.ts:344 The indexer did not reach a requested block before the wait's deadline. **When to use** Catch it to decide what to do about LAG. The read itself worked: the indexer answered every poll and is simply behind, so the choices are to wait longer, to show the caller that the data is not there yet, or to read the same fact from chain instead. `latestProcessedBlock` says how far it had got, so the decision can be made on the size of the gap rather than on the timeout alone. **Gotchas** This is NOT an [IndexerError](IndexerError.md): the indexer was reachable throughout. A request that failed to complete during the wait surfaces as [IndexerError](IndexerError.md), and a chain the indexer serves no metadata row for does too — neither is cured by waiting. **Example** (Falling back to chain when the index is behind) ```ts import { IndexerWaitTimeoutError } from "@somnia-chain/markets-sdk"; try { await exchange.client.waitForIndexedBlock(exchange.client.config.chain.id, receipt.blockNumber); } catch (e) { if (!(e instanceof IndexerWaitTimeoutError)) throw e; console.warn(`indexer is ${e.targetBlock - (e.latestProcessedBlock ?? 0)} blocks behind`); } ``` ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new IndexerWaitTimeoutError**(`targetBlock`, `latestProcessedBlock`, `timeoutMs`, `waitedMs`, `polls`): `IndexerWaitTimeoutError` Defined in: packages/sdk/src/errors.ts:357 Creates a wait-timeout error carrying the observation that ran out of time. **Details** - `targetBlock`: Block the caller waited for. - `latestProcessedBlock`: Last height the indexer reported, or `null` when it reported a chain row that had processed nothing. - `timeoutMs`: Deadline the wait was given. - `waitedMs`: Time actually spent waiting. - `polls`: Number of metadata reads performed. #### Parameters ##### targetBlock `number` ##### latestProcessedBlock `number` \| `null` ##### timeoutMs `number` ##### waitedMs `number` ##### polls `number` #### Returns `IndexerWaitTimeoutError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### targetBlock > `readonly` **targetBlock**: `number` Defined in: packages/sdk/src/errors.ts:358 *** ### latestProcessedBlock > `readonly` **latestProcessedBlock**: `number` \| `null` Defined in: packages/sdk/src/errors.ts:359 *** ### timeoutMs > `readonly` **timeoutMs**: `number` Defined in: packages/sdk/src/errors.ts:360 *** ### waitedMs > `readonly` **waitedMs**: `number` Defined in: packages/sdk/src/errors.ts:361 *** ### polls > `readonly` **polls**: `number` Defined in: packages/sdk/src/errors.ts:362 --- # /docs/typescript/api/index/classes/InvalidInputError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / InvalidInputError # Class: InvalidInputError Defined in: packages/sdk/src/errors.ts:87 The call itself was wrong — a bad argument, an unknown symbol, or a method used against the wrong kind of market. Thrown *before* any network round-trip. **Details** This says the *caller* is at fault, in contrast to [NotConfiguredError](NotConfiguredError.md) (the client is missing a config value) and [ContractRevertError](ContractRevertError.md) (the call was well-formed but the chain rejected it). **Gotchas** Never retry this. The arguments are wrong, so the same call fails the same way forever — fix the input instead of backing off. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new InvalidInputError**(`message`, `options?`): `InvalidInputError` Defined in: packages/sdk/src/errors.ts:104 Creates an invalid-input error with an optional underlying cause. **Details** - `message`: What was wrong with the input. - `options`: Standard `cause` passthrough, plus `chainIds` when the fault is a chain choice. #### Parameters ##### message `string` ##### options? `ErrorOptions` & `object` #### Returns `InvalidInputError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### chainIds? > `readonly` `optional` **chainIds?**: readonly `number`[] Defined in: packages/sdk/src/errors.ts:94 The chain ids of a call that named no chain, or named two chains that do not agree. Set by `exchange.client` and `exchange.trader` on a multi-chain exchange (the chains it spans) and by `createReactivity` (the engine's chain, then the wallet's). Absent on every other input error. --- # /docs/typescript/api/index/classes/InvariantError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / InvariantError # Class: InvariantError Defined in: packages/sdk/src/raise.ts:29 Thrown when an invariant the code had already established turns out false. **Details** Seeing this in a log means the SDK's own reasoning was wrong — not that a caller did anything invalid. That distinction is why it is its own class. **Gotchas** It should never be caught to control flow, only reported as a bug. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new InvariantError**(`message`): `InvariantError` Defined in: packages/sdk/src/raise.ts:30 #### Parameters ##### message `string` #### Returns `InvariantError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) --- # /docs/typescript/api/index/classes/NetworkTape [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / NetworkTape # Class: NetworkTape Defined in: packages/sdk/src/networkTape.ts:126 The live network-wide order-flow tape. Construct via [SomniaMarketsClient.createNetworkTape](../interfaces/SomniaMarketsClient.md#createnetworktape); nothing connects until the first [subscribe](#subscribe), and the socket closes when the last listener unsubscribes. Rows are read synchronously off [bids](#bids) / [fills](#fills) / [asks](#asks) after a listener fires. ## Properties ### bids > **bids**: [`TapeOrder`](../interfaces/TapeOrder.md)[] = `[]` Defined in: packages/sdk/src/networkTape.ts:128 Newest-first ring buffer of bid placements (capped at `maxRows`). *** ### fills > **fills**: [`TapeFill`](../interfaces/TapeFill.md)[] = `[]` Defined in: packages/sdk/src/networkTape.ts:130 Newest-first ring buffer of fills. *** ### asks > **asks**: [`TapeOrder`](../interfaces/TapeOrder.md)[] = `[]` Defined in: packages/sdk/src/networkTape.ts:132 Newest-first ring buffer of ask placements. ## Methods ### subscribe() > **subscribe**(`listener`): () => `void` Defined in: packages/sdk/src/networkTape.ts:172 Register a listener (fired, microtask-coalesced, after each applied batch — read the row buffers in it). The FIRST subscription opens the socket; the returned unsubscribe closes it again when it releases the last one. #### Parameters ##### listener () => `void` #### Returns () => `void` *** ### getStatus() > **getStatus**(): [`NetworkTapeStatus`](../interfaces/NetworkTapeStatus.md) Defined in: packages/sdk/src/networkTape.ts:181 #### Returns [`NetworkTapeStatus`](../interfaces/NetworkTapeStatus.md) --- # /docs/typescript/api/index/classes/NotConfiguredError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / NotConfiguredError # Class: NotConfiguredError Defined in: packages/sdk/src/errors.ts:164 The feature needs a contract address (or URL) that this client wasn't given. **Details** The SDK degrades by feature rather than refusing to construct: most [SomniaMarketsAddresses](../interfaces/SomniaMarketsAddresses.md) entries are optional, and the methods that need one throw this when it's absent. **Gotchas** Because construction succeeds, a missing address surfaces at the first call that needs it rather than at `new SomniaMarkets(…)` — so a feature can look wired up until it's exercised. The fix is always config-side (pass the address, or the method's own override param), never a retry. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new NotConfiguredError**(`what`, `detail`): `NotConfiguredError` Defined in: packages/sdk/src/errors.ts:173 Creates a missing-configuration error for one operation. **Details** - `what`: The config key or contract the operation needs (e.g. `"addresses.oracleHub"`). - `detail`: What was being attempted, and how to supply it. #### Parameters ##### what `string` ##### detail `string` #### Returns `NotConfiguredError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### what > `readonly` **what**: `string` Defined in: packages/sdk/src/errors.ts:174 --- # /docs/typescript/api/index/classes/RpcError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RpcError # Class: RpcError Defined in: packages/sdk/src/errors.ts:399 A JSON-RPC / WebSocket request to the node did not complete, or the node refused a transaction. **Details** For a read, the request produced no chain answer (connection refused, timeout, unsupported method, subscription dropped). For a write, the node can also have answered with a refusal (nonce too low, insufficient funds). **Gotchas** A call that *did* reach the chain and was rejected by a contract is a [ContractRevertError](ContractRevertError.md) instead. Check for that first when branching. A write whose signed transaction may already be on the node throws the subclass [TransactionOutcomeUnknownError](TransactionOutcomeUnknownError.md). Test for it before this class: sending that write again can execute it twice. From the local-signer and session-key executors, a plain `RpcError` means the node refused the transaction or nothing was sent. Other writes do not guarantee this: a wallet client can fail after it broadcast, and admin, lend and bridge writes do not make the distinction yet. After one of those throws `RpcError`, check the chain before you send again. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Extended by - [`TransactionOutcomeUnknownError`](TransactionOutcomeUnknownError.md) ## Constructors ### Constructor > **new RpcError**(`operation`, `detail`, `options?`): `RpcError` Defined in: packages/sdk/src/errors.ts:421 Creates an RPC error with operation context and an optional cause. **Details** - `operation`: What was attempted (e.g. `"eth_sendRawTransaction"`, `"watchBook"`). - `detail`: Why it failed. - `options`: Standard `cause` passthrough — the underlying viem/transport error — plus `chainId` when the failing chain is known. #### Parameters ##### operation `string` ##### detail `string` ##### options? `ErrorOptions` & `object` #### Returns `RpcError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### chainId? > `readonly` `optional` **chainId?**: `number` Defined in: packages/sdk/src/errors.ts:410 The chain whose read failed. Set only on an exchange with two or more chains, in two cases. The account reads of `SomniaMarkets` (`fetchBalance`, `fetchOpenOrders`, `fetchOrders`, `getOrdersPage`, `getOrderHistoryPage`, `fetchMyTrades`, `fetchPositions`, `fetchOpenStopOrders`, `watchUser`) set it when the read spans more than one chain, or when the read has no market and no chain filter, also if it then touches only one chain. `fetchDataStatus` sets it on the error it throws when every chain fails. Absent on every other RPC error. *** ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:422 --- # /docs/typescript/api/index/classes/SignerRequiredError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SignerRequiredError # Class: SignerRequiredError Defined in: packages/sdk/src/errors.ts:193 An authenticated (writing) method was called on a read-only client. **Details** Construct the exchange with a `privateKey`, an `account`, or a `walletClient` to unlock writes. Distinct from [NotConfiguredError](NotConfiguredError.md): nothing is missing from the *addresses*, the client simply has no signer. ## Extends - [`SomniaMarketsError`](SomniaMarketsError.md) ## Constructors ### Constructor > **new SignerRequiredError**(`operation`, `guidance?`): `SignerRequiredError` Defined in: packages/sdk/src/errors.ts:205 Creates a signer-required error for one authenticated operation. **Details** - `operation`: The method that needs a signer (e.g. `"createOrder"`). - `guidance`: What would satisfy it, when the default ("construct SomniaMarkets with a signer") is not the fix — a trader whose executor cannot sign typed data needs a different executor, not a different root. Kept on the error as `guidance` so a caller can branch on it without parsing the message. #### Parameters ##### operation `string` ##### guidance? `string` = `"construct SomniaMarkets with a privateKey / account / walletClient"` #### Returns `SignerRequiredError` #### Overrides [`SomniaMarketsError`](SomniaMarketsError.md).[`constructor`](SomniaMarketsError.md#constructor) ## Properties ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:206 *** ### guidance > `readonly` **guidance**: `string` = `"construct SomniaMarkets with a privateKey / account / walletClient"` Defined in: packages/sdk/src/errors.ts:207 --- # /docs/typescript/api/index/classes/SomniaMarkets [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarkets # Class: SomniaMarkets Defined in: packages/sdk/src/unified/exchange.ts:667 ## Constructors ### Constructor > **new SomniaMarkets**(`config`): `SomniaMarkets` Defined in: packages/sdk/src/unified/exchange.ts:816 Create one owner for Markets reads, watches, and optional signing. Reconciliation is off unless its positive block interval and bounded depth are supplied. #### Parameters ##### config [`SomniaMarketsConfig`](../type-aliases/SomniaMarketsConfig.md) #### Returns `SomniaMarkets` #### Throws [InvalidInputError](InvalidInputError.md) If reconciliation bounds are invalid, or if `indexerLimits` carries a bound the governor cannot use — a count that is not a whole number of at least 1, a delay of `0` or less, or any non-finite value. Checked here so a limit that would disable the in-flight cap or the backoff schedule fails at construction rather than under load. Also if `chains` is empty, binds one chain twice, or binds one indexer to two chains (URLs compare with scheme and host lower-cased, default port dropped and trailing slashes dropped). #### Throws [NotConfiguredError](NotConfiguredError.md) If the indexer endpoint is absent. ## Properties ### markets > **markets**: `Record`\<`string`, [`UnifiedMarket`](../interfaces/UnifiedMarket.md)\> = `{}` Defined in: packages/sdk/src/unified/exchange.ts:673 Unified markets keyed by MARKET symbol (populated by loadMarkets). *** ### symbols > **symbols**: `string`[] = `[]` Defined in: packages/sdk/src/unified/exchange.ts:675 All market symbols (populated by loadMarkets). *** ### has > `readonly` **has**: `object` Defined in: packages/sdk/src/unified/exchange.ts:692 Capability map — which unified verbs this venue supports (the ccxt `exchange.has` convention, for capability-probing bot code). Every listed verb is implemented here, so every flag is `true`. #### fetchMarkets > `readonly` **fetchMarkets**: `true` = `true` [SomniaMarkets.fetchMarkets](#fetchmarkets) #### fetchOrderBook > `readonly` **fetchOrderBook**: `true` = `true` [SomniaMarkets.fetchOrderBook](#fetchorderbook) #### fetchTrades > `readonly` **fetchTrades**: `true` = `true` [SomniaMarkets.fetchTrades](#fetchtrades) #### fetchOHLCV > `readonly` **fetchOHLCV**: `true` = `true` [SomniaMarkets.fetchOHLCV](#fetchohlcv) #### fetchBalance > `readonly` **fetchBalance**: `true` = `true` [SomniaMarkets.fetchBalance](#fetchbalance) #### fetchOpenOrders > `readonly` **fetchOpenOrders**: `true` = `true` [SomniaMarkets.fetchOpenOrders](#fetchopenorders) #### getOrderHistoryPage > `readonly` **getOrderHistoryPage**: `true` = `true` [SomniaMarkets.getOrderHistoryPage](#getorderhistorypage) #### getOrdersPage > `readonly` **getOrdersPage**: `true` = `true` [SomniaMarkets.getOrdersPage](#getorderspage) #### fetchMyTrades > `readonly` **fetchMyTrades**: `true` = `true` [SomniaMarkets.fetchMyTrades](#fetchmytrades) #### fetchStatus > `readonly` **fetchStatus**: `true` = `true` [SomniaMarkets.fetchStatus](#fetchstatus) #### createOrder > `readonly` **createOrder**: `true` = `true` [SomniaMarkets.createOrder](#createorder) #### cancelOrder > `readonly` **cancelOrder**: `true` = `true` [SomniaMarkets.cancelOrder](#cancelorder) #### watchOrderBook > `readonly` **watchOrderBook**: `true` = `true` [SomniaMarkets.watchOrderBook](#watchorderbook) #### watchTrades > `readonly` **watchTrades**: `true` = `true` [SomniaMarkets.watchTrades](#watchtrades) #### watchOrders > `readonly` **watchOrders**: `true` = `true` [SomniaMarkets.watchOrders](#watchorders) #### watchMyTrades > `readonly` **watchMyTrades**: `true` = `true` [SomniaMarkets.watchMyTrades](#watchmytrades) #### fetchPositions > `readonly` **fetchPositions**: `true` = `true` [SomniaMarkets.fetchPositions](#fetchpositions) #### fetchFundingRate > `readonly` **fetchFundingRate**: `true` = `true` [SomniaMarkets.fetchFundingRate](#fetchfundingrate) #### fetchFundingRateHistory > `readonly` **fetchFundingRateHistory**: `true` = `true` [SomniaMarkets.fetchFundingRateHistory](#fetchfundingratehistory) — the key did not previously exist in this map, so it had to be ADDED rather than flipped. #### watchPrice > `readonly` **watchPrice**: `true` = `true` [SomniaMarkets.watchPrice](#watchprice) #### fetchPrice > `readonly` **fetchPrice**: `true` = `true` [SomniaMarkets.fetchPrice](#fetchprice) #### fetchPriceOHLCV > `readonly` **fetchPriceOHLCV**: `true` = `true` [SomniaMarkets.fetchPriceOHLCV](#fetchpriceohlcv) ## Accessors ### chainIds #### Get Signature > **get** **chainIds**(): `number`[] Defined in: packages/sdk/src/unified/exchange.ts:880 Numeric chain ids this exchange spans, in binding order (the first is the primary). ##### Returns `number`[] *** ### chainIdsWithoutIndexer #### Get Signature > **get** **chainIdsWithoutIndexer**(): `number`[] Defined in: packages/sdk/src/unified/exchange.ts:905 The chains bound with no `indexerUrl`, in binding order. This is how the account reads report which chains they skipped. A chain-only binding, such as Hideki (50383) with no hosted indexer, can read balances and resting orders from the chain but has no indexed data. On a read over more than one chain, the facade account reads skip the indexer legs of these chains instead of throwing `NotConfiguredError`: - [fetchBalance](#fetchbalance) keeps their ERC-20 and native balances and skips their binary outcome holdings. - [fetchOpenOrders](#fetchopenorders) reads their resting orders from the chain, over the perp pools that [loadMarkets](#loadmarkets) discovered on that chain. - [fetchOrders](#fetchorders), [getOrdersPage](#getorderspage), [fetchMyTrades](#fetchmytrades), [fetchOpenStopOrders](#fetchopenstoporders) and [watchUser](#watchuser) skip these chains. A skipped chain adds no rows. Its absence from a result does not mean that the account has no orders or trades there. A read scoped to one of these chains still throws `NotConfiguredError` when it has no chain-readable leg. ##### Returns `number`[] *** ### client #### Get Signature > **get** **client**(): [`SomniaMarketsClientWithObservations`](../interfaces/SomniaMarketsClientWithObservations.md) Defined in: packages/sdk/src/unified/exchange.ts:924 The native engine of a single-chain exchange — bigint-exact, address-keyed. The escape hatch for reads and watches the unified verbs do not cover. **Gotchas** On an exchange with more than one chain binding this throws. A pool address or market id can name a different market on each chain, so a read with no chain could return another chain's data. Use [SomniaMarkets.engineFor](#enginefor) with the chain id there. ##### Throws [InvalidInputError](InvalidInputError.md) If the exchange spans more than one chain. `chainIds` lists the chains it spans. ##### Returns [`SomniaMarketsClientWithObservations`](../interfaces/SomniaMarketsClientWithObservations.md) *** ### trader #### Get Signature > **get** **trader**(): [`Trader`](../interfaces/Trader.md) Defined in: packages/sdk/src/unified/exchange.ts:1092 The raw write tier of a single-chain exchange, bound to its signer — bigint-exact `placeOrder`/`mintSet`/`faucet`/… for anything the unified verbs don't cover. **Gotchas** On an exchange with more than one chain binding this throws. A pool address or market id can name a different market on each chain, so a write with no chain could land on another chain. Use [SomniaMarkets.traderFor](#traderfor) with the chain id there. ##### Throws [InvalidInputError](InvalidInputError.md) If the exchange spans more than one chain (`chainIds` lists them), or the private key is malformed. ##### Throws [SignerRequiredError](SignerRequiredError.md) If no signer is configured. ##### Throws [NotConfiguredError](NotConfiguredError.md) If the account has no executor for the chain. ##### Returns [`Trader`](../interfaces/Trader.md) *** ### walletAddress #### Get Signature > **get** **walletAddress**(): `` `0x${string}` `` \| `undefined` Defined in: packages/sdk/src/unified/exchange.ts:1121 The authenticated wallet address, if a signer was configured. ##### Returns `` `0x${string}` `` \| `undefined` *** ### perpDiscoveryError #### Get Signature > **get** **perpDiscoveryError**(): [`SomniaMarketsError`](SomniaMarketsError.md) \| `null` Defined in: packages/sdk/src/unified/exchange.ts:1187 Why chain-tier perp discovery did not run on the last [loadMarkets](#loadmarkets), or `null` when it ran (or was never applicable). `loadMarkets()` contains a discovery failure rather than throwing, because it is the implicit prerequisite of nearly every symbol-based verb and a chain failure must not take the SPOT and OUTCOME market lists down with it. This is where that contained failure is reported, with the underlying error preserved in `cause`. **When to use** Check it after `loadMarkets()` whenever a SHORT perp list would be worse than an error — a market page, an order router, anything that would otherwise present "this market does not exist". Then either tell the user the list is incomplete, or call `loadMarkets()` again. A load that recorded a failure is not served from the cache, so the next bare call re-runs discovery. `loadMarkets(true)` also retries. **Gotchas** - On a multi-chain exchange this is the FIRST failing chain's error, in the order of the `chains` config. [perpDiscoveryErrorsByChain](#perpdiscoveryerrorsbychain) reports every failing chain. - Do NOT infer this from `perpStatus` being absent. That works only when the indexer already carries a perp row to inspect; with a configured factory and an indexer carrying none, a failed discovery yields an EMPTY perp list with no market to check. This accessor answers in both cases. - `null` does not mean the venue has perps. A chain with no perps plane deployed (local anvil) never attempts discovery and reports `null` too. [perpDiscoverySkipped](#perpdiscoveryskipped) reports that case, so read BOTH before you tell a user the venue has no perps. **Example** (Refusing to show a possibly-short perp list) ```ts await exchange.loadMarkets(); if (exchange.perpDiscoveryError) { // loadMarkets(true) reloads every chain. await exchange.loadMarkets(true); } if (exchange.perpDiscoveryError) { const partial = exchange.perpDiscoveryPartialFailure; throw new Error( partial ? `perp list incomplete: ${partial.failed} of ${partial.total} markets unread` : "perp discovery failed; the perp list may be short", ); } ``` ##### Returns [`SomniaMarketsError`](SomniaMarketsError.md) \| `null` *** ### perpDiscoveryErrorsByChain #### Get Signature > **get** **perpDiscoveryErrorsByChain**(): `Record`\<`number`, [`SomniaMarketsError`](SomniaMarketsError.md)\> Defined in: packages/sdk/src/unified/exchange.ts:1213 Every chain whose perp discovery failed on the last [loadMarkets](#loadmarkets), keyed by chain id. A chain with no failure has no key, so `{}` means discovery failed on no chain. [perpDiscoveryError](#perpdiscoveryerror) reports only the first failing chain. On a multi-chain exchange, use this accessor to name each chain whose perp list may be short. Each value is the same typed error that [perpDiscoveryError](#perpdiscoveryerror) would hold for that chain alone, with the underlying error in `cause`. **Gotchas** - Each read returns a new object. Changes to it do not change the exchange. - It resets on every load that runs, so it always describes the LAST load. ##### Returns `Record`\<`number`, [`SomniaMarketsError`](SomniaMarketsError.md)\> *** ### perpDiscoveryPartialFailure #### Get Signature > **get** **perpDiscoveryPartialFailure**(): \{ `failed`: `number`; `total`: `number`; \} \| `null` Defined in: packages/sdk/src/unified/exchange.ts:1226 How much of the chain-only perp set was lost when discovery PARTIALLY failed, or `null` when it did not. Typed counts rather than prose in a message, so a consumer can decide on them — `{ failed: 1, total: 4 }` reads as "three of four chain-only markets are listed". Always `null` when [perpDiscoveryError](#perpdiscoveryerror) is null, and also null when discovery failed outright rather than partly (nothing was read, so there is no ratio). ##### Returns \{ `failed`: `number`; `total`: `number`; \} \| `null` *** ### perpDiscoveryPartialFailuresByChain #### Get Signature > **get** **perpDiscoveryPartialFailuresByChain**(): `Record`\<`number`, \{ `failed`: `number`; `total`: `number`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:1245 The partial-discovery counts of the last [loadMarkets](#loadmarkets), keyed by chain id. A chain has a key only when its discovery PARTIALLY failed. [perpDiscoveryPartialFailure](#perpdiscoverypartialfailure) reports the counts of the first failing chain only. This accessor gives the counts of each chain, so `{ 50312: { failed: 1, total: 4 } }` reads as "chain 50312 lists three of its four chain-only markets". A chain whose discovery failed outright has a key in [perpDiscoveryErrorsByChain](#perpdiscoveryerrorsbychain) and no key here, because nothing was read. **Gotchas** - Each read returns a new object. Changes to it do not change the exchange. ##### Returns `Record`\<`number`, \{ `failed`: `number`; `total`: `number`; \}\> *** ### perpDiscoverySkipped #### Get Signature > **get** **perpDiscoverySkipped**(): \{ `reason`: `"no-factory-route"`; \} \| `null` Defined in: packages/sdk/src/unified/exchange.ts:1300 Why the last [loadMarkets](#loadmarkets) did not LOOK for perp pools, or `null` when it did look. `"no-factory-route"` means the SDK had no way to reach the PerpPoolFactory. It finds the factory either from a configured `addresses.perpPoolFactory`, or from the `marginBank` of an indexed perp row. With neither — a reachable indexer that carries no perp rows, and no configured address — discovery returns an empty set without asking anything. This is the one state the error accessors cannot report. Nothing failed, so [perpDiscoveryError](#perpdiscoveryerror) and [registryReadError](#registryreaderror) are both `null`, and an empty perp list would otherwise be indistinguishable from a venue that genuinely has no perps. **When to use** Read it before you tell a user "this venue has no perps". A non-null value means "not looked", not "none exist". **Gotchas** - This is INFORMATIONAL, not an alert. A non-null value is normal and permanent on a venue with no perps plane — Somnia mainnet today, and a local anvil deployment. Do not surface it as an error there. - It reports "the SDK had no way to look", never "a read failed". A failed registry read on a chain leaves this `null` for that chain: the empty row set is then a symptom of that failure, which [registryReadError](#registryreaderror) already names. - For ONE engine it is likewise never set together with [perpDiscoveryError](#perpdiscoveryerror). That accessor means a route was found and the read failed; this one means no route was found and nothing was read. On a multi-chain exchange both can be non-null at once, each reporting a different chain. - It resets on every load, so re-read it after `loadMarkets(true)`. - The realistic transient cause is an indexer that was wiped or is reindexing below the factory's first deploy block. The spot and binary rows are short in that window too; [registryReadError](#registryreaderror) does not cover it, and `exchange.client.getIndexerFreshness` is the general signal for lag. **Example** (Telling "no perps here" apart from "could not look") ```ts await exchange.loadMarkets(); const perps = Object.values(exchange.markets).filter((m) => m.type === "swap"); if (perps.length === 0 && exchange.perpDiscoverySkipped) { console.log("perp discovery was skipped:", exchange.perpDiscoverySkipped.reason); } ``` ##### Returns \{ `reason`: `"no-factory-route"`; \} \| `null` *** ### registryReadError #### Get Signature > **get** **registryReadError**(): [`SomniaMarketsError`](SomniaMarketsError.md) \| `null` Defined in: packages/sdk/src/unified/exchange.ts:1346 Why the indexer's market registry could not be read on the last [loadMarkets](#loadmarkets), or `null` when the read COMPLETED. `loadMarkets()` contains this failure rather than throwing, for the same reason it contains a perp discovery failure: it is the implicit prerequisite of nearly every symbol-based verb, and an indexer outage must not take down the perp markets the chain can enumerate on its own. This is where that contained failure is reported, with the underlying error preserved in `cause`. In practice it is an [IndexerError](IndexerError.md) carrying `operation` and `detail`. **When to use** Check it after `loadMarkets()` whenever an EMPTY market list would be worse than an error. `null` together with an empty [symbols](#symbols) is the unambiguous "this venue genuinely has no markets"; non-null with an empty list means the registry could not be read and the list says nothing about what exists. To retry, call `loadMarkets()` again. A load that recorded a failure is not served from the cache, so the next bare call re-runs the sweep. `loadMarkets(true)` also retries. **Gotchas** - On a multi-chain exchange this is the FIRST failing chain's error, in the order of the `chains` config. [registryReadErrorsByChain](#registryreaderrorsbychain) reports every failing chain. - This is all-or-nothing for one chain. A registry sweep that succeeded but dropped unparseable rows is a different condition, reported by `listRegistryMarketsChecked` through `RegistrySweep.dropped`. - Cleared on every `loadMarkets()` that actually runs, so it always describes the LAST load, never an older one. **Example** (Telling an outage apart from an empty venue) ```ts await exchange.loadMarkets(); if (exchange.registryReadError) { // loadMarkets(true) reloads every chain. await exchange.loadMarkets(true); } if (exchange.registryReadError) { throw new Error("the market registry could not be read; the market list may be short"); } if (exchange.symbols.length === 0) { console.log("this venue has no markets"); } ``` ##### Returns [`SomniaMarketsError`](SomniaMarketsError.md) \| `null` *** ### registryReadErrorsByChain #### Get Signature > **get** **registryReadErrorsByChain**(): `Record`\<`number`, [`SomniaMarketsError`](SomniaMarketsError.md)\> Defined in: packages/sdk/src/unified/exchange.ts:1368 Every chain whose indexer registry read failed on the last [loadMarkets](#loadmarkets), keyed by chain id. A chain with no failure has no key, so `{}` means every registry read completed. [registryReadError](#registryreaderror) reports only the first failing chain. On a multi-chain exchange, use this accessor to name each chain whose market list may be short. Each value is the same typed error that [registryReadError](#registryreaderror) would hold for that chain alone. In practice it is an [IndexerError](IndexerError.md) carrying `operation` and `detail`. **Gotchas** - A chain bound with no `indexerUrl` always has a key here. Its value is a [NotConfiguredError](NotConfiguredError.md), because that chain has no registry to read. - Each read returns a new object. Changes to it do not change the exchange. - It resets on every load that runs, so it always describes the LAST load. ##### Returns `Record`\<`number`, [`SomniaMarketsError`](SomniaMarketsError.md)\> *** ### accounts #### Get Signature > **get** **accounts**(): [`ExchangeSmartAccounts`](../interfaces/ExchangeSmartAccounts.md) Defined in: packages/sdk/src/unified/exchange.ts:3985 The smart-accounts surface across this exchange's chains: derive the one address, scan every covered chain, fan one signed authorization out into per-chain creation calls, and build the multi-chain account the exchange trades through. See [ExchangeSmartAccounts](../interfaces/ExchangeSmartAccounts.md); the one-chain surface is `client.accounts`. ##### Returns [`ExchangeSmartAccounts`](../interfaces/ExchangeSmartAccounts.md) *** ### collateralReadErrors #### Get Signature > **get** **collateralReadErrors**(): `Readonly`\<`Record`\<`number`, [`CollateralReadError`](../type-aliases/CollateralReadError.md)\>\> Defined in: packages/sdk/src/unified/exchange.ts:4012 Failed reads from the last completed collateral balance sweep, keyed by chain. Available after `createOrder` checks or `ensureFunds`, including successful bridge plans. Empty before the first sweep and after a complete successful read. Target-chain failures throw and leave this snapshot unchanged. Concurrent sweeps replace it in completion order; a shortfall error retains its own snapshot. ##### Returns `Readonly`\<`Record`\<`number`, [`CollateralReadError`](../type-aliases/CollateralReadError.md)\>\> *** ### bridge #### Get Signature > **get** **bridge**(): [`ExchangeBridge`](../interfaces/ExchangeBridge.md) Defined in: packages/sdk/src/unified/exchange.ts:4021 The bridge between this exchange's chains, through the account's executors: plan a transfer, or execute one and wait for it to land. See [ExchangeBridge](../interfaces/ExchangeBridge.md). ##### Returns [`ExchangeBridge`](../interfaces/ExchangeBridge.md) ## Methods ### engineFor() > **engineFor**(`chainId`): [`SomniaMarketsClientWithObservations`](../interfaces/SomniaMarketsClientWithObservations.md) Defined in: packages/sdk/src/unified/exchange.ts:949 The native engine bound to one configured chain — bigint-exact, address-keyed. The escape hatch for that chain. **Gotchas** Throws [NotConfiguredError](NotConfiguredError.md) for a chain this exchange has no binding for. #### Parameters ##### chainId `number` #### Returns [`SomniaMarketsClientWithObservations`](../interfaces/SomniaMarketsClientWithObservations.md) *** ### traderFor() > **traderFor**(`chainId`): [`Trader`](../interfaces/Trader.md) Defined in: packages/sdk/src/unified/exchange.ts:1046 The raw write tier for one chain this exchange spans, bound to its signer — bigint-exact `placeOrder`/`approveBuilder`/`setPerpLeverage`/… for anything the unified verbs do not cover. **Details** The trader uses the engine of `chainId`, so its writes share that engine's nonce lane. With a [SomniaMarketsAccount](../interfaces/SomniaMarketsAccount.md) it writes through `account.executors[chainId]`. It is built on first use and replaced after [SomniaMarkets.setSigner](#setsigner) or [SomniaMarkets.close](#close). #### Parameters ##### chainId `number` #### Returns [`Trader`](../interfaces/Trader.md) #### Throws [NotConfiguredError](NotConfiguredError.md) If the exchange has no binding for `chainId`, or the account has no executor for it. #### Throws [SignerRequiredError](SignerRequiredError.md) If no signer is configured. #### Throws [InvalidInputError](InvalidInputError.md) If the private key is malformed or the signer cannot send on `chainId`. *** ### setSigner() > **setSigner**(`signer`): `void` Defined in: packages/sdk/src/unified/exchange.ts:1109 Bind (or replace) the exchange's signer after construction. Browser apps construct the exchange at boot for public reads, then call this when the user's wallet connects — and again with `{}` on disconnect, which returns the exchange to unauthenticated reads. Replaces the trader every authenticated verb and `walletAddress` resolve against; live watches and market data are unaffected. #### Parameters ##### signer [`SomniaMarketsSignerConfig`](../interfaces/SomniaMarketsSignerConfig.md) #### Returns `void` #### Throws [InvalidInputError](InvalidInputError.md) If a [SomniaMarketsAccount](../interfaces/SomniaMarketsAccount.md) has an executor for a chain this exchange does not span, for another chain, or acting as another address. The previous signer stays bound. *** ### loadMarkets() > **loadMarkets**(`reload?`): `Promise`\<`Record`\<`string`, [`UnifiedMarket`](../interfaces/UnifiedMarket.md)\>\> Defined in: packages/sdk/src/unified/exchange.ts:1420 Load (or reload) the market registry: every market as a unified, symbol-keyed market object. Call once before anything symbol-based. **Perp markets come from two sources.** The indexer's rows are unioned with the PerpPoolFactory's, because the indexer builds its perp set dynamically from `PerpPoolDeployed` and a pool deployed above its current head is live on chain and absent there. A market only the chain knows carries [UnifiedMarket.indexed](../interfaces/UnifiedMarket.md#indexed) `false`; read that field's docs before touching anything history-derived on it. **A read failure is contained, not thrown.** This method is the implicit prerequisite of nearly every symbol-based verb, so letting one source's failure out would take every other source down with it. Both sources report instead of throwing: the indexer registry read through [registryReadError](#registryreaderror), and perp discovery through [perpDiscoveryError](#perpdiscoveryerror) — which also covers the PARTIAL case where some chain-only markets were read and others were not. Each chain loads on its own, and [registryReadErrorsByChain](#registryreaderrorsbychain), [perpDiscoveryErrorsByChain](#perpdiscoveryerrorsbychain) and [perpDiscoveryPartialFailuresByChain](#perpdiscoverypartialfailuresbychain) report the failures of each chain. So an indexer outage still returns the perp markets the chain can enumerate, and a chain outage still returns the indexer's spot and outcome lists. **A caller that treated a throw as "the registry is unreadable" must now check `registryReadError` instead.** **Discovery coverage per kind.** - **Perp** — chain-complete through the PerpPoolFactory, so it survives an empty or unreachable indexer. One caveat: with NO indexed perp row the factory is found only from a configured `addresses.perpPoolFactory`, because the bootstrap route otherwise reads the `marginBank` off an indexed row. Configure it for a venue whose indexer carries no perp rows. - **Binary** — indexer-only here. Live discovery of NEW binary markets does not need this method: `watchMarkets({ discover: true })` adds them from the chain's `MarketCreated` events. - **Spot** — indexer-only. `SpotPoolRegistry` answers "is this pool registered", so it cannot be enumerated from the chain. **Gotchas** - A bare call returns the cached registry when every chain is loaded and the last load recorded no failure. When a chain's registry read or perp discovery failed, a bare call reads that chain again, so a chain that failed once does not stay missing. A chain that no load has read yet, for example after only reads filtered to another chain, loads the same way. The other chains keep their cached markets. `loadMarkets(true)` reloads every chain. - A verb that loads markets for you, such as `fetchBalance`, `fetchMyTrades` or `fetchPositions`, retries a failed chain at most once in 30 seconds. The 30 seconds start when that chain's last load settled. Before then, the verb uses the cached markets, and the failure accessors keep the recorded error and failing chain. So a persistent failure does not re-run the full registry sweep and perp discovery on every verb. A bare `loadMarkets()`, `fetchMarkets()`, `ensureFunds` and `loadMarkets(true)` do not wait: they retry at once. - A call that starts while a retry of a chain it needs is running waits for that retry and gets its result. It does not start a second retry. - Symbols are unique across the loaded chains. When a chain loads later than the others, a symbol that it shares with a market on another chain changes on both chains. - A [NotConfiguredError](NotConfiguredError.md) failure does not cause a retry. It reports a missing config value, which a retry cannot fix. A chain bound with no `indexerUrl` records one on every load. - Concurrent cold reads share discovery. Each explicit reload waits for prior discovery, then re-reads independently. **Details** - `reload`: Re-read everything, including the live tradeability gates and the binary pools' grids. - Throws [NotConfiguredError](NotConfiguredError.md) - the load needed a chain read (ERC-20 metadata for an unlabeled token, or a binary pool's grid) and the owner has neither a `wsRpcUrl` nor a chain whose `rpcUrls` carry a WebSocket endpoint. Thrown before any request goes out, so it means misconfiguration rather than an outage — an outage reaches [registryReadError](#registryreaderror) or [perpDiscoveryError](#perpdiscoveryerror) instead. - Throws [InvariantError](InvariantError.md) - the SDK's own reasoning was wrong (a market the symbol registry did not name). Report it as a defect; there is nothing for a caller to do about it. The complete union is [SomniaMarketsLoadMarketsError](../type-aliases/SomniaMarketsLoadMarketsError.md). Neither an unreachable indexer nor an unreadable chain is in it: both are contained and reported through the accessors named above. #### Parameters ##### reload? `boolean` = `false` #### Returns `Promise`\<`Record`\<`string`, [`UnifiedMarket`](../interfaces/UnifiedMarket.md)\>\> *** ### market() > **market**(`ref`): [`Tradable`](../interfaces/Tradable.md) Defined in: packages/sdk/src/unified/exchange.ts:1995 Resolve any handle (symbol, tradable symbol, pool/market address, market id) to its tradable. Requires loadMarkets(). **Gotchas** Resolves MORE than [fetchMarkets](#fetchmarkets) lists. A settled binary market the wallet still holds a position, a fill or an order in is added here the first time a read names it (`fetchBalance`, `fetchMyTrades`, `fetchOpenOrders`, `fetchOrders`), by market id and BinaryMarket address — never by pool, which by then serves the next market in the series. Such a market can be redeemed and reported; every pool-routed verb refuses it. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) #### Returns [`Tradable`](../interfaces/Tradable.md) *** ### priceToPrecision() > **priceToPrecision**(`ref`, `price`): `number` Defined in: packages/sdk/src/unified/exchange.ts:2015 Snap a price to the market's tick grid (rounds down; binary prices are also clamped inside (0, 1)). **When to use** Use before createOrder with computed prices. Spot/perp ticks come from the market row; binary ticks come from the pool, read once by [loadMarkets](#loadmarkets) — so a pool recycled mid-session keeps the grid captured at load time until `loadMarkets(true)` refreshes it. **Gotchas** - Throws [InvalidInputError](InvalidInputError.md) if the market is binary and its pool's parameters could not be read — quantizing against a guessed grid is what produced off-tick rejections, so this fails loudly instead. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### price `number` #### Returns `number` *** ### amountToPrecision() > **amountToPrecision**(`ref`, `amount`): `number` Defined in: packages/sdk/src/unified/exchange.ts:2036 Snap an amount to the market's lot grid (rounds down). Spot/perp lots come from the market row; binary lots come from the pool, read once by [loadMarkets](#loadmarkets) — so a pool recycled mid-session keeps the grid captured at load time until `loadMarkets(true)` refreshes it. **Gotchas** - Throws [InvalidInputError](InvalidInputError.md) if the market is binary and its pool's parameters could not be read. Previously such a market fell back to a one-whole-token lot, silently flooring every sub-token amount to 0. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### amount `number` #### Returns `number` *** ### fetchMarkets() > **fetchMarkets**(): `Promise`\<[`UnifiedMarket`](../interfaces/UnifiedMarket.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:2053 Every market as an array — [loadMarkets](#loadmarkets) (called if needed), minus the symbol keying. **When to use** Use as the ccxt-shaped sibling for list-style consumers. #### Returns `Promise`\<[`UnifiedMarket`](../interfaces/UnifiedMarket.md)[]\> *** ### fetchOrderBook() > **fetchOrderBook**(`ref`, `options?`): `Promise`\<[`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md)\> Defined in: packages/sdk/src/unified/exchange.ts:2194 One-shot book read from the contract (head-fresh; no watch needed). **When to use** Use when one book snapshot is enough. For a continuously-current zero-round-trip book, use [watchOrderBook](#watchorderbook). Both sides use one selected head, or `options.blockNumber`. Empty books keep that pin. A numeric second argument remains the level limit. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### options? `number` \| [`FetchOrderBookOptions`](../interfaces/FetchOrderBookOptions.md) #### Returns `Promise`\<[`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md)\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol, depth, or pin is invalid. #### Throws [NotConfiguredError](NotConfiguredError.md) If the owner has no chain endpoint. #### Throws [RpcError](RpcError.md) If the head selection or either read fails. #### Throws [ContractRevertError](ContractRevertError.md) If the contract rejects a read. #### Throws [InvalidInputError](InvalidInputError.md) If the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. *** ### fetchTrades() > **fetchTrades**(`ref`, `since?`, `limit?`): `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:2224 Recent public trades with authoritative block and log positions (indexer, newest first). #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### since? `number` ##### limit? `number` = `50` #### Returns `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol or source position is invalid. #### Throws [IndexerError](IndexerError.md) If the indexer read fails. #### Throws [NotConfiguredError](NotConfiguredError.md) If the chain's indexer is absent or does not index that chain. #### Throws [InvalidInputError](InvalidInputError.md) If the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. *** ### fetchOHLCV() > **fetchOHLCV**(`ref`, `timeframe?`, `since?`, `limit?`): `Promise`\<[`UnifiedOHLCV`](../type-aliases/UnifiedOHLCV.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:2284 OHLCV candles (indexer), oldest first as [ms,o,h,l,c,vol] rows. Timeframes: 1m 5m 15m 1h 4h 1d. **Example** (Reading candles) The last 24 hourly candles, destructured per row. ```ts const candles = await exchange.fetchOHLCV("SOMI/USDC", "1h", undefined, 24); for (const [ts, open, high, low, close, volume] of candles) { console.log(new Date(ts).toISOString(), open, high, low, close, volume); } ``` - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### timeframe? `string` = `"5m"` ##### since? `number` ##### limit? `number` = `500` #### Returns `Promise`\<[`UnifiedOHLCV`](../type-aliases/UnifiedOHLCV.md)[]\> *** ### fetchTicker() > **fetchTicker**(`ref`): `Promise`\<[`UnifiedTicker`](../interfaces/UnifiedTicker.md)\> Defined in: packages/sdk/src/unified/exchange.ts:2340 Rolling 24h ticker (indexer): OHLC + base/quote volume folded from the hourly candles, `last` from the freshest fill. NO-outcome tradables view prices through the 1−p lens like every other read. **Gotchas** The two halves of this response fail independently, and each reports its own state. Read `statsState` and `perpState`; do not infer either from a missing field. The 24h half is contained. A candle request that fails with an `IndexerError`, and a market with `indexed: false` (no request is sent), both give `statsState: "unavailable"`, and then `open`, `high`, `low`, `change`, `percentage`, `statsAsOf`, `baseVolume` and `quoteVolume` are all absent. The call still resolves, so the perp chain numbers — mark, index, funding and open interest — survive an indexer outage. `last` and `lastSource` also survive, from the cached market row. `baseVolume` of `0` is a true zero: a successful read over a window with no fills. It is not the same as an absent volume. **Example** (Reading a ticker) Drive a price strip off one call. ```ts const tk = await exchange.fetchTicker("SOMI/USDC"); if (tk.statsState === "ok") console.log(tk.last, tk.percentage, tk.baseVolume); else console.log(tk.last, "24h statistics unavailable"); ``` #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) #### Returns `Promise`\<[`UnifiedTicker`](../interfaces/UnifiedTicker.md)\> #### Throws [InvalidInputError](InvalidInputError.md) when `ref` names no loaded market. #### Throws [NotConfiguredError](NotConfiguredError.md) when the market's chain has no binding on this exchange. - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. *** ### fetchBalance() > **fetchBalance**(`filter?`): `Promise`\<[`UnifiedBalances`](../interfaces/UnifiedBalances.md)\> Defined in: packages/sdk/src/unified/exchange.ts:2515 Wallet balances for every currency the loaded markets use (+ native). **Gotchas** `free === total`: funds escrowed in resting orders live in the pools, not the wallet, so they simply don't appear here. - Throws [SignerRequiredError](SignerRequiredError.md) - balances are per-account, so this needs a signer (or an `account`) even though it only reads. - Throws [NotConfiguredError](NotConfiguredError.md) - `filter.chainId` names a chain this exchange does not span. - Throws [IndexerError](IndexerError.md) - the outcome-holdings read needed the indexer and it was unreachable, or the indexer served a position on a market it has no row for. Distinct from an empty result: no balances is `{}`, not a throw. The `loadMarkets()` this calls first does NOT throw on an unreachable indexer; it reports through [registryReadError](#registryreaderror), so a balance set can be short rather than absent. - Throws [RpcError](RpcError.md) - a chain balance read did not complete. A failed read is never reported as a zero balance or a missing key. - Throws [ContractRevertError](ContractRevertError.md) - a token's `balanceOf` reverted. With no `filter.chainId` this reads every chain and throws when any chain fails. On an exchange with more than one chain, the thrown `IndexerError` or `RpcError` then has `chainId` set to the chain that failed. Pass `filter.chainId` to read one chain only (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). A chain bound with no `indexerUrl` reports its ERC-20 and native balances and no outcome holdings, because holdings are indexer data. Such chains are listed in [chainIdsWithoutIndexer](#chainidswithoutindexer). **Example** (Reading balances) ERC-20s key by currency code; binary outcome holdings key by TRADABLE symbol. ```ts const bal = await exchange.fetchBalance(); console.log(bal.USDC?.total); // collateral in the wallet console.log(bal["BTC-95000-31DEC26/USDC#YES"]?.total); // YES shares held // A holding on a market that already SETTLED is listed under that market's // own symbol, even though `fetchMarkets()` no longer lists the market. for (const [symbol, held] of Object.entries(bal)) { if (symbol.includes("#") && !exchange.symbols.includes(symbol.split("#")[0] ?? "")) { console.log("settled, redeemable:", symbol, held.total); } } ``` #### Parameters ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`UnifiedBalances`](../interfaces/UnifiedBalances.md)\> *** ### fetchOpenOrders() > **fetchOpenOrders**(`ref?`, `limit?`, `filter?`): `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:2644 Open orders (indexer view). **When to use** Use for an occasional snapshot; a trading loop should prefer [watchOrders](#watchorders). **Details** `limit` is applied BY THE QUERY, per venue — not to the merged result. An unscoped call reads all three venues, so it can return up to 3 × `limit` rows; a `ref`-scoped call reads only that venue. The default is 200 per venue. - `ref`: Restrict to one tradable (symbol or address). Omit for all. - `limit`: Max orders PER VENUE the query returns (default 200). - `filter.chainId`: Read only this chain. With no `ref` and no `filter.chainId` this reads every chain and throws when any chain fails. On an exchange with more than one chain, the thrown `IndexerError`, or the `RpcError` of an on-chain order read, then has `chainId` set to the chain that failed (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). On each indexed chain, the binary, spot and perp portfolio reads run at the same time. The result keeps chain binding order, then binary, spot, perp order within a chain, whatever order the reads finish in. When more than one read fails, the error is the first one to arrive. On a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)) this reads the resting orders from the chain instead, over the perp pools that [loadMarkets](#loadmarkets) discovered there. Those rows have no `txHash` and no `timestamp`. **Gotchas** The indexer view lags the chain slightly. This read needs the indexer and throws `IndexerError` while it is unreachable. Do NOT wrap it in a catch that returns an empty list: a bot that does so believes it has nothing resting during an outage, and then quotes again on top of its own live orders. The chain-backed substitute is `exchange.client.getOpenOrdersOnchain(pools, owner)`, which answers from the pool contracts at one pinned block. It returns raw rows without a market, a symbol or a binary YES/NO side, so it is a substitute for quote management rather than a drop-in replacement for this verb. On SPOT the same limit also bounds the PENDING STOP ORDERS the underlying portfolio read returns — one query variable caps both sets. That list is not part of this verb's result, so the coupling is invisible here, but a caller reading `client.getSpotPortfolio` directly with a small `ordersLimit` will see a correspondingly short `pendingStopOrders`. #### Parameters ##### ref? [`MarketHandle`](../type-aliases/MarketHandle.md) ##### limit? `number` ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If `ref` is unknown, or `ref` is not on `filter.chainId`. #### Throws [NotConfiguredError](NotConfiguredError.md) If `filter.chainId` names a chain this exchange does not span. *** ### fetchOrders() > **fetchOrders**(`ref?`, `since?`, `limit?`, `params?`): `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:2740 The wallet's orders across every lifecycle status (indexer), newest first — the history counterpart to [fetchOpenOrders](#fetchopenorders). Scope to one tradable with `ref`; page with `limit`/`params.offset`, both forwarded to the query as a true offset window over one ordered set. (Its siblings page differently: [fetchMyTrades](#fetchmytrades) pages a fill tape to satisfy `limit`, and [fetchOpenOrders](#fetchopenorders) applies its limit per venue.) `params.chainId` reads only that chain (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). With no `ref` and no `params.chainId` this reads every chain and throws when any chain fails. On an exchange with more than one chain, the thrown `IndexerError` then has `chainId` set to the chain that failed. A read over more than one chain skips a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)). **Example** (Reading order history) The last 50 orders on one book, whatever became of them. ```ts const orders = await exchange.fetchOrders("SOMI/USDC", undefined, 50); for (const o of orders) console.log(o.status, o.side, o.amount, o.txHash); ``` #### Parameters ##### ref? [`MarketHandle`](../type-aliases/MarketHandle.md) ##### since? `number` ##### limit? `number` = `100` ##### params? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) & `object` = `{}` #### Returns `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If `ref` is unknown, or `ref` is not on `params.chainId`. #### Throws [NotConfiguredError](NotConfiguredError.md) If `params.chainId` names a chain this exchange does not span, or the one chain the read touches has no indexer. *** ### getOrderHistoryPage() > **getOrderHistoryPage**(`options?`): `Promise`\<[`UnifiedOrdersPage`](../type-aliases/UnifiedOrdersPage.md)\> Defined in: packages/sdk/src/unified/exchange.ts:2824 Read one raw-row page of the authenticated owner's indexed order history. Use this method to traverse indexed order records with immutable order identities. The records and offset window are mutable. They are not an immutable lifecycle log or a current Open Orders snapshot. The default `limit` is 100 and the default `offset` is 0. Continuation depends on raw rows, so a full page can have no display orders and still continue. The result is partial because changes can make pages skip or repeat rows. Exhaustion does not prove complete account state. The `status` option is an indexed history filter. In particular, `status: "Open"` cannot establish completeness, removals, continuity, or action freshness. Use a separately supported current-state flow when the caller needs the SDK's current open-order view. The `chainId` option reads only that chain. With no `ref` and no `chainId` this reads every chain and throws when any chain fails. On an exchange with more than one chain, the thrown `IndexerError` then has `chainId` set to the chain that failed. A read over more than one chain skips a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)). **Example** (Following order-history page offsets) ```ts let offset = 0; while (true) { const page = await exchange.getOrderHistoryPage({ limit: 100, offset }); for (const order of page.orders) console.log(order.identity, order.status); if (page.nextOffset === null) break; offset = page.nextOffset; } ``` #### Parameters ##### options? [`SomniaMarketsGetOrdersPageOptions`](../type-aliases/SomniaMarketsGetOrdersPageOptions.md) = `{}` #### Returns `Promise`\<[`UnifiedOrdersPage`](../type-aliases/UnifiedOrdersPage.md)\> #### Throws [InvalidInputError](InvalidInputError.md) If the ref, status, limit, or offset is invalid, or the ref is not on `chainId`. #### Throws [SignerRequiredError](SignerRequiredError.md) If no account is configured. #### Throws [IndexerError](IndexerError.md) If the indexer read or producer-row conversion fails. #### Throws [NotConfiguredError](NotConfiguredError.md) If `chainId` names a chain this exchange does not span, or the chain's indexer is absent or does not index that chain. *** ### getOrdersPage() > **getOrdersPage**(`options?`): `Promise`\<[`UnifiedOrdersPage`](../type-aliases/UnifiedOrdersPage.md)\> Defined in: packages/sdk/src/unified/exchange.ts:2839 Read one raw-row page of the authenticated owner's indexed order history. This compatibility name has the same result, pagination, `chainId` option, and errors as [SomniaMarkets.getOrderHistoryPage](#getorderhistorypage). #### Parameters ##### options? [`SomniaMarketsGetOrdersPageOptions`](../type-aliases/SomniaMarketsGetOrdersPageOptions.md) = `{}` #### Returns `Promise`\<[`UnifiedOrdersPage`](../type-aliases/UnifiedOrdersPage.md)\> #### Throws [InvalidInputError](InvalidInputError.md) If the ref, status, limit, or offset is invalid, or the ref is not on `chainId`. #### Throws [SignerRequiredError](SignerRequiredError.md) If no account is configured. #### Throws [IndexerError](IndexerError.md) If the indexer read or producer-row conversion fails. #### Throws [NotConfiguredError](NotConfiguredError.md) If `chainId` names a chain this exchange does not span, or the chain's indexer is absent or does not index that chain. *** ### fetchPortfolioAnalytics() > **fetchPortfolioAnalytics**(`timeframe`, `params?`): `Promise`\<[`PortfolioAnalytics`](../interfaces/PortfolioAnalytics.md)\> Defined in: packages/sdk/src/unified/exchange.ts:3136 The wallet's portfolio metrics plane over a timeframe: a holdings curve, an equity curve, per-bucket PnL, money-weighted return, volume, and fees saved versus a comparison taker rate. Computed client-side from the wallet's indexed fills (avg-cost basis) marked to candle closes — no server aggregate involved. The two curves measure different things. `holdings` is what the traded book is worth at each sample, so it is a level. `equity` is the window's cumulative realized and unrealized PnL, so it is a change. Neither counts a token that arrived without a fill: read balances from the chain for what the wallet itself holds. Read `HoldingsPoint` before presenting the level — it states where its sign and its completeness end. SPOT-scoped today: binary outcomes settle rather than mark, and the perp account plane (funding, margin) joins the fold as new event kinds when perp analytics land. The indexer returns only the wallet's SPOT fills, so binary and perp rows are not transferred. Fills are paged to exhaustion — truncating would drop the OLDEST fills and silently corrupt the carried-in cost basis, not just undercount volume. Chains are read concurrently, one page in flight per chain. An optional page budget counts pages across all chains and rejects with an incomplete-history error instead of returning partial PnL. A failure on one chain rejects the call, and on a multi-chain exchange an indexer failure carries that `chainId`. Each call starts at the newest page, including after a previous empty result. Fills whose taker direction the indexer has not resolved (`takerIsBid` null), or where the wallet's role (maker vs taker) is unknowable, are skipped rather than guessed. The money-weighted return needs to know what capital the wallet put in. Fills alone cannot say — capital that never passed through a trade is invisible to them — so without `funding` the capital base is a trades-only proxy that overstates the return for a wallet trading a small part of its balance. Pass `funding` to measure against real external capital, and read `mwrr.capitalBasis` to see which definition applied. **Example** (Measuring portfolio performance) ```ts const p = await exchange.fetchPortfolioAnalytics("7d"); console.log(p.pnl.totalUsd, p.mwrr.return, p.equity.length); ``` #### Parameters ##### timeframe [`PortfolioTimeframe`](../type-aliases/PortfolioTimeframe.md) ##### params? [`SomniaMarketsFetchPortfolioAnalyticsOptions`](../interfaces/SomniaMarketsFetchPortfolioAnalyticsOptions.md) = `{}` #### Returns `Promise`\<[`PortfolioAnalytics`](../interfaces/PortfolioAnalytics.md)\> #### Throws [InvalidInputError](InvalidInputError.md) If the optional page budget is invalid. #### Throws [SignerRequiredError](SignerRequiredError.md) If no account is configured. #### Throws [IndexerError](IndexerError.md) If an indexer read fails. #### Throws [IndexerUnavailableError](IndexerUnavailableError.md) If the SDK refuses the indexer read locally. #### Throws [FillHistoryUnavailableError](FillHistoryUnavailableError.md) If the indexer cannot identify the served fill dataset. #### Throws [FillHistoryRestartRequiredError](FillHistoryRestartRequiredError.md) If the fill dataset changes while history is paged. #### Throws [IncompleteHistoryError](IncompleteHistoryError.md) If the budget ends or a cursor cycles before complete history is read. #### Throws [NotConfiguredError](NotConfiguredError.md) If the chain's indexer is absent or does not index that chain. *** ### fetchMyTrades() > **fetchMyTrades**(`ref?`, `since?`, `limit?`, `filter?`): `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:3337 My historical trades, newest-first across every venue. **Details** Reads the unified fill tape (`getUserFills`), so the scope, the window and the limit are applied by the INDEXER rather than to an already-truncated page. This is what makes a narrow question answerable: a `ref`-scoped call returns that market's fills however old they are, where a per-venue read would have capped at its newest 50 across all markets first and left nothing to filter. `limit` counts rows YOU receive. A fill on a market outside the loaded registry is hydrated by its market id, so a settled market's fills keep their own symbol; only a row the indexer has no market for at all is dropped. The read therefore pages until it has `limit` resolvable rows or the tape runs out — asking the query for exactly `limit` would under-deliver by however many it then dropped. - `ref`: Restrict to one tradable (symbol or address). Omit for all. - `since`: Lower time bound, **milliseconds** — same clock as [UnifiedTrade.timestamp](../interfaces/UnifiedTrade.md#timestamp), so a value read off a previous row can be passed straight back. Converted to the indexer's unix seconds internally. - `limit`: Max rows to return (default 50). - `filter.chainId`: Read only this chain. With no `ref` and no `filter.chainId` this reads every chain and throws when any chain fails; on an exchange with more than one chain the thrown `IndexerError` then has `chainId` set to the chain that failed. A read over more than one chain skips a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)). #### Parameters ##### ref? [`MarketHandle`](../type-aliases/MarketHandle.md) ##### since? `number` ##### limit? `number` = `50` ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol or source position is invalid, or `ref` is not on `filter.chainId`. #### Throws [IndexerError](IndexerError.md) If the indexer read fails. #### Throws [SignerRequiredError](SignerRequiredError.md) If no account is configured. #### Throws [NotConfiguredError](NotConfiguredError.md) If `filter.chainId` names a chain this exchange does not span, or the chain's indexer is absent or does not index that chain. *** ### fetchStatus() > **fetchStatus**(): `Promise`\<[`ExchangeStatus`](../interfaces/ExchangeStatus.md)\> Defined in: packages/sdk/src/unified/exchange.ts:3472 Read the local chain-tail status without network requests. "ok" means no watches are held or the tail is connected. "connecting" means a watch is awaiting its first head. "error" means a previously live socket was lost or the tail retains an operational failure. #### Returns `Promise`\<[`ExchangeStatus`](../interfaces/ExchangeStatus.md)\> *** ### fetchDataStatus() > **fetchDataStatus**(): `Promise`\<[`ExchangeDataStatus`](../interfaces/ExchangeDataStatus.md)\> Defined in: packages/sdk/src/unified/exchange.ts:3508 Observe independent indexer freshness and per-asset price health once. No polling starts. The top-level verdict describes only the chain tails. `indexer` is the PRIMARY chain's freshness; `indexerByChain` carries every configured chain's. Use fetchStatus for a local-only snapshot. This is the health surface, so it measures each chain on its own. When one chain's measurement fails, the call still resolves: that chain's error is in `indexerErrorByChain` and the chain has no key in `indexerByChain`. The call throws only when every configured chain fails. It then throws the primary chain's error. On an exchange with more than one chain, that `IndexerError` or `RpcError` has `chainId` set to the primary chain. #### Returns `Promise`\<[`ExchangeDataStatus`](../interfaces/ExchangeDataStatus.md)\> #### Throws Configured chain or metadata arguments are invalid, on every chain. #### Throws Indexer metadata could not be read, on every chain. #### Throws The owner has no chain transport, on every chain. #### Throws Independent chain measurement failed, on every chain. *** ### watchOrderBook() > **watchOrderBook**(`ref`, `limit?`): `Promise`\<[`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md)\> Defined in: packages/sdk/src/unified/exchange.ts:3661 Streaming book off the local store: zero round-trips, current to the last block; each await resolves on the next book change. **Example** (Watching the order book) A quoting loop: wake on every book change, read the touch. ```ts while (true) { const book = await exchange.watchOrderBook("SOMI/USDC", 5); const [bestBid] = book.bids[0] ?? []; const [bestAsk] = book.asks[0] ?? []; console.log(`bid ${bestBid} / ask ${bestAsk}`); } ``` Block provenance comes from the native owner. Background failures appear in tail status. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### limit? `number` = `10` #### Returns `Promise`\<[`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md)\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol or source position is invalid. #### Throws [NotConfiguredError](NotConfiguredError.md) If the owner has no chain endpoint. #### Throws [IndexerError](IndexerError.md) If snapshot initialization fails. #### Throws [RpcError](RpcError.md) If chain catch-up fails. #### Throws [ContractRevertError](ContractRevertError.md) If a required contract read reverts. #### Throws [InvalidInputError](InvalidInputError.md) If the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Throws A `DOMException` named `AbortError` if [SomniaMarkets.unwatchMarket](#unwatchmarket) or [SomniaMarkets.close](#close) releases the market while this call waits, or while it hydrates and the hydration succeeds. This is caller cancellation. *** ### watchTrades() > **watchTrades**(`ref`, `limit?`): `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:3705 Streaming public trades (the live tape), newest first. **Example** (Watching trades) Print each fill as it lands (`[0]` is always the latest). ```ts while (true) { const [latest] = await exchange.watchTrades("SOMI/USDC", 1); if (latest) console.log(`${latest.side ?? "?"} ${latest.amount} @ ${latest.price}`); } ``` Block provenance comes from the native owner. Background failures appear in tail status. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### limit? `number` = `50` #### Returns `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol or source position is invalid. #### Throws [NotConfiguredError](NotConfiguredError.md) If the owner has no chain endpoint. #### Throws [IndexerError](IndexerError.md) If snapshot initialization fails. #### Throws [RpcError](RpcError.md) If chain catch-up fails. #### Throws [ContractRevertError](ContractRevertError.md) If a required contract read reverts. #### Throws [InvalidInputError](InvalidInputError.md) If the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Throws A `DOMException` named `AbortError` if [SomniaMarkets.unwatchMarket](#unwatchmarket) or [SomniaMarkets.close](#close) releases the market while this call waits, or while it hydrates and the hydration succeeds. This is caller cancellation. *** ### watchOrders() > **watchOrders**(`ref`, `limit?`): `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:3766 Streaming view of MY orders on this tradable (authenticated). **When to use** Use to learn that a resting order filled: its status flips to "closed". **Example** (Waiting for an order) Place a limit order, then block until it fully fills (or dies). ```ts const placed = await exchange.createOrder(symbol, "limit", "buy", 10, 0.62); while (placed.status === "open") { const orders = await exchange.watchOrders(symbol); // resolves on the next change const mine = orders.find((o) => o.id === placed.id); if (!mine || mine.status !== "open") break; // filled, canceled, or expired } ``` - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. - Throws a `DOMException` named `AbortError` - [SomniaMarkets.unwatchMarket](#unwatchmarket) or [SomniaMarkets.close](#close) released the market while this call waited, or while it hydrated and the hydration succeeded. This is caller cancellation. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### limit? `number` = `100` #### Returns `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)[]\> *** ### watchMyTrades() > **watchMyTrades**(`ref`, `limit?`): `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:3819 Streaming view of MY fills on this tradable (authenticated). Block provenance comes from the native owner. Background failures appear in tail status. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### limit? `number` = `50` #### Returns `Promise`\<[`UnifiedTrade`](../interfaces/UnifiedTrade.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If the symbol or source position is invalid. #### Throws [NotConfiguredError](NotConfiguredError.md) If the owner has no chain endpoint. #### Throws [IndexerError](IndexerError.md) If snapshot initialization fails. #### Throws [RpcError](RpcError.md) If chain catch-up fails. #### Throws [ContractRevertError](ContractRevertError.md) If a required contract read reverts. #### Throws [SignerRequiredError](SignerRequiredError.md) If no account is configured. #### Throws [InvalidInputError](InvalidInputError.md) If the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Throws A `DOMException` named `AbortError` if [SomniaMarkets.unwatchMarket](#unwatchmarket) or [SomniaMarkets.close](#close) releases the market while this call waits, or while it hydrates and the hydration succeeds. This is caller cancellation. *** ### unwatchMarket() > **unwatchMarket**(`ref`): `Promise`\<`void`\> Defined in: packages/sdk/src/unified/exchange.ts:3910 Release one market's streaming resources and keep the exchange open. **When to use** Use when a consumer stops following a market, for example a bot that moves to the next symbol in a rotating binary series. Without this call the exchange holds every watched market until [SomniaMarkets.close](#close). **Details** The first `watchOrderBook`, `watchTrades`, `watchOrders` or `watchMyTrades` call on a market opens one market watch. The other calls on that market share it. This call releases that watch and every streaming channel on the market, for all its outcomes. Other markets are not affected. - A pending `watch*` wait on the market rejects with a `DOMException` named `AbortError`. This is caller cancellation, not an SDK failure. - A `watch*` call still hydrating the market rejects with that `AbortError` when hydration succeeds, and its watch is released then. If hydration fails, the call rejects with the hydration error instead. - The next `watch*` call on the market opens a fresh watch. A late hydration from before the release cannot replace that watch or stop it. - The client keeps the market's live data for a 30-second linger after the last holder releases it, so a quick rewatch skips a new snapshot. Then it drops the market's orders and fills. It keeps the market row. - Releasing a market that is not watched does nothing. Calling this twice is the same as calling it once, and it is safe before or after `close()`. The cache entry and the channels are released before this returns. The returned promise resolves when the watch handle is stopped: at once for a hydrated watch, or when a hydration in progress settles. Awaiting it is optional. A symbol that no longer resolves, for example one that a later `loadMarkets(true)` dropped, is still released by its market symbol. An on-chain ref (an address, a market id or a `{ chainId, id }` ref) must resolve: it names no symbol, so an ambiguous or unknown one rejects. Price watches from `watchPrice` are not affected; `close()` releases them. **Example** (Following a rotating series) ```ts let current: string | undefined; async function follow(next: string) { if (current) await exchange.unwatchMarket(current); current = next; return exchange.watchOrderBook(next, 5); } ``` #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) The market or any of its tradables, in any form [SomniaMarkets.market](#market) accepts. #### Returns `Promise`\<`void`\> #### Throws [InvalidInputError](InvalidInputError.md) If `ref` is an on-chain ref (an address, a market id or a `{ chainId, id }` ref) that does not resolve to exactly one market. *** ### watchUser() > **watchUser**(`filter?`): `Promise`\<[`WatchHandle`](../interfaces/WatchHandle.md)\> Defined in: packages/sdk/src/unified/exchange.ts:3955 Hydrate and hold the signer's order/fill history on EVERY configured chain, behind one handle. Each chain's engine opens its own ref-counted user watch; stopping the handle releases all of them. Activity then arrives on the per-market `watch*` verbs with each event's `chainId`. **Gotchas** - Throws [SignerRequiredError](SignerRequiredError.md) - no signer on this exchange. - Throws [NotConfiguredError](NotConfiguredError.md) - `filter.chainId` names a chain this exchange does not span, or the one chain the watch touches has no indexer. - Throws [RpcError](RpcError.md) - a chain's socket could not open. The chains open at the same time. The call waits for every chain to settle, then stops each handle that opened, including one that opened after the failure, before the error propagates. When more than one chain fails, the error is the one from the first failing chain in binding order. On an exchange with more than one chain and no `filter.chainId`, its `chainId` is set to that chain. Pass `filter.chainId` to watch one chain only (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). A watch over more than one chain skips a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)), because a user watch loads its history from the indexer. #### Parameters ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`WatchHandle`](../interfaces/WatchHandle.md)\> *** ### ensureFunds() > **ensureFunds**(`params`, `options?`): `Promise`\<[`ExchangeBridgeResult`](../interfaces/ExchangeBridgeResult.md) \| `null`\> Defined in: packages/sdk/src/unified/exchange.ts:4092 Make sure the account holds `amount` of a currency on one chain, bridging the shortfall from the richest other configured chain when it does not. `createOrder(…, { funding: "auto" })` bridges the same way, but it finds the order's escrow token by address instead of by code. **Details** - `code`: the currency's code — the key [fetchBalance](#fetchbalance) uses (`"USDso"`, `"STT"`, …). Addresses differ per chain; the code names the asset. On `chainId` it resolves to the native coin, else the bridge registry's token for that code, else a listed market's token with that code. The bridge route then follows that token's address, never the code. - `chainId`: the chain the funds must end up on. - `amount`: raw units of the currency on that chain. Resolves with `null` when no new bridge leg was needed, else the bridge result. Other-chain read failures remain available through [collateralReadErrors](#collateralreaderrors). A shortfall error also retains them in `readErrors` and its aggregate `cause`. Calls for the same account, chain and currency run one at a time on this exchange, so two concurrent calls do not both bridge the same shortfall. A `createOrder(…, { funding: "auto" })` for the same key keeps its place in that queue until its order is sent, so the next call reads the balance after that order took its escrow. Each call in the queue can wait a full delivery timeout, so waits add up. A leg that timed out stays pending on this exchange. When a later call for the same key finds a shortfall, it waits for that message first and sends no new leg for it. When the balance already covers the amount, it does not wait. This state is in memory only: a new exchange instance does not know about an earlier leg. `close()` ends the delivery waits of every call that started before it, including calls still in the queue. Such a call opens no new wait. A leg it sends is reported as pending. **Gotchas** - Throws [CollateralOnWrongChainError](CollateralOnWrongChainError.md) - no other configured chain holds enough, or the currency has no bridge route. - Throws [InvalidInputError](InvalidInputError.md) - `amount` is positive and no token on `chainId` carries `code`. - Throws [BridgeLiquidityError](BridgeLiquidityError.md) - a native route's destination router holds less than the shortfall. Nothing was sent. - Throws [BridgeDeliveryTimeoutError](BridgeDeliveryTimeoutError.md) - a bridge leg was not delivered within the timeout or before `close()`. The leg is the one this call sent, or a pending leg from an earlier call, in which case this call sent nothing. The error carries `messageId`. A later call on this exchange waits for that message again and sends no new leg for it. From another process or instance, check `delivered(messageId)` on the destination Mailbox first, or the funds move twice. - Throws [RpcError](RpcError.md) - a balance read or a bridge step failed. A failed destination router read (`operation: "getBalance"`) sent nothing. See [ExchangeBridge.transfer](../interfaces/ExchangeBridge.md#transfer) for the other bridge `RpcError` cases. #### Parameters ##### params ###### code `string` ###### chainId `number` ###### amount `bigint` ##### options? [`ExchangeBridgeTransferOptions`](../interfaces/ExchangeBridgeTransferOptions.md) = `{}` #### Returns `Promise`\<[`ExchangeBridgeResult`](../interfaces/ExchangeBridgeResult.md) \| `null`\> *** ### watchPrice() > **watchPrice**(`asset`): `Promise`\<[`UnifiedPrice`](../interfaces/UnifiedPrice.md)\> Defined in: packages/sdk/src/unified/exchange.ts:4488 Streaming price off the local price store: zero round-trips, current to the last pushed tick; each await resolves on the next price change. **Details** First call hydrates the ref-counted feed watch. **Gotchas** Requires `config.priceFeed` to be set, INCLUDING its `quote`: an unpinned feed rejects a live watch with a `NotConfiguredError` naming `config.priceFeed.quote`, because the tick tape's cursor is unique only within one quote. The one-shot price reads still work unpinned. #### Parameters ##### asset `string` #### Returns `Promise`\<[`UnifiedPrice`](../interfaces/UnifiedPrice.md)\> *** ### fetchPrice() > **fetchPrice**(`asset`): `Promise`\<[`UnifiedPrice`](../interfaces/UnifiedPrice.md) \| `null`\> Defined in: packages/sdk/src/unified/exchange.ts:4511 One-shot current price (indexer HTTP read; no watch needed), or null if the feed has no observations yet. #### Parameters ##### asset `string` #### Returns `Promise`\<[`UnifiedPrice`](../interfaces/UnifiedPrice.md) \| `null`\> *** ### fetchPriceOHLCV() > **fetchPriceOHLCV**(`asset`, `timeframe?`, `since?`, `limit?`): `Promise`\<[`UnifiedOHLCV`](../type-aliases/UnifiedOHLCV.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:4527 OHLC price candles (EMA oracle), oldest first as [ms,o,h,l,c,vol] rows. **Details** Timeframes: 1m 1h 1d (aliases for the feed's M1/H1/D1). **Gotchas** `vol` is the oracle update count for the bucket (NOT trade volume). #### Parameters ##### asset `string` ##### timeframe? `string` = `"1m"` ##### since? `number` ##### limit? `number` = `500` #### Returns `Promise`\<[`UnifiedOHLCV`](../type-aliases/UnifiedOHLCV.md)[]\> *** ### createOrder() > **createOrder**(`ref`, `type`, `side`, `amount`, `price?`, `params?`): `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)\> Defined in: packages/sdk/src/unified/exchange.ts:4600 Place an order. **Details** Works identically for every market kind: the tradable symbol carries the outcome, `side` is plain buy/sell, prices and amounts are human units in the tradable's own terms. `type: "market"` computes a crossing limit from the best opposite level ± `params.slippage` (default 1%) and sends it IOC. Resolves once mined, with fills decoded from the same round-trip. **Gotchas** A NO price is the NO probability — the YES-terms complement is handled internally. The price and quantity are ALIGNED to the market's tick and lot grids before they are sent, because the pool rejects an off-grid value outright. Alignment never moves a value against you: a buy price rounds down, a sell price rounds up, and a quantity always rounds down, so the order is never larger or worse priced than you asked for. The returned [UnifiedOrder](../interfaces/UnifiedOrder.md) carries what was actually placed, which may differ from the arguments by up to one tick or lot — read `price` and `amount` back from it rather than assuming your inputs. Pre-aligning with [priceToPrecision](#pricetoprecision) / [amountToPrecision](#amounttoprecision) makes this a no-op, since aligning an aligned value changes nothing. Note [priceToPrecision](#pricetoprecision) always rounds DOWN, for either side; this path is side-aware instead, so for a sell the two can differ by one tick. A quantity below one whole lot throws [InvalidInputError](InvalidInputError.md) rather than silently placing a zero-quantity order. - Throws [SignerRequiredError](SignerRequiredError.md) - the exchange was built without a `privateKey` / `account` / `walletClient`. - Throws [InvalidInputError](InvalidInputError.md) - unknown symbol (call `loadMarkets()` first), a `"limit"` order with no price, or a `"market"` order whose opposite book side is empty so no crossing price exists. - Throws [ContractRevertError](ContractRevertError.md) - the chain rejected the order. Branch on `errorName` for the protocol's own reason (e.g. `InsufficientBalance`, `ExpiredOrderMustBeCancelled`). Also thrown before anything is sent when a spot pre-check read (`getAutoPullRequirement`, `getManualVaultMode`) reverts. - Throws [RpcError](RpcError.md) - the node refused the transaction, or a pre-check read (pool requirement, vault mode, balance) failed before anything was sent. - Throws [TransactionOutcomeUnknownError](TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [CollateralOnWrongChainError](CollateralOnWrongChainError.md) - the collateral pre-check (see `funding`) found a shortfall on the market's chain: in the wallet, or in the pool vault under manual vault mode. Nothing was sent. **Example** (Placing binary orders) Rest a bid at 62% on YES, then take the NO book at market. ```ts const rested = await exchange.createOrder("BTC-95000-31DEC26/USDC#YES", "limit", "buy", 25, 0.62); console.log(rested.status, rested.filled); // "open" 0 — or "closed" if it crossed const taken = await exchange.createOrder("BTC-95000-31DEC26/USDC#NO", "market", "sell", 10, undefined, { slippage: 0.02, // accept up to 2% past the best bid }); ``` - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. - Throws [BridgeLiquidityError](BridgeLiquidityError.md) - `funding: "auto"` needs a native bridge route whose destination router holds less than the shortfall. Nothing was sent. - Throws [BridgeDeliveryTimeoutError](BridgeDeliveryTimeoutError.md) - with `funding: "auto"`, a bridge leg was not delivered within the timeout or before `close()`. The leg is the one this call sent, or a pending leg from an earlier call on the same account, chain and token, in which case nothing was sent. No order was placed. See [SomniaMarkets.ensureFunds](#ensurefunds). - Throws [RpcError](RpcError.md) - with `funding: "auto"`, a balance read or the bridge failed. See [SomniaMarkets.ensureFunds](#ensurefunds). #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### type `"market"` \| `"limit"` ##### side `"buy"` \| `"sell"` ##### amount `number` ##### price? `number` ##### params? [`CreateOrderParams`](../interfaces/CreateOrderParams.md) = `{}` #### Returns `Promise`\<[`UnifiedOrder`](../interfaces/UnifiedOrder.md)\> *** ### cancelOrder() > **cancelOrder**(`id`, `ref?`): `Promise`\<\{ `id`: `string`; `symbol`: `string`; `chainId`: `number`; `status`: `"canceled"`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:4801 Cancel a resting order by id (from createOrder / watchOrders). **Gotchas** - Throws [SignerRequiredError](SignerRequiredError.md) - no signer on this exchange. - Throws [InvalidInputError](InvalidInputError.md) - unknown symbol. - Throws [ContractRevertError](ContractRevertError.md) - the cancel did not land; `errorName` says why (an already-filled or already-canceled order reverts). - Throws [RpcError](RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Cancelling an open order) ```ts const placed = await exchange.createOrder("SOMI/USDC", "limit", "buy", 10, 0.55); if (placed.status === "open") await exchange.cancelOrder(placed.id, "SOMI/USDC"); ``` #### Parameters ##### id `string` \| [`ChainOrderRef`](../interfaces/ChainOrderRef.md) ##### ref? [`MarketHandle`](../type-aliases/MarketHandle.md) #### Returns `Promise`\<\{ `id`: `string`; `symbol`: `string`; `chainId`: `number`; `status`: `"canceled"`; `info`: `unknown`; \}\> *** ### createStopOrder() > **createStopOrder**(`ref`, `type`, `side`, `amount`, `triggerPrice`, `price?`, `params?`): `Promise`\<[`UnifiedStopOrder`](../interfaces/UnifiedStopOrder.md)\> Defined in: packages/sdk/src/unified/exchange.ts:4892 Place a stop / take-profit order: rests OFF the book on the market's stop registry and fires as a market or limit order when the pool's mark price crosses `triggerPrice`. The trigger direction is inferred from which side of the current mark the trigger sits on; pass `params.triggerDirection` to pin it explicitly. **Gotchas** The trigger, limit price and quantity are aligned to the market's grids, and the trigger aligns AWAY from the mark so it cannot land on it (a trigger equal to the mark fires the instant it is armed). The limit price aligns like any order price — a buy down, a sell up — so it never becomes worse than stated. Those two rules are independent, so a limit set exactly EQUAL to the trigger can end up one tick inside it: a buy stop at trigger `0.5004`, limit `0.5004` on a `0.001` grid arms at `0.501` and rests a `0.500` bid, which may not fill. That is deliberate — pulling the limit up to meet the trigger would make you pay more than you asked. Set the limit a tick or two past the trigger when you want the triggered order to cross. - Throws [SignerRequiredError](SignerRequiredError.md) - the exchange was built without a `privateKey` / `account` / `walletClient`. - Throws [InvalidInputError](InvalidInputError.md) - unknown symbol, a non-spot market, a market with no stop registry, a `"limit"` stop with no price, a sub-lot quantity, or no mark yet to infer the trigger direction from (pass `params.triggerDirection`). - Throws [IndexerError](IndexerError.md) - the pool's mark was needed (to infer the trigger direction, or to price a market stop's protective limit) and the indexer read did not complete. A limit stop with `params.triggerDirection` set needs no mark. - Throws [ContractRevertError](ContractRevertError.md) - the registry or the pool rejected the placement (or the operator grant / escrow approval that precedes it). Branch on `errorName`. - Throws [RpcError](RpcError.md) - a pre-placement chain read did not complete, or the node refused a transaction. - Throws [TransactionOutcomeUnknownError](TransactionOutcomeUnknownError.md) - a transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Placing a stop order) A stop-loss: sell 5 if the mark drops to 1.10. ```ts const stop = await exchange.createStopOrder("SOMI/USDC", "market", "sell", 5, 1.10); // …later: await exchange.cancelStopOrder(stop.id, "SOMI/USDC"); ``` #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### type `"market"` \| `"limit"` ##### side `"buy"` \| `"sell"` ##### amount `number` ##### triggerPrice `number` ##### price? `number` ##### params? ###### triggerDirection? `"above"` \| `"below"` #### Returns `Promise`\<[`UnifiedStopOrder`](../interfaces/UnifiedStopOrder.md)\> *** ### fetchOpenStopOrders() > **fetchOpenStopOrders**(`ref?`, `filter?`): `Promise`\<[`UnifiedStopOrder`](../interfaces/UnifiedStopOrder.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:5019 The wallet's pending (armed, untriggered) stop orders, newest first. Scope to one tradable with `ref`, or to one chain with `filter.chainId`. With no `ref` and no `filter.chainId` this reads every chain and throws when any chain fails. On an exchange with more than one chain, the thrown `IndexerError` then has `chainId` set to the chain that failed (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). A read over more than one chain skips a chain bound with no `indexerUrl` (see [chainIdsWithoutIndexer](#chainidswithoutindexer)). #### Parameters ##### ref? [`MarketHandle`](../type-aliases/MarketHandle.md) ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`UnifiedStopOrder`](../interfaces/UnifiedStopOrder.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If `ref` is unknown, or `ref` is not on `filter.chainId`. #### Throws [NotConfiguredError](NotConfiguredError.md) If `filter.chainId` names a chain this exchange does not span, or the one chain the read touches has no indexer. *** ### cancelStopOrder() > **cancelStopOrder**(`id`, `ref`): `Promise`\<\{ `id`: `string`; `symbol`: `string`; `chainId`: `number`; `status`: `"canceled"`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5065 Cancel a pending stop order on its registry (refunds the keeper payment). `id` comes from [fetchOpenStopOrders](#fetchopenstoporders). #### Parameters ##### id `string` ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) #### Returns `Promise`\<\{ `id`: `string`; `symbol`: `string`; `chainId`: `number`; `status`: `"canceled"`; `info`: `unknown`; \}\> *** ### fetchFundingRate() > **fetchFundingRate**(`ref`): `Promise`\<[`UnifiedFundingRate`](../interfaces/UnifiedFundingRate.md)\> Defined in: packages/sdk/src/unified/exchange.ts:5088 Live funding-rate + mark/index snapshot for a perp market (chain read). #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) #### Returns `Promise`\<[`UnifiedFundingRate`](../interfaces/UnifiedFundingRate.md)\> *** ### fetchFundingRateHistory() > **fetchFundingRateHistory**(`ref`, `since?`, `limit?`): `Promise`\<[`UnifiedFundingRate`](../interfaces/UnifiedFundingRate.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:5159 Historical funding rates for a perp market, oldest first (ccxt-standard shape). Reads the INDEXED series rather than the chain: only one funding value is readable on chain at a time. Positional `(symbol, since, limit)` follows the ccxt convention set by `fetchOHLCV`, unlike the object-options readers on the client. `fundingRate` is normalized to a per-8h fraction using each row's own `fundingWindowSec`, so the series stays consistent across a parameter change. The raw indexed row is on `info` for anything more specific — including `spanStart` / `spanEnd`, which matter because a row's accrual reaches BACKWARDS from its timestamp and a lazily-settled one can cover hours. `since` is a CURSOR, not just a window bound: passing it walks FORWARD from that point, so the ccxt pagination idiom terminates. **Details** - `ref`: market symbol or pool address - `since`: unix MILLISECONDS (ccxt convention), inclusive; acts as a forward cursor - `limit`: max rows (default 100) **Example** (Paging through funding history) ```ts let since = startOfHistory; for (;;) { const page = await exchange.fetchFundingRateHistory("BTC/USDSO:USDSO", since, 100); if (page.length === 0) break; consume(page); since = page[page.length - 1].timestamp + 1; // advances } ``` Without the forward ordering this loop spins: the underlying read pages newest-first, so narrowing the window from below still returns the newest N and `since` never gets past the tail. Omitting `since` keeps the newest-first behaviour, which is what a "latest funding" read wants — `fetchOHLCV` has the same split. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### since? `number` ##### limit? `number` #### Returns `Promise`\<[`UnifiedFundingRate`](../interfaces/UnifiedFundingRate.md)[]\> *** ### fetchPositions() > **fetchPositions**(`refs?`, `filter?`): `Promise`\<[`UnifiedPosition`](../interfaces/UnifiedPosition.md)[]\> Defined in: packages/sdk/src/unified/exchange.ts:5216 Open perp positions (authenticated; on-chain MarginBank reads). Pass symbols to scope; defaults to every loaded perp market. **Gotchas** Called with NO refs, this reads only the perps the registry loaded, so a short perp set gives a short result rather than an error. Check [perpDiscoverySkipped](#perpdiscoveryskipped) and [perpDiscoveryError](#perpdiscoveryerror) before you read an empty result as "this account holds no perp positions". Passing explicit refs turns an unloaded symbol into an `InvalidInputError` instead. `filter.chainId` reads only that chain; every ref must then be on it. Otherwise the read spans the chains of its markets and throws when any chain fails. On a read over more than one chain, and on a read with no refs and no `filter.chainId` on an exchange with more than one chain, the thrown `IndexerError` or `RpcError` has `chainId` set to the chain that failed (see [SomniaMarketsChainFilter](../interfaces/SomniaMarketsChainFilter.md)). The pool state (mark, index, funding) is read only for a pool where the account holds a position. When that read fails for one pool, for example because its oracle reverts, the position still lists with `perpState: "degraded"`, and `markPrice` and `unrealizedPnl` are absent. The other positions are not affected. Branch on `perpState`, not on the absence of `markPrice`. #### Parameters ##### refs? [`MarketHandle`](../type-aliases/MarketHandle.md)[] ##### filter? [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) = `{}` #### Returns `Promise`\<[`UnifiedPosition`](../interfaces/UnifiedPosition.md)[]\> #### Throws [InvalidInputError](InvalidInputError.md) If a ref is unknown or not a perp, or a ref is not on `filter.chainId`. #### Throws [NotConfiguredError](NotConfiguredError.md) If `filter.chainId` names a chain this exchange does not span. *** ### depositMargin() > **depositMargin**(`ref`, `amount`): `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5321 Deposit collateral into the perp MarginBank (human quote units, e.g. USDso). One cross-margin balance covers every perp market. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### amount `number` #### Returns `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> *** ### withdrawMargin() > **withdrawMargin**(`ref`, `amount`): `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5340 Withdraw free collateral from the perp MarginBank (human quote units). #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### amount `number` #### Returns `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> *** ### mintSet() > **mintSet**(`ref`, `amount`): `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5382 Mint complete sets: `amount` collateral → `amount` of EVERY outcome. **Example** (Minting complete sets) Mint 100 sets (100 USDC → 100 YES + 100 NO), then sell the side you don't want. ```ts await exchange.mintSet("BTC-95000-31DEC26/USDC", 100); await exchange.createOrder("BTC-95000-31DEC26/USDC#NO", "limit", "sell", 100, 0.38); ``` - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### amount `number` #### Returns `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> *** ### burnSet() > **burnSet**(`ref`, `amount`): `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5401 Burn complete sets back to collateral. - Throws [InvalidInputError](InvalidInputError.md) - the market is a SETTLED binary market (resolved, voided or finalized). Its pool now serves the next market in the series, so only `redeem`, balances and history remain. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) ##### amount `number` #### Returns `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> *** ### redeem() > **redeem**(`ref`, `amount`, `options?`): `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> Defined in: packages/sdk/src/unified/exchange.ts:5463 Redeem outcome tokens for collateral after settlement. Settlement- extraction v2 routes by `marketId`. When the caller omits the leg, the SDK verifies the BinaryMarket state and reads its winner on-chain. **Example** (Redeeming a winning position) After resolution, redeem the winning side found in the balance map. The market has left `fetchMarkets()` by then (a settled series market is not tradable), but `fetchBalance()` still reports the holding under the market's symbol and that symbol still resolves here. ```ts const bal = await exchange.fetchBalance(); const winning = bal["BTC-95000-31DEC26/USDC#YES"]?.total ?? 0; if (winning > 0) await exchange.redeem("BTC-95000-31DEC26/USDC", winning); ``` **Gotchas** A VOIDED market has no winning outcome — both legs pay — so the auto-lookup cannot pick one and `redeem` throws. Pass `{ outcomeIdx }` for the leg you hold, and call once per leg to claim both. An unresolved market also throws instead of guessing from an unfinalized payout vector. **Errors** - Throws [InvalidInputError](InvalidInputError.md) for an unknown or non-binary market, an invalid amount, or an omitted leg when the on-chain market is unresolved, voided, or does not store an exact one-hot resolved payout vector. - Throws [NotConfiguredError](NotConfiguredError.md) when the binary module address is not configured. - Throws [SignerRequiredError](SignerRequiredError.md) when the exchange has no usable signer. - Throws [RpcError](RpcError.md) when a market or approval read does not complete, or the node refuses a transaction. - Throws [TransactionOutcomeUnknownError](TransactionOutcomeUnknownError.md) when an approval or redemption transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](ContractRevertError.md) when a market read, operator approval, or redemption transaction is rejected by a contract. #### Parameters ##### ref [`MarketHandle`](../type-aliases/MarketHandle.md) Market symbol or id. ##### amount `number` Outcome-token amount to burn, in display units. ##### options? [`RedeemOptions`](../interfaces/RedeemOptions.md) Optional leg selection. Omit it on a resolved market to verify the terminal state and read the winner on-chain. A voided market requires `options.outcomeIdx` because both legs are redeemable and only the caller knows which one they hold. #### Returns `Promise`\<\{ `hash`: `string`; `info`: `unknown`; \}\> *** ### close() > **close**(): `Promise`\<`void`\> Defined in: packages/sdk/src/unified/exchange.ts:5541 Release every watch, channel, socket, and timer this exchange holds and stop the client's live machinery. **Details** This includes the chain WebSocket, so a Node process that has touched the chain exits on its own once this resolves. The instance stays usable for one-shot fetch calls: a later read reopens a connection, and a later `close()` releases that one too. A pending `watch*` wait, and a `watch*` call whose market hydration succeeds after this call starts, rejects with a `DOMException` named `AbortError`. A hydration that fails rejects with its own error. To release one market and keep the rest, use [SomniaMarkets.unwatchMarket](#unwatchmarket). It also ends the bridge delivery waits of every `bridge.transfer`, `ensureFunds` and auto-funded `createOrder` that started before it, including calls still queued for funding. Such a call opens no new wait. `bridge.transfer` resolves with `delivered: false`, and `ensureFunds` throws `BridgeDeliveryTimeoutError`. The leg stays pending, and the next `ensureFunds` for its key waits for it on a shortfall. **Gotchas** Each exchange owns its own chain socket, even when several use the same `wsRpcUrl`, so closing one never affects another. A viem client taken from `getViemClient()` before this call belongs to the closed connection: its requests reject with viem's `SocketClosedError`. #### Returns `Promise`\<`void`\> --- # /docs/typescript/api/index/classes/SomniaMarketsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsError # Class: SomniaMarketsError Defined in: packages/sdk/src/errors.ts:63 Base class for every error the SDK raises. **When to use** Use when you want "anything the SDK itself rejected" without enumerating subclasses — typically an application's top-level boundary. To branch on *what went wrong*, catch (or `instanceof`-test) the subclass instead; each one documents the action it implies. **Gotchas** Catching this is not the same as catching everything. Errors from a `walletClient` supplied by the app can surface as-is, so keep an `else throw e` arm. Debug sink failures are contained and do not escape. **Example** (Branching on SDK errors) ```ts import { SomniaMarketsError, ContractRevertError } from "@somnia-chain/markets-sdk"; try { await exchange.createOrder("BTC-95000-31DEC26/USDC#YES", "limit", "buy", 10, 0.62); } catch (e) { if (e instanceof ContractRevertError) console.error("chain rejected:", e.errorName); else if (e instanceof SomniaMarketsError) console.error("sdk:", e.message); else throw e; } ``` ## Extends - `Error` ## Extended by - [`InvalidInputError`](InvalidInputError.md) - [`FillHistoryRestartRequiredError`](FillHistoryRestartRequiredError.md) - [`FillHistoryUnavailableError`](FillHistoryUnavailableError.md) - [`NotConfiguredError`](NotConfiguredError.md) - [`SignerRequiredError`](SignerRequiredError.md) - [`IndexerError`](IndexerError.md) - [`IncompleteHistoryError`](IncompleteHistoryError.md) - [`IndexerWaitTimeoutError`](IndexerWaitTimeoutError.md) - [`RpcError`](RpcError.md) - [`ContractRevertError`](ContractRevertError.md) - [`CollateralOnWrongChainError`](CollateralOnWrongChainError.md) - [`BridgeLiquidityError`](BridgeLiquidityError.md) - [`BridgeDeliveryTimeoutError`](BridgeDeliveryTimeoutError.md) - [`InvariantError`](InvariantError.md) ## Constructors ### Constructor > **new SomniaMarketsError**(`message`, `options?`): `SomniaMarketsError` Defined in: packages/sdk/src/errors.ts:64 #### Parameters ##### message `string` ##### options? `ErrorOptions` #### Returns `SomniaMarketsError` #### Overrides `Error.constructor` --- # /docs/typescript/api/index/classes/TransactionOutcomeUnknownError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransactionOutcomeUnknownError # Class: TransactionOutcomeUnknownError Defined in: packages/sdk/src/errors.ts:480 A write signed a transaction that may have reached the node, and the SDK did not observe its receipt. The transaction can still mine. **When to use** Catch this before [RpcError](RpcError.md) on every write. Do not send the same write again until you know what happened to `hash`: read its receipt, or read the state the write changes (for an order, your open orders at chain head). A blind retry can place the order twice. **Details** The built-in executors throw it when the send left the SDK and then the answer was lost: the realtime send timed out or its socket dropped, or the receipt wait after `eth_sendRawTransaction` or a wallet's `sendTransaction` failed. A refusal the node answered (nonce too low, insufficient funds, a revert) is a plain [RpcError](RpcError.md) or a [ContractRevertError](ContractRevertError.md). - `chainId`: the chain the transaction was sent on. - `operation`: the request whose answer was lost (e.g. `"eth_sendRawTransactionSync"`). - `hash`: the transaction hash. Absent only when the protocol gives none before the receipt, as with `somnia_sendSessionTransaction`. Then read the state the write changes instead. It extends [RpcError](RpcError.md), so an existing `instanceof RpcError` arm still catches it. **Example** (Looking up the hash before sending again) ```ts import { TransactionOutcomeUnknownError } from "@somnia-chain/markets-sdk"; try { await exchange.trader.placeOrder(params); } catch (e) { if (!(e instanceof TransactionOutcomeUnknownError)) throw e; const viem = exchange.client.getViemClient(); const receipt = e.hash ? await viem.getTransactionReceipt({ hash: e.hash }).catch(() => null) : null; if (receipt === null) { // Unknown still: read your open orders at chain head before placing again. } } ``` ## Extends - [`RpcError`](RpcError.md) ## Constructors ### Constructor > **new TransactionOutcomeUnknownError**(`fields`, `options?`): `TransactionOutcomeUnknownError` Defined in: packages/sdk/src/errors.ts:496 Creates an outcome-unknown error. **Details** - `fields.chainId`: The chain the transaction was sent on. - `fields.operation`: The request whose answer was lost. - `fields.hash`: The signed transaction's hash, when the protocol gives one. - `options`: Standard `cause` passthrough — the transport error that lost the answer. #### Parameters ##### fields ###### chainId `number` ###### operation `string` ###### hash? `` `0x${string}` `` ##### options? `ErrorOptions` #### Returns `TransactionOutcomeUnknownError` #### Overrides [`RpcError`](RpcError.md).[`constructor`](RpcError.md#constructor) ## Properties ### operation > `readonly` **operation**: `string` Defined in: packages/sdk/src/errors.ts:422 #### Inherited from [`RpcError`](RpcError.md).[`operation`](RpcError.md#operation) *** ### chainId > `readonly` **chainId**: `number` Defined in: packages/sdk/src/errors.ts:482 The chain the transaction was sent on. #### Overrides [`RpcError`](RpcError.md).[`chainId`](RpcError.md#chainid) *** ### hash? > `readonly` `optional` **hash?**: `` `0x${string}` `` Defined in: packages/sdk/src/errors.ts:484 The transaction hash; absent only when the protocol returns none before the receipt. --- # /docs/typescript/api/index/functions/accrueCompounded [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / accrueCompounded # Function: accrueCompounded() > **accrueCompounded**(`indexRay`, `rateRay`, `lastUpdateTimestamp`, `nowSec`): `bigint` Defined in: packages/sdk/src/lend/math.ts:45 Grow a borrow-side index compounded from `lastUpdateTimestamp` to `nowSec` at `rateRay`, using Aave's three-term binomial expansion of (1+r/s)^dt (MathUtils .calculateCompoundedInterest). Returns the ray index current to `nowSec`. ## Parameters ### indexRay `bigint` ### rateRay `bigint` ### lastUpdateTimestamp `number` ### nowSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/accrueLinear [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / accrueLinear # Function: accrueLinear() > **accrueLinear**(`indexRay`, `rateRay`, `lastUpdateTimestamp`, `nowSec`): `bigint` Defined in: packages/sdk/src/lend/math.ts:31 Grow a supply-side index linearly from `lastUpdateTimestamp` to `nowSec` at `rateRay` (Aave accrues deposit interest linearly between updates). Returns the ray index current to `nowSec`. ## Parameters ### indexRay `bigint` ### rateRay `bigint` ### lastUpdateTimestamp `number` ### nowSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/annualizedFundingRate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / annualizedFundingRate # Function: annualizedFundingRate() > **annualizedFundingRate**(`rate`, `fundingWindowSec`): `number` Defined in: packages/sdk/src/funding.ts:119 Annualized funding rate as a JS number fraction (0.01 = 1% APR). Returns a `number` deliberately, unlike its siblings: APR is a display quantity, and at an 8h window this is roughly `rate x 1095`, so the 1e18 scale carries far more precision than any axis label needs. Never round-trip a settlement amount through it. ## Parameters ### rate `bigint` ### fundingWindowSec `number` ## Returns `number` --- # /docs/typescript/api/index/functions/asExecuteError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / asExecuteError # Function: asExecuteError() > **asExecuteError**(`caught`, `operation`, `context?`): [`ExecutorExecuteError`](../type-aliases/ExecutorExecuteError.md) Defined in: packages/sdk/src/executor/boundary.ts:26 Normalize a failure raised while executing calls to [ExecutorExecuteError](../type-aliases/ExecutorExecuteError.md): a member of that union passes through as itself, a revert with data decodes to [ContractRevertError](../classes/ContractRevertError.md), anything else becomes [RpcError](../classes/RpcError.md) naming `operation`, the original as `cause`. A [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) passes through with its `chainId`, `operation` and `hash` unchanged, so a wrapper over an inner executor (a safe, a smart account) reports the hash of the outer transaction it sent. This function never creates one: only the code that sent the transaction knows that the bytes may have left. ## Parameters ### caught `unknown` ### operation `string` ### context? [`RevertContext`](../interfaces/RevertContext.md) = `{}` ## Returns [`ExecutorExecuteError`](../type-aliases/ExecutorExecuteError.md) --- # /docs/typescript/api/index/functions/asSignTypedDataError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / asSignTypedDataError # Function: asSignTypedDataError() > **asSignTypedDataError**(`caught`): [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/executor/boundary.ts:47 Normalize a typed-data signing failure to [ExecutorSignTypedDataError](../type-aliases/ExecutorSignTypedDataError.md): a wallet's rejection or a custom signer's own error becomes [RpcError](../classes/RpcError.md) with the original as `cause`; an [RpcError](../classes/RpcError.md) passes through. ## Parameters ### caught `unknown` ## Returns [`RpcError`](../classes/RpcError.md) --- # /docs/typescript/api/index/functions/assertCallsOnChain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / assertCallsOnChain # Function: assertCallsOnChain() > **assertCallsOnChain**(`chainId`, `calls`): `void` Defined in: packages/sdk/src/executor/guard.ts:25 Throw [InvalidInputError](../classes/InvalidInputError.md) when any call names a chain other than the executor's, or when there is nothing to execute. Applied by every built-in executor as its first step; a custom executor should call it too. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `calls` is empty, or a call's `chainId` is not `chainId`. The complete union is [AssertCallsOnChainError](../type-aliases/AssertCallsOnChainError.md). ## Parameters ### chainId `number` ### calls readonly [`UnsignedCall`](../interfaces/UnsignedCall.md)[] ## Returns `void` --- # /docs/typescript/api/index/functions/averageEntryPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / averageEntryPrice # Function: averageEntryPrice() > **averageEntryPrice**(`input`): `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:1331 Average entry price for a YES/NO position, in the outcome's OWN terms (raw), derived from the wallet's BUY fills on that outcome. A binary fill's `fillPrice` is always YES-terms, so the NO leg enters at the complement. Only buys are averaged — this is the cost basis an unrealized-PnL display compares the live mark against. Returns `null` when there are no matching buys (show a dash, not a bogus 0 that reads as +100%). NOTE: complete-set mints don't appear in fills; positions built by mint+sell carry a fills-only basis here, same as [computePositionPnL](computePositionPnL.md) without router actions. ## Parameters ### input #### trades readonly [`EntryTrade`](../interfaces/EntryTrade.md)[] #### outcomeIndex `number` 0 = YES, 1 = NO. #### oneShare `bigint` `10 ** decimals` — one whole outcome share in raw terms. ## Returns `bigint` \| `null` --- # /docs/typescript/api/index/functions/balanceFloor [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / balanceFloor # Function: balanceFloor() > **balanceFloor**(`raw`, `decimals?`): `number` Defined in: packages/sdk/src/units.ts:525 Convert a raw balance to the largest JS number that does not exceed it — full token precision, no lot/display quantum. `Number(formatUnits(raw))` rounds to nearest, so on high-precision balances it can land a ULP above the true value; this nudges the result down until it round-trips back to ≤ `raw`. Size "max" orders against this, never against a nearest-rounded conversion — a max that exceeds the wallet by one ULP is an on-chain "insufficient balance" revert. The round-trip is verified through the same number-to-raw conversion the write path applies, so the guarantee holds for the value `createOrder` will actually send rather than for a differently-rounded stand-in. ## Parameters ### raw `bigint` ### decimals? `number` = `Store.DECIMALS` ## Returns `number` --- # /docs/typescript/api/index/functions/binaryFillsFor [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryFillsFor # Function: binaryFillsFor() > **binaryFillsFor**(`account`, `fills`, `decimals?`): [`BinaryPnlFill`](../interfaces/BinaryPnlFill.md)[] Defined in: packages/sdk/src/units.ts:325 Derive per-account [BinaryPnlFill](../interfaces/BinaryPnlFill.md)s from the raw [FillRow](../type-aliases/FillRow.md)s the indexer returns (as from `getUserFills`), from `account`'s perspective. Skips fills whose side/kind the indexer hasn't fully bridged (unknown side), and re-expresses the fill's price into the outcome the account traded (the book is YES-terms; a NO trade prices at `1 − yesPrice`). SCOPE IS THE CALLER'S JOB: no market filter is applied here, so pass ONE market's fills when the result feeds cost basis, selected by [FillRow.market](../type-aliases/FillRow.md#market) (never by `pool` — see there). ## Parameters ### account `string` ### fills [`FillRow`](../type-aliases/FillRow.md)[] ### decimals? `number` = `Store.DECIMALS` ## Returns [`BinaryPnlFill`](../interfaces/BinaryPnlFill.md)[] --- # /docs/typescript/api/index/functions/binaryFillsFromPortfolio [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryFillsFromPortfolio # Function: binaryFillsFromPortfolio() > **binaryFillsFromPortfolio**(`trades`, `decimals?`): [`BinaryPnlFill`](../interfaces/BinaryPnlFill.md)[] Defined in: packages/sdk/src/units.ts:371 Derive [BinaryPnlFill](../interfaces/BinaryPnlFill.md)s from one market's slice of a portfolio's trades (as from `getPortfolio`). The portfolio view already resolves the account's own side per fill, so this only re-expresses the YES-terms `fillPrice` into the traded outcome (a NO trade prices at `1 − yesPrice`) and skips fills whose side the indexer hasn't bridged yet. **Gotchas** The portfolio reads cut `trades` two ways, and BOTH have to be checked before a total derived from them means anything — this function reports no warning of its own. They cap the page (default 50) and page newest-first: `tradesTruncated` says whether that cap was hit. They also WINDOW the leg — by default to the last seven days — and `tradesSince` is the bound that was applied. A wallet whose fills predate the window comes back with `tradesTruncated: false` and an incomplete `trades`, so the flag alone is not enough. For a whole-history PnL ask for the history first: `since: 0` (with a `tradesLimit` to match), then check `tradesTruncated`. ## Parameters ### trades [`PortfolioTrade`](../type-aliases/PortfolioTrade.md)[] ### decimals? `number` = `Store.DECIMALS` ## Returns [`BinaryPnlFill`](../interfaces/BinaryPnlFill.md)[] --- # /docs/typescript/api/index/functions/binaryResolutionMode [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryResolutionMode # Function: binaryResolutionMode() > **binaryResolutionMode**(`strike`): [`BinaryResolutionMode`](../type-aliases/BinaryResolutionMode.md) Defined in: packages/sdk/src/markets.ts:836 Read a binary market's [BinaryResolutionMode](../type-aliases/BinaryResolutionMode.md) off its `strike` — the ONE place that reading happens. Strike 0 is reference mode DECLARING "no fixed strike": a sentinel, never a $0 threshold. `_strikeLabel` treats 0 as "no strike fragment" and reference resolution compares two numeric answers instead of reading a strike at all, so every market the current creator mints holds to it — but nothing in `_validateCreate` cross-checks it against `referenceQuestionId`, so it is convention rather than an enforced invariant. Centralized here so the day that changes is a one-line change. Takes either encoding: the indexer serves `strike` as a decimal string, the contract event as a `uint256`. ## Parameters ### strike `string` \| `bigint` \| `null` \| `undefined` ## Returns [`BinaryResolutionMode`](../type-aliases/BinaryResolutionMode.md) --- # /docs/typescript/api/index/functions/blockActivityKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / blockActivityKey # Function: blockActivityKey() > **blockActivityKey**(`blockNumber`, `opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:234 Key for `client.getBlockActivity(blockNumber, opts)`. The block alone identifies the question — the client resolves the anchoring timestamp itself, so there is no second argument that could disagree with it. ## Parameters ### blockNumber `bigint` \| `null` \| `undefined` ### opts? [`BlockActivityOptions`](../type-aliases/BlockActivityOptions.md) ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/bookMidPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / bookMidPrice # Function: bookMidPrice() > **bookMidPrice**(`book`): `number` \| `null` Defined in: packages/sdk/src/unified/quotes.ts:139 Midpoint of the book's best bid/ask, or null when either side is empty. ## Parameters ### book [`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md) ## Returns `number` \| `null` --- # /docs/typescript/api/index/functions/boundaryPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / boundaryPrice # Function: boundaryPrice() > **boundaryPrice**(`m`, `openingPrices`): \{ `raw`: `string`; `posted`: `boolean`; \} \| `null` Defined in: packages/sdk/src/markets.ts:1505 The level a binary market's outcome is measured against, in the oracle's price scale — the one answer to that question, for every surface that asks. Which source supplies it is exactly [BinaryMarket.mode](../type-aliases/BinaryMarket.md): - `"reference"` — the posted answer to the market's reference question, from the `openingPrices` map that `client.getOpeningPrices` returns. `null` until the oracle posts it, which is a real and temporary state. - `"fixed"` — the market's own `strike`, known from creation. Null on a chain-seeded market row, whose `strike`/`mode` are both null — same em dash as an unposted reference answer, which is what a surface with no boundary to show wants either way. `posted` says WHICH, because it decides what a caller may CLAIM about the number: only a posted answer has an "answered at" instant, so only it may be labelled as one. Returning it here rather than letting callers re-test the map keeps the label and the value derived from one decision. Lives here rather than in a UI because it is protocol knowledge, not presentation: which of two mechanisms a venue chose. Scale is the caller's to apply, as with any raw oracle value. ## Parameters ### m `Pick`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md), `"id"` \| `"strike"` \| `"mode"`\> ### openingPrices `Record`\<`string`, `string` \| `null`\> ## Returns \{ `raw`: `string`; `posted`: `boolean`; \} \| `null` --- # /docs/typescript/api/index/functions/buildFundingRateSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / buildFundingRateSeries # Function: buildFundingRateSeries() > **buildFundingRateSeries**\<`T`\>(`rows`, `intervalSeconds`, `from`, `to`, `limit`): [`FundingRateSeries`](../type-aliases/FundingRateSeries.md)\<`T`\> Defined in: packages/sdk/src/funding.ts:353 Densify a page of rollup rows into a chart-ready series, and report whether the page was truncated. Split out of the React hook on purpose: the truncation rule is the part that misleads if it is wrong, and it is worth asserting without a DOM. `truncated` is `rows.length >= limit` — `listFundingRateCandles` pages newest-first, so a FULL page means older buckets were dropped, NOT that funding stopped. A caller that renders a truncated window without saying so shows missing history as a funding pause; the densifier declines to invent those older slots, which is why the returned window can be shorter than `[from, to)` and why `firstBucketStart` is reported rather than assumed to equal `from`. **Details** - `rows`: a page from `listFundingRateCandles`, any order - `intervalSeconds`: the grid resolution the rows were queried at - `from`: window start, unix seconds (snapped down to the grid) - `to`: window end, unix seconds (exclusive) - `limit`: the `limit` the page was requested with, for the truncation test ## Type Parameters ### T `T` *extends* [`FundingBucketLike`](../interfaces/FundingBucketLike.md) ## Parameters ### rows readonly `T`[] ### intervalSeconds `number` ### from `number` \| `bigint` ### to `number` \| `bigint` ### limit `number` ## Returns [`FundingRateSeries`](../type-aliases/FundingRateSeries.md)\<`T`\> --- # /docs/typescript/api/index/functions/byNewestFirst [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / byNewestFirst # Function: byNewestFirst() > **byNewestFirst**(`a`, `b`): `number` Defined in: packages/sdk/src/activity.ts:1024 Newest first, breaking a shared timestamp on block then log position. EXPORTED because it is the order `getMarketActivity` pages by: a caller merging its own rows into that page (the live tail, say) must sort by the same rule, and a hand-copied comparator is free to drift from the paging contract with nothing to catch it. ## Parameters ### a [`MarketActivity`](../type-aliases/MarketActivity.md) ### b [`MarketActivity`](../type-aliases/MarketActivity.md) ## Returns `number` --- # /docs/typescript/api/index/functions/cadenceBandSec [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / cadenceBandSec # Function: cadenceBandSec() > **cadenceBandSec**(`cadenceSec`): `object` Defined in: packages/sdk/src/interval.ts:167 The inclusive window of raw `intervalSec` values that count as `cadenceSec` — `cadenceSec ± ` [CADENCE\_TOLERANCE\_SEC](../variables/CADENCE_TOLERANCE_SEC.md). This is what turns a cadence filter into a range predicate server-side, so "15m" returns the 898s and 899s markets of the same series rather than only the exact-900s ones. Rungs are far enough apart that the bands never overlap. THROWS on a non-finite or non-positive cadence rather than banding it. The other helpers here answer 0/null for junk because their callers render the result; this one's output becomes a Hasura predicate, where `NaN` would go on the wire as the string `"NaN"` and a `<= 0` cadence would quietly select a 1–5s band that matches nothing. A filter that silently matches nothing is the worst of the three outcomes: it looks like an empty result set rather than the caller error it is. **Gotchas** - Throws RangeError when `cadenceSec` is not a positive finite number. ## Parameters ### cadenceSec `number` ## Returns `object` ### minSec > **minSec**: `number` ### maxSec > **maxSec**: `number` --- # /docs/typescript/api/index/functions/candlesKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / candlesKey # Function: candlesKey() > **candlesKey**(`pool`, `intervalSeconds`, `opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:142 Key for `client.getCandles(pool, intervalSeconds, opts)`. ## Parameters ### pool `string` \| `null` \| `undefined` ### intervalSeconds `number` ### opts? #### limit? `number` Max candles. #### from? `number` Range start (unix seconds). #### to? `number` Range end (unix seconds). ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/ceilRawAmount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ceilRawAmount # Function: ceilRawAmount() > **ceilRawAmount**(`raw`, `decimals`, `quantum`): `bigint` Defined in: packages/sdk/src/units.ts:602 Ceil a raw on-chain amount UP to a whole multiple of `quantum` (a human decimal string — the market's lot size for base amounts, or a display precision like "0.01" for quote). The mirror of [floorRawBalance](floorRawBalance.md), for sizing a **minimum**: a minimum rounded DOWN falls below what the pool requires and the order is rejected as under the minimum — the exact mirror of the max-order revert the floors prevent. An amount below one quantum rises to one whole quantum rather than collapsing to `0` the way the floor does. Returns a `bigint`, unlike the floors, which return `number`. A minimum is checked against the lot boundary exactly, and no `double` can hold one: the nearest `double` to `0.1` at 18 decimals sits tens of wei off, which puts it below the minimum itself. Convert at the edge if you need a number — `Number(formatUnits(result, decimals))`. ## Parameters ### raw `bigint` ### decimals `number` ### quantum `string` ## Returns `bigint` --- # /docs/typescript/api/index/functions/chainMarketRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / chainMarketRef # Function: chainMarketRef() > **chainMarketRef**(`chainId`, `id`): [`ChainMarketRef`](../interfaces/ChainMarketRef.md) Defined in: packages/sdk/src/chainRef.ts:69 Build a [ChainMarketRef](../interfaces/ChainMarketRef.md). ## Parameters ### chainId `number` ### id `string` ## Returns [`ChainMarketRef`](../interfaces/ChainMarketRef.md) --- # /docs/typescript/api/index/functions/chainOrderRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / chainOrderRef # Function: chainOrderRef() > **chainOrderRef**(`chainId`, `pool`, `id`): [`ChainOrderRef`](../interfaces/ChainOrderRef.md) Defined in: packages/sdk/src/chainRef.ts:74 Build a [ChainOrderRef](../interfaces/ChainOrderRef.md). ## Parameters ### chainId `number` ### pool `` `0x${string}` `` ### id `string` ## Returns [`ChainOrderRef`](../interfaces/ChainOrderRef.md) --- # /docs/typescript/api/index/functions/claimableFrom [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / claimableFrom # Function: claimableFrom() > **claimableFrom**(`inputs`): [`ClaimablePosition`](../interfaces/ClaimablePosition.md)[] Defined in: packages/sdk/src/derivedReads.ts:914 Filter and shape settled positions into [ClaimablePosition](../interfaces/ClaimablePosition.md)s. A position is claimable when the market is voided or when it holds the winning outcome. A void pays against the stored vector. Loser-side and still-trading positions are omitted. **Errors** Throws [InvalidInputError](../classes/InvalidInputError.md) when a void has a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. ## Parameters ### inputs [`ClaimableInput`](../interfaces/ClaimableInput.md)[] ## Returns [`ClaimablePosition`](../interfaces/ClaimablePosition.md)[] --- # /docs/typescript/api/index/functions/computeBinaryPnl [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / computeBinaryPnl # Function: computeBinaryPnl() > **computeBinaryPnl**(`fills`, `balances`, `market`, `opts?`): [`BinaryPnl`](../interfaces/BinaryPnl.md) Defined in: packages/sdk/src/units.ts:413 Realized + unrealized binary PnL for one account, avg-cost basis — a PURE helper (no indexer/chain dependency). `fills` are the account's own trades (from [binaryFillsFor](binaryFillsFor.md)); `balances` its current YES/NO holdings (from `getOutcomeBalances`); `market` supplies decimals + resolution state. Realized PnL accrues on sells (proceeds − avg cost of the tokens sold). Unrealized marks the remaining position: to the book-clamped last price while trading (see [markYesPrice](markYesPrice.md); pass `opts.bookTop` so a live quote beyond a stale print corrects the mark), and to the settlement payout once resolved: 1 for the winning outcome, 0 for the loser, and on a void each leg's share of the market's stored payout vector — a half per side under the `UNIFORM` void policy, `[p, D−p]` at the closing YES price on a `CLOB_SNAPSHOT` void that captured a two-sided close. An unresolved market that has never traded has no mark. When `market.lastPrice` is null and `opts.bookTop` supplies no quote, `mark`, `value` and `unrealized` are `null` on both legs, as are the combined `unrealized` and `total`. `realized` and `avgCost` stay exact, because neither depends on a mark. **Errors** Throws [InvalidInputError](../classes/InvalidInputError.md) when a void has a present but invalid payout vector. A missing legacy vector keeps the documented half-payout fallback. ## Parameters ### fills [`BinaryPnlFill`](../interfaces/BinaryPnlFill.md)[] ### balances [`OutcomeBalances`](../type-aliases/OutcomeBalances.md) ### market `Pick`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md), `"quoteDecimals"` \| `"lastPrice"` \| `"winningOutcome"` \| `"voided"` \| `"payoutNumerators"` \| `"payoutDenominator"`\> ### opts? #### bookTop? [`YesBookTop`](../interfaces/YesBookTop.md) Top of the YES book — clamps the mark to live quotes (see [markYesPrice](markYesPrice.md)). ## Returns [`BinaryPnl`](../interfaces/BinaryPnl.md) --- # /docs/typescript/api/index/functions/computePortfolioAnalytics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / computePortfolioAnalytics # Function: computePortfolioAnalytics() > **computePortfolioAnalytics**(`events`, `opts`): [`PortfolioAnalytics`](../interfaces/PortfolioAnalytics.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:454 Fold portfolio flow events into the metrics plane. PURE — every input is explicit, so it runs identically in apps, bots, and tests. `events` may arrive in any order; they are sorted oldest-first internally. Events before the window establish the carried-in cost basis; events inside it drive the equity curve. Supply [PortfolioFundingEvent](../interfaces/PortfolioFundingEvent.md)s to measure the return against real external capital. Without them the capital base falls back to a trades-only proxy that overstates the return for an account trading a small part of its balance; `mwrr.capitalBasis` reports which definition applied. **Gotchas** - Throws [InvalidInputError](../classes/InvalidInputError.md) — a sampling bound is not a finite number: `asOf`, any event's `timestamp`, or the window start they derive. The equity series is sampled from those bounds, so a non-finite one leaves the loop's exit comparison false forever and the process allocates until it dies. The offending field is named in the message. Nothing is substituted and no event is dropped — an invalid time is the caller's to fix, and guessing one would silently misplace money on the curve. ## Parameters ### events readonly [`PortfolioFlowEvent`](../type-aliases/PortfolioFlowEvent.md)[] ### opts [`PortfolioAnalyticsOptions`](../interfaces/PortfolioAnalyticsOptions.md) ## Returns [`PortfolioAnalytics`](../interfaces/PortfolioAnalytics.md) --- # /docs/typescript/api/index/functions/computePositionPnL [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / computePositionPnL # Function: computePositionPnL() > **computePositionPnL**(`events`, `balances`, `market`, `oneCollateral`, `opts?`): [`BinaryPositionPnL`](../interfaces/BinaryPositionPnL.md) Defined in: packages/sdk/src/derivedReads.ts:521 Fold a [PnLEvent](../interfaces/PnLEvent.md) stream + current balances into a [BinaryPositionPnL](../interfaces/BinaryPositionPnL.md), avg-cost basis, RAW units. `oneCollateral = 10^quoteDecimals`. Prices arrive in YES terms; a NO event is re-expressed to NO terms (`oneCollateral − yesPrice`) here so the two books stay separate. THE STREAM MUST BE IN CHAIN ORDER - block, then log index. This is an average-cost roll, so order changes the answer: a sale folded before the buy that opened the leg is clamped to nothing and its realization is lost. A [PnLEvent](../interfaces/PnLEvent.md) carries no timestamp, and ordering by the unix second would not be enough anyway, since two events routinely share one. [pnlEventsFor](pnlEventsFor.md) produces a stream that satisfies this. An unresolved market that has never traded has no mark price. When `market.lastPrice` is null and `opts.bookTop` supplies no quote, `markPrice`, `markValue` and `unrealizedPnl` are `null` on both legs and on the total. `balance`, `costBasis`, `avgCost` and `realizedPnl` stay exact, because none of them depends on a mark. **Errors** Throws [InvalidInputError](../classes/InvalidInputError.md) when a void has a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. ## Parameters ### events [`PnLEvent`](../interfaces/PnLEvent.md)[] ### balances #### balanceYes `bigint` #### balanceNo `bigint` ### market `Pick`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md), `"quoteDecimals"` \| `"lastPrice"` \| `"winningOutcome"` \| `"voided"` \| `"payoutNumerators"` \| `"payoutDenominator"`\> ### oneCollateral `bigint` ### opts? #### bookTop? [`YesBookTop`](../interfaces/YesBookTop.md) Top of the YES book — clamps the mark to live quotes (see [markYesPrice](markYesPrice.md)). ## Returns [`BinaryPositionPnL`](../interfaces/BinaryPositionPnL.md) --- # /docs/typescript/api/index/functions/consoleDebugSink [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / consoleDebugSink # Function: consoleDebugSink() > **consoleDebugSink**(`opts?`): (`e`) => `void` Defined in: packages/sdk/src/debug.ts:347 Ready-made console renderer for [ClientConfig.debug](../interfaces/ClientConfig.md#debug) — prints the event stream as an indented span tree, the zero-setup way to watch what a client is doing. Output shape — `▶` opens a span, `◀` closes it with its duration, `·` is a mid-span annotation, and log events print flat with their scope: ```text [sdk] ▶ trader.placeOrder { params: { pool: "0x…", side: "BUY_YES" } } [sdk] ▶ trade.execute { functionName: "placeBinaryOrder", … } [sdk] liveTail applying logs { received: 3, … } [sdk] · trade.execute { hash: "0x…" } [sdk] ◀ trade.execute 38.2ms [sdk] ◀ trader.placeOrder 41.0ms ``` **Details** Indentation is reconstructed from `parentId`, so trees stay correct when concurrent operations interleave. `warn`-level logs and failed spans route to `console.warn`; everything else goes to `console.debug` (in browser devtools, enable the *Verbose* level to see it). - `opts`: `prefix` replaces the leading `[sdk]` tag on every line — useful to tell two clients apart in one console. - Returns: A sink to pass as [ClientConfig.debug](../interfaces/ClientConfig.md#debug). **Gotchas** The sink keeps per-span depth state, so build one per client rather than sharing an instance. ## Parameters ### opts? #### prefix? `string` ## Returns (`e`) => `void` ## See [debugCollector](debugCollector.md) for capturing events in tests instead of printing. **Example** (Enabling console logs) Opt in from devtools without redeploying — `localStorage.setItem("sdk-debug", "1")` and reload: ```ts const exchange = new SomniaMarkets({ ...config, debug: localStorage.getItem("sdk-debug") ? consoleDebugSink() : undefined, }); ``` --- # /docs/typescript/api/index/functions/debugCollector [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / debugCollector # Function: debugCollector() > **debugCollector**(): [`DebugCollector`](../interfaces/DebugCollector.md) Defined in: packages/sdk/src/debug.ts:422 Build a fresh event collector — the test-side counterpart of [consoleDebugSink](consoleDebugSink.md), for asserting that an operation produced the spans/logs you expect (or for ad-hoc capture in a REPL). **Details** - Returns: An independent [DebugCollector](../interfaces/DebugCollector.md); nothing is shared between calls, so parallel tests can each have their own. **Example** (Collecting test traces) Assert a trader write went through the execute pipeline exactly once: ```ts const collector = debugCollector(); const exchange = new SomniaMarkets({ ...config, debug: collector.sink }); await exchange.trader.placeOrder(params); expect(collector.starts("trade.execute")).toHaveLength(1); expect(collector.ends("trade.execute")[0].error).toBeUndefined(); ``` ## Returns [`DebugCollector`](../interfaces/DebugCollector.md) --- # /docs/typescript/api/index/functions/decodeAmendOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodeAmendOrder # Function: decodeAmendOrder() > **decodeAmendOrder**(`receipt`, `pool`): [`DecodedAmendment`](../interfaces/DecodedAmendment.md) Defined in: packages/sdk/src/decode/orders.ts:154 Decode one amendment from its receipt. The pool returns the new order id, but an EOA cannot read return data, so it comes from `OrderPlaced` instead. A single amend reverts outright when its replacement does not rest or fill, so a receipt that reached here carries exactly one placement. ## Parameters ### receipt `TransactionReceipt` ### pool `` `0x${string}` `` ## Returns [`DecodedAmendment`](../interfaces/DecodedAmendment.md) --- # /docs/typescript/api/index/functions/decodeAmendOrders [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodeAmendOrders # Function: decodeAmendOrders() > **decodeAmendOrders**(`receipt`, `pool`, `amendmentCount`): [`DecodedBatchAmendment`](../interfaces/DecodedBatchAmendment.md) Defined in: packages/sdk/src/decode/orders.ts:199 Decode a batch amendment from its receipt. `amendOrders` is all-or-nothing, so every amendment either placed a replacement or the whole tx reverted — which means the n-th `OrderPlaced` is the n-th amendment's replacement, with no rejection gaps to skip. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `amendmentCount` is negative, fractional, or not a safe integer (the result is allocated to that length). The complete union is [DecodeAmendOrdersError](../type-aliases/DecodeAmendOrdersError.md). ## Parameters ### receipt `TransactionReceipt` ### pool `` `0x${string}` `` ### amendmentCount `number` ## Returns [`DecodedBatchAmendment`](../interfaces/DecodedBatchAmendment.md) --- # /docs/typescript/api/index/functions/decodeBinaryVenueFeeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodeBinaryVenueFeeParams # Function: decodeBinaryVenueFeeParams() > **decodeBinaryVenueFeeParams**(`feeParams`): \{ `version`: `number`; `params`: [`BinaryVenueParams`](../interfaces/BinaryVenueParams.md); \} \| `null` Defined in: packages/sdk/src/operatorReads.ts:146 Decode a BINARY_V1 venue's `feeParams` bytes back into (version, rates) for display — pure/local, mirrors BinaryMarketsModule's own dual decoder: 192 bytes ⇒ legacy v2 (policy implied `UNIFORM`), 224 bytes ⇒ v3 (policy word). Returns null for anything else (empty / non-BINARY_V1 venue, wrong version-for-shape, or an on-chain-unreachable policy value). ## Parameters ### feeParams `` `0x${string}` `` ## Returns ### Type Literal \{ `version`: `number`; `params`: [`BinaryVenueParams`](../interfaces/BinaryVenueParams.md); \} #### version > **version**: `number` The payload's schema version tag (2 legacy, 3 current). #### params > **params**: [`BinaryVenueParams`](../interfaces/BinaryVenueParams.md) The decoded plain-bps venue fee rates (+ resolved `voidPolicy`). *** `null` --- # /docs/typescript/api/index/functions/decodeOutcomeId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodeOutcomeId # Function: decodeOutcomeId() > **decodeOutcomeId**(`id`): [`DecodedOutcomeId`](../interfaces/DecodedOutcomeId.md) Defined in: packages/sdk/src/ids.ts:70 Split an outcome id back into `{ pool, nonce, idx }` — the inverse of [outcomeId](outcomeId.md). ## Parameters ### id `bigint` ## Returns [`DecodedOutcomeId`](../interfaces/DecodedOutcomeId.md) --- # /docs/typescript/api/index/functions/decodePerpStopOrderIds [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodePerpStopOrderIds # Function: decodePerpStopOrderIds() > **decodePerpStopOrderIds**(`logs`, `registry`): `bigint`[] Defined in: packages/sdk/src/perp/stops.ts:812 Registry order ids from a receipt's logs, in the registry's own (GTE, LTE) order. The ids only surface through `PendingOrderCreated` — the create functions' return value is unreadable from a receipt — so this is the only way to learn what a placement created. `trader.placePerpStopOrder` calls it for you; it is exported for the build path, where the caller sends the transaction and so holds the only copy of the receipt. Filters to `registry`'s own logs: another contract could emit a matching signature, and in a batched UserOp several contracts' logs share one receipt. **Details** - `logs`: The receipt's logs. - `registry`: The PerpStopOrderRegistry the placement targeted. - Returns: The created ids, oldest first; empty if the receipt created none. **Example** (Decoding submitted stop IDs) ```ts const { stopOrder } = await trader.buildPlacePerpStopOrder({ registry, pool, isBid: false, quantity: 10_000_000n, triggerPrice: 90_000_000_000_000_000_000n, triggerOperator: 1, stopOrderType: 1, skipOperatorApproval: true, }); const receipt = await myBatcher.send([stopOrder]); const [stopOrderId] = decodePerpStopOrderIds(receipt.logs, registry); ``` ## Parameters ### logs readonly `object`[] ### registry `` `0x${string}` `` ## Returns `bigint`[] --- # /docs/typescript/api/index/functions/decodePlaceOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodePlaceOrder # Function: decodePlaceOrder() > **decodePlaceOrder**(`receipt`, `pool?`): [`DecodedPlacement`](../interfaces/DecodedPlacement.md) Defined in: packages/sdk/src/decode/orders.ts:121 Decode an order placement from its receipt: the resting order id (`OrderPlaced`) and the fills (`OrderFilled`). Works for binary, spot and perp pools — they share the OrderBook events. **Details** - `receipt`: The mined receipt, from whoever sent the transaction. - `pool`: Decode only the logs this pool emitted. Pass it when the receipt may carry another pool's events (a safe transaction that touched two pools); omit it to accept the OrderBook events of any emitter. Pure — the same function the sending verbs use, so a call built by `buildPlaceOrder` and sent elsewhere decodes to exactly what `placeOrder` would have returned. **Example** (Decoding a receipt the app obtained itself) ```ts const { order } = await trader.buildPlaceSpotOrder(params); const receipt = await myAccountLayer.send(order); // your safe, relayer, … const { orderId, fills } = decodePlaceOrder(receipt, params.pool); ``` ## Parameters ### receipt `TransactionReceipt` ### pool? `` `0x${string}` `` ## Returns [`DecodedPlacement`](../interfaces/DecodedPlacement.md) --- # /docs/typescript/api/index/functions/decodeRevert [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / decodeRevert # Function: decodeRevert() > **decodeRevert**(`caught`, `context?`): [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/revert.ts:204 Decodes a caught contract failure into a [ContractRevertError](../classes/ContractRevertError.md). **Details** Never throws and never returns undefined: an undecodable revert still produces the typed error, because "the chain rejected this" is useful even when the bytes are a mystery. - `caught`: The value thrown by viem / the transport. - `context`: Which contract and function were called, for the message. - Returns: A ContractRevertError — with `errorName` + `args` when the revert data matched one of the protocol's custom errors, else `reason` (a require string) or `data` (unrecognized bytes) preserved, and `caught` in `cause`. **Gotchas** Decodes unconditionally: it does not first check whether the failure IS a revert, so a transport error (timeout, disconnect) passed here comes back as a ContractRevertError with no `errorName`. Callers inside the SDK use the internal `isRevert` / `toSdkError` pair to make that distinction; neither is exported, so a consumer should pass values it already knows to be revert data — which is the usual case when decoding a failed call's own error. ## Parameters ### caught `unknown` ### context? [`RevertContext`](../interfaces/RevertContext.md) = `{}` ## Returns [`ContractRevertError`](../classes/ContractRevertError.md) --- # /docs/typescript/api/index/functions/densifyFundingBuckets [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / densifyFundingBuckets # Function: densifyFundingBuckets() > **densifyFundingBuckets**\<`T`\>(`candles`, `intervalSeconds`, `from`, `to`): (`T` \| \{ `bucketStart`: `string`; `intervalSeconds`: `number`; `avgFundingRate8h`: `"0"`; `coverage`: `"0"`; `filled`: `true`; \})[] Defined in: packages/sdk/src/funding.ts:237 Fill the bucket-grid slots a candle query did not return, over `[from, to)`. Rollup candles are **sparse by construction**: a window touched by no settlement's covered span produces no row, because nothing triggered a write. A chart that plots the rows as-is silently closes those gaps and draws funding that never accrued. This is the ONLY densification the presentation tier should do, and the constraint is as much about what it must not do: - Missing slots are emitted as **zero** rate with **zero coverage** — never as a carry-forward of the previous rate. Carrying forward is the specific error the protocol docs call out: gaps are genuinely zero-funding intervals, and carrying the last rate through the 22h outage these pools actually had would fabricate ~2.6% of funding out of nothing. - It is not interpolation. Nothing is smoothed, and no real value is altered. - `coverage: "0"` is what lets a chart hatch or grey the slot rather than draw a zero that looks like a measurement. A filled slot and a genuinely-zero measured slot are different facts, and only `coverage` distinguishes them. - **It never fills slots older than the oldest row it was given.** This is the truncation guard, and it matters because `listFundingRateCandles` pages newest-first: 30 days of hourly buckets is 720 rows against a default `limit` of 500, so a caller who asks for a month gets the newest 500 and no indication that anything was dropped. Filling the 220 missing older slots would render nine days as a funding pause that never happened — reintroducing exactly the ambiguity `coverage` exists to remove, one layer up. Refusing to invent them means the window can come back SHORTER than `[from, to)`: read the first element's `bucketStart` rather than assuming it equals `from`, and page with `offset` if you need the rest. Returned oldest-first, which is chart order — note that `listFundingRateCandles` serves newest-first. **Details** - `candles`: rows from [client.listFundingRateCandles](../interfaces/SomniaMarketsClient.md#listfundingratecandles), any order - `intervalSeconds`: the grid resolution the rows were queried at - `from`: window start, unix seconds (snapped down to the grid) - `to`: window end, unix seconds (exclusive) ## Type Parameters ### T `T` *extends* [`FundingBucketLike`](../interfaces/FundingBucketLike.md) ## Parameters ### candles readonly `T`[] ### intervalSeconds `number` ### from `number` \| `bigint` ### to `number` \| `bigint` ## Returns (`T` \| \{ `bucketStart`: `string`; `intervalSeconds`: `number`; `avgFundingRate8h`: `"0"`; `coverage`: `"0"`; `filled`: `true`; \})[] --- # /docs/typescript/api/index/functions/estPayoutFor [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / estPayoutFor # Function: estPayoutFor() > **estPayoutFor**(`input`): `bigint` Defined in: packages/sdk/src/derivedReads.ts:830 Compute the estimated payout for one settled position (raw collateral). Winner: `amount × (10_000 − feeBps) / 10_000`; voided: `amount × payoutNumerators[outcomeIdx] / payoutDenominator`; loser: 0. A void pays its stored vector, which is a half per side under the `UNIFORM` policy and `[p, D−p]` on a `CLOB_SNAPSHOT` void that captured a two-sided close. When the vector is absent the estimate falls back to the half, which is what this returned for every void before the vector existed. A void is never fee-charged, so no settlement fee applies on this branch — the raw vector and the fee-scaled one are identical for a void. **Errors** Throws [InvalidInputError](../classes/InvalidInputError.md) when a void has a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. ## Parameters ### input [`ClaimableInput`](../interfaces/ClaimableInput.md) ## Returns `bigint` --- # /docs/typescript/api/index/functions/estimateMarketOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / estimateMarketOrder # Function: estimateMarketOrder() > **estimateMarketOrder**(`book`, `side`, `amount`, `denomination?`): [`MarketOrderEstimate`](../interfaces/MarketOrderEstimate.md) \| `null` Defined in: packages/sdk/src/unified/quotes.ts:112 Estimate a market order's execution by walking one side of the book: buys walk the asks, sells walk the bids, consuming `amount` in either the base or the quote denomination. The four combinations: - buy + quote — spend a quote budget, learn the base received. - buy + base — target a base size, learn the quote cost. - sell + base — deliver a base size, learn the quote received. - sell + quote — target quote proceeds, learn the base sold. Returns `null` when the relevant side is empty or `amount` is non-positive. A partial walk (book thinner than the order) returns what WOULD fill — compare `baseFilled`/`quoteFilled` against the request to detect it. ## Parameters ### book [`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md) ### side `"buy"` \| `"sell"` ### amount `number` ### denomination? [`QuoteDenomination`](../type-aliases/QuoteDenomination.md) = `"base"` ## Returns [`MarketOrderEstimate`](../interfaces/MarketOrderEstimate.md) \| `null` --- # /docs/typescript/api/index/functions/fillKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fillKind # Function: fillKind() > **fillKind**(`takerSide`, `makerSide`): [`BinaryFillKind`](../type-aliases/BinaryFillKind.md) Defined in: packages/sdk/src/store.ts:568 Classify a binary fill from its two sides: opposite trades on ONE outcome are direct (`DIRECT_YES`/`DIRECT_NO`); two buys mint a YES+NO pair from collateral, two sells burn one back. Mirror of the indexer's `fillKind` (BinaryPool._isPair matrix — keep in lockstep). **Details** - `takerSide`: The taker's [BinarySide](../type-aliases/BinarySide.md). - `makerSide`: The maker's [BinarySide](../type-aliases/BinarySide.md). ## Parameters ### takerSide [`BinarySide`](../type-aliases/BinarySide.md) ### makerSide [`BinarySide`](../type-aliases/BinarySide.md) ## Returns [`BinaryFillKind`](../type-aliases/BinaryFillKind.md) --- # /docs/typescript/api/index/functions/fillsWithinSlippage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fillsWithinSlippage # Function: fillsWithinSlippage() > **fillsWithinSlippage**(`book`, `side`, `amount`, `slippage`, `denomination?`): `boolean` Defined in: packages/sdk/src/unified/quotes.ts:156 Whether a market order of `amount` (in `denomination`) fills COMPLETELY within `slippage` of the mid price: buys spend against asks at or below `mid·(1+slippage)`, sells deliver into bids at or above `mid·(1−slippage)`. Levels are sorted best-first, so the first level outside the band ends the walk. False when the book is empty, the mid is unknown, or the in-band liquidity can't cover the size — the caller should refuse the order rather than fill deep. ## Parameters ### book [`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md) ### side `"buy"` \| `"sell"` ### amount `number` ### slippage `number` ### denomination? [`QuoteDenomination`](../type-aliases/QuoteDenomination.md) = `"base"` ## Returns `boolean` --- # /docs/typescript/api/index/functions/floorRawBalance [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / floorRawBalance # Function: floorRawBalance() > **floorRawBalance**(`raw`, `decimals`, `quantum`): `number` Defined in: packages/sdk/src/units.ts:569 Floor a raw on-chain balance to a whole multiple of `quantum` (a human decimal string — the market's lot size for base amounts, or a display precision like "0.01" for quote) and return it as a JS number that is provably ≤ the true balance. Flooring happens in raw (bigint) space, so float rounding can never push a "max" order above the wallet. ## Parameters ### raw `bigint` ### decimals `number` ### quantum `string` ## Returns `number` --- # /docs/typescript/api/index/functions/formatIntervalLabel [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / formatIntervalLabel # Function: formatIntervalLabel() > **formatIntervalLabel**(`sec`): `string` \| `null` Defined in: packages/sdk/src/interval.ts:187 Compact human label for a cadence in SECONDS, in the largest unit up to hours that divides it cleanly: `600 → "10m"`, `900 → "15m"`, `3600 → "1h"`, `14400 → "4h"`, `86400 → "24h"`, `172800 → "48h"`, `90 → "90s"`. Returns `null` on non-finite/non-positive input (callers pick their own placeholder). Does NOT snap — pass a snapped value, or use [marketIntervalLabel](marketIntervalLabel.md), to first shed off-by-one-second noise. ## Parameters ### sec `number` ## Returns `string` \| `null` --- # /docs/typescript/api/index/functions/fromHuman [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fromHuman # Function: fromHuman() > **fromHuman**(`human`, `decimals?`): `bigint` Defined in: packages/sdk/src/units.ts:54 Human amount (number or decimal string) → raw bigint at `decimals`, for the write API (`placeOrder` price/quantity, `mintSet` amount, …). Pass the selected binary market's `quoteDecimals`; the default is 6. Accepts a string to avoid float rounding (`fromHuman("0.1")`), or a number for convenience. **Gotchas** A number carrying more fraction digits than `decimals` is ROUNDED to scale (half-away-from-zero, via `toFixed`): `fromHuman(0.1234567, 6)` is `123457n`. That is a deliberate, long-standing choice — the alternative (throwing) would reject ordinary computed values like a mid price. Pass a string when you need the exact value preserved or rejected instead. ## Parameters ### human `string` \| `number` ### decimals? `number` = `Store.DECIMALS` ## Returns `bigint` --- # /docs/typescript/api/index/functions/fundingRate1h [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fundingRate1h # Function: fundingRate1h() > **fundingRate1h**(`rate`, `fundingWindowSec`): `bigint` Defined in: packages/sdk/src/funding.ts:96 The rate per hour. ## Parameters ### rate `bigint` ### fundingWindowSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/fundingRate8h [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fundingRate8h # Function: fundingRate8h() > **fundingRate8h**(`rate`, `fundingWindowSec`): `bigint` Defined in: packages/sdk/src/funding.ts:87 The rate per 8 hours — the primary presentation axis, matching the convention used by Hyperliquid and Binance. A no-op while `fundingWindowSec` is 28800, which it is on every live pool. Use it anyway: it is what keeps a chart correct across a window change. ## Parameters ### rate `bigint` ### fundingWindowSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/fundingRatePerInterval [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / fundingRatePerInterval # Function: fundingRatePerInterval() > **fundingRatePerInterval**(`rate`, `fundingWindowSec`, `fundingIntervalSec`): `bigint` Defined in: packages/sdk/src/funding.ts:106 The rate that accrues per settlement interval — what an account actually pays or receives at each settlement. ## Parameters ### rate `bigint` ### fundingWindowSec `number` ### fundingIntervalSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/getMarketTypePlugin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / getMarketTypePlugin # Function: getMarketTypePlugin() > **getMarketTypePlugin**(`marketType`): [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\<`unknown`\> \| `undefined` Defined in: packages/sdk/src/marketTypes/index.ts:29 Resolve a market-type plugin by its bytes4 id (case-insensitive), or undefined if unregistered. ## Parameters ### marketType `` `0x${string}` `` ## Returns [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\<`unknown`\> \| `undefined` --- # /docs/typescript/api/index/functions/intervalsPerWindow [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / intervalsPerWindow # Function: intervalsPerWindow() > **intervalsPerWindow**(`fundingWindowSec`, `fundingIntervalSec`): `number` Defined in: packages/sdk/src/funding.ts:137 Intervals per calculation window — `n`. The per-interval divisor: each settlement accrues `rate / n` of the emitted per-window rate. **It is not a cap on what a lazily-settled emit accrues, and never treat it as one.** The contract's catch-up horizon is ONE interval, so a settlement charges at most `rate / n` however long the gap was, and the excess is forgiven rather than deferred. Read `FundingRateUpdate.intervalsAccrued` for what a given settlement actually accrued; deriving it as `min(intervalsSettled, n)` is the specific error the protocol interface warns against, and it renders funding across intervals that were forgiven. ## Parameters ### fundingWindowSec `number` ### fundingIntervalSec `number` ## Returns `number` --- # /docs/typescript/api/index/functions/isBinaryMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isBinaryMarket # Function: isBinaryMarket() > **isBinaryMarket**(`m`): `m is BinaryMarket` Defined in: packages/sdk/src/markets.ts:466 Narrow a [Market](../type-aliases/Market.md) to its binary variant. ## Parameters ### m [`Market`](../type-aliases/Market.md) ## Returns `m is BinaryMarket` --- # /docs/typescript/api/index/functions/isChainMarketRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isChainMarketRef # Function: isChainMarketRef() > **isChainMarketRef**(`handle`): `handle is ChainMarketRef` Defined in: packages/sdk/src/chainRef.ts:57 True when `handle` is a [ChainMarketRef](../interfaces/ChainMarketRef.md) rather than a bare string. ## Parameters ### handle [`MarketHandle`](../type-aliases/MarketHandle.md) ## Returns `handle is ChainMarketRef` --- # /docs/typescript/api/index/functions/isChainOrderRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isChainOrderRef # Function: isChainOrderRef() > **isChainOrderRef**(`id`): `id is ChainOrderRef` Defined in: packages/sdk/src/chainRef.ts:64 True when `id` is a [ChainOrderRef](../interfaces/ChainOrderRef.md) rather than a bare order id string. ## Parameters ### id `string` \| [`ChainOrderRef`](../interfaces/ChainOrderRef.md) ## Returns `id is ChainOrderRef` --- # /docs/typescript/api/index/functions/isFundingStale [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isFundingStale # Function: isFundingStale() > **isFundingStale**(`lastFundingUpdateAt`, `fundingIntervalSec`, `nowSec`, `staleAfterIntervals?`): `boolean` Defined in: packages/sdk/src/funding.ts:177 Whether a pool's funding has gone stale — no settlement for `staleAfterIntervals` worth of time. Settlement is permissionless and LAZY, so a due settlement simply may not have happened. One missed interval is routine; a sustained gap means funding is not accruing, and on the zero-open-interest branch it is being forgiven with no event at all. Two intervals is a deliberately forgiving default. ## Parameters ### lastFundingUpdateAt `bigint` ### fundingIntervalSec `number` ### nowSec `bigint` ### staleAfterIntervals? `number` = `2` ## Returns `boolean` --- # /docs/typescript/api/index/functions/isLiquidationKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isLiquidationKind # Function: isLiquidationKind() > **isLiquidationKind**(`kind`): kind is "AutoDeleveraged" \| "CloseOutMarginSettled" \| "BadDebtAbsorbed" \| "PositionTransferred" \| "AccountLiquidated" \| "PositionLiquidated" \| "PositionTakenOver" \| "ResidualBadDebt" \| "ResidualBackedByOpenPnl" \| "AdlCapacityShortfall" \| "AdlPriceCapacityExhausted" \| "AdlSessionDiscarded" \| "PositionSkipped" \| "Throttled" \| "KeeperReward" \| "OrderPanicked" \| "CoverageDeclined" Defined in: packages/sdk/src/perp/history.ts:142 Whether a wire `kind` is one this SDK version knows, narrowing it to [LiquidationKind](../type-aliases/LiquidationKind.md). This is the seam between the open rows and the closed filter, and it exists because the two really are different: [LiquidationEvent.kind](../type-aliases/LiquidationEvent.md#kind) is whatever the DEPLOYED indexer wrote, which can outrun a pinned SDK, while [ListLiquidationsOptions.kind](../interfaces/ListLiquidationsOptions.md#kind) is a value the caller chooses and must not be able to misspell. Narrow a row's kind to switch on it exhaustively, or to pass it back into the filter; the false branch is the honest "a kind this version does not know" rather than a cast over it. ## Parameters ### kind `string` ## Returns kind is "AutoDeleveraged" \| "CloseOutMarginSettled" \| "BadDebtAbsorbed" \| "PositionTransferred" \| "AccountLiquidated" \| "PositionLiquidated" \| "PositionTakenOver" \| "ResidualBadDebt" \| "ResidualBackedByOpenPnl" \| "AdlCapacityShortfall" \| "AdlPriceCapacityExhausted" \| "AdlSessionDiscarded" \| "PositionSkipped" \| "Throttled" \| "KeeperReward" \| "OrderPanicked" \| "CoverageDeclined" --- # /docs/typescript/api/index/functions/isLocalPrecompileUnavailable [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isLocalPrecompileUnavailable # Function: isLocalPrecompileUnavailable() > **isLocalPrecompileUnavailable**(`chainId`): `boolean` Defined in: packages/sdk/src/preflight.ts:413 True when a chain id belongs to a network WITHOUT the Somnia reactivity precompile — i.e. a local anvil/hardhat dev chain (31337 / 1337), where `enableReactivity` / `triggerRoll` cannot work. Somnia testnet/mainnet return false. Use to fill the `precompileAvailable` flag the validators take. ## Parameters ### chainId `number` ## Returns `boolean` --- # /docs/typescript/api/index/functions/isPerpMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isPerpMarket # Function: isPerpMarket() > **isPerpMarket**(`m`): `m is PerpMarket` Defined in: packages/sdk/src/markets.ts:497 Narrow a [Market](../type-aliases/Market.md) to its perp variant. ## Parameters ### m [`Market`](../type-aliases/Market.md) ## Returns `m is PerpMarket` --- # /docs/typescript/api/index/functions/isSomniaMarketsAccount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isSomniaMarketsAccount # Function: isSomniaMarketsAccount() > **isSomniaMarketsAccount**(`value`): `value is SomniaMarketsAccount` Defined in: packages/sdk/src/account.ts:67 True when a signer config value is a [SomniaMarketsAccount](../interfaces/SomniaMarketsAccount.md) rather than a viem account or address. ## Parameters ### value `unknown` ## Returns `value is SomniaMarketsAccount` --- # /docs/typescript/api/index/functions/isSpotMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / isSpotMarket # Function: isSpotMarket() > **isSpotMarket**(`m`): `m is SpotMarket` Defined in: packages/sdk/src/markets.ts:488 Narrow a [Market](../type-aliases/Market.md) to its spot variant. ## Parameters ### m [`Market`](../type-aliases/Market.md) ## Returns `m is SpotMarket` --- # /docs/typescript/api/index/functions/lendRayRateToApy [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / lendRayRateToApy # Function: lendRayRateToApy() > **lendRayRateToApy**(`rateRay`): `number` Defined in: packages/sdk/src/lend/math.ts:95 Convert a ray annual rate (a reserve's `liquidityRateRay` / `variableBorrowRateRay`) to the per-second-compounded APY fraction Aave UIs display (0.05 = 5%). **When to use** Use to display a rate — this exists so apps don't each re-derive `(1 + r/s)^s - 1` from the ray rate. Position math stays in bigint ray space ([rayMul](rayMul.md), [accrueCompounded](accrueCompounded.md)). **Details** - `rateRay`: Annual rate in ray (1e27) units, as returned in [LendReserve](../interfaces/LendReserve.md). - Returns: The compounded annual yield as a plain fraction (`0.031` ⇒ 3.1% APY). **Gotchas** Display-only — the one place the lend surface hands back a `number`. **Example** (Converting a ray rate) ```ts const reserves = await lend.listReserves(); const usdso = reserves.find((r) => r.symbol === "USDso"); if (usdso) console.log(`supply APY ${(lendRayRateToApy(usdso.liquidityRateRay) * 100).toFixed(2)}%`); ``` ## Parameters ### rateRay `bigint` ## Returns `number` --- # /docs/typescript/api/index/functions/listMarketTypePlugins [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / listMarketTypePlugins # Function: listMarketTypePlugins() > **listMarketTypePlugins**(): [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\<`unknown`\>[] Defined in: packages/sdk/src/marketTypes/index.ts:39 All registered market-type plugins (e.g. to render a "pick a market type" list in a venue-creation wizard). ## Returns [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\<`unknown`\>[] --- # /docs/typescript/api/index/functions/markOutcomePosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / markOutcomePosition # Function: markOutcomePosition() > **markOutcomePosition**(`input`): [`OutcomePositionMark`](../interfaces/OutcomePositionMark.md) Defined in: packages/sdk/src/derivedReads.ts:1402 Mark an outcome position: `value = balance × mark`, `upnl = balance × (mark − avgEntry)`. When `avgEntry` is unknown (no buys indexed yet) only `value` is computed and the PnL fields stay `null` — a dash beats an invented zero basis. ## Parameters ### input #### balance `bigint` Outcome-token balance held (raw units). #### markPrice `bigint` Live mark price in the outcome's own terms (raw). #### avgEntry `bigint` \| `null` Average entry price in the outcome's own terms (raw), or `null`. #### oneShare `bigint` ## Returns [`OutcomePositionMark`](../interfaces/OutcomePositionMark.md) --- # /docs/typescript/api/index/functions/markYesPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / markYesPrice # Function: markYesPrice() > **markYesPrice**(`top`, `lastPrice`): `bigint` \| `null` Defined in: packages/sdk/src/units.ts:157 Mark-to-market YES price (raw): the book mid when two-sided, otherwise the last trade clamped into the surviving side's bound. The clamp reconciles the two failure modes of a one-sided book: marking to the lone quote outright flashes the full bid-ask spread as a loss right after a taker clears the top of the book, while marking to the last trade alone freezes the mark at a stale print when the market genuinely runs away — a resting quote BEYOND the last print is live, executable information and supersedes it. With no last trade the lone side is all there is; `null` only when the book is empty and nothing has traded. ## Parameters ### top [`YesBookTop`](../interfaces/YesBookTop.md) ### lastPrice `string` \| `bigint` \| `null` \| `undefined` ## Returns `bigint` \| `null` --- # /docs/typescript/api/index/functions/marketActivityKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketActivityKey # Function: marketActivityKey() > **marketActivityKey**(`market`, `opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:175 Key for `client.getMarketActivity(market, opts)`. `kinds` is sorted and joined, so two callers that ask for the same kinds in a different order share one cache entry — the read does not depend on the order. ## Parameters ### market `string` \| `null` \| `undefined` ### opts? [`MarketActivityOptions`](../type-aliases/MarketActivityOptions.md) ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/marketCreatorsKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketCreatorsKey # Function: marketCreatorsKey() > **marketCreatorsKey**(`opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:295 Key for `client.listMarketCreators(opts)`. ## Parameters ### opts? [`MarketCreatorFilter`](../type-aliases/MarketCreatorFilter.md) & `object` ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/marketFeesKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketFeesKey # Function: marketFeesKey() > **marketFeesKey**(`marketId`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:257 Key for `client.getMarketFees(marketId)`. ## Parameters ### marketId `string` \| `null` \| `undefined` ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/marketIntervalLabel [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketIntervalLabel # Function: marketIntervalLabel() > **marketIntervalLabel**(`m`): `string` \| `null` Defined in: packages/sdk/src/interval.ts:212 The served timeframe label for a binary market: resolve the cadence ([resolveIntervalSec](resolveIntervalSec.md)), snap it to its ladder rung ([snapToCadence](snapToCadence.md)), then label it ([formatIntervalLabel](formatIntervalLabel.md)) — so a market reads as `"1m"` / `"5m"` / `"15m"` / `"1h"` / `"4h"` / `"24h"` whether or not its roll spilled. A window matching no rung (a series' bootstrap partial, a non-ladder cadence) keeps its own short window. Returns `null` when the market has no determinable cadence (SPOT/PERP). This is what the SDK stamps onto `BinaryMarket.interval` and trade-history rows. Snapping to the LADDER rather than to the nearest minute/hour is what stops a row's own badge contradicting the group it was filed under: a 1m member that rolled 4s late is indexed at 56s, which the plain unit snap has no rung to reach for and labels `"56s"`. ## Parameters ### m [`IntervalSource`](../type-aliases/IntervalSource.md) ## Returns `string` \| `null` --- # /docs/typescript/api/index/functions/marketKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketKey # Function: marketKey() > **marketKey**(`outcomeId`): `bigint` Defined in: packages/sdk/src/ids.ts:88 The settlement `marketKey` for any outcome id of a market: `id >> 8`. Both the YES id and the NO id of the same market map to the SAME key (they differ only in the low 8 idx bits), so this keys the per-market `BinarySettlement` record regardless of which side's id you pass. Named `marketKey(yesId)` for the canonical YES-id caller, but any outcome id of the market works. ## Parameters ### outcomeId `bigint` ## Returns `bigint` --- # /docs/typescript/api/index/functions/marketOnchainKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketOnchainKey # Function: marketOnchainKey() > **marketOnchainKey**(`marketId`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:379 Key for `client.getMarketOnchain(marketId)`. ## Parameters ### marketId `string` \| `null` \| `undefined` ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/marketStats24hFromCandles [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketStats24hFromCandles # Function: marketStats24hFromCandles() > **marketStats24hFromCandles**(`candles`, `nowSec`): [`MarketStats24h`](../interfaces/MarketStats24h.md) Defined in: packages/sdk/src/derivedReads.ts:181 Fold candle buckets whose `bucketStart >= nowSec − 86400` into a [MarketStats24h](../interfaces/MarketStats24h.md). `candles` are oldest-first (as `getCandles` returns). Pure — the wiring in createClient just fetches the candles first. ## Parameters ### candles [`Candle`](../type-aliases/Candle.md)[] ### nowSec `number` ## Returns [`MarketStats24h`](../interfaces/MarketStats24h.md) --- # /docs/typescript/api/index/functions/marketsKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marketsKey # Function: marketsKey() > **marketsKey**(`opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:99 Key for `client.listMarkets(opts)`. ## Parameters ### opts? #### marketType? [`MarketType`](../type-aliases/MarketType.md) Restrict to one market kind. #### limit? `number` Page size. #### offset? `number` Page offset. ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/maxVenueFeeBpsKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / maxVenueFeeBpsKey # Function: maxVenueFeeBpsKey() > **maxVenueFeeBpsKey**(`chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:370 Key for `client.getMaxVenueFeeBps()`. ## Parameters ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/midYesPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / midYesPrice # Function: midYesPrice() > **midYesPrice**(`bestYesBid`, `bestYesAsk`): `bigint` \| `undefined` Defined in: packages/sdk/src/derivedReads.ts:1293 The mid YES price (raw) from the best book levels — `(bid + ask) / 2` when both sides are quoted, otherwise whichever single side exists. `undefined` when the book is empty. For an ODDS display; positions should mark with [markYesPrice](markYesPrice.md) instead (a lone bid/ask is not a fair mark). ## Parameters ### bestYesBid `bigint` \| `undefined` ### bestYesAsk `bigint` \| `undefined` ## Returns `bigint` \| `undefined` --- # /docs/typescript/api/index/functions/netInternalTransfers [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / netInternalTransfers # Function: netInternalTransfers() > **netInternalTransfers**(`events`, `chainIds`): [`PortfolioFundingEvent`](../interfaces/PortfolioFundingEvent.md)[] Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:137 Remove the bridge legs that move capital between an exchange's OWN chains from a funding list. A transfer from one configured chain to another leaves the account's capital where it was, so counting its origin leg as a withdrawal and its destination leg as a deposit distorts the capital base on both sides. **Details** - Two legs with the same `transferId`, opposite `direction`, and both `chainId`s in `chainIds` are one internal transfer: both are dropped. - An `out` leg whose `counterpartyChainId` is in `chainIds` but whose `in` leg is absent (still in flight, or outside the window) is dropped alone: the capital is in transit and stays in the base. - An `in` leg whose `counterpartyChainId` is in `chainIds` but whose `out` leg is absent is dropped for the same reason — the capital was already in the base on the origin chain. - Every other event, including a leg to or from a chain outside `chainIds`, is an external movement and passes through unchanged. Pure: returns a new array, in the input order. ## Parameters ### events readonly [`PortfolioFundingEvent`](../interfaces/PortfolioFundingEvent.md)[] ### chainIds readonly `number`[] ## Returns [`PortfolioFundingEvent`](../interfaces/PortfolioFundingEvent.md)[] --- # /docs/typescript/api/index/functions/nextBackoffDelayMs [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / nextBackoffDelayMs # Function: nextBackoffDelayMs() > **nextBackoffDelayMs**(`attempt`, `random`, `limits?`): `number` Defined in: packages/sdk/src/config.ts:393 Delay before retry `attempt` (0-based): exponential backoff with FULL jitter, `random` scaled onto `[0, base * 2 ** attempt]`, capped at `maxDelayMs`. **Details** Full jitter, not a fixed interval and not bare doubling — both leave clients retrying in lockstep, which is how a slow endpoint becomes a storm. The caller supplies the draw (`Math.random()` in production), so the function is pure: the same inputs give the same delay, and a poll loop outside the SDK can pace itself on the same schedule. **Example** (Pacing a poll loop on the SDK schedule) ```ts import { nextBackoffDelayMs } from "@somnia-chain/markets-sdk"; let failures = 0; for (;;) { const ok = await readOnce(); failures = ok ? 0 : failures + 1; await new Promise((r) => setTimeout(r, failures ? nextBackoffDelayMs(failures - 1, Math.random()) : 60_000)); } ``` ## Parameters ### attempt `number` ### random `number` ### limits? [`IndexerLimits`](../interfaces/IndexerLimits.md) = `{}` ## Returns `number` ## Throws [InvalidInputError](../classes/InvalidInputError.md) If `attempt` is not a finite number >= 0, `random` is outside `[0, 1)`, or `limits.baseDelayMs`/`limits.maxDelayMs` is not a finite number > 0. --- # /docs/typescript/api/index/functions/normalizeFundingRate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / normalizeFundingRate # Function: normalizeFundingRate() > **normalizeFundingRate**(`rate`, `fundingWindowSec`, `targetSec`): `bigint` Defined in: packages/sdk/src/funding.ts:73 Re-express a per-window funding rate on a different denominator. `rate_target = rate * targetSec / fundingWindowSec`, in 1e18 fixed point. Truncates toward zero, matching the contract's integer arithmetic; sign is preserved. **Details** - `rate`: the rate as stored/emitted: per `fundingWindowSec`, 1e18-scaled, signed - `fundingWindowSec`: the rate's denominator, from the same row or state read - `targetSec`: the denominator to convert to **Example** (Normalizing an interval rate) ```ts const perInterval = normalizeFundingRate(st.fundingRate, st.fundingWindowSec, st.fundingIntervalSec); ``` ## Parameters ### rate `bigint` ### fundingWindowSec `number` ### targetSec `number` ## Returns `bigint` --- # /docs/typescript/api/index/functions/operatorsKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / operatorsKey # Function: operatorsKey() > **operatorsKey**(`opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:266 Key for `client.listOperators(opts)`. ## Parameters ### opts? [`OperatorFilter`](../type-aliases/OperatorFilter.md) & `object` ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/oracleAdaptersKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / oracleAdaptersKey # Function: oracleAdaptersKey() > **oracleAdaptersKey**(`opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:325 Key for `client.listOracleAdapters(opts)`. ## Parameters ### opts? #### owner? `string` Restrict to adapters owned by this address. #### approved? `boolean` Restrict to approved (true) / unapproved (false) adapters. #### limit? `number` Page size. #### offset? `number` Page offset. ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/outcomeId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / outcomeId # Function: outcomeId() > **outcomeId**(`pool`, `nonce`, `idx`): `bigint` Defined in: packages/sdk/src/ids.ts:46 The ERC-6909 outcome id for `pool`'s market at `nonce`, outcome `idx`. `id = (uint160(pool) << 72) | (nonce << 8) | idx`. Pool is a 0x-address; nonce is the pool's `marketNonce` for the target market (1 on a fresh pool, ++ on each recycle); idx is 0 (YES) or 1 (NO). ## Parameters ### pool `string` ### nonce `number` \| `bigint` ### idx [`OutcomeIdx`](../type-aliases/OutcomeIdx.md) ## Returns `bigint` --- # /docs/typescript/api/index/functions/outcomeMarkPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / outcomeMarkPrice # Function: outcomeMarkPrice() > **outcomeMarkPrice**(`input`): `bigint` \| `undefined` Defined in: packages/sdk/src/derivedReads.ts:1369 Live mark price for one outcome in its own terms (raw): YES marks at the YES mid, NO at the complement. `undefined` when there's no mid to mark to. ## Parameters ### input #### outcomeIndex `number` #### yesMid `bigint` \| `undefined` YES mark (raw), e.g. from [markYesPrice](markYesPrice.md). #### oneShare `bigint` ## Returns `bigint` \| `undefined` --- # /docs/typescript/api/index/functions/perpLiquidationPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpLiquidationPrice # Function: perpLiquidationPrice() > **perpLiquidationPrice**(`p`): `bigint` \| `null` Defined in: packages/sdk/src/perp/margin.ts:446 Solve for the mark price at which one market's position trips maintenance margin — the shared kernel behind `client.getLiquidationPrice` and `client.previewPerpLiquidationPrice`, which is why a current and a projected price cannot disagree on identical inputs. Pure: no client, no block, no I/O. Feed it a consistent snapshot and it is exact arithmetic. **Both sides of the inequality move with the price.** Liquidation begins where `equity == mmReq` — `MarginBank._classify` returns `PartialLiquidation` the moment `equity < mmReq`. Equity moves with the mark through unrealized PnL, at `size / oneBase` per unit of price. But `mmReq` moves too, because `_marketHealthFromSnapshot` recomputes it as `ceil(|size| × mark × mmBps / (oneBase × 10000))` against the CURRENT mark. Solving `equity(p) == mmReq(p)` therefore carries a factor a fixed-`mmReq` estimate drops: ```text long p = mark − (equity − mmReq) × oneBase × 10000 / (|size| × (10000 − mmBps)) short p = mark + (equity − mmReq) × oneBase × 10000 / (|size| × (10000 + mmBps)) ``` Dropping that factor errs conservative on a long and **optimistic on a short** — reporting the liquidation further away than it is, on the side whose loss is unbounded. At a 250 bps maintenance threshold it misplaces a short's liquidation by ~2.5% of the distance to it. **A single-market solve, deliberately.** Only this market's mark is varied; every other market's contribution stays at the value baked into `equity` and `mmReq`. So the answer is "the price at which THIS market's move alone trips maintenance", which is what a per-position liquidation price means under cross margin. A correlated move across several markets liquidates sooner, and nothing here claims otherwise. Also held constant: pending funding (already netted into `equity`), the mark's own EMA lag, and any fill landing between the read and the move. **Details** - Returns: The liquidation price in raw quote units per whole base, floored at 0 (a price cannot go negative) — or `null` when the position is flat, or when `mmBps` is exactly 10000 on a long, where price cancels out of the inequality entirely and no price triggers liquidation. That last case is unreachable on a real pool: `PerpPool._validatePerpPoolParameters` enforces `initialMarginBps ≤ 10000` and `maintenanceMarginBps < initialMarginBps`, so `mmBps < 10000` on every market. ## Parameters ### p [`PerpLiquidationPriceInputs`](../interfaces/PerpLiquidationPriceInputs.md) ## Returns `bigint` \| `null` --- # /docs/typescript/api/index/functions/perpMarkForPnl [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpMarkForPnl # Function: perpMarkForPnl() > **perpMarkForPnl**(`state`): `object` Defined in: packages/sdk/src/perp/state.ts:117 The price to mark a perp position at, and whether it came from the mark feed. Extracted and tested rather than written inline at the call site, because the inline version is a one-line regression waiting to happen. `getPerpState` reads the mark via `tryGetMarkPrice`, which REPORTS staleness rather than reverting on it — so the naive `markPrice - entryPrice` takes the meaningless 0 price word from a stale feed and produces a 100% loss on every open position. An earlier `getMarkPrice()` read reverted instead, which failed loudly; making the read more robust made the derived number silently worse until this guard. The index price is the fallback rather than "no value": it is a separate oracle the pool already trusts for funding, and dropping positions out of a portfolio view is its own kind of wrong. Callers that want a MARK READING (rather than something to mark against) should report undefined on staleness instead — see `fetchFundingRate`. ## Parameters ### state `Pick`\<[`PerpStateOnchain`](../interfaces/PerpStateOnchain.md), `"markPrice"` \| `"markPriceOk"` \| `"indexPrice"`\> ## Returns `object` ### price > **price**: `bigint` ### fromIndex > **fromIndex**: `boolean` --- # /docs/typescript/api/index/functions/perpOrderMarginQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpOrderMarginQuote # Function: perpOrderMarginQuote() > **perpOrderMarginQuote**(`p`): [`PerpOrderMarginQuote`](../interfaces/PerpOrderMarginQuote.md) Defined in: packages/sdk/src/perp/margin.ts:2042 The pool's placement arithmetic — pure, no client, no block. Split out of [SomniaMarketsClient.previewPerpOrderMargin](../interfaces/SomniaMarketsClient.md#previewperpordermargin) so the FORWARD question ("what does this order cost") and the INVERSE one (`client.getMaxPerpOrderSize`, "what is the largest order I can place") are answered by the same code rather than by two ports of the same contract. They cannot drift, which matters more here than usual: a max size computed by a second, subtly different rule reverts on placement, and the term such a rule most often drops is [PerpOrderMarginQuote.adverseGapPortion](../interfaces/PerpOrderMarginQuote.md#adversegapportion). **Auto-pull (T70) is modelled iff [PerpOrderMarginQuoteInputs.wallet](../interfaces/PerpOrderMarginQuoteInputs.md#wallet) is supplied**, and supplying it is a statement about the SENDER, not about the account: `PerpPool._autoPullMargin` fires only when `msg.sender == order.owner`. Given a wallet, the gates below describe the balance the pool will have topped up to before it locks; without one they describe the in-bank balance alone, which is what an operator- or registry-routed placement actually faces. The no-wallet path is arithmetically identical to the pre-T70 one. ## Parameters ### p [`PerpOrderMarginQuoteInputs`](../interfaces/PerpOrderMarginQuoteInputs.md) ## Returns [`PerpOrderMarginQuote`](../interfaces/PerpOrderMarginQuote.md) --- # /docs/typescript/api/index/functions/perpPositionAnalytics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpPositionAnalytics # Function: perpPositionAnalytics() > **perpPositionAnalytics**(`p`): [`PerpPositionMetrics`](../interfaces/PerpPositionMetrics.md) Defined in: packages/sdk/src/perp/margin.ts:911 Split one position into PnL, funding, notional and its three margin requirements — pure, no client, no block. A direct port of `MarginBank._computePositionMetrics` and `_marketHealthFromSnapshot`. Exported so a caller can re-run it against a live store, a hypothetical mark, or a position it is about to open, without a round-trip — and so a table and a detail view cannot disagree on identical inputs. ## Parameters ### p [`PerpPositionAnalyticsInputs`](../interfaces/PerpPositionAnalyticsInputs.md) ## Returns [`PerpPositionMetrics`](../interfaces/PerpPositionMetrics.md) --- # /docs/typescript/api/index/functions/pnlEventsFor [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / pnlEventsFor # Function: pnlEventsFor() > **pnlEventsFor**(`account`, `fills`, `routerActions`): [`PnLEvent`](../interfaces/PnLEvent.md)[] Defined in: packages/sdk/src/derivedReads.ts:403 Derive the [PnLEvent](../interfaces/PnLEvent.md) stream for `account` from raw [FillRow](../type-aliases/FillRow.md)s (order-book fills) + [RouterActionRecord](../type-aliases/RouterActionRecord.md)s (mint/merge complete sets), merged into ONE oldest-first timeline so the avg-cost roll sees mints and fills in the order they happened. ORDERED BY CHAIN POSITION, not by input order: block, then log index, compared as exact integers and read from each row's `id`. `timestamp` takes no part - it is metadata, and two events routinely share one second, so the order rows arrive in is NOT the order they happened (fills are fetched newest-first) and a buy and a sell in one second would otherwise fold sell-first and lose the realization to the clamp. Fills whose side isn't bridged yet are skipped (can't attribute an outcome). Mint/merge use the record's `amount` (each outcome's set size). Redeem actions are ignored (they settle the position at payout, they don't change cost basis of a still-open book). SCOPE IS THE CALLER'S JOB: no market filter is applied here, so pass ONE market's fills, selected by `FillRow.market` (never by `pool` — see there). **Errors** Throws [InvalidInputError](../classes/InvalidInputError.md) when a row carries a malformed number. Two cases: - an `id` that is not `` `${blockNumber}_${logIndex}` ``, so the row cannot be placed in chain order; - a `quantity`, `fillPrice` or mint/merge `amount` that is not a number. EVERY one of those must be an UNSIGNED DECIMAL run — `BigInt` alone would read `""`, a sign, or an `0x`/`0o`/`0b` prefix, silently sorting a row somewhere it does not belong or folding a quantity nobody wrote. `timestamp` is NOT read: it is metadata, and ordering on it would let a wrong one override the position it disagrees with. Rows from `getUserFills` and the router-action reads always satisfy this; a caller assembling its own rows must. Nothing is defaulted, because a defaulted value silently changes an average-cost roll and returns a wrong basis. ## Parameters ### account `string` ### fills [`FillRow`](../type-aliases/FillRow.md)[] ### routerActions [`RouterActionRecord`](../type-aliases/RouterActionRecord.md)[] ## Returns [`PnLEvent`](../interfaces/PnLEvent.md)[] --- # /docs/typescript/api/index/functions/portfolioKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / portfolioKey # Function: portfolioKey() > **portfolioKey**(`account`, `opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:121 Key for `client.getPortfolio(account, opts)`. ## Parameters ### account `string` \| `null` \| `undefined` ### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/positionMarkState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / positionMarkState # Function: positionMarkState() > **positionMarkState**(`input`): [`PositionMarkState`](../type-aliases/PositionMarkState.md) Defined in: packages/sdk/src/derivedReads.ts:1453 Classify how a position marks from its market's status/resolution: a resolved market pays its winning outcome, a voided one refunds, a still-trading one marks live, and anything expired-but-unresolved is settling (marking to a stale book there flashes phantom PnL). ## Parameters ### input #### status `string` BinaryMarketStatus string from the market row. #### voided `boolean` #### winningOutcome `number` \| `null` \| `undefined` Winning outcome index (0 = YES, 1 = NO), or null until resolved. #### outcomeIndex `number` #### expirySec `number` Market expiry (unix seconds). #### nowSec `number` Reference "now" (unix seconds). ## Returns [`PositionMarkState`](../type-aliases/PositionMarkState.md) --- # /docs/typescript/api/index/functions/preflightChain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightChain # Function: preflightChain() > **preflightChain**(`connectedChainId`, `expectedChainId`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:397 Validate the wallet is on the expected chain (a machinery write on the wrong chain either reverts or lands on the wrong deployment). A standalone gate the wizard runs before any step. ## Parameters ### connectedChainId `number` ### expectedChainId `number` ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightCreateQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightCreateQuote # Function: preflightCreateQuote() > **preflightCreateQuote**(`q`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:249 Validate a create-market call can proceed under §8e: the payer's balance covers the FULL create value `getSchedulingCost(def) + resolveReserve()` — the reserve is attached to the create and earmarked at onBind (excess is refunded in-tx). No separate prepaid-balance gate. ## Parameters ### q [`CreateQuotePreflightInput`](../interfaces/CreateQuotePreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightHub [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightHub # Function: preflightHub() > **preflightHub**(`h`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:191 Validate the OracleHub is live: approved on the module, its balance above the reactivity-bond floor, and its subscription armed (where the precompile exists). Protocol-admin view — an operator can't fix these, but a panel surfaces them so a dead hub isn't debugged at the create-market step. ## Parameters ### h [`HubPreflightInput`](../interfaces/HubPreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightMarketCreator [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightMarketCreator # Function: preflightMarketCreator() > **preflightMarketCreator**(`c`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:288 Validate a MarketCreator is funded enough to roll (a warning, not a hard blocker — a creator with a series but no balance still exists, it just can't roll until funded). For the exact per-roll amount, run [preflightCreateQuote](preflightCreateQuote.md) with the live hub quote. ## Parameters ### c [`MarketCreatorPreflightInput`](../interfaces/MarketCreatorPreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightOperator [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightOperator # Function: preflightOperator() > **preflightOperator**(`op`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:104 Validate that an operator is a sound base for machinery: the caller owns it, it is enabled, and it has a non-zero fee recipient. ## Parameters ### op [`OperatorPreflightInput`](../interfaces/OperatorPreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightRoll [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightRoll # Function: preflightRoll() > **preflightRoll**(`r`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:373 Validate the preconditions for `triggerRoll`: the series is registered, the chain has the precompile, and the creator holds native to pay the roll. ## Parameters ### r [`RollPreflightInput`](../interfaces/RollPreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightSeries # Function: preflightSeries() > **preflightSeries**(`s`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:329 Validate a series config matches the module's constraints: non-zero `seriesId`, non-empty `asset`, `intervalSec >= 60`, non-zero collateral. ## Parameters ### s [`SeriesPreflightInput`](../interfaces/SeriesPreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/preflightVenue [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / preflightVenue # Function: preflightVenue() > **preflightVenue**(`v`): [`PreflightResult`](../interfaces/PreflightResult.md) Defined in: packages/sdk/src/preflight.ts:146 Validate a venue is ready to host a market: the caller owns its operator, its creation flag is on, and its market type is bound to a module. ## Parameters ### v [`VenuePreflightInput`](../interfaces/VenuePreflightInput.md) ## Returns [`PreflightResult`](../interfaces/PreflightResult.md) --- # /docs/typescript/api/index/functions/priceToProbability [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / priceToProbability # Function: priceToProbability() > **priceToProbability**(`rawPrice`, `decimals?`): `number` Defined in: packages/sdk/src/units.ts:109 Raw YES price → YES probability in [0, 1]. Pass the binary market's `quoteDecimals`; the default is 6. ## Parameters ### rawPrice `string` \| `bigint` ### decimals? `number` = `Store.DECIMALS` ## Returns `number` --- # /docs/typescript/api/index/functions/probabilityToPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / probabilityToPrice # Function: probabilityToPrice() > **probabilityToPrice**(`probability`, `decimals?`): `bigint` Defined in: packages/sdk/src/units.ts:119 YES probability in [0, 1] → raw YES price (the `price` field of placeOrder). Pass the binary market's `quoteDecimals`; the default is 6. ## Parameters ### probability `number` ### decimals? `number` = `Store.DECIMALS` ## Returns `bigint` --- # /docs/typescript/api/index/functions/quoteBinaryOrderOverBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / quoteBinaryOrderOverBook # Function: quoteBinaryOrderOverBook() > **quoteBinaryOrderOverBook**(`book`, `side`, `quantity`, `oneCollateral`): [`BinaryOrderQuote`](../interfaces/BinaryOrderQuote.md) Defined in: packages/sdk/src/derivedReads.ts:105 Walk the live book crossing the opposite side for a market order of `quantity` on `side` — the pure kernel behind `client.quoteBinaryOrder`. `oneCollateral = 10^quoteDecimals` (full collateral = a share worth 1). ## Parameters ### book [`BinaryOrderBook`](../interfaces/BinaryOrderBook.md) ### side [`BinarySide`](../type-aliases/BinarySide.md) ### quantity `bigint` ### oneCollateral `bigint` ## Returns [`BinaryOrderQuote`](../interfaces/BinaryOrderQuote.md) --- # /docs/typescript/api/index/functions/quoteBinarySellOverBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / quoteBinarySellOverBook # Function: quoteBinarySellOverBook() > **quoteBinarySellOverBook**(`book`, `side`, `quantity`, `oneCollateral`, `params`): [`BinarySellQuote`](../interfaces/BinarySellQuote.md) \| `null` Defined in: packages/sdk/src/derivedReads.ts:1230 Build a market SELL that unwinds `quantity` of an outcome by crossing the resting bids, with a slippage cushion below the best bid — the sell-side sibling of [quoteBinaryStakeOverBook](quoteBinaryStakeOverBook.md). Pinning the protective limit to the exact best bid means any tick of book churn between the quote and on-chain execution leaves the IOC uncrossable — a sell into a busy book fills nothing. The limit instead sits a cushion below the best bid, aligned DOWN to the tick grid (never below one tick): the order still fills each resting bid at its own price, best-first. Unlike the buy side, `quantity` is NOT sized to the book — it's the caller's position, lot-aligned. The quote walks the crossable bids and reports `fillableQuantity`/`estProceeds` so a thin book surfaces as a partial unwind up front rather than a silent IOC cancel. Returns `null` when there's nothing to sell (including a position below the pool's `minQuantity`) or no bid to cross — disable the Sell control rather than sending a doomed order. **Details** - `book`: The live four-sided book (NO sides pre-inverted). - `side`: "SELL_YES" (Up position) or "SELL_NO" (Down position). - `quantity`: Outcome-token quantity to sell, raw units (snapped down to the lot grid). - `oneCollateral`: `10^quoteDecimals` — one whole outcome share. - `params`: The pool's tick/lot grid + slippage policy. ## Parameters ### book [`BinaryOrderBook`](../interfaces/BinaryOrderBook.md) ### side [`BinarySellSide`](../type-aliases/BinarySellSide.md) ### quantity `bigint` ### oneCollateral `bigint` ### params [`BinaryCrossingParams`](../interfaces/BinaryCrossingParams.md) ## Returns [`BinarySellQuote`](../interfaces/BinarySellQuote.md) \| `null` --- # /docs/typescript/api/index/functions/quoteBinaryStakeOverBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / quoteBinaryStakeOverBook # Function: quoteBinaryStakeOverBook() > **quoteBinaryStakeOverBook**(`book`, `side`, `stake`, `oneCollateral`, `params`): [`BinaryStakeQuote`](../interfaces/BinaryStakeQuote.md) \| `null` Defined in: packages/sdk/src/derivedReads.ts:1094 Convert a collateral stake into a market BUY by walking the live book — so the quoted shares and payout match what the order will actually fill, not an optimistic top-of-book estimate. The inverse of [quoteBinaryOrderOverBook](quoteBinaryOrderOverBook.md): that sizes cost from a quantity; this sizes quantity from a collateral budget. The sweep buys down the asks cheapest-first, accumulating shares while the escrow at the running protective price (the worst level touched) stays within the stake — the max loss never exceeds it. A pricier level lowers that ceiling, so the sweep naturally stops once the next level can't fit. The protective limit is then padded with a slippage cushion (so the IOC still crosses if the book ticks up before it lands), aligned UP to the tick grid, capped a tick below one collateral; the quantity is re-fit to the stake at the padded price and snapped DOWN to a whole lot, so the escrow can never exceed the stake. Returns `null` when nothing is fillable — empty book, a stake too small to buy a single lot (or the pool's `minQuantity`), or degenerate grid params (`tickSize`/`lotSize`/`oneCollateral`/`stake` ≤ 0). **Details** - `book`: The live four-sided book (NO sides pre-inverted). - `side`: "BUY_YES" (Up) or "BUY_NO" (Down). - `stake`: Collateral budget, raw units. - `oneCollateral`: `10^quoteDecimals` — one whole outcome share. - `params`: The pool's tick/lot grid + slippage policy. ## Parameters ### book [`BinaryOrderBook`](../interfaces/BinaryOrderBook.md) ### side [`BinaryBuySide`](../type-aliases/BinaryBuySide.md) ### stake `bigint` ### oneCollateral `bigint` ### params [`BinaryCrossingParams`](../interfaces/BinaryCrossingParams.md) ## Returns [`BinaryStakeQuote`](../interfaces/BinaryStakeQuote.md) \| `null` --- # /docs/typescript/api/index/functions/rayMul [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / rayMul # Function: rayMul() > **rayMul**(`a`, `b`): `bigint` Defined in: packages/sdk/src/lend/math.ts:20 Ray-multiply two ray fixed-point numbers, rounding half-up (Aave WadRayMath.rayMul). ## Parameters ### a `bigint` ### b `bigint` ## Returns `bigint` --- # /docs/typescript/api/index/functions/realizedFundingPerBase [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / realizedFundingPerBase # Function: realizedFundingPerBase() > **realizedFundingPerBase**(`cumulativeStart`, `cumulativeEnd`): `bigint` Defined in: packages/sdk/src/funding.ts:162 Realized funding over a range, in raw quote units per WHOLE base unit. Takes the two cumulative-index samples rather than a rate, because the cumulative index is the ground truth for accrual: the difference is exact over any range, with no interpolation, no zero-fill reasoning and no cap arithmetic. A rate-based estimate is not equivalent — it cannot see forgiven intervals or index-price movement. The result is in RAW quote units (atoms). To show it as a token amount, divide by `10 ** quoteDecimals` — and note the collateral is 18dp on the live deployment, so a human figure is `(end - start) / 1e18 / 1e18`. Treating the returned value as whole tokens overstates it by the quote scale. Signed: positive means longs paid shorts over the range. ## Parameters ### cumulativeStart `bigint` ### cumulativeEnd `bigint` ## Returns `bigint` --- # /docs/typescript/api/index/functions/resolveIntervalSec [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / resolveIntervalSec # Function: resolveIntervalSec() > **resolveIntervalSec**(`m`): `number` \| `null` Defined in: packages/sdk/src/interval.ts:46 Resolve a binary market's series cadence in SECONDS: prefer the indexer-derived `intervalSec`, else fall back to `expiry − tradingStart`. Returns `null` when neither yields a positive number (SPOT/PERP rows, or a market missing both signals). ## Parameters ### m [`IntervalSource`](../type-aliases/IntervalSource.md) ## Returns `number` \| `null` --- # /docs/typescript/api/index/functions/roundPriceToTick [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / roundPriceToTick # Function: roundPriceToTick() > **roundPriceToTick**(`price`, `tickSize`, `direction`): `bigint` Defined in: packages/sdk/src/units.ts:732 Snap a raw price onto the venue's `tickSize`, refusing to produce a price the pool rejects outright. [snapRawToGrid](snapRawToGrid.md) with the zero guard a price needs and a quantity must not have. **Details** The pool checks `price != 0` before it checks tick alignment, so a price under one tick that floors to `0` reverts `InvalidPrice` — and reverts it for a reason the caller did not choose. A positive price below one tick therefore comes back as one whole tick, the nearest price that exists on the grid. A non-positive price is a caller mistake rather than a rounding question, so it throws instead of being nudged onto the grid. `direction` belongs to the value: a resting limit rounds toward the caller, a crossing limit rounds away so it still sweeps. See [snapRawToGrid](snapRawToGrid.md). ## Parameters ### price `bigint` ### tickSize `bigint` ### direction [`RawGridDirection`](../type-aliases/RawGridDirection.md) ## Returns `bigint` ## Example **Align a resting buy limit that may sit below one tick** ```ts import { roundPriceToTick } from "@somnia-chain/markets-sdk"; const tickSize = 1_000_000_000_000_000n; // 1e15, an 18-decimal venue roundPriceToTick(2_500_000_000_000_000n, tickSize, "down"); // 2e15, floored roundPriceToTick(2_500_000_000_000_000n, tickSize, "up"); // 3e15, ceiled roundPriceToTick(400_000_000_000_000n, tickSize, "down"); // 1e15, never 0n ``` ## Throws when `tickSize` or `price` is not positive. --- # /docs/typescript/api/index/functions/sideOfKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / sideOfKind # Function: sideOfKind() > **sideOfKind**(`kind`): [`BinarySide`](../type-aliases/BinarySide.md) Defined in: packages/sdk/src/store.ts:551 Map an on-chain `OrderKind` index (from `BinaryOrderPlaced.kind`) to a [BinarySide](../type-aliases/BinarySide.md). Replaces the v1 `(isBid, userData)` decode — the pool now states the kind explicitly, so the SDK/indexer join the `BinaryOrderPlaced` event (by orderId) instead of inferring the side from userData. ## Parameters ### kind `number` \| `bigint` ## Returns [`BinarySide`](../type-aliases/BinarySide.md) --- # /docs/typescript/api/index/functions/slippageForCrossing [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / slippageForCrossing # Function: slippageForCrossing() > **slippageForCrossing**(`price`, `tickSize`, `opts?`): `bigint` Defined in: packages/sdk/src/derivedReads.ts:1005 Slippage cushion for a crossing `price` (raw, same units): the larger of the bps fraction and the fixed tick floor. A market IOC only crosses at or better than its protective limit, so pinning that limit to the exact crossing price means any tick of book churn between the quote and on-chain execution leaves it uncrossable — the order fills nothing. The cushion only widens how far the sweep will chase a moving book; fills still land at each resting level's own price. ## Parameters ### price `bigint` ### tickSize `bigint` ### opts? `Pick`\<[`BinaryCrossingParams`](../interfaces/BinaryCrossingParams.md), `"slippageBps"` \| `"slippageMinTicks"`\> ## Returns `bigint` --- # /docs/typescript/api/index/functions/snapIntervalSec [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / snapIntervalSec # Function: snapIntervalSec() > **snapIntervalSec**(`sec`, `toleranceSec?`): `number` Defined in: packages/sdk/src/interval.ts:70 Snap a raw cadence (seconds) to its nearest natural unit — minute (< 1h), hour (< 1d), else day — but ONLY when the raw value sits within `toleranceSec` of that unit, i.e. it is genuine off-by-a-second jitter (899 → 900, 3601 → 3600, 86399 → 86400). A value further than the tolerance from any unit is a real partial / non-standard window and is returned UNCHANGED, never bucketed up: `840 → 840` ("14m"), `870 → 870` ("14m30s" is not clean, so → "870s"), `5400 → 5400` ("90m"), `86100 → 86100` (23h55m, NOT "24h"). Because a series-registered market carries an EXACT on-chain `intervalSec`, the snap is a no-op on real cadences; the tolerance only matters on the `expiry − tradingStart` fallback path. Non-positive → 0. ## Parameters ### sec `number` ### toleranceSec? `number` = `2` ## Returns `number` --- # /docs/typescript/api/index/functions/snapRawToGrid [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / snapRawToGrid # Function: snapRawToGrid() > **snapRawToGrid**(`raw`, `step`, `direction`): `bigint` Defined in: packages/sdk/src/units.ts:684 Snap a raw on-chain value onto a raw-units grid — a venue's `tickSize` for a price, or its `lotSize` for a quantity. Both come from the pool's `getOrderBookParameters`. Returns the aligned raw value. **When to use** Reach for this on the engine path, where a caller holds `bigint` price and quantity and calls `Trader.placeOrder` directly. The unified facade snaps for you — `exchange.createOrder` aligns price and quantity before it signs — so a facade caller does not need this. The pool rejects anything off the grid: an off-tick price reverts `InvalidPrice`, an off-lot quantity reverts `InvalidQuantity`. **Details** `direction` belongs to the VALUE, not to the order side. Rounding the wrong way is a real loss rather than a formatting choice, and the side does not determine it: a RESTING buy limit rounds down to stay at or below the price the caller accepted, while a CROSSING buy limit rounds up so it still sweeps every level it was computed to reach. Both ship today, so a `side` parameter would silently invert one of them. Pass the direction you mean. **Gotchas** Rounding DOWN can return `0`, and for a PRICE that is the one value the pool always rejects (`InvalidPrice`). This helper does not hide that: a shared kernel that floored a price to one tick and a quantity to zero would be keying its behaviour on which of the two it was handed, which is exactly the guess this signature exists to avoid. Use [roundPriceToTick](roundPriceToTick.md) for a price, which refuses to produce `0`. For a quantity, `0` is the honest answer — the caller has no size left and must branch rather than submit dust. This aligns to the grid and nothing else. It does not check `minQuantity`, which the pool tests BEFORE lot alignment and reverts as `QuantityBelowMinimum`. On every venue this repository deploys `tickSize == lotSize == minQuantity`, so alignment satisfies the minimum there; on an external spot or perp book the two can differ, and a caller sizing against a minimum wants [ceilRawAmount](ceilRawAmount.md). ## Parameters ### raw `bigint` ### step `bigint` ### direction [`RawGridDirection`](../type-aliases/RawGridDirection.md) ## Returns `bigint` ## Example **Align a computed price and quantity before placing an order** ```ts const trader = client.createTrader({ privateKey }); // `tickSize` and `lotSize` are the pool's own increments. const { tickSize, lotSize } = await client.getBinaryBookParams(pool); // A crossing buy rounds the limit UP so it still sweeps every level. const price = snapRawToGrid(rawPrice, tickSize, "up"); // Size rounds DOWN so it never exceeds what the caller has. const quantity = snapRawToGrid(rawQuantity, lotSize, "down"); // A quantity that floors to nothing is a real answer — branch, don't submit. if (quantity > 0n) { await trader.placeOrder({ pool, side: "BUY_YES", price, quantity }); } ``` ## Throws when `step` is not positive. --- # /docs/typescript/api/index/functions/snapToCadence [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / snapToCadence # Function: snapToCadence() > **snapToCadence**(`sec`): `number` Defined in: packages/sdk/src/interval.ts:138 Snap a raw cadence (seconds) to the [CADENCE\_LADDER\_SEC](../variables/CADENCE_LADDER_SEC.md) rung it is within [CADENCE\_TOLERANCE\_SEC](../variables/CADENCE_TOLERANCE_SEC.md) of — `898 → 900`, `59 → 60`, `3599 → 3600` — so scheduling jitter groups and filters as the cadence it is. A window that matches no rung falls through to [snapIntervalSec](snapIntervalSec.md), which keeps a genuinely different window out of a cadence it isn't (`3163 → 3163`, `1437 → 1437`) but still applies its own ±2s unit snap, so an off-ladder cadence lands on a clean unit rather than on itself: `598 → 600` ("10m"). Non-positive → 0. ## Parameters ### sec `number` ## Returns `number` --- # /docs/typescript/api/index/functions/syncStatusKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / syncStatusKey # Function: syncStatusKey() > **syncStatusKey**(`chainId`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:361 Key for `client.getSyncStatus(chainId)`. The read itself names its chain, so the chain is already the key's last element and this factory takes no trailing `{ chainId }`. ## Parameters ### chainId `number` ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/toHuman [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / toHuman # Function: toHuman() > **toHuman**(`raw`, `decimals?`): `number` Defined in: packages/sdk/src/units.ts:24 Raw integer (string or bigint) → human number for DISPLAY ONLY. Lossy past ~15 significant digits (it's an IEEE double) — never round-trip money through this; use it for labels/charts. `decimals` defaults to 6, which is only correct for a six-decimal token. Pass the selected market's `quoteDecimals` for binary collateral/prices or `baseDecimals` for base quantities. ## Parameters ### raw `string` \| `bigint` ### decimals? `number` = `Store.DECIMALS` ## Returns `number` --- # /docs/typescript/api/index/functions/toHumanString [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / toHumanString # Function: toHumanString() > **toHumanString**(`raw`, `decimals?`): `string` Defined in: packages/sdk/src/units.ts:34 Raw integer → exact human STRING (no precision loss). For display where you want the full value, or to feed another decimal library. ## Parameters ### raw `string` \| `bigint` ### decimals? `number` = `Store.DECIMALS` ## Returns `string` --- # /docs/typescript/api/index/functions/tradeContextKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / tradeContextKey # Function: tradeContextKey() > **tradeContextKey**(`id`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:206 Key for `client.getTradeContext(id)`. A fill id is `${blockNumber}_${logIndex}` — already unique and already lower-case, so it is used verbatim rather than case-folded like an address. It is unique on one chain only, so a multi-chain app passes the chain. ## Parameters ### id `string` \| `null` \| `undefined` ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/transactionActivityKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / transactionActivityKey # Function: transactionActivityKey() > **transactionActivityKey**(`txHash`, `opts?`, `chain?`): [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) Defined in: packages/sdk/src/queryKeys.ts:218 Key for `client.getTransactionActivity(txHash, opts)`. The hash is case-folded: a caller that pastes a checksummed hash and one that pastes it lower-cased are asking the same question. ## Parameters ### txHash `string` \| `null` \| `undefined` ### opts? [`TransactionActivityOptions`](../type-aliases/TransactionActivityOptions.md) ### chain? [`QueryKeyChainOptions`](../interfaces/QueryKeyChainOptions.md) ## Returns [`ClientQueryKey`](../type-aliases/ClientQueryKey.md) --- # /docs/typescript/api/index/functions/upPercent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / upPercent # Function: upPercent() > **upPercent**(`rawYes`, `decimals`): `number` \| `null` Defined in: packages/sdk/src/units.ts:759 The Up probability as a whole-percent integer (e.g. `0.546` → `55`). ## Parameters ### rawYes `string` \| `bigint` \| `null` \| `undefined` ### decimals `number` \| `undefined` ## Returns `number` \| `null` --- # /docs/typescript/api/index/functions/upProbability [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / upProbability # Function: upProbability() > **upProbability**(`rawYes`, `decimals`): `number` \| `null` Defined in: packages/sdk/src/units.ts:748 Market-implied **Up** probability in [0, 1] from a raw YES price, or `null` when the price is missing/unusable. One source for header stats and trade rails so they always agree — pass the book mid, falling back to last price. ## Parameters ### rawYes `string` \| `bigint` \| `null` \| `undefined` ### decimals `number` \| `undefined` ## Returns `number` \| `null` --- # /docs/typescript/api/index/interfaces/AcceptOperatorOwnershipParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AcceptOperatorOwnershipParams # Interface: AcceptOperatorOwnershipParams Defined in: packages/sdk/src/operatorAdmin.ts:174 Params for [OperatorAdmin.acceptOperatorOwnership](OperatorAdmin.md#acceptoperatorownership). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:176 The operator with a pending transfer staged to the caller. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:178 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/AcceptPerpWalletLinkParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AcceptPerpWalletLinkParams # Interface: AcceptPerpWalletLinkParams Defined in: packages/sdk/src/trade.ts:1105 Inputs to [Trader.acceptPerpWalletLink](Trader.md#acceptperpwalletlink) — accept a main's standing offer. The signer is the CHILD. From here the child's position-increasing orders can draw on `main`'s wallet. ## Extends - [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md) ## Properties ### registry? > `optional` **registry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1070 The LinkedWalletRegistry. Skips resolution entirely. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`registry`](PerpWalletLinkTarget.md#registry) *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1072 MarginBank address — its `getLinkedWalletRegistry()` is read (never cached). #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`marginBank`](PerpWalletLinkTarget.md#marginbank) *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1074 A PerpPool — its `marginBank()` is read (and cached), then the registry. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`pool`](PerpWalletLinkTarget.md#pool) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1080 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`gas`](PerpWalletLinkTarget.md#gas) *** ### main > **main**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1107 The main whose offer to accept. It must have an offer standing for the signer. --- # /docs/typescript/api/index/interfaces/AccountHealth [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AccountHealth # Interface: AccountHealth Defined in: packages/sdk/src/perp/margin.ts:107 An account's cross-margin health, standalone (equity vs the IM/MM/CM requirements + the derived status). A lighter read than [SomniaMarketsClient.getMarginAccount](SomniaMarketsClient.md#getmarginaccount) when only health matters. ## Properties ### equity > **equity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:109 Account equity = unlockedCollateralBalance + Σ(uPnl) − Σ(fundingOwed) (signed). *** ### imReq > **imReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:114 Initial-margin requirement: Σ notional × initialMarginBps / 10000 across all markets (raw collateral units). *** ### mmReq > **mmReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:116 Maintenance-margin requirement (same basis, maintenanceMarginBps; raw). *** ### cmReq > **cmReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:118 Close-out-margin requirement (same basis, closeOutMarginBps; raw). *** ### marginStatus > **marginStatus**: [`MarginStatus`](../type-aliases/MarginStatus.md) Defined in: packages/sdk/src/perp/margin.ts:120 Health bucket derived from equity vs the requirements (see [MarginStatus](../type-aliases/MarginStatus.md)). --- # /docs/typescript/api/index/interfaces/AdoptFromParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AdoptFromParams # Interface: AdoptFromParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:227 Params for [MarketCreatorAdmin.adoptFrom](MarketCreatorAdmin.md#adoptfrom). ## Properties ### successor > **successor**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:232 The INCOMING (v2) creator that adopts. Caller must be its owner; it must share `old`'s operator/venue/owner and have its reactivity gas params set. *** ### old > **old**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:234 The quiesced predecessor whose series + pending qid routing are inherited. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:236 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/AmendOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AmendOrderParams # Interface: AmendOrderParams Defined in: packages/sdk/src/trade.ts:964 Inputs to [Trader.amendOrder](Trader.md#amendorder) — cancel ONE resting order and place its replacement atomically, with no gap on the book. **Gotchas** — the replacement loses queue priority (it re-enters at the back of the price-time queue for its price); use [Trader.reduceOrder](Trader.md#reduceorder) to shrink an order in place instead. The call is NON-PAYABLE: the cancel leg delivers the old order's freed native to the WALLET, which the non-payable place leg cannot reach, so a native auto-pull amend reverts — fund native replacements from a manual-vault balance. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:966 SpotPool or PerpPool address. NOT a BinaryPool — see [Trader.amendOrder](Trader.md#amendorder). *** ### oldOrderId > **oldOrderId**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:968 The resting order being replaced (decimal string or bigint). *** ### alwaysPlace? > `optional` **alwaysPlace?**: `boolean` Defined in: packages/sdk/src/trade.ts:975 How to handle an `oldOrderId` already filled/cancelled when the tx lands. False (default) reverts `AmendOldOrderGone`; true skips the cancel leg and places the replacement anyway (opt-in upsert). It never tolerates an ownership failure — someone else's live order still reverts `IncorrectSender`. *** ### newOrder > **newOrder**: [`BatchOrderRequest`](BatchOrderRequest.md) Defined in: packages/sdk/src/trade.ts:977 The replacement order. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:983 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/AmendOrderResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AmendOrderResult # Interface: AmendOrderResult Defined in: packages/sdk/src/trade.ts:991 Result of a single amend — the id of the replacement order. ## Extends - [`TxResult`](TxResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### newOrderId > **newOrderId**: `bigint` Defined in: packages/sdk/src/trade.ts:1002 The replacement's NEW order id — update local tracking, the old id is gone. Reconstructed from the `OrderPlaced` log, since the pool's `uint128` return is not readable from a receipt. `0n` means the id could not be reconstructed (no `OrderPlaced` in the receipt). It does NOT mean the replacement failed: a single amend reverts outright when its replacement does not rest or fill, so a successful tx always carries one. *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/trade.ts:1004 Fills executed by the replacement order. --- # /docs/typescript/api/index/interfaces/AmendOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AmendOrdersParams # Interface: AmendOrdersParams Defined in: packages/sdk/src/trade.ts:903 Inputs to [Trader.amendOrders](Trader.md#amendorders) — cancel N orders and place their replacements atomically. The replacement loses queue priority; use `reduceOrder` to shrink one in place without re-queueing. **Gotchas** — ALL-OR-NOTHING: the first replacement the book will not honour reverts everything with `AmendReplacementRejected(requestIndex, reason)`. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:905 SpotPool or PerpPool address. NOT a BinaryPool. *** ### amendments > **amendments**: `object`[] Defined in: packages/sdk/src/trade.ts:907 The amendments to apply, in array order. Must be non-empty. #### oldOrderId > **oldOrderId**: `string` \| `bigint` The resting order being replaced (decimal string or bigint). #### alwaysPlace? > `optional` **alwaysPlace?**: `boolean` How to handle an `oldOrderId` already filled/cancelled when the tx lands. False (default) reverts `AmendOldOrderGone`; true skips the cancel leg and places the replacement anyway (opt-in upsert). It never tolerates an ownership failure — someone else's live order still reverts. #### newOrder > **newOrder**: [`BatchOrderRequest`](BatchOrderRequest.md) The replacement order. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:925 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/AmendOrdersResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AmendOrdersResult # Interface: AmendOrdersResult Defined in: packages/sdk/src/trade.ts:933 Result of a batch amend — the ids of the replacement orders. ## Extends - [`TxResult`](TxResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### newOrderIds > **newOrderIds**: `bigint`[] Defined in: packages/sdk/src/trade.ts:946 New order ids, index-aligned with the submitted `amendments`. Reconstructed from `OrderPlaced` logs, since the pool's `uint128[]` return is not readable from a receipt. `0n` means the id could not be reconstructed — the receipt carried fewer `OrderPlaced` events than there were amendments. It does **not** mean the replacement failed to rest: `OrderPlaced` fires for every accepted order, including one that fills completely and never reaches the book (`OrderRested` is the rest-only event). Amend is all-or-nothing, so in a successful tx every slot is populated. *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/trade.ts:948 Fills executed by the replacement orders. --- # /docs/typescript/api/index/interfaces/ApproveBuilderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ApproveBuilderParams # Interface: ApproveBuilderParams Defined in: packages/sdk/src/trade.ts:297 Opt a routing/builder frontend in to charge up to `maxFeeBpsTimes1k` (pool bps×1000 unit) per order the trader submits with that builder code. Set 0 to revoke. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:299 Pool address (binary, spot, or perp). The approval is per-pool. *** ### builder > **builder**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:301 Builder/routing frontend address. *** ### maxFeeBpsTimes1k > **maxFeeBpsTimes1k**: `bigint` Defined in: packages/sdk/src/trade.ts:303 Max per-order builder fee to allow (pool bps×1000). 0 revokes. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:309 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ArmFirstRollParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ArmFirstRollParams # Interface: ArmFirstRollParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:192 Params for [MarketCreatorAdmin.armFirstRoll](MarketCreatorAdmin.md#armfirstroll). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:194 The MarketCreator owning the series. Caller must be its owner. *** ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:199 The series whose first roll is armed; refuses re-arming or an already-rolled series. *** ### firesAtSec > **firesAtSec**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:205 Future, interval-aligned Unix-seconds boundary to arm the series' first roll at (typically the outgoing creator's current-market expiry for a seamless migration). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:207 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/AutoPullRequirement [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AutoPullRequirement # Interface: AutoPullRequirement Defined in: packages/sdk/src/spot/poolReads.ts:43 What a pool would consume for an order — see [SomniaMarketsClient.getAutoPullRequirement](SomniaMarketsClient.md#getautopullrequirement). ## Properties ### inputToken > **inputToken**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:45 Token the pool would take: quote on a buy, base on a sell. *** ### requiredAmount > **requiredAmount**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:47 WORST-CASE amount of `inputToken` the order could consume. *** ### delta > **delta**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:52 `requiredAmount` minus the owner's current vault balance of `inputToken`, or 0 when the vault already covers it. --- # /docs/typescript/api/index/interfaces/BalanceQuery [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BalanceQuery # Interface: BalanceQuery Defined in: packages/sdk/src/balances.ts:88 A token to read a balance for in a `getBalances` batch. Omit `id` for a plain ERC-20 (`balanceOf(account)`); provide `id` to read an ERC-6909 outcome position (`balanceOf(account, id)`) on the outcome-token singleton `token`. ## Properties ### token > **token**: `` `0x${string}` `` Defined in: packages/sdk/src/balances.ts:90 ERC-20 token, or the ERC-6909 outcome-token singleton when `id` is set. *** ### id? > `optional` **id?**: `bigint` Defined in: packages/sdk/src/balances.ts:92 ERC-6909 position id (`yesId`/`noId`). Absent → read `token` as a plain ERC-20. --- # /docs/typescript/api/index/interfaces/BatchCancelOutcome [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BatchCancelOutcome # Interface: BatchCancelOutcome Defined in: packages/sdk/src/trade.ts:678 One id's outcome in a [Trader.cancelOrders](Trader.md#cancelorders) batch. ## Properties ### orderId > **orderId**: `bigint` Defined in: packages/sdk/src/trade.ts:680 The order id this entry reports on. *** ### cancelled > **cancelled**: `boolean` Defined in: packages/sdk/src/trade.ts:687 True when this id was cancelled in this transaction. False means the contract SKIPPED it — already filled, already cancelled, expired-and-swept, or not owned by the signer. A skip is inferred from the absence of an event, so it does NOT distinguish a benign race from a caller-side mistake. --- # /docs/typescript/api/index/interfaces/BatchOrderRequest [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BatchOrderRequest # Interface: BatchOrderRequest Defined in: packages/sdk/src/trade.ts:872 The replacement order in an amendment. Mirrors the pool's `PlaceOrderRequest` struct; the owner is the amend caller, not a per-request field. ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:874 True = buy/bid, false = sell/ask. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:876 Limit price, raw quote units per whole base. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:878 Base quantity, raw base units. *** ### expireTimestampNs? > `optional` **expireTimestampNs?**: `bigint` Defined in: packages/sdk/src/trade.ts:880 Order expiry in ns. Defaults to ~50y (GTC). *** ### orderType? > `optional` **orderType?**: `number` Defined in: packages/sdk/src/trade.ts:882 0 limit (default), 1 FillOrKill, 2 market/IOC, 3 PostOnly. See [ORDER\_TYPE](../variables/ORDER_TYPE.md). *** ### selfMatchingOption? > `optional` **selfMatchingOption?**: `number` Defined in: packages/sdk/src/trade.ts:884 Self-match behaviour, default 0. See [SELF\_MATCHING\_OPTION](../variables/SELF_MATCHING_OPTION.md). *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:886 Routing/builder address to attribute this order to; omit for none. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:888 Per-order builder fee in the pool's bps×1000 unit. 0 = none. *** ### userData? > `optional` **userData?**: `bigint` Defined in: packages/sdk/src/trade.ts:890 Opaque market-maker bookkeeping tag, forwarded verbatim. Default 0. --- # /docs/typescript/api/index/interfaces/BatchPlaceOutcome [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BatchPlaceOutcome # Interface: BatchPlaceOutcome Defined in: packages/sdk/src/trade.ts:627 One request's outcome in a [Trader.placeSpotOrders](Trader.md#placespotorders) batch. ## Properties ### success > **success**: `boolean` Defined in: packages/sdk/src/trade.ts:633 True when this request produced an order. False for a benign non-placement — a PostOnly that would have crossed, an unfilled FillOrKill, an IOC that found no liquidity, an already-expired expiry, or a CancelTaker self-match. *** ### orderId? > `optional` **orderId?**: `bigint` Defined in: packages/sdk/src/trade.ts:635 The resting order's id, or `undefined` when `success` is false. --- # /docs/typescript/api/index/interfaces/BinaryBookParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryBookParams # Interface: BinaryBookParams Defined in: packages/sdk/src/orders.ts:718 A binary pool's order-book increments, as the pool reports them. ## Properties ### tickSize > **tickSize**: `bigint` Defined in: packages/sdk/src/orders.ts:720 Price increment, raw collateral units per whole outcome token. *** ### minQuantity > **minQuantity**: `bigint` Defined in: packages/sdk/src/orders.ts:722 Minimum order quantity, raw outcome-token units. *** ### lotSize > **lotSize**: `bigint` Defined in: packages/sdk/src/orders.ts:724 Quantity increment, raw outcome-token units. --- # /docs/typescript/api/index/interfaces/BinaryCrossingParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryCrossingParams # Interface: BinaryCrossingParams Defined in: packages/sdk/src/derivedReads.ts:970 The price/quantity grid a BinaryPool enforces on orders, plus the slippage policy the stake/sell builders pad their protective limit with. `tickSize` and `lotSize` come from the pool's on-chain order-book parameters (`client.getBinaryBookParams`) — the pool rejects any price off the tick grid and any quantity off the lot grid (`InvalidQuantity`). ## Properties ### tickSize > **tickSize**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:972 Price increment (raw collateral units) — limits must be a multiple. *** ### lotSize > **lotSize**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:974 Quantity increment (raw outcome-token units) — sizes must be a multiple. *** ### minQuantity? > `optional` **minQuantity?**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:981 Smallest order size the pool accepts (raw outcome-token units) — a lot multiple that may exceed a single lot; the pool rejects anything smaller (`QuantityBelowMinimum`). Quotes that land below it return `null`. #### Default `0n` (no floor beyond the lot grid) *** ### slippageBps? > `optional` **slippageBps?**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:986 Slippage cushion in bps of the crossing price. #### Default [DEFAULT\_SLIPPAGE\_BPS](../variables/DEFAULT_SLIPPAGE_BPS.md) (300 = 3%) *** ### slippageMinTicks? > `optional` **slippageMinTicks?**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:991 Minimum slippage cushion in ticks. #### Default [DEFAULT\_SLIPPAGE\_MIN\_TICKS](../variables/DEFAULT_SLIPPAGE_MIN_TICKS.md) (10) --- # /docs/typescript/api/index/interfaces/BinaryOrderBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryOrderBook # Interface: BinaryOrderBook Defined in: packages/sdk/src/orders.ts:682 Both books for a market, 4-sided. NO levels are the YES book inverted into NO terms (price = 1 − yesPrice), matching BinaryPool's pricing. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:684 Pinned chain block or scope applied-event watermark; absent without provenance. *** ### yesBids > **yesBids**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:689 Resting YES bids, best (highest price) first — raw collateral units per whole outcome token. *** ### yesAsks > **yesAsks**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:691 Resting YES asks, best (lowest price) first. *** ### noBids > **noBids**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:693 NO bids derived from the YES asks (price = 1 − yesPrice), best (highest) first. *** ### noAsks > **noAsks**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:695 NO asks derived from the YES bids (price = 1 − yesPrice), best (lowest) first. --- # /docs/typescript/api/index/interfaces/BinaryOrderQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryOrderQuote # Interface: BinaryOrderQuote Defined in: packages/sdk/src/derivedReads.ts:34 The result of quoting a market order against the live book — the "you'll pay ~$X, average Y, slippage Z" preview. All prices/amounts are RAW units in the OUTCOME's own terms (a BUY_NO quote is priced in NO terms). ## Properties ### avgPrice > **avgPrice**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:39 Volume-weighted average fill price (raw units per whole outcome token), in the quoted outcome's terms. `0n` if nothing fills. *** ### cost > **cost**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:44 Total cost for a BUY (raw collateral paid) / total proceeds for a SELL (raw collateral received) = Σ(levelQty × levelPrice) / oneCollateral. *** ### filledQuantity > **filledQuantity**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:49 How much of `quantity` actually crosses the resting book (raw outcome units). Less than `quantity` when the book is too thin to fill it all. *** ### wouldRest > **wouldRest**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:54 The unfilled remainder that would rest as a maker order (raw outcome units) — `quantity − filledQuantity`. *** ### levelsConsumed > **levelsConsumed**: `number` Defined in: packages/sdk/src/derivedReads.ts:56 Number of price levels the order consumed (partially or fully). *** ### slippageVsMid > **slippageVsMid**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:62 Signed slippage of `avgPrice` vs the book mid, in raw price units (avgPrice − mid for a buy; mid − avgPrice for a sell — positive = worse than mid). `0n` if the book has no mid (a side is empty) or nothing fills. --- # /docs/typescript/api/index/interfaces/BinaryOutcomePnl [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryOutcomePnl # Interface: BinaryOutcomePnl Defined in: packages/sdk/src/units.ts:249 One outcome leg's slice of a [BinaryPnl](BinaryPnl.md). HUMAN numbers (quote/collateral units) throughout — display-grade, like [toHuman](../functions/toHuman.md). ## Properties ### realized > **realized**: `number` Defined in: packages/sdk/src/units.ts:251 Realized on this outcome's sells: proceeds − avg cost of the tokens sold. *** ### unrealized > **unrealized**: `number` \| `null` Defined in: packages/sdk/src/units.ts:253 The remaining balance marked to `mark`, minus its avg cost. `null` when [mark](#mark) is unknown. *** ### avgCost > **avgCost**: `number` Defined in: packages/sdk/src/units.ts:255 Average cost per token of the fills-derived holding; 0 when none held. *** ### mark > **mark**: `number` \| `null` Defined in: packages/sdk/src/units.ts:269 The price this leg is valued at: the book-clamped last while trading (see [markYesPrice](../functions/markYesPrice.md); the NO leg at its complement), or the settlement payout once resolved — 1 for the winning outcome, 0 for the loser, and on a void this leg's share of the market's stored payout vector (a half under the `UNIFORM` void policy, `[p, D−p]` on a captured `CLOB_SNAPSHOT` void). `null` when the market has NO price to value against — it has never traded and no book top was supplied. Do not read that as `0`: a zero YES mark is also a full-value NO mark, which reports a fabricated total loss on one leg and a fabricated total gain on the other. [value](#value) and [unrealized](#unrealized) are `null` with it. *** ### value > **value**: `number` \| `null` Defined in: packages/sdk/src/units.ts:271 Mark value of the current balance: `balance × mark`. `null` when [mark](#mark) is unknown. --- # /docs/typescript/api/index/interfaces/BinaryOutcomePositionPnL [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryOutcomePositionPnL # Interface: BinaryOutcomePositionPnL Defined in: packages/sdk/src/derivedReads.ts:249 One outcome's half of a binary position, RAW units — the YES or NO book on its own, as the fold already computes it before summing into the market totals. **Why this exists.** Every money field on [BinaryPositionPnL](BinaryPositionPnL.md) is blended across both outcomes, which is unusable for a wallet holding BOTH. Buy 10 YES at `0.20` and 10 NO at `0.80`, mark YES at `0.40`: the legs are `+2.00` and `-2.00` and the blended `unrealizedPnl` is `0.00`. Neither position row can show that zero as its own PnL. Legs are only reachable through a position row, so the key that names one (`yes` / `no`) is also the only label it needs. Legs sum EXACTLY to the totals — `costBasis`, `markValue`, `unrealizedPnl` and `realizedPnl` are stored here first and added up, so integer division cannot make a leg disagree with the total it belongs to. `avgCost` and `markPrice` are per-token rates and do NOT sum. ## Properties ### balance > **balance**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:251 This outcome's current token balance (raw). *** ### costBasis > **costBasis**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:253 Remaining cost basis of THIS leg's balance (raw collateral). *** ### avgCost > **avgCost**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:271 Average cost per whole token of this outcome (raw collateral per token), for DISPLAY. `0n` when the leg holds nothing. A rate, not an amount: does not sum across legs. It is rounded independently of [BinaryOutcomePositionPnL.costBasis](#costbasis), and the two do NOT reconstruct each other. `costBasis` comes straight off the aggregate book (`balance * cost / quantity`); this rate floors that same book to one whole token, and each floor loses a different remainder. They can even disagree in kind: on a zero-decimal collateral a leg of 5 tokens costing 2 has a `costBasis` of `2` and an `avgCost` of `0`, because a per-token rate under one raw unit has nowhere to go. So value a position with `costBasis`, and show `avgCost`. Deriving either from the other returns a different number in ~2999 of 3000 awkward-quantity cases, which is why both are published. *** ### markPrice > **markPrice**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:285 The price this leg is marked at (raw collateral per whole token): the book-clamped last price while trading, or the settlement payout once resolved. A rate: does not sum, but while trading the two legs' prices add up to one whole collateral unit. `null` when the market has NO price to mark against — it has never traded and no book top was supplied, so [markYesPrice](../functions/markYesPrice.md) returns `null`. Do not read that as `0n`: a zero YES mark is also a FULL-collateral NO mark, which reports a fabricated total loss on one leg and a fabricated total gain on the other. [markValue](#markvalue) and [unrealizedPnl](#unrealizedpnl) are `null` with it, because both are derived from this price. *** ### markValue > **markValue**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:287 Mark value of this leg's balance (raw collateral); `null` when [markPrice](#markprice) is unknown. *** ### unrealizedPnl > **unrealizedPnl**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:289 This leg's `markValue - costBasis` (raw, signed); `null` when [markPrice](#markprice) is unknown. *** ### realizedPnl > **realizedPnl**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:291 Realized PnL from this outcome's sells (raw, signed). --- # /docs/typescript/api/index/interfaces/BinaryPnl [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryPnl # Interface: BinaryPnl Defined in: packages/sdk/src/units.ts:282 Realized + unrealized PnL for one account in one binary market, computed purely from its fills + current outcome balances + the market row. Returns HUMAN numbers (quote/collateral units), keyed per outcome (YES/NO) plus a combined total — display-grade, like [toHuman](../functions/toHuman.md). ## Properties ### yes > **yes**: [`BinaryOutcomePnl`](BinaryOutcomePnl.md) Defined in: packages/sdk/src/units.ts:284 PnL attributable to the YES outcome (human quote units). *** ### no > **no**: [`BinaryOutcomePnl`](BinaryOutcomePnl.md) Defined in: packages/sdk/src/units.ts:286 PnL attributable to the NO outcome (human quote units). *** ### realized > **realized**: `number` Defined in: packages/sdk/src/units.ts:288 yes.realized + no.realized. *** ### unrealized > **unrealized**: `number` \| `null` Defined in: packages/sdk/src/units.ts:290 yes.unrealized + no.unrealized; `null` when the market has no price to mark against. *** ### total > **total**: `number` \| `null` Defined in: packages/sdk/src/units.ts:292 realized + unrealized; `null` when the market has no price to mark against. --- # /docs/typescript/api/index/interfaces/BinaryPnlFill [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryPnlFill # Interface: BinaryPnlFill Defined in: packages/sdk/src/units.ts:301 One account-perspective fill for [computeBinaryPnl](../functions/computeBinaryPnl.md): which outcome, how many tokens, at what raw YES-terms price, and whether the account BOUGHT. ## Properties ### outcomeIndex > **outcomeIndex**: `number` Defined in: packages/sdk/src/units.ts:303 0 = YES, 1 = NO. *** ### isBuy > **isBuy**: `boolean` Defined in: packages/sdk/src/units.ts:305 True = the account bought (added) this outcome; false = sold (reduced). *** ### quantity > **quantity**: `string` \| `bigint` Defined in: packages/sdk/src/units.ts:307 Fill quantity, raw outcome-token units (decimal string or bigint). *** ### price > **price**: `string` \| `bigint` Defined in: packages/sdk/src/units.ts:309 Fill price for the fill's own outcome, raw quote units (0..10^decimals). --- # /docs/typescript/api/index/interfaces/BinaryPositionPnL [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryPositionPnL # Interface: BinaryPositionPnL Defined in: packages/sdk/src/derivedReads.ts:307 An account's position + cost basis + PnL in one binary market, RAW units. ACCOUNTING ASSUMPTION: weighted-average cost. Cost basis is reconstructed from the account's order-book fills on the market (buys add cost at the fill's outcome price; sells realize against the running average) folded with mint/merge router actions (a complete-set mint adds one YES + one NO at the split cost `oneCollateral` total; a merge removes a pair at avg cost). `markValue`/`unrealizedPnl` mark the CURRENT balances to the book-clamped last price while trading (see [markYesPrice](../functions/markYesPrice.md)), or to the settlement payout once resolved. ## Properties ### balanceYes > **balanceYes**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:309 Current YES outcome-token balance (raw). *** ### balanceNo > **balanceNo**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:311 Current NO outcome-token balance (raw). *** ### costBasis > **costBasis**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:313 Total remaining cost basis across both outcomes (raw collateral). *** ### avgCost > **avgCost**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:318 Blended average cost per whole outcome token held (raw collateral per token). `0n` when nothing is held. *** ### markValue > **markValue**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:324 Mark value of the current balances (raw collateral). `null` when the market has no price to mark against — see [BinaryOutcomePositionPnL.markPrice](BinaryOutcomePositionPnL.md#markprice). *** ### unrealizedPnl > **unrealizedPnl**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:329 markValue − costBasis (raw, signed). `null` when the market has no price to mark against — see [BinaryOutcomePositionPnL.markPrice](BinaryOutcomePositionPnL.md#markprice). *** ### realizedPnl > **realizedPnl**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:334 Realized PnL from sells (proceeds − avg cost of tokens sold), raw signed. Best-effort over indexed order-book sell fills (see accounting note). *** ### outcomes > **outcomes**: `object` Defined in: packages/sdk/src/derivedReads.ts:344 The same position split into its YES and NO books — see [BinaryOutcomePositionPnL](BinaryOutcomePositionPnL.md) for why every field above is unusable to a wallet holding both outcomes. Always present, both legs, even when one holds nothing (a zero-balance leg can still carry `realizedPnl` from earlier sells). Filter on `balance > 0n` to list only open legs. #### yes > **yes**: [`BinaryOutcomePositionPnL`](BinaryOutcomePositionPnL.md) #### no > **no**: [`BinaryOutcomePositionPnL`](BinaryOutcomePositionPnL.md) --- # /docs/typescript/api/index/interfaces/BinarySellQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinarySellQuote # Interface: BinarySellQuote Defined in: packages/sdk/src/derivedReads.ts:1173 A market SELL that unwinds an outcome position, shaped to feed straight into `trader.placeOrder({ pool, side, price: yesPrice, quantity, orderType: ORDER_TYPE.MARKET })`. All values RAW units. See [quoteBinaryStakeOverBook](../functions/quoteBinaryStakeOverBook.md) for the family's full mental model. ## Properties ### side > **side**: [`BinarySellSide`](../type-aliases/BinarySellSide.md) Defined in: packages/sdk/src/derivedReads.ts:1175 The sell side quoted ("SELL_YES" | "SELL_NO"). *** ### yesPrice > **yesPrice**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1177 Protective floor in YES terms (raw, tick-aligned) — what `placeOrder` takes. *** ### limitPrice > **limitPrice**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1182 The same protective floor in the sold outcome's OWN terms (raw) — the cushioned best bid. Display this. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1184 Outcome-token quantity to sell (raw, lot-aligned) — the size submitted. *** ### fillableQuantity > **fillableQuantity**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1191 How much of `quantity` the resting bids at or above the floor can absorb (raw, ≤ `quantity`). The IOC cancels the rest unfilled — when this is short of `quantity`, show the user a partial-unwind warning instead of implying the whole position exits. *** ### estProceeds > **estProceeds**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1197 Collateral proceeds if `fillableQuantity` fills at the resting bids' own prices (raw, rounded down) — an estimate: bids can churn between the quote and execution. --- # /docs/typescript/api/index/interfaces/BinaryStakeQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryStakeQuote # Interface: BinaryStakeQuote Defined in: packages/sdk/src/derivedReads.ts:1038 A stake-sized market BUY, shaped to feed straight into `trader.placeOrder({ pool, side, price: yesPrice, quantity, orderType: ORDER_TYPE.MARKET })`. All values RAW units. ## Properties ### side > **side**: [`BinaryBuySide`](../type-aliases/BinaryBuySide.md) Defined in: packages/sdk/src/derivedReads.ts:1040 The buy side quoted ("BUY_YES" | "BUY_NO"). *** ### yesPrice > **yesPrice**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1045 Protective limit in YES terms (raw, tick-aligned) — what `placeOrder` takes. The deepest level the sweep touched plus the slippage cushion. *** ### limitPrice > **limitPrice**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1050 The same protective limit in the traded outcome's OWN terms (raw) — equals `yesPrice` for BUY_YES, `oneCollateral − yesPrice` for BUY_NO. Display this. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1055 Outcome-token quantity bought (raw, lot-aligned) — the payout if this side wins. *** ### escrow > **escrow**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1060 Collateral the order escrows (raw) — `quantity × limitPrice`, rounded up. The max loss; never above the stake. --- # /docs/typescript/api/index/interfaces/BinaryVenueParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryVenueParams # Interface: BinaryVenueParams Defined in: packages/sdk/src/operatorReads.ts:64 Plain-bps fee rates for a BINARY_V1 venue (see BinaryMarketsModule.BinaryVenueParams). Each rate is capped at the module's `MAX_FEE_BPS` (currently 1_000 = 10%). ## Properties ### makerFeeBps > **makerFeeBps**: `number` Defined in: packages/sdk/src/operatorReads.ts:66 Pool protocol fee charged on maker-side fills (bps). *** ### takerFeeBps > **takerFeeBps**: `number` Defined in: packages/sdk/src/operatorReads.ts:68 Pool protocol fee charged on taker-side fills (bps). *** ### maxBuilderFeeBps > **maxBuilderFeeBps**: `number` Defined in: packages/sdk/src/operatorReads.ts:70 Per-order builder/routing fee ceiling the pool enforces at placeOrder (bps). *** ### routingFeeBps > **routingFeeBps**: `number` Defined in: packages/sdk/src/operatorReads.ts:75 Advertised default routing fee for frontends routing through this venue (bps); must be <= `maxBuilderFeeBps`. *** ### settlementFeeBps > **settlementFeeBps**: `number` Defined in: packages/sdk/src/operatorReads.ts:82 Fee skimmed from the WINNING payout on redemption of a resolved market (bps; 0 = none). Frozen into each market at creation — a later `updateVenue` only affects markets created afterward. Never charged on voided (capital-refund) redemptions. *** ### voidPolicy? > `optional` **voidPolicy?**: [`VenueVoidPolicy`](../type-aliases/VenueVoidPolicy.md) Defined in: packages/sdk/src/operatorReads.ts:89 Void payout policy for markets created under this venue (v3 field). Omitted ⇒ `UNIFORM`. Like the fee rates it freezes per market at creation (resolved against the provisioned pool's capability — an old pool without the capture surface downgrades a `CLOB_SNAPSHOT` wish to `UNIFORM`). --- # /docs/typescript/api/index/interfaces/BookLevel [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BookLevel # Interface: BookLevel Defined in: packages/sdk/src/store.ts:456 One aggregated price level of a resting book (raw units). ## Properties ### price > **price**: `bigint` Defined in: packages/sdk/src/store.ts:461 Level price — raw quote/collateral units per whole base/outcome token, in the book's native terms (YES terms for binary, quote-per-base for spot). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/store.ts:463 Total resting size at this price — raw base/outcome units. --- # /docs/typescript/api/index/interfaces/BookTopsOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BookTopsOnchain # Interface: BookTopsOnchain Defined in: packages/sdk/src/orders.ts:566 Chain-sourced top of book for many markets, all read at ONE block. ## Properties ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/orders.ts:568 The block every top below was read at. *** ### tops > **tops**: `Record`\<`string`, [`BookTop`](../type-aliases/BookTop.md)\> Defined in: packages/sdk/src/orders.ts:570 Lowercased marketId → [BookTop](../type-aliases/BookTop.md); empty-book markets are absent. --- # /docs/typescript/api/index/interfaces/BridgeStepEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BridgeStepEvent # Interface: BridgeStepEvent Defined in: packages/sdk/src/unified/bridge.ts:59 One step of a bridge transfer as it happens, for a status UI. ## Properties ### kind > **kind**: `"approve"` \| `"bridge"` \| `"deliver"` Defined in: packages/sdk/src/unified/bridge.ts:61 Which leg. `deliver` is the destination-side landing. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/bridge.ts:63 Chain the step happens on. *** ### status > **status**: `"timeout"` \| `"sent"` \| `"delivered"` \| `"confirmed"` Defined in: packages/sdk/src/unified/bridge.ts:65 `sent` when the origin transaction was submitted, `confirmed` when it mined, `delivered` when the destination router paid out, `timeout` when delivery was not observed in time. *** ### hash? > `optional` **hash?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:67 Transaction hash, when the step has one. --- # /docs/typescript/api/index/interfaces/BuilderApprovalRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BuilderApprovalRef # Interface: BuilderApprovalRef Defined in: packages/sdk/src/fees.ts:328 Identifies one user's approval of one builder on one pool — the triple both `getBuilderApproval` and `getEffectiveBuilderApproval` key on. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/fees.ts:330 The pool the approval lives on (binary, spot, or perp). *** ### user > **user**: `` `0x${string}` `` Defined in: packages/sdk/src/fees.ts:332 The approving user. *** ### builder > **builder**: `` `0x${string}` `` Defined in: packages/sdk/src/fees.ts:334 The approved builder. --- # /docs/typescript/api/index/interfaces/BurnSetParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BurnSetParams # Interface: BurnSetParams Defined in: packages/sdk/src/trade.ts:1647 Inputs to [Trader.burnSet](Trader.md#burnset) — surrender equal YES + NO, get collateral back. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1649 BinaryPool address — pool burns the caller's YES + NO and refunds collateral. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1651 Outcome amount to burn (same for YES + NO). *** ### outcomeToken? > `optional` **outcomeToken?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1656 Outcome-token singleton; resolved from the pool if omitted. Both YES + NO are covered by a single operator approval on it. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1658 Ensure the pool is an operator on the outcome-token singleton (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1664 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelAllOrdersEmpty [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelAllOrdersEmpty # Interface: CancelAllOrdersEmpty Defined in: packages/sdk/src/trade.ts:737 Result of [Trader.cancelAllOrders](Trader.md#cancelallorders) when nothing was resting. A kill switch that finds an empty book has SUCCEEDED, so this is not an error. No transaction was sent, so there is no hash and no receipt — which is why the result is a union rather than a [CancelOrdersResult](CancelOrdersResult.md) with optional fields. Branch on `sent`. ## Properties ### sent > **sent**: `false` Defined in: packages/sdk/src/trade.ts:739 Always `false` here: no transaction was broadcast. *** ### orderIds > **orderIds**: \[\] Defined in: packages/sdk/src/trade.ts:741 Always empty: nothing was resting. *** ### outcomes > **outcomes**: \[\] Defined in: packages/sdk/src/trade.ts:743 Always empty: nothing was cancelled. --- # /docs/typescript/api/index/interfaces/CancelAllOrdersOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelAllOrdersOptions # Interface: CancelAllOrdersOptions Defined in: packages/sdk/src/trade.ts:706 Options for [Trader.cancelAllOrders](Trader.md#cancelallorders) — the kill switch that pulls every resting order the signer holds on one pool. ## Properties ### source? > `optional` **source?**: `"chain"` \| `"live"` Defined in: packages/sdk/src/trade.ts:718 Where the resting ids come from. - `"chain"` (default): one `eth_call` to the pool's own `getOwnOpenOrders`. Complete, and correct on a pool the live tail does not watch. - `"live"`: the live store, so the cancel costs NO read at all. Needs an active watch covering the pool; without one this throws instead of reporting a false empty. #### Default ```ts "chain" ``` *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:724 Gas ceiling for the cancel tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelAllOrdersSent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelAllOrdersSent # Interface: CancelAllOrdersSent Defined in: packages/sdk/src/trade.ts:752 Result of [Trader.cancelAllOrders](Trader.md#cancelallorders) when orders were resting and a cancel transaction went out. Carries everything [CancelOrdersResult](CancelOrdersResult.md) does. ## Extends - [`CancelOrdersResult`](CancelOrdersResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`CancelOrdersResult`](CancelOrdersResult.md).[`hash`](CancelOrdersResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`CancelOrdersResult`](CancelOrdersResult.md).[`receipt`](CancelOrdersResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`CancelOrdersResult`](CancelOrdersResult.md).[`executionTimeMicros`](CancelOrdersResult.md#executiontimemicros) *** ### outcomes > **outcomes**: [`BatchCancelOutcome`](BatchCancelOutcome.md)[] Defined in: packages/sdk/src/trade.ts:697 Per-id outcomes, index-aligned with the `orderIds` input. #### Inherited from [`CancelOrdersResult`](CancelOrdersResult.md).[`outcomes`](CancelOrdersResult.md#outcomes) *** ### sent > **sent**: `true` Defined in: packages/sdk/src/trade.ts:754 Always `true` here: a cancel transaction was broadcast. *** ### orderIds > **orderIds**: `bigint`[] Defined in: packages/sdk/src/trade.ts:756 The ids the read found resting, in the order they were sent to the pool. --- # /docs/typescript/api/index/interfaces/CancelExpiredOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelExpiredOrdersParams # Interface: CancelExpiredOrdersParams Defined in: packages/sdk/src/trade.ts:367 Permissionless keeper drain: clean an explicit list of EXPIRED resting orders on a pool, returning each order's locked escrow to its owner. Best-effort — non-expired or stale ids are silently skipped on-chain (no revert). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:369 BinaryPool (or SpotPool) address whose expired orders to clean. *** ### orderIds > **orderIds**: (`string` \| `bigint`)[] Defined in: packages/sdk/src/trade.ts:371 uint128 OrderIds to attempt to clean (decimal strings or bigints). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:377 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelOrderParams # Interface: CancelOrderParams Defined in: packages/sdk/src/trade.ts:318 Inputs to [Trader.cancelOrder](Trader.md#cancelorder) — cancel one resting order, returning its remaining escrow to the owner. Works on spot AND binary pools. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:320 BinaryPool (or SpotPool) address hosting the resting order. *** ### orderId > **orderId**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:322 uint128 OrderId (decimal string or bigint). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:328 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelOrdersParams # Interface: CancelOrdersParams Defined in: packages/sdk/src/trade.ts:660 Inputs to [Trader.cancelOrders](Trader.md#cancelorders) — pull several resting orders on ONE pool in a single transaction. Works on spot AND binary pools. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:662 SpotPool (or BinaryPool) address hosting the resting orders. *** ### orderIds > **orderIds**: (`string` \| `bigint`)[] Defined in: packages/sdk/src/trade.ts:664 uint128 OrderIds to cancel (decimal strings or bigints). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:670 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelOrdersResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelOrdersResult # Interface: CancelOrdersResult Defined in: packages/sdk/src/trade.ts:695 Result of [Trader.cancelOrders](Trader.md#cancelorders). ## Extends - [`TxResult`](TxResult.md) ## Extended by - [`CancelAllOrdersSent`](CancelAllOrdersSent.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### outcomes > **outcomes**: [`BatchCancelOutcome`](BatchCancelOutcome.md)[] Defined in: packages/sdk/src/trade.ts:697 Per-id outcomes, index-aligned with the `orderIds` input. --- # /docs/typescript/api/index/interfaces/CancelPerpStopOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelPerpStopOrdersParams # Interface: CancelPerpStopOrdersParams Defined in: packages/sdk/src/trade.ts:1607 Inputs to [Trader.cancelPerpStopOrders](Trader.md#cancelperpstoporders) — cancel several of the signer's pending stops in one transaction, refunded in a single transfer. The way to tear down a linked pair: cancelling ONE leg only unlinks the other, which stays armed. Every id must be live and owned by the signer — one bad id reverts the whole batch. ## Properties ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1609 The PerpStopOrderRegistry holding the pending orders. *** ### orderIds > **orderIds**: (`string` \| `bigint`)[] Defined in: packages/sdk/src/trade.ts:1611 The pending order ids (decimal strings or bigints). Must be non-empty. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1617 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CancelPerpWalletLinkProposalParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelPerpWalletLinkProposalParams # Interface: CancelPerpWalletLinkProposalParams Defined in: packages/sdk/src/trade.ts:1119 Inputs to [Trader.cancelPerpWalletLinkProposal](Trader.md#cancelperpwalletlinkproposal) — withdraw an offer the signer made and the child has not accepted. The signer is the MAIN. An accepted link is torn down with [Trader.unlinkPerpWallet](Trader.md#unlinkperpwallet) instead. ## Extends - [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md) ## Properties ### registry? > `optional` **registry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1070 The LinkedWalletRegistry. Skips resolution entirely. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`registry`](PerpWalletLinkTarget.md#registry) *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1072 MarginBank address — its `getLinkedWalletRegistry()` is read (never cached). #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`marginBank`](PerpWalletLinkTarget.md#marginbank) *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1074 A PerpPool — its `marginBank()` is read (and cached), then the registry. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`pool`](PerpWalletLinkTarget.md#pool) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1080 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`gas`](PerpWalletLinkTarget.md#gas) *** ### child > **child**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1121 The child whose pending offer to withdraw. --- # /docs/typescript/api/index/interfaces/CancelStopOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelStopOrderParams # Interface: CancelStopOrderParams Defined in: packages/sdk/src/trade.ts:1441 Inputs to [Trader.cancelStopOrder](Trader.md#cancelstoporder) and [Trader.cancelPerpStopOrder](Trader.md#cancelperpstoporder) — cancel a pending (untriggered) stop order on its registry. Shared by both venues because the cancel takes nothing venue-specific: an id and the registry that issued it. Which registry that is follows from the method you call, so pass the SpotStopOrderRegistry to the spot cancel and the PerpStopOrderRegistry to the perp one — ids are per-registry and mean nothing on the other. ## Properties ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1443 The stop-order registry holding the pending order — spot or perp, per the method. *** ### orderId > **orderId**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:1445 The pending order's id on the registry (decimal string or bigint). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1451 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/CaptureCloseParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CaptureCloseParams # Interface: CaptureCloseParams Defined in: packages/sdk/src/trade.ts:419 Permissionless closing-price capture on a BinaryPool (capture-generation pools only). Callable by anyone once the market's expiry passes; stores the closing book's bid/ask mid and lifts the closing-book lock, letting post-expiry cancels/sweeps of alive-at-close orders proceed on a not-yet-terminal market. Self-incentivized: whoever wants the book dismantled (a maker reclaiming escrow, a keeper draining toward release) captures first. Reverts `CloseAlreadyCaptured` when already captured/terminal-latched, `CaptureTooEarly` before expiry, `CaptureStepsExhausted` when the scan budget runs out (retry with a bigger `maxSteps`). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:421 BinaryPool address whose closing price to capture. *** ### maxSteps? > `optional` **maxSteps?**: `bigint` Defined in: packages/sdk/src/trade.ts:428 Per-side scan budget in orders visited — only stale (earlier-expired, unswept) orders above the closing book consume steps. 0 selects the pool default (256). #### Default ```ts 0n ``` *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:434 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ChainMarketRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ChainMarketRef # Interface: ChainMarketRef Defined in: packages/sdk/src/chainRef.ts:26 A market named together with the chain it lives on. Accepted wherever a symbol, pool address or market id is accepted (`exchange.market(ref)`, `createOrder(ref, …)`, `fetchOrderBook(ref)`, …). **Details** `id` is anything the symbol table resolves — a symbol, a tradable symbol (`…#YES`), a pool address, a market id or a BinaryMarket address. `chainId` pins which chain's table answers, so an id that exists on two chains (the same CREATE2 pool on L1 and Hideki) is never ambiguous. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/chainRef.ts:28 Numeric chain id the market lives on. *** ### id > **id**: `string` Defined in: packages/sdk/src/chainRef.ts:30 Symbol, tradable symbol, pool address, market id or BinaryMarket address. --- # /docs/typescript/api/index/interfaces/ChainOrderRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ChainOrderRef # Interface: ChainOrderRef Defined in: packages/sdk/src/chainRef.ts:39 An order named together with its chain and pool. `cancelOrder` accepts one in place of a bare decimal order id. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/chainRef.ts:41 Numeric chain id the order's pool lives on. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/chainRef.ts:43 The pool the order rests on (lowercased or checksummed — compared case-insensitively). *** ### id > **id**: `string` Defined in: packages/sdk/src/chainRef.ts:45 On-chain order id, decimal string. --- # /docs/typescript/api/index/interfaces/ClaimOwedParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimOwedParams # Interface: ClaimOwedParams Defined in: packages/sdk/src/trade.ts:1895 Claim an accrued push-fallback balance on the settlement singleton (a payout that could not be pushed to a reverting recipient was booked to `owed`). ## Properties ### token > **token**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1897 The token to claim (the market's collateral token). *** ### settlement? > `optional` **settlement?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1899 BinarySettlement address; resolved from `config.addresses.binarySettlement` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1905 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ClaimPerpStopSomiParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimPerpStopSomiParams # Interface: ClaimPerpStopSomiParams Defined in: packages/sdk/src/trade.ts:1460 Inputs to [Trader.claimPerpStopSomi](Trader.md#claimperpstopsomi) — recover the SOMI a perp stop registry owes the signer after a refund transfer failed. ## Properties ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1462 The perp stop-order registry holding the unclaimed balance. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1468 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ClaimPerpVoucherParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimPerpVoucherParams # Interface: ClaimPerpVoucherParams Defined in: packages/sdk/src/trade.ts:1194 Inputs to [Trader.claimPerpVoucher](Trader.md#claimperpvoucher) — claim the one-time credit voucher as the signer. Supply ONE of `distributor`, `marginBank` or `pool`. `distributor` is used as given. Otherwise the SDK reads `getCreditGranter()` off the bank, because the bank decides which distributor it accepts credit from. `pool` resolves the bank first. A bank holding no credit granter throws [NotConfiguredError](../classes/NotConfiguredError.md): the voucher programme is off on that deployment. ## Properties ### distributor? > `optional` **distributor?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1196 The VoucherDistributor. Skips resolution entirely. *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1198 MarginBank address — its `getCreditGranter()` is read (never cached). *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1200 A PerpPool — its `marginBank()` is read (and cached), then the distributor. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1206 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ClaimableInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimableInput # Interface: ClaimableInput Defined in: packages/sdk/src/derivedReads.ts:775 A settled binary position to evaluate for claimability. ## Properties ### marketId > **marketId**: `string` Defined in: packages/sdk/src/derivedReads.ts:777 Market id (bytes32 hex), passed through to the output. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/derivedReads.ts:779 The market's pool address, passed through to the output. *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/derivedReads.ts:781 0 = YES, 1 = NO — which outcome this position holds. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:783 Held outcome-token balance (raw). Non-positive positions are dropped. *** ### winningOutcome > **winningOutcome**: `number` \| `null` Defined in: packages/sdk/src/derivedReads.ts:785 Winning outcome (0/1) when resolved; null when voided/unresolved. *** ### voided > **voided**: `boolean` Defined in: packages/sdk/src/derivedReads.ts:792 True when the market voided. A void redeems against the market's stored payout vector ([ClaimableInput.payoutNumerators](#payoutnumerators)), which is a half per side under the `UNIFORM` void policy but `[p, D−p]` on a `CLOB_SNAPSHOT` void that captured a two-sided close. *** ### payoutNumerators? > `optional` **payoutNumerators?**: `string`[] \| `null` Defined in: packages/sdk/src/derivedReads.ts:800 Per-outcome payout numerators the market settled to (decimal strings), from `BinaryMarket.payoutNumerators`. Supply these on a voided position so the payout comes from the vector rather than an assumed half. Null/omitted on markets indexed before the vector fields existed — the estimate then falls back to the half, unchanged from pre-vector behaviour. *** ### payoutDenominator? > `optional` **payoutDenominator?**: `string` \| `null` Defined in: packages/sdk/src/derivedReads.ts:802 Denominator the numerators are scaled against (decimal string); null/omitted with them. *** ### status > **status**: `string` Defined in: packages/sdk/src/derivedReads.ts:804 Market lifecycle status ("Resolved" | "Voided" | …), passed through to the output. *** ### settlementFeeBps > **settlementFeeBps**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:806 Settlement fee in bps (1 = 0.01%); the winner payout skims this. --- # /docs/typescript/api/index/interfaces/ClaimablePosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimablePosition # Interface: ClaimablePosition Defined in: packages/sdk/src/derivedReads.ts:749 One redeemable outcome position in a settled market — shaped to feed straight into `trader.redeemMany({ entries: [...] })`. ## Properties ### marketId > **marketId**: `string` Defined in: packages/sdk/src/derivedReads.ts:751 Market id (bytes32 hex) — `entries[].marketId` for redeemMany. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/derivedReads.ts:753 The market's pool address (lowercased). *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/derivedReads.ts:755 0 = YES, 1 = NO — `entries[].outcomeIdx` for redeemMany. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:757 Redeemable outcome-token balance (raw) — `entries[].amount` for redeemMany. *** ### estPayout > **estPayout**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:765 Estimated collateral payout net of the settlement fee (raw). Winner: amount × (1 − fee); voided: amount × the market's stored payout vector for this outcome (a half per side under the `UNIFORM` void policy, `[p, D−p]` on a captured `CLOB_SNAPSHOT` void; a void is never fee-charged). Loser side: 0. See [estPayoutFor](../functions/estPayoutFor.md). *** ### status > **status**: `string` Defined in: packages/sdk/src/derivedReads.ts:767 Market lifecycle status driving the claim ("Resolved" | "Voided" | …). --- # /docs/typescript/api/index/interfaces/ClientConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClientConfig # Interface: ClientConfig Defined in: packages/sdk/src/config.ts:434 Configuration for a [SomniaMarketsClient](SomniaMarketsClient.md). Each transport is required only by the features that use it: `indexerUrl` powers the indexer reads and the live watches' snapshot hydration (omit it for a chain-only client — smart accounts, executors, on-chain reads — and those reads throw [NotConfiguredError](../classes/NotConfiguredError.md)); `chain` + `wsRpcUrl` power the live tail, on-chain reads, and writes, but the WebSocket socket is opened lazily, so an indexer-only client (e.g. server-side GraphQL reads) that never touches the chain never opens one. ## Properties ### reconciliation? > `optional` **reconciliation?**: [`TailReconciliationConfig`](TailReconciliationConfig.md) Defined in: packages/sdk/src/config.ts:442 Optional diagnostic, off by default. At most once per interval, recover logs through one target and compare both top-N sides at that block and timestamp. Costs chunked getLogs plus one header and two book reads per watched pool. Failures and retained divergence evidence appear in getLiveStatus(). It never replaces seed orders or the event-derived store. *** ### indexerUrl? > `optional` **indexerUrl?**: `string` Defined in: packages/sdk/src/config.ts:450 Envio/Hasura GraphQL endpoint (HTTP). Same-origin relative paths are fine. Optional: a chain-only client (smart accounts, executors, on-chain reads) needs none; every indexer read and live watch then throws [NotConfiguredError](../classes/NotConfiguredError.md) naming this field. An empty string counts as absent. *** ### indexerHeaders? > `optional` **indexerHeaders?**: `Record`\<`string`, `string`\> Defined in: packages/sdk/src/config.ts:458 Extra headers sent with every indexer request — e.g. a Hasura role / admin-secret for SERVER-side reads that need privileges the public role lacks (notably `_aggregate` fields, which envio hides from the public role). MUST stay server-only; never construct a browser client with a secret here. *** ### indexerLimits? > `optional` **indexerLimits?**: [`IndexerLimits`](IndexerLimits.md) Defined in: packages/sdk/src/config.ts:472 Bounds on how hard this client may push [ClientConfig.indexerUrl](#indexerurl). Defaults to [DEFAULT\_INDEXER\_LIMITS](../variables/DEFAULT_INDEXER_LIMITS.md); supplied fields override it one by one. Owned by this client: two clients on one endpoint keep separate counters, so one client's outage never fails another's reads. Throws [InvalidInputError](../classes/InvalidInputError.md) at construction on a bound the governor cannot use: a count (`maxInFlight`, `breakerThreshold`, `maxAttempts`, `maxQueued`) that is not a whole number of at least 1, a delay of `0` or less, or any non-finite value. A cap of `0` would queue every read forever, a fractional one would admit more reads than it names, and a zero or `NaN` delay would fire every retry immediately, so none is accepted quietly. *** ### signal? > `optional` **signal?**: `AbortSignal` Defined in: packages/sdk/src/config.ts:490 Cancels this client's in-flight INDEXER reads when aborted — pass one per request on a server, or a component's controller signal in a UI, so a navigation away stops work already on the wire. **Details** Client-wide, not per-read: it is combined with the SDK's own request timeout (whichever fires first wins). An abort re-throws YOUR abort reason unwrapped rather than an [IndexerError](../classes/IndexerError.md), so `name === "AbortError"` checks keep working — a cancellation is not an indexer failure. **Gotchas** Covers indexer reads only. Chain reads go over the WebSocket transport, which is bounded by its own request timeout instead. *** ### chain > **chain**: `Chain` Defined in: packages/sdk/src/config.ts:492 viem chain the markets live on. *** ### wsRpcUrl? > `optional` **wsRpcUrl?**: `string` Defined in: packages/sdk/src/config.ts:504 Chain WebSocket RPC — the single chain transport. The live tail subscribes to logs + new heads over it, and all on-chain reads/writes use it too. There is no HTTP fallback: the SDK assumes a healthy WebSocket. Optional when `chain` carries a WebSocket endpoint — every definition in `@somnia-chain/markets-sdk/chains` does (`rpcUrls.default.webSocket`), so with those this is only an override. viem's own `somniaTestnet` lacks one, so with that chain (or any ws-less definition) it stays required and the first chain touch throws [NotConfiguredError](../classes/NotConfiguredError.md) without it. *** ### fees? > `optional` **fees?**: [`FixedFees`](FixedFees.md) Defined in: packages/sdk/src/config.ts:509 Fixed fees for SDK-signed writes (default [DEFAULT\_FEES](../variables/DEFAULT_FEES.md)). Override for a chain whose base fee can exceed the default ceiling. *** ### addresses? > `optional` **addresses?**: [`SomniaMarketsAddresses`](SomniaMarketsAddresses.md) Defined in: packages/sdk/src/config.ts:514 Protocol contract addresses — used by the write client, the live tail's factory watch, and /system reads. *** ### priceFeed? > `optional` **priceFeed?**: [`PriceFeedConfig`](PriceFeedConfig.md) Defined in: packages/sdk/src/config.ts:521 The realtime price-feed endpoint (see [PriceFeedConfig](PriceFeedConfig.md)). One endpoint serves every asset; callers filter by asset. Required only for the price-feed methods (`watchPrice`, `getLivePrice`, `fetchPrices`, …); a client that never touches prices needs none. *** ### debug? > `optional` **debug?**: (`e`) => `void` Defined in: packages/sdk/src/config.ts:554 Opt-in debug/tracing sink. Unset (the default) means the SDK emits nothing and does no debug-only work. When set, the client sends every [DebugEvent](../type-aliases/DebugEvent.md) it produces — structured log lines plus span start/annotate/end events around trader calls and live-tail hydration — and the sink decides everything else: filtering, formatting, toggling, or forwarding to a real tracer (the shape maps 1:1 onto OpenTelemetry). Two sinks ship with the package: `consoleDebugSink` (indented span tree) and `debugCollector` (test capture). The toggle mechanism belongs to the app, not the SDK: **Example** (Enabling debug output) Explorer (dev) — flip on from devtools via localStorage; a Node bot gates a JSON-lines sink on an env var instead: ```ts const devExchange = new SomniaMarkets({ ...config, debug: localStorage.getItem("sdk-debug") ? consoleDebugSink() : undefined, }); const botExchange = new SomniaMarkets({ ...config, debug: process.env.SDK_DEBUG ? (e) => console.log(JSON.stringify(e, (_, v) => (typeof v === "bigint" ? v.toString() : v))) : undefined, }); ``` #### Parameters ##### e [`DebugEvent`](../type-aliases/DebugEvent.md) #### Returns `void` --- # /docs/typescript/api/index/interfaces/ClosingPriceState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClosingPriceState # Interface: ClosingPriceState Defined in: packages/sdk/src/orders.ts:760 A pool's closing-price capture state (see `Trader.captureClose`). `state`: - `"OPEN"`: no capture yet — post-expiry removals of alive-at-close orders revert `CloseNotCaptured` while the market is not terminal. - `"CAPTURED"`: two-sided capture stored; `closingMid` is the bid/ask mid in raw book-price units (scale `oneCollateral`). - `"CAPTURED_DEGENERATE"`: capture ran but a side had no closing order — no mid; a void falls back to uniform. - `"TERMINAL_LATCH"`: a removal observed the market already terminal; the lock lifted without a capture. ## Properties ### closingMid > **closingMid**: `bigint` Defined in: packages/sdk/src/orders.ts:762 Captured closing mid in raw book-price units (0 unless `state === "CAPTURED"`). *** ### oneCollateral > **oneCollateral**: `bigint` Defined in: packages/sdk/src/orders.ts:764 The pool's price scale (`10 ** collateralDecimals`). *** ### state > **state**: `"OPEN"` \| `"CAPTURED"` \| `"CAPTURED_DEGENERATE"` \| `"TERMINAL_LATCH"` Defined in: packages/sdk/src/orders.ts:766 Decoded close state. --- # /docs/typescript/api/index/interfaces/ContractMeta [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ContractMeta # Interface: ContractMeta Defined in: packages/sdk/src/markets.ts:2317 owner / implementation / native balance for a deployed contract — the diagnostics the /system dashboard shows. `owner` is null when the contract isn't Ownable; `impl` is read from the EIP-1967 slot only when `proxy` is true (null otherwise, or when the slot is empty). Each sub-read degrades to null/0 independently so one missing getter never fails the whole card. ## Properties ### owner > **owner**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/markets.ts:2319 Ownable `owner()`, or null when the contract exposes no owner getter. *** ### impl > **impl**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/markets.ts:2324 EIP-1967 implementation address — null unless read as a proxy with a non-empty slot. *** ### balance > **balance**: `bigint` Defined in: packages/sdk/src/markets.ts:2326 Native (SOMI) balance, raw wei (18dp); 0n when the read fails. --- # /docs/typescript/api/index/interfaces/CreateMarketCreatorParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateMarketCreatorParams # Interface: CreateMarketCreatorParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:47 Params for [MarketCreatorAdmin.createMarketCreator](MarketCreatorAdmin.md#createmarketcreator). ## Properties ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:49 Owner of the minted creator (can register series / trigger rolls). *** ### factory? > `optional` **factory?**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:57 Factory to mint from. Defaults to `config.addresses.marketCreatorFactory` (v1). Pass `config.addresses.marketCreatorFactoryV2` explicitly to mint an interval/bucket-mode `MarketCreatorV2` instead — the rest of this admin's surface (registerSeries / triggerRoll / armFirstRoll / …) targets either version unchanged, since v2's instance ABI is a superset of v1's here. *** ### adapter? > `optional` **adapter?**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:63 Oracle adapter the creator's markets resolve against. Defaults to the protocol's OracleHub (`config.addresses.oracleHub`) — Oracle v2's ONE approved adapter; there is nothing to mint or arm per operator. *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:65 Origin operator id the creator's markets are attributed to. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:71 Origin venue id (within the operator). Must be a BINARY_V1 venue whose create path does NOT require a venue signature — the automated roll loop cannot produce per-create signatures. *** ### defaultBookParams > **defaultBookParams**: [`OrderBookParams`](OrderBookParams.md) Defined in: packages/sdk/src/marketCreatorAdmin.ts:73 Default order-book config stamped onto every market the creator deploys. *** ### core? > `optional` **core?**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:78 Core BinaryMarketsModule the creator binds to. Defaults to `config.addresses.binaryModule`. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:80 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/CreateMarketCreatorResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateMarketCreatorResult # Interface: CreateMarketCreatorResult Defined in: packages/sdk/src/marketCreatorAdmin.ts:88 Result of [MarketCreatorAdmin.createMarketCreator](MarketCreatorAdmin.md#createmarketcreator) — the two addresses the factory minted, decoded from the receipt's `MarketCreatorCreated` event. ## Extends - [`TxResult`](TxResult.md) ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:90 The minted MarketCreator address (decoded from `MarketCreatorCreated`). *** ### policy > **policy**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:92 The minted MarketCreatorPolicy address (decoded from `MarketCreatorCreated`). *** ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) --- # /docs/typescript/api/index/interfaces/CreateOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateOrderParams # Interface: CreateOrderParams Defined in: packages/sdk/src/unified/exchange.ts:407 The optional trailing params bag of [SomniaMarkets.createOrder](../classes/SomniaMarkets.md#createorder) — time-in-force, market-order slippage, and builder-fee attribution. Everything here has a working default. ## Properties ### timeInForce? > `optional` **timeInForce?**: `"GTC"` \| `"IOC"` \| `"FOK"` \| `"PO"` Defined in: packages/sdk/src/unified/exchange.ts:409 "IOC" | "FOK" | "PO" (post-only). Default GTC (rest). *** ### postOnly? > `optional` **postOnly?**: `boolean` Defined in: packages/sdk/src/unified/exchange.ts:411 Alias for timeInForce: "PO". *** ### slippage? > `optional` **slippage?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:413 Market-order slippage bound vs the best opposite level (default 0.01 = 1%). *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/exchange.ts:419 Routing/builder frontend to attribute the order to. Requires a prior `client.createTrader().approveBuilder(...)` opt-in on the pool, else a non-zero `builderFeeBpsTimes1k` reverts. Works on binary, spot and perp. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/unified/exchange.ts:424 Per-order builder/routing fee in the pool's native bps×1000 unit (must not exceed the effective approval / the pool's max builder fee). *** ### funding? > `optional` **funding?**: `"auto"` \| `"explicit"` \| `"skip"` Defined in: packages/sdk/src/unified/exchange.ts:455 What to do when the order's collateral is not on the market's chain. - `"explicit"` (the default on a multi-chain exchange): check the escrow token's balance on the market's chain and throw [CollateralOnWrongChainError](../classes/CollateralOnWrongChainError.md) — with where the funds are and a ready bridge plan — instead of sending anything. - `"auto"`: bridge the shortfall from the richest other configured chain through [SomniaMarkets.ensureFunds](../classes/SomniaMarkets.md#ensurefunds), wait for delivery, then place. The order lands seconds after the call. A native route whose destination router cannot pay out throws [BridgeLiquidityError](../classes/BridgeLiquidityError.md) and sends nothing. Auto-funded orders for the same account, chain and escrow token are checked and placed one at a time, so each one sees the balance after the one before it took its escrow. - `"skip"` (the default on a single-chain exchange, where there is nowhere else the collateral could be): no balance check — the single round-trip, for a hot path that funds itself. Checked on a binary buy's collateral and on every spot order. A perp order draws on the MarginBank and a binary sell escrows outcome tokens, so neither is checked here. A spot order is sized by the pool: the check reads the pool's `getAutoPullRequirement` (fees included, net of the account's pool vault balance). When the vault covers the order, that read is the whole check. Otherwise the wallet must hold the remainder (as native coin for a native-base sell). Under manual vault mode the pool never pulls from the wallet, so a vault shortfall throws with no bridge plan, even under `"auto"`: deposit into the pool vault instead. --- # /docs/typescript/api/index/interfaces/CreateQuotePreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateQuotePreflightInput # Interface: CreateQuotePreflightInput Defined in: packages/sdk/src/preflight.ts:228 Inputs for the create-quote preflight (§8e EARMARK-AT-CREATION): what the payer (the funding wallet or MarketCreator contract) holds vs the FULL create value — `getSchedulingCost(def) + resolveReserve()`. The reserve is attached to the create and LOCKED per-market at onBind; there is no separate prepaid gate. Fetch the total with `quoteCreateMarketValue(def)`, or fetch the two legs (`getSchedulingCost(def)` + `resolveReserve()`) separately. ## Properties ### balanceWei > **balanceWei**: `bigint` Defined in: packages/sdk/src/preflight.ts:230 Native balance (wei) of whoever pays the create (EOA or MarketCreator). *** ### schedulingCostWei > **schedulingCostWei**: `bigint` Defined in: packages/sdk/src/preflight.ts:232 The hub's marginal `getSchedulingCost(def)` quote (0 = dedup reuse). *** ### resolveReserveWei > **resolveReserveWei**: `bigint` Defined in: packages/sdk/src/preflight.ts:238 The hub's `resolveReserve()` — the reserve ATTACHED to the create and locked per-market at onBind (the bind reverts `WrongReserveAttached` if the attached value is not exactly this). --- # /docs/typescript/api/index/interfaces/CreateVenueParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateVenueParams # Interface: CreateVenueParams Defined in: packages/sdk/src/operatorAdmin.ts:186 Params for [OperatorAdmin.createVenue](OperatorAdmin.md#createvenue). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:188 The operator the venue is created under. Caller must be its owner. *** ### marketType > **marketType**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:190 Market-type id (e.g. `MarketTypeIds.BINARY_V1`); immutable once set. *** ### config > **config**: [`VenueConfigInput`](VenueConfigInput.md) Defined in: packages/sdk/src/operatorAdmin.ts:192 The venue's initial config (fee params, recipient, policy, signer, …). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:194 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/CreateVenueResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CreateVenueResult # Interface: CreateVenueResult Defined in: packages/sdk/src/operatorAdmin.ts:202 Result of [OperatorAdmin.createVenue](OperatorAdmin.md#createvenue) — carries the venue id the contract generated, which markets reference to inherit the venue's fees. ## Extends - [`TxResult`](TxResult.md) ## Properties ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:204 The contract-generated venue id (decoded from `VenueCreated`). *** ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) --- # /docs/typescript/api/index/interfaces/DebugCollector [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DebugCollector # Interface: DebugCollector Defined in: packages/sdk/src/debug.ts:384 Captured debug-event stream with typed filters — what [debugCollector](../functions/debugCollector.md) returns. Pass [sink](#sink) as [ClientConfig.debug](ClientConfig.md#debug), run the operation under test, then assert on the filters. ## Properties ### events > **events**: [`DebugEvent`](../type-aliases/DebugEvent.md)[] Defined in: packages/sdk/src/debug.ts:386 Every event received, in emission order (spans interleaved with logs). *** ### sink > **sink**: (`e`) => `void` Defined in: packages/sdk/src/debug.ts:388 The collecting sink — pass as [ClientConfig.debug](ClientConfig.md#debug). #### Parameters ##### e [`DebugEvent`](../type-aliases/DebugEvent.md) #### Returns `void` ## Methods ### starts() > **starts**(`name?`): `object`[] Defined in: packages/sdk/src/debug.ts:390 Span start events, optionally filtered by span name (e.g. `"trade.execute"`). #### Parameters ##### name? `string` #### Returns *** ### ends() > **ends**(`name?`): `object`[] Defined in: packages/sdk/src/debug.ts:392 Span end events, optionally filtered by span name — carry `durationMs`/`error`. #### Parameters ##### name? `string` #### Returns *** ### annotations() > **annotations**(`name?`): `object`[] Defined in: packages/sdk/src/debug.ts:394 Mid-span annotate events, optionally filtered by span name. #### Parameters ##### name? `string` #### Returns *** ### logs() > **logs**(`scope?`): `object`[] Defined in: packages/sdk/src/debug.ts:396 Log events, optionally filtered by scope (e.g. `"liveTail"`). #### Parameters ##### scope? `string` #### Returns --- # /docs/typescript/api/index/interfaces/DecodedAmendment [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DecodedAmendment # Interface: DecodedAmendment Defined in: packages/sdk/src/decode/orders.ts:139 What a single amendment left on the book, decoded from its receipt. ## Properties ### newOrderId > **newOrderId**: `bigint` Defined in: packages/sdk/src/decode/orders.ts:141 The replacement order's id, from the first `OrderPlaced`; `0n` when none was found. *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/decode/orders.ts:143 Every `OrderFilled` the amendment produced, in log order. --- # /docs/typescript/api/index/interfaces/DecodedBatchAmendment [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DecodedBatchAmendment # Interface: DecodedBatchAmendment Defined in: packages/sdk/src/decode/orders.ts:172 What a batch amendment left on the book, decoded from its receipt. ## Properties ### newOrderIds > **newOrderIds**: `bigint`[] Defined in: packages/sdk/src/decode/orders.ts:174 Replacement ids, positional to the amendments; `0n` where none was found. *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/decode/orders.ts:176 Every `OrderFilled` the batch produced, in log order. --- # /docs/typescript/api/index/interfaces/DecodedOutcomeId [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DecodedOutcomeId # Interface: DecodedOutcomeId Defined in: packages/sdk/src/ids.ts:56 The decoded components of an outcome id. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/ids.ts:58 The pool address (the encoded high 160 bits), lowercased 0x-hex. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/ids.ts:60 The pool's market nonce this id belongs to. *** ### idx > **idx**: `number` Defined in: packages/sdk/src/ids.ts:62 The outcome index (0 = YES, 1 = NO). --- # /docs/typescript/api/index/interfaces/DecodedPlacement [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DecodedPlacement # Interface: DecodedPlacement Defined in: packages/sdk/src/decode/orders.ts:88 What a placement left on the book, decoded from its receipt. ## Properties ### orderId? > `optional` **orderId?**: `bigint` Defined in: packages/sdk/src/decode/orders.ts:90 The resting order's id, from the LAST `OrderPlaced`; absent when nothing rested (a full fill, an IOC remainder). *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/decode/orders.ts:92 Every `OrderFilled` the placement produced, in log order. --- # /docs/typescript/api/index/interfaces/DepositMarginParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DepositMarginParams # Interface: DepositMarginParams Defined in: packages/sdk/src/trade.ts:1013 Inputs to [Trader.depositMargin](Trader.md#depositmargin) — fund the signer's cross-margin MarginBank balance (one balance backs every perp pool on that bank). ## Properties ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1015 MarginBank address (from the PerpMarket row), or pass `pool` to resolve it. *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1017 A PerpPool — its `marginBank()` is read (and cached) when `marginBank` is omitted. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1019 Collateral amount to deposit, raw units (e.g. USDso 18dp). *** ### collateral? > `optional` **collateral?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1021 Collateral token; read from the bank's getSystemConfig (cached) if omitted. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1023 Approve the collateral to the BANK if allowance is short (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1029 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/DepositVaultNativeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DepositVaultNativeParams # Interface: DepositVaultNativeParams Defined in: packages/sdk/src/trade.ts:1270 Inputs to [Trader.depositVaultNative](Trader.md#depositvaultnative) and [Trader.depositVaultNativeFor](Trader.md#depositvaultnativefor) — pre-fund a native balance in a pool's internal vault. The amount travels as `msg.value`. ## Properties ### vault > **vault**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1272 The ERC20Vault to deposit into — the pool address. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1274 Native amount to deposit, wei. Must be > 0. *** ### owner? > `optional` **owner?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1279 Account to credit. Omit to credit the signer; set it to fund ANOTHER account's vault balance (an operator pre-funding a bot wallet). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1285 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/DepositVaultParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DepositVaultParams # Interface: DepositVaultParams Defined in: packages/sdk/src/trade.ts:1242 Inputs to [Trader.depositVault](Trader.md#depositvault) — pre-fund an ERC-20 balance in a pool's internal vault. ## Properties ### vault > **vault**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1247 The ERC20Vault to deposit into — the pool address (SpotPool/BinaryPool ARE ERC20Vaults). *** ### token > **token**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1252 ERC-20 to deposit. NOT the native sentinel — use [Trader.depositVaultNative](Trader.md#depositvaultnative) for native (the contract reverts `UseDepositNative`). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1254 Amount to deposit, raw units. Must be > 0. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1260 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/EnableHubReactivityParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / EnableHubReactivityParams # Interface: EnableHubReactivityParams Defined in: packages/sdk/src/oracleHub.ts:494 Parameters for [OracleHubAdmin.enableReactivity](OracleHubAdmin.md#enablereactivity) / [OracleHubAdmin.migrateSubscription](OracleHubAdmin.md#migratesubscription). ## Properties ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:496 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/EntryTrade [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / EntryTrade # Interface: EntryTrade Defined in: packages/sdk/src/derivedReads.ts:1309 The one slice of a portfolio trade the entry-price math needs. ## Properties ### side > **side**: [`BinarySide`](../type-aliases/BinarySide.md) \| `null` Defined in: packages/sdk/src/derivedReads.ts:1311 The account's side on the fill, or null when not yet bridged. *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/derivedReads.ts:1313 Fill price in YES terms (raw collateral units per whole outcome token). *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/derivedReads.ts:1315 Outcome-token quantity filled (raw units). --- # /docs/typescript/api/index/interfaces/EquityPoint [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / EquityPoint # Interface: EquityPoint Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:185 One sample of the equity (cumulative window PnL) series. ## Properties ### t > **t**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:187 Sample time (ms). *** ### valueUsd > **valueUsd**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:189 Cumulative realized + unrealized PnL since the window start, USD. --- # /docs/typescript/api/index/interfaces/Erc20Metadata [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Erc20Metadata # Interface: Erc20Metadata Defined in: packages/sdk/src/balances.ts:42 ERC-20 token metadata (`symbol`, `name`, `decimals`) read in one fan-out. Handy to label a collateral/base token the indexer hasn't denormalized. ## Properties ### symbol > **symbol**: `string` Defined in: packages/sdk/src/balances.ts:44 Token ticker, e.g. "USDso". *** ### name > **name**: `string` Defined in: packages/sdk/src/balances.ts:46 Full token name, e.g. "Somnia USD". *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/balances.ts:48 Display decimals scaling the token's raw units (raw / 10^decimals = human). --- # /docs/typescript/api/index/interfaces/ExchangeBridge [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeBridge # Interface: ExchangeBridge Defined in: packages/sdk/src/unified/bridge.ts:127 The bridge, reached as `exchange.bridge`: plan and execute transfers between the exchange's own chains through the account's executors. ## Methods ### plan() > **plan**(`params`): [`BridgeTransfer`](../../chains/interfaces/BridgeTransfer.md) Defined in: packages/sdk/src/unified/bridge.ts:133 Plan a transfer between two configured chains — pure, nothing sent. Throws [NotConfiguredError](../classes/NotConfiguredError.md) when either chain is not one of the exchange's, [InvalidInputError](../classes/InvalidInputError.md) when the token has no route between them. #### Parameters ##### params [`ExchangeBridgeParams`](ExchangeBridgeParams.md) #### Returns [`BridgeTransfer`](../../chains/interfaces/BridgeTransfer.md) *** ### transfer() > **transfer**(`params`, `options?`): `Promise`\<[`ExchangeBridgeResult`](ExchangeBridgeResult.md)\> Defined in: packages/sdk/src/unified/bridge.ts:163 Plan and execute: the origin legs go through the origin chain's executor (a safe packs approval and bridge into one transaction), then delivery of that one message is awaited on the destination engine's socket. **Details** The message id comes from the origin receipt: the origin Mailbox's `Dispatch` whose sender is the origin router and whose destination is the target chain, paired with the `DispatchId` after it. The wait resolves only on the destination Mailbox's `ProcessId` for that id, and reads the router's `ReceivedTransferRemote` from the same transaction. A delivery to the same recipient from another message does not count. The wait also asks the destination Mailbox `delivered(messageId)`, so a message that landed before the watch opened still resolves. That read only covers the window before the watch: when it fails, the watch or the timeout decides. **Gotchas** - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - a chain outside the exchange, or no executor for the origin chain. - Throws [SignerRequiredError](../classes/SignerRequiredError.md) - the exchange has no account to bridge for. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the token has no route between the two chains, the amount is not positive, or the executor refused the call list. - Throws [BridgeLiquidityError](../classes/BridgeLiquidityError.md) - a native route's destination router holds less than the amount. Nothing was sent. - Throws [RpcError](../classes/RpcError.md) - `operation` names the step. `getBalance`: the destination router's balance read failed, and nothing was sent. `transferRemote`: the origin transaction was sent and mined as reverted. `bridge message id`: the origin transaction was mined, but its receipt holds no single Mailbox dispatch from the origin router to the destination. The funds may be in flight. `watch bridge delivery`: the destination watch failed after the origin leg was mined, and the funds may be in flight; or the delivery transaction holds no `ReceivedTransferRemote` from the router. `waitForTransactionReceipt`: the message was processed, but the delivery receipt read failed. Any other `operation` comes from the executor's send, and the transaction may have been sent. - Throws [ContractRevertError](../classes/ContractRevertError.md) - an origin leg reverted, in simulation or on chain. - Resolves with `delivered: false` and the `messageId` when the message was not processed within the timeout, or when the exchange closes after this call started. The transfer may still land. It is not undone. #### Parameters ##### params [`ExchangeBridgeParams`](ExchangeBridgeParams.md) ##### options? [`ExchangeBridgeTransferOptions`](ExchangeBridgeTransferOptions.md) #### Returns `Promise`\<[`ExchangeBridgeResult`](ExchangeBridgeResult.md)\> --- # /docs/typescript/api/index/interfaces/ExchangeBridgeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeBridgeParams # Interface: ExchangeBridgeParams Defined in: packages/sdk/src/unified/bridge.ts:39 Parameters for [ExchangeBridge.plan](ExchangeBridge.md#plan) and [ExchangeBridge.transfer](ExchangeBridge.md#transfer). ## Properties ### token > **token**: [`BridgeToken`](../../chains/type-aliases/BridgeToken.md) Defined in: packages/sdk/src/unified/bridge.ts:41 Token to bridge. *** ### from > **from**: `number` Defined in: packages/sdk/src/unified/bridge.ts:43 Chain id to send FROM — must be one of the exchange's chains. *** ### to > **to**: `number` Defined in: packages/sdk/src/unified/bridge.ts:45 Chain id to send TO — must be one of the exchange's chains. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/unified/bridge.ts:47 Amount in base units of the ORIGIN side's decimals. *** ### recipient? > `optional` **recipient?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:49 Who receives on the destination. Defaults to the exchange's account (the same address on every chain). *** ### approveAmount? > `optional` **approveAmount?**: `bigint` Defined in: packages/sdk/src/unified/bridge.ts:51 Approve more than `amount` on a collateral route, or `0n` to skip the approval. --- # /docs/typescript/api/index/interfaces/ExchangeBridgeResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeBridgeResult # Interface: ExchangeBridgeResult Defined in: packages/sdk/src/unified/bridge.ts:98 What [ExchangeBridge.transfer](ExchangeBridge.md#transfer) resolves with. ## Properties ### plan > **plan**: [`BridgeTransfer`](../../chains/interfaces/BridgeTransfer.md) Defined in: packages/sdk/src/unified/bridge.ts:100 The plan that was executed. *** ### bridgeHash > **bridgeHash**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:102 Hash of the origin transaction that carried the bridge call (and the approval, when a safe packed both). *** ### approveHash? > `optional` **approveHash?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:104 Hash of the separate approval transaction, when one was sent on its own. *** ### messageId > **messageId**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:110 The Hyperlane message id of this transfer, decoded from the origin receipt. After a timeout, `delivered(messageId)` on the destination Mailbox tells whether the message has landed since. *** ### delivered > **delivered**: `boolean` Defined in: packages/sdk/src/unified/bridge.ts:112 True when the destination Mailbox processed this message within the timeout. *** ### deliveryHash? > `optional` **deliveryHash?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/bridge.ts:118 Hash of the destination transaction that delivered, when the SDK observed it. Absent when the message was already delivered before the watch opened: the Mailbox answers `delivered` with a boolean only. --- # /docs/typescript/api/index/interfaces/ExchangeBridgeTransferOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeBridgeTransferOptions # Interface: ExchangeBridgeTransferOptions Defined in: packages/sdk/src/unified/bridge.ts:75 Options for [ExchangeBridge.transfer](ExchangeBridge.md#transfer). ## Properties ### onStep? > `optional` **onStep?**: (`step`) => `void` Defined in: packages/sdk/src/unified/bridge.ts:77 Called on every step transition. #### Parameters ##### step [`BridgeStepEvent`](BridgeStepEvent.md) #### Returns `void` *** ### deliveryTimeoutMs? > `optional` **deliveryTimeoutMs?**: `number` Defined in: packages/sdk/src/unified/bridge.ts:90 How long to wait for delivery on the destination before giving up, counted from when the origin transaction is mined. The default is 180 s, about 20 times the measured median on the Hideki 2 lane. This bound stops once the destination Mailbox processes the message, and the read of the delivery receipt after that is given the same bound again. So a transfer whose message is processed just before the deadline can take up to twice this value in the worst case: the wait for `ProcessId`, then a destination node that never serves the receipt. Both legs are bounded, and neither falls back to the RPC client's own default. --- # /docs/typescript/api/index/interfaces/ExchangeDataStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeDataStatus # Interface: ExchangeDataStatus Defined in: packages/sdk/src/unified/exchange.ts:17 Opt-in mixed-tier status; each data source retains its own verdict. ## Extends - [`ExchangeStatus`](ExchangeStatus.md) ## Properties ### status > **status**: `"error"` \| `"ok"` \| `"connecting"` Defined in: packages/sdk/src/unified/exchange.ts:8 Existing chain-tail verdict only; no indexer or price threshold is inferred. #### Inherited from [`ExchangeStatus`](ExchangeStatus.md).[`status`](ExchangeStatus.md#status) *** ### updated > **updated**: `number` Defined in: packages/sdk/src/unified/exchange.ts:10 Wall-clock completion time, in milliseconds. #### Inherited from [`ExchangeStatus`](ExchangeStatus.md).[`updated`](ExchangeStatus.md#updated) *** ### info > **info**: [`TailStatus`](TailStatus.md) Defined in: packages/sdk/src/unified/exchange.ts:12 The PRIMARY chain's live-tail snapshot (watch count, socket + resync state). #### Inherited from [`ExchangeStatus`](ExchangeStatus.md).[`info`](ExchangeStatus.md#info) *** ### byChain > **byChain**: `Record`\<`number`, [`TailStatus`](TailStatus.md)\> Defined in: packages/sdk/src/unified/exchange.ts:14 Every configured chain's live-tail status, keyed by chain id. #### Inherited from [`ExchangeStatus`](ExchangeStatus.md).[`byChain`](ExchangeStatus.md#bychain) *** ### indexer? > `optional` **indexer?**: [`IndexerFreshness`](../type-aliases/IndexerFreshness.md) \| `null` Defined in: packages/sdk/src/unified/exchange.ts:25 The PRIMARY chain's raw independently measured indexer lag. An indexer with no metadata row for the chain fails the binding check with `NotConfiguredError` instead, so `null` is normally not reached; it remains for a row that goes missing after the check passed. The field is absent when the primary chain's measurement failed; `indexerErrorByChain` then holds that chain's error. *** ### indexerByChain > **indexerByChain**: `Record`\<`number`, [`IndexerFreshness`](../type-aliases/IndexerFreshness.md) \| `null`\> Defined in: packages/sdk/src/unified/exchange.ts:31 The indexer lag of every chain whose measurement succeeded, keyed by chain id. `null` means the chain's metadata row is absent. A chain whose measurement failed has no key here; its error is in `indexerErrorByChain`. *** ### indexerErrorByChain? > `optional` **indexerErrorByChain?**: `Record`\<`number`, [`SomniaMarketsClientGetIndexerFreshnessError`](../type-aliases/SomniaMarketsClientGetIndexerFreshnessError.md)\> Defined in: packages/sdk/src/unified/exchange.ts:37 The error of every chain whose measurement failed, keyed by chain id. Each value is the original error from that chain's read. The field is present only when at least one chain failed, so a fully healthy result keeps its old shape. *** ### prices > **prices**: `object`[] Defined in: packages/sdk/src/unified/exchange.ts:39 Every asset with price state, independently classified. #### asset > **asset**: `string` #### health > **health**: [`PriceFeedHealth`](../type-aliases/PriceFeedHealth.md) --- # /docs/typescript/api/index/interfaces/ExchangeSmartAccounts [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeSmartAccounts # Interface: ExchangeSmartAccounts Defined in: packages/sdk/src/unified/smartAccounts.ts:49 The exchange-level smart-accounts surface, reached as `exchange.accounts`. Spans every configured chain the accounts SDK covers; a configured chain it does not cover (a local anvil beside a testnet) is skipped where skipping is safe and refused where it is not — each member says which. ## Methods ### addressOf() > **addressOf**(`accountId`, `index`): `` `0x${string}` `` Defined in: packages/sdk/src/unified/smartAccounts.ts:57 The address `(accountId, index)` derives to — the same on every covered chain. Pure; no read. - Throws [InvalidInputError](../classes/InvalidInputError.md) - no configured chain is covered by the accounts SDK. #### Parameters ##### accountId `` `0x${string}` `` ##### index `bigint` #### Returns `` `0x${string}` `` *** ### scan() > **scan**(`accountId`, `options?`): `Promise`\<`CrossChainScan`\> Defined in: packages/sdk/src/unified/smartAccounts.ts:66 Scan `accountId`'s derived accounts on every covered configured chain at once: which slots are deployed where, which are empty, and which reads did not answer. Chain reads (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - no configured chain is covered, or the range is empty or wider than the accounts SDK's scan cap. #### Parameters ##### accountId `` `0x${string}` `` ##### options? ###### maxIndex? `bigint` ###### indices? readonly `bigint`[] #### Returns `Promise`\<`CrossChainScan`\> *** ### buildCreateAccounts() > **buildCreateAccounts**(`authorization`, `signature`): readonly [`UnsignedAccountCreation`](UnsignedAccountCreation.md)[] Defined in: packages/sdk/src/unified/smartAccounts.ts:76 Turn one signed authorization (from `client.accounts.buildAccountAuthorization` — its domain omits the chain id for exactly this) into one creation call PER covered configured chain. Each call needs its own funded sender; a chain that fails is retried on its own, not rolled back. - Throws [InvalidInputError](../classes/InvalidInputError.md) - no configured chain is covered. #### Parameters ##### authorization `AccountAuthorization` ##### signature `` `0x${string}` `` #### Returns readonly [`UnsignedAccountCreation`](UnsignedAccountCreation.md)[] *** ### accountFor() > **accountFor**(`accountId`, `index`, `inner`): [`SomniaMarketsAccount`](SomniaMarketsAccount.md) Defined in: packages/sdk/src/unified/smartAccounts.ts:98 The multi-chain account the exchange trades through, in one call: the derived address plus a smart-account executor per covered configured chain, each driving the account through `inner` on that chain. Hand the result to the exchange config's `account`. **Gotchas** A configured chain the accounts SDK does not cover gets NO executor — writes routed there will be refused by the facade's own missing-executor handling, not silently sent as someone else. A `{ sessionSeed }` inner signs locally on every chain; no request carries the seed. See [SmartAccountInner](../type-aliases/SmartAccountInner.md). - Throws [InvalidInputError](../classes/InvalidInputError.md) - no configured chain is covered, the seed is not 32 bytes of hex, or a factory returns an executor for another chain or a `createExecutor({ sessionSeed })` executor. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - a covered chain's engine has no chain transport. #### Parameters ##### accountId `` `0x${string}` `` ##### index `bigint` ##### inner [`SmartAccountInner`](../type-aliases/SmartAccountInner.md) #### Returns [`SomniaMarketsAccount`](SomniaMarketsAccount.md) --- # /docs/typescript/api/index/interfaces/ExchangeStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeStatus # Interface: ExchangeStatus Defined in: packages/sdk/src/unified/exchange.ts:6 Local chain-tail status, available without indexer or RPC requests. ## Extended by - [`ExchangeDataStatus`](ExchangeDataStatus.md) ## Properties ### status > **status**: `"error"` \| `"ok"` \| `"connecting"` Defined in: packages/sdk/src/unified/exchange.ts:8 Existing chain-tail verdict only; no indexer or price threshold is inferred. *** ### updated > **updated**: `number` Defined in: packages/sdk/src/unified/exchange.ts:10 Wall-clock completion time, in milliseconds. *** ### info > **info**: [`TailStatus`](TailStatus.md) Defined in: packages/sdk/src/unified/exchange.ts:12 The PRIMARY chain's live-tail snapshot (watch count, socket + resync state). *** ### byChain > **byChain**: `Record`\<`number`, [`TailStatus`](TailStatus.md)\> Defined in: packages/sdk/src/unified/exchange.ts:14 Every configured chain's live-tail status, keyed by chain id. --- # /docs/typescript/api/index/interfaces/ExecuteOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExecuteOptions # Interface: ExecuteOptions Defined in: packages/sdk/src/executor/types.ts:29 Per-call knobs the writer hands an executor. Everything is optional; an executor that has no use for a field ignores it. ## Properties ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/executor/types.ts:31 Gas ceiling for the transaction (the writer's default when unset). Never estimated. *** ### context? > `optional` **context?**: `object` Defined in: packages/sdk/src/executor/types.ts:40 What the WRITE does, for error messages: the function name of the last call in the list. Each call names its own `functionName` and an executor reads that first; this is the fallback for a call that carries none. An executor threads it into the [ContractRevertError](../classes/ContractRevertError.md) it raises so a revert reads "placeBinaryOrder reverted: …" rather than naming only the address. #### functionName? > `optional` **functionName?**: `string` *** ### parentSpan? > `optional` **parentSpan?**: [`Span`](Span.md) Defined in: packages/sdk/src/executor/types.ts:45 The writer's debug span, so an executor that traces (the built-in ones do) nests its sign/broadcast spans under the write. Foreign executors ignore it. --- # /docs/typescript/api/index/interfaces/Executed [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Executed # Interface: Executed Defined in: packages/sdk/src/executor/types.ts:62 What an executor hands back: the receipt it already holds, fetched once by whoever sent the transaction, plus any INNER failure it detected that the receipt's own status does not show. **Details** `failure` is how a safe reports a swallowed revert: the outer transaction mines with `status: "success"` while the safe's failure event says the inner call reverted. The writer throws it exactly as it throws a reverted receipt, so a caller never has to know which actor sent the write. ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/executor/types.ts:64 Hash of the transaction the executor sent (the OUTER transaction for a safe). *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/executor/types.ts:66 The mined receipt, as the executor received it. *** ### failure? > `optional` **failure?**: [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/executor/types.ts:68 An inner failure the executor detected on a receipt whose status is success. *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/executor/types.ts:77 Node-side end-to-end time of the send in microseconds (mempool, finality and execution), as the node reported it with the receipt. The built-in local-signer and session-key executors set it from the `executionTimeMicros` field of `eth_sendRawTransactionSync` and `somnia_sendSessionTransaction`. Leave it unset when the send path does not report it; the writer passes it through to the write's result. --- # /docs/typescript/api/index/interfaces/Executor [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Executor # Interface: Executor Defined in: packages/sdk/src/executor/types.ts:160 Executes unsigned calls on ONE chain as ONE actor and returns the receipt. **Details** - `chainId` is the only chain this executor sends on. A call carrying another `chainId` is refused with [InvalidInputError](../classes/InvalidInputError.md) before anything is signed — the guard every built-in executor applies through [assertCallsOnChain](../functions/assertCallsOnChain.md), and one a custom executor should apply too. - `actor` is the address the pool sees as `msg.sender`: the signer for a key or wallet, the session account for a session key, the safe itself for a safe. The writer reads allowances and operator grants for it. - `execute` takes a LIST because a safe can pack several calls into one transaction (an approval and the order it enables). An executor that cannot batch executes the calls in order, each as its own transaction, and STOPS at the first receipt whose `status` is `"reverted"` or that carries a `failure`, returning that receipt so the writer throws it — the calls after it are never sent. When every call succeeds it returns the last receipt. **Gotchas** An executor never fetches a receipt it already has: the SDK decodes the order id and fills from `receipt.logs`. Return the receipt the send gave you (`eth_sendRawTransactionSync` and `somnia_sendSessionTransaction` both return it in the same call). **Example** (A custom executor over an app's own account layer) ```ts const executor: Executor = { chainId: 5031, actor: safeAddress, async execute(calls) { const hash = await myAccountLayer.sendBatch(calls); // your safe, your relayer… const receipt = await myAccountLayer.waitForReceipt(hash); return { hash, receipt }; // decoded by the SDK from here }, }; const trader = exchange.client.createTrader({ executor }); ``` ## Properties ### chainId > `readonly` **chainId**: `number` Defined in: packages/sdk/src/executor/types.ts:162 The one chain this executor sends on. *** ### actor > `readonly` **actor**: `` `0x${string}` `` Defined in: packages/sdk/src/executor/types.ts:164 The address the chain sees as the caller of every call this executor sends. *** ### signTypedData? > `readonly` `optional` **signTypedData?**: [`TypedDataSigner`](../type-aliases/TypedDataSigner.md) Defined in: packages/sdk/src/executor/types.ts:198 Present on actors that can sign EIP-712 typed data as themselves. - Throws [RpcError](../classes/RpcError.md) - the signer failed or refused; `cause` has the original. The complete union is [ExecutorSignTypedDataError](../type-aliases/ExecutorSignTypedDataError.md). ## Methods ### execute() > **execute**(`calls`, `options?`): `Promise`\<[`Executed`](Executed.md)\> Defined in: packages/sdk/src/executor/types.ts:190 Send `calls` (one transaction where possible) and return the receipt. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `calls` is empty or names another chain, the accounts SDK refuses a smart account's input, or a session send has no positive gas limit. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - a chain read the executor needs has no chain transport. - Throws [RpcError](../classes/RpcError.md) - the signer, transport or node failed, or the node refused the transaction; `cause` has the original. From the local-signer and session-key executors, nothing was sent or the node refused it. A wallet can fail after it broadcast. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - a signed transaction may have reached the node and its receipt was not observed. `hash` names it (absent for a session send). Look it up before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the send surfaced a revert with data before mining. The complete union is [ExecutorExecuteError](../type-aliases/ExecutorExecuteError.md). A MINED revert is not a throw: it comes back as a `"reverted"` receipt for the writer to decode. **Retry rule.** Never send a write again after a `TransactionOutcomeUnknownError` until you know what happened to `hash`. Read its receipt, or read the state the write changes. A blind retry can execute the write twice. #### Parameters ##### calls readonly [`UnsignedCall`](UnsignedCall.md)[] ##### options? [`ExecuteOptions`](ExecuteOptions.md) #### Returns `Promise`\<[`Executed`](Executed.md)\> --- # /docs/typescript/api/index/interfaces/FaucetParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FaucetParams # Interface: FaucetParams Defined in: packages/sdk/src/trade.ts:2189 Inputs to [Trader.faucet](Trader.md#faucet) — mint TestUSDC to the signer (testnet only). ## Properties ### amount? > `optional` **amount?**: `bigint` Defined in: packages/sdk/src/trade.ts:2191 Amount to mint (default 10,000 × 10^decimals). *** ### testUsdc? > `optional` **testUsdc?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2193 TestUSDC address; defaults to the configured one. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2199 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/FetchOrderBookOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FetchOrderBookOptions # Interface: FetchOrderBookOptions Defined in: packages/sdk/src/unified/exchange.ts:218 Options for a unified chain book snapshot. ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:220 Maximum levels per side, defaults to 10. The legacy numeric argument still works. *** ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/unified/exchange.ts:222 Pin both sides to this exact block; omitted selects one head. --- # /docs/typescript/api/index/interfaces/FinalizeMarketParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FinalizeMarketParams # Interface: FinalizeMarketParams Defined in: packages/sdk/src/trade.ts:1914 Permissionless keeper entry: finalize a settled market (sweep its pool's backing + resolution snapshot to the settlement singleton). No-op-guarded. ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1916 bytes32 marketId to finalize; the market must be resolved or voided. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1918 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1924 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/FixedFees [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FixedFees # Interface: FixedFees Defined in: packages/sdk/src/config.ts:274 Fixed EIP-1559 fees every SDK-signed write uses. The SDK never estimates fees — no per-order eth_gasPrice / fee-history round-trip. `maxFeePerGas` is a ceiling (the tx pays base fee + tip, the rest is refunded), so a generous fixed value costs nothing extra on Somnia's flat gas market. ## Properties ### maxFeePerGas > **maxFeePerGas**: `bigint` Defined in: packages/sdk/src/config.ts:276 Total fee ceiling (wei per gas); the unspent margin over base fee + tip refunds. *** ### maxPriorityFeePerGas > **maxPriorityFeePerGas**: `bigint` Defined in: packages/sdk/src/config.ts:278 Priority tip (wei per gas) paid to the proposer on top of the base fee. --- # /docs/typescript/api/index/interfaces/FundHubParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundHubParams # Interface: FundHubParams Defined in: packages/sdk/src/oracleHub.ts:434 Parameters for [OracleHubAdmin.fundHub](OracleHubAdmin.md#fundhub). ## Properties ### amountWei > **amountWei**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:440 Native amount (wei) sent to the hub's `receive()` — tops up the reactivity bond the precompile debits callbacks from. NOT credited to any operator (resolution funding is attached per-market at create/onBind). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:442 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/FundMarketCreatorParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundMarketCreatorParams # Interface: FundMarketCreatorParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:100 Params for [MarketCreatorAdmin.fundMarketCreator](MarketCreatorAdmin.md#fundmarketcreator). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:102 The MarketCreator to fund. *** ### amountWei > **amountWei**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:104 Native amount (wei) to send to the creator's `receive()`. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:106 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/FundingBucketLike [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingBucketLike # Interface: FundingBucketLike Defined in: packages/sdk/src/funding.ts:191 The subset of a funding candle this densification needs. ## Properties ### bucketStart > **bucketStart**: `string` Defined in: packages/sdk/src/funding.ts:192 *** ### intervalSeconds > **intervalSeconds**: `number` Defined in: packages/sdk/src/funding.ts:193 --- # /docs/typescript/api/index/interfaces/GetAutoPullRequirementParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetAutoPullRequirementParams # Interface: GetAutoPullRequirementParams Defined in: packages/sdk/src/spot/poolReads.ts:20 Identifies an order shape to price for funding — see [SomniaMarketsClient.getAutoPullRequirement](SomniaMarketsClient.md#getautopullrequirement). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:22 SpotPool to ask. *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:24 Account whose vault balance the shortfall is measured against. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/spot/poolReads.ts:26 True = buy base (input is quote); false = sell base (input is base). *** ### price > **price**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:28 Limit price, raw quote units per whole base. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:30 Base quantity, raw base units. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:35 Builder fee in bps × 1000 (the contract's own encoding — 2500 = 2.5 bps). #### Default ```ts 0n (no builder) ``` --- # /docs/typescript/api/index/interfaces/GetBankruptcyPriceOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetBankruptcyPriceOptions # Interface: GetBankruptcyPriceOptions Defined in: packages/sdk/src/perp/margin.ts:1250 Options for the client's `getBankruptcyPrice` method. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1255 Read at this block instead of the current head. Pass an enumeration's `asOfBlock` to price its holders on the same consistent snapshot. --- # /docs/typescript/api/index/interfaces/GetBinaryOrderBookOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetBinaryOrderBookOptions # Interface: GetBinaryOrderBookOptions Defined in: packages/sdk/src/orders.ts:1343 Options for a native binary chain snapshot. ## Extends - [`GetSpotOrderBookOptions`](GetSpotOrderBookOptions.md) ## Properties ### decimals? > `optional` **decimals?**: `number` Defined in: packages/sdk/src/orders.ts:1345 Collateral decimals for NO inversion. Defaults to 6. *** ### depth? > `optional` **depth?**: `number` Defined in: packages/sdk/src/orders.ts:1351 Maximum levels per side. Defaults to 12 for spot and 10 for binary. #### Inherited from [`GetSpotOrderBookOptions`](GetSpotOrderBookOptions.md).[`depth`](GetSpotOrderBookOptions.md#depth) *** ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:1353 Exact block for both sides. Omitted: sample one head and pin both reads. #### Inherited from [`GetSpotOrderBookOptions`](GetSpotOrderBookOptions.md).[`blockNumber`](GetSpotOrderBookOptions.md#blocknumber) --- # /docs/typescript/api/index/interfaces/GetBookTopsOnchainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetBookTopsOnchainOptions # Interface: GetBookTopsOnchainOptions Defined in: packages/sdk/src/orders.ts:552 Options for one chain-sourced top-of-book batch read. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:558 Read at this exact block instead of pinning the current head. Every pool in the call quotes the SAME block either way — that pin, not the batching, is what makes the tops of N markets comparable to each other. --- # /docs/typescript/api/index/interfaces/GetManualVaultModeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetManualVaultModeParams # Interface: GetManualVaultModeParams Defined in: packages/sdk/src/spot/vaultMode.ts:70 Identifies one user's vault mode on one pool — see [SomniaMarketsClient.getManualVaultMode](SomniaMarketsClient.md#getmanualvaultmode). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/vaultMode.ts:72 The SpotPool to read. *** ### user > **user**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/vaultMode.ts:74 The user whose mode to read. --- # /docs/typescript/api/index/interfaces/GetOpenOrdersOnchainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetOpenOrdersOnchainOptions # Interface: GetOpenOrdersOnchainOptions Defined in: packages/sdk/src/orders.ts:1066 Options for `client.getOpenOrdersOnchain(pools, owner, opts)`. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:1072 Read at this exact block instead of pinning the current head. Every read in the call quotes the SAME block either way — that pin is what makes the ids and their details agree. --- # /docs/typescript/api/index/interfaces/GetOrderOnchainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetOrderOnchainOptions # Interface: GetOrderOnchainOptions Defined in: packages/sdk/src/orders.ts:865 Options for one on-chain order read. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:903 Read the order as of the END of this block instead of at head. For a maker order a fill has already consumed: the fill removes it in the same transaction, so `fill.blockNumber - 1n` is the last height that still holds it. `OrderFilled` names the maker only by id, and the pool keeps no record of a removed order at head. What this recovers is the maker's IDENTITY state - `isBid`, `owner`, `userData`, `expireTimestampNs` - which no path changes under a given id, so it is exact at any height the order existed, and which no fill log carries: `OrderFilled` names the maker by id alone. Only `OrderPlaced` carries it, and a consumer that was not listening when the maker rested does not have that log - which is the whole case for this read. `price` is immutable too, and is the one immutable field NOT to read for: a fill executes at the MAKER's resting price, and the book emits that same `price` as the fill event's own. Reading the maker order to price a fill is redundant work. BOTH quantities are block-level, and neither is per-fill. A block read cannot see between transactions, so `fullQuantity` and `quantityRemaining` are the values at the block BOUNDARY: an earlier transaction in the fill's own block may have filled this maker, or reduced it - `reduceOrder` decrements both by the same amount, under the same id. Take `quantityFilled` and `makerRemainingQuantity` from the event; no block-level read reconstructs per-transaction size. Two more edges answer plausibly rather than failing: - A PARTIAL fill leaves the order in place, so a read at the fill's OWN block succeeds with a smaller `quantityRemaining` where a full fill answers `null`. - An order PLACED AND FILLED in one block does not exist at `blockNumber - 1n`, so that read is `null` and the caller needs the placement from the same block's `OrderPlaced` instead. A recent block answers against a full node. An old one needs ARCHIVE state, so this serves a live tape, not a backfill or a replay of last week. --- # /docs/typescript/api/index/interfaces/GetOutcomeBalanceParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetOutcomeBalanceParams # Interface: GetOutcomeBalanceParams Defined in: packages/sdk/src/binary/portfolio.ts:529 Identifies one ERC-6909 outcome position — see `getOutcomeBalance`. ## Properties ### outcomeToken > **outcomeToken**: `` `0x${string}` `` Defined in: packages/sdk/src/binary/portfolio.ts:531 The outcome-token singleton address (from `MarketOnchain`). *** ### account > **account**: `` `0x${string}` `` Defined in: packages/sdk/src/binary/portfolio.ts:533 The balance's owner. *** ### id > **id**: `bigint` Defined in: packages/sdk/src/binary/portfolio.ts:535 The position id — the market's `yesId`/`noId`. --- # /docs/typescript/api/index/interfaces/GetOwnOpenOrdersOnchainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetOwnOpenOrdersOnchainOptions # Interface: GetOwnOpenOrdersOnchainOptions Defined in: packages/sdk/src/orders.ts:997 Options for `client.getOwnOpenOrdersOnchain(pool, owner, opts)`. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:1003 Read at this exact block instead of at head. Supply it to join these ids with other reads at one state — an id read at head and a detail read a block later can disagree, because a fill removes an order. --- # /docs/typescript/api/index/interfaces/GetPerpMaxLeverageOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetPerpMaxLeverageOptions # Interface: GetPerpMaxLeverageOptions Defined in: packages/sdk/src/perp/margin.ts:2948 Options for the client's `getPerpMaxLeverage` method. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:2954 Read at this block instead of the current head. Pass an enumeration's or an analytics row's `asOfBlock` to keep the cap on the same consistent snapshot as the figures it is combined with. --- # /docs/typescript/api/index/interfaces/GetPerpSideHoldersOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetPerpSideHoldersOptions # Interface: GetPerpSideHoldersOptions Defined in: packages/sdk/src/perp/margin.ts:1136 Options for `getPerpSideHolders` (the client's `getPerpSideHolders` method). ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1141 Pin the enumeration to this block instead of the current head — e.g. the `asOfBlock` of the other side's call, so both sides describe one state. *** ### pageSize? > `optional` **pageSize?**: `number` Defined in: packages/sdk/src/perp/margin.ts:1147 Holders fetched per contract call. #### Default ```ts 1000 ``` --- # /docs/typescript/api/index/interfaces/GetPoolMarketBindingOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetPoolMarketBindingOptions # Interface: GetPoolMarketBindingOptions Defined in: packages/sdk/src/markets.ts:2146 Options for `client.getPoolMarketBinding(pool, opts)`. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/markets.ts:2151 Read at this block instead of the current head. Supply it to join this binding with other reads at one state. --- # /docs/typescript/api/index/interfaces/GetSpotOrderBookOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetSpotOrderBookOptions # Interface: GetSpotOrderBookOptions Defined in: packages/sdk/src/orders.ts:1349 Options for a native chain snapshot. ## Extended by - [`GetBinaryOrderBookOptions`](GetBinaryOrderBookOptions.md) ## Properties ### depth? > `optional` **depth?**: `number` Defined in: packages/sdk/src/orders.ts:1351 Maximum levels per side. Defaults to 12 for spot and 10 for binary. *** ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:1353 Exact block for both sides. Omitted: sample one head and pin both reads. --- # /docs/typescript/api/index/interfaces/GetVaultBalanceParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetVaultBalanceParams # Interface: GetVaultBalanceParams Defined in: packages/sdk/src/binary/portfolio.ts:486 Identifies one owner's claimable balance in one pool vault — see [client.getVaultBalance](SomniaMarketsClient.md#getvaultbalance). ## Properties ### vault > **vault**: `` `0x${string}` `` Defined in: packages/sdk/src/binary/portfolio.ts:488 The ERC20Vault address (the pool address). *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/binary/portfolio.ts:490 The balance's owner. *** ### token > **token**: `` `0x${string}` `` Defined in: packages/sdk/src/binary/portfolio.ts:492 The ERC-20 address (or the vault's native sentinel). *** ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/binary/portfolio.ts:504 Read the balance as of this block instead of at head. For an answer that combines this balance with other reads at one height: the withdrawable balance is contract state behind an append-only payout history, so there is no indexed entity to reconstruct it from at a past height, and serving this half at head would silently mix heights inside one response. A recent block answers against a full node. An old one needs ARCHIVE state, and a node without it rejects the read rather than returning a wrong number. --- # /docs/typescript/api/index/interfaces/GovernanceAdmin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GovernanceAdmin # Interface: GovernanceAdmin Defined in: packages/sdk/src/governanceAdmin.ts:48 The protocol-admin governance surface on BinaryMarketsModule — the one seam an operator can't self-serve (see the module notes above). Built via `client.createGovernanceAdmin(config)` with a signer ([GovernanceAdminConfig](OracleHubAdminConfig.md)); the write is module-owner only, the reads are open chain point reads. Every write throws `ContractRevertError` when the chain rejects it — at simulation, at send, or as a mined receipt with `status: "reverted"` (the reason is recovered by replaying the call at that block while the node still has the state) — and `RpcError` when the send or the receipt read does not complete. A reverted write never resolves as if it had been confirmed. ## Methods ### setAdapterApproved() > **setAdapterApproved**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/governanceAdmin.ts:55 Approve (or revoke) an oracle adapter on the module — the inert→live gate for a factory-minted adapter. MODULE-OWNER ONLY: reverts for any other caller, so a UI shows this only to the protocol admin (see [GovernanceAdmin.isModuleOwner](#ismoduleowner)). #### Parameters ##### p [`SetAdapterApprovedParams`](SetAdapterApprovedParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### getModuleOwner() > **getModuleOwner**(): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/governanceAdmin.ts:57 The module owner (the protocol admin). Needs `config.addresses.binaryModule`. #### Returns `Promise`\<`` `0x${string}` ``\> *** ### isModuleOwner() > **isModuleOwner**(`addr`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/governanceAdmin.ts:62 Whether `addr` is the module owner — gate the `setAdapterApproved` UI on this. Needs `config.addresses.binaryModule`. #### Parameters ##### addr `` `0x${string}` `` #### Returns `Promise`\<`boolean`\> --- # /docs/typescript/api/index/interfaces/HandoffToParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HandoffToParams # Interface: HandoffToParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:244 Params for [MarketCreatorAdmin.handoffTo](MarketCreatorAdmin.md#handoffto). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:246 The OUTGOING creator to retire. Caller must be its owner. *** ### successor > **successor**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:248 The incoming creator (same owner + venue) the float is swept to. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:250 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/HoldingsPoint [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HoldingsPoint # Interface: HoldingsPoint Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:197 One sample of the holdings series: the traded book, marked. ## Properties ### t > **t**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:199 Sample time (ms). *** ### valueUsd > **valueUsd**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:201 Marked value of the open positions this sample could price, USD. *** ### unpricedMarkets > **unpricedMarkets**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:216 How many open markets this sample could NOT price, and so left out of [HoldingsPoint.valueUsd](#valueusd). A market with no candle sample and no last price has no mark. The fold values that position at zero, which is a real price standing in for a missing one — so the level silently loses a position the wallet still holds. This count is how a caller knows. Zero means the sample priced everything and the value is the whole book. Present the shortfall rather than hiding it. A wallet holding one quiet market reads as poorer than it is, which is the fault SMK-45 reports at the account level. --- # /docs/typescript/api/index/interfaces/HubPreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HubPreflightInput # Interface: HubPreflightInput Defined in: packages/sdk/src/preflight.ts:173 Inputs for the hub-step preflight: the hub's on-chain status (from `OracleHubAdmin.getHubStatus`, or the subset a caller already holds) and whether the connected chain supports the reactivity precompile (local anvil does NOT). Unlike the retired adapter step, the armed state IS cheaply readable on-chain (`subscriptionId != 0`). ## Properties ### status > **status**: `Pick`\<[`HubStatus`](HubStatus.md), `"approved"` \| `"subscriptionId"` \| `"balanceWei"`\> Defined in: packages/sdk/src/preflight.ts:175 The subset of [HubStatus](HubStatus.md) the check needs. *** ### precompileAvailable > **precompileAvailable**: `boolean` Defined in: packages/sdk/src/preflight.ts:180 Whether the connected chain has the Somnia reactivity precompile (false on local anvil). --- # /docs/typescript/api/index/interfaces/HubQuestionState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HubQuestionState # Interface: HubQuestionState Defined in: packages/sdk/src/oracleHub.ts:297 One question's live dedup state on the hub. ## Properties ### questionKey > **questionKey**: `` `0x${string}` `` Defined in: packages/sdk/src/oracleHub.ts:302 Canonical dedup key for the definition (zero for non-template definitions, which bypass dedup). *** ### oracleQuestionId > **oracleQuestionId**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:304 The ACTIVE question id the key resolves to (0n = never scheduled). *** ### bindCount > **bindCount**: `number` Defined in: packages/sdk/src/oracleHub.ts:306 Lifetime bind count for that question (drives the cap-split). *** ### markets > **markets**: `` `0x${string}` ``[] Defined in: packages/sdk/src/oracleHub.ts:308 Every marketId bound to the question (the fan-out list the drain walks). --- # /docs/typescript/api/index/interfaces/HubStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HubStatus # Interface: HubStatus Defined in: packages/sdk/src/oracleHub.ts:316 Live on-chain status of the hub (the point read a panel confirms). ## Properties ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/oracleHub.ts:318 Hub owner — the account gated into `withdraw` / gas + drain param writes. *** ### balanceWei > **balanceWei**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:323 Total native balance (wei) the hub holds (Σ earmarked + accrued credit + reactivity bond float). *** ### approved > **approved**: `boolean` Defined in: packages/sdk/src/oracleHub.ts:328 Whether the module has the hub approved (`approvedAdapters(hub)`) — the wired/live gate. *** ### subscriptionId > **subscriptionId**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:330 Reactivity subscription id; 0n until `enableReactivity` succeeds. *** ### priorityFeePerGas > **priorityFeePerGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:332 Reactivity-callback tip (wei per gas). *** ### maxFeePerGas > **maxFeePerGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:334 Reactivity-callback fee ceiling (wei per gas); one factor of `resolveReserve`. *** ### gasLimit > **gasLimit**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:336 Gas limit each reactivity callback runs with. *** ### perMarketResolveGas > **perMarketResolveGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:338 Per-market resolve-slice gas constant (sizes `resolveReserve`). *** ### callbackBaseGas > **callbackBaseGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:340 Explicitly-attributed callback overhead gas constant (metering). *** ### maxResolvesPerCallback > **maxResolvesPerCallback**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:342 Belt-and-suspenders cap on markets resolved per callback. *** ### resolveGasReserve > **resolveGasReserve**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:344 Gas reserve that breaks the drain loop to the next block. *** ### resolveReserveWei > **resolveReserveWei**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:346 Per-market resolution reserve attached+locked at onBind (`resolveReserve()`, wei). *** ### pendingResolves > **pendingResolves**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:348 Markets still queued for resolution across all pending qids. --- # /docs/typescript/api/index/interfaces/IndependentHead [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndependentHead # Interface: IndependentHead Defined in: packages/sdk/src/syncStatus.ts:343 Independent chain observation shared by a group of reads. It is not a snapshot pin. ## Properties ### chainId > `readonly` **chainId**: `number` Defined in: packages/sdk/src/syncStatus.ts:345 Owner chain. *** ### blockNumber > `readonly` **blockNumber**: `bigint` Defined in: packages/sdk/src/syncStatus.ts:347 Latest height returned by the owner's RPC. *** ### timestamp > `readonly` **timestamp**: `bigint` Defined in: packages/sdk/src/syncStatus.ts:349 Block time in Unix seconds. *** ### observedAt > `readonly` **observedAt**: `number` Defined in: packages/sdk/src/syncStatus.ts:351 Wall-clock time at RPC completion, in milliseconds. --- # /docs/typescript/api/index/interfaces/IndexedPool [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedPool # Interface: IndexedPool Defined in: packages/sdk/src/pools.ts:174 The indexer's per-pool aggregate (`Pool`; id = lowercased pool address) — the long-lived BinaryPool contract that outlives any single market. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/pools.ts:176 Lowercased pool address (== address). *** ### address > **address**: `string` Defined in: packages/sdk/src/pools.ts:178 Lowercased pool address (== id). *** ### collateral > **collateral**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:180 Collateral token the pool is bound to for its whole life (lowercased). *** ### creator > **creator**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:185 The pool's creator — its first-deploy market creator, the only party that can reuse it (lowercased). *** ### currentMarketId > **currentMarketId**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:190 marketId of the pool's CURRENT binding; null when finalized + released and awaiting reuse. *** ### currentNonce > **currentNonce**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:192 Pool market nonce of the current binding (decimal string). *** ### generationCount > **generationCount**: `number` Defined in: packages/sdk/src/pools.ts:194 Number of markets this pool has served (== the latest nonce). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/pools.ts:196 Timestamp (unix seconds) of the pool's first MarketCreated. *** ### updatedAtTimestamp > **updatedAtTimestamp**: `string` Defined in: packages/sdk/src/pools.ts:198 Timestamp (unix seconds) of the last binding change. --- # /docs/typescript/api/index/interfaces/IndexerLimits [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerLimits # Interface: IndexerLimits Defined in: packages/sdk/src/config.ts:317 Bounds on how hard one client may push its indexer: in-flight cap, circuit breaker, backoff schedule. They only ever reduce load, so [DEFAULT\_INDEXER\_LIMITS](../variables/DEFAULT_INDEXER_LIMITS.md) is safe to leave alone. **Gotchas** The SDK does not retry by default (`maxAttempts` is 1). A caller that already retries — a React Query `retry`, a polling loop — must not raise it, or the two multiply. ## Properties ### maxInFlight? > `optional` **maxInFlight?**: `number` Defined in: packages/sdk/src/config.ts:322 Reads on the wire at once (default 12). The rest queue locally, holding no indexer connection, and still honour their caller's abort signal. *** ### breakerThreshold? > `optional` **breakerThreshold?**: `number` Defined in: packages/sdk/src/config.ts:327 Consecutive endpoint failures that open the breaker (default 5): timeouts and overload responses (HTTP 429, 502, 503, 504). Only these count — a 400 is the query's fault. Any answer clears the count. *** ### breakerCooldownMs? > `optional` **breakerCooldownMs?**: `number` Defined in: packages/sdk/src/config.ts:333 How long the breaker stays open (default 30_000 ms). Reads fail at once with [IndexerUnavailableError](../classes/IndexerUnavailableError.md) and nothing is sent. Then one trial read decides: an answer closes the breaker, another failure restarts the wait. *** ### baseDelayMs? > `optional` **baseDelayMs?**: `number` Defined in: packages/sdk/src/config.ts:335 First backoff step in ms (default 500), doubled per attempt before jitter. *** ### maxDelayMs? > `optional` **maxDelayMs?**: `number` Defined in: packages/sdk/src/config.ts:337 Ceiling the doubling stops at, in ms (default 30_000), applied before jitter. *** ### maxAttempts? > `optional` **maxAttempts?**: `number` Defined in: packages/sdk/src/config.ts:339 Attempts the boundary makes per read (default 1 — no retry). See the gotcha above. *** ### maxQueued? > `optional` **maxQueued?**: `number` Defined in: packages/sdk/src/config.ts:346 Reads allowed to WAIT for a slot (default 100). Past this the read is refused with [IndexerUnavailableError](../classes/IndexerUnavailableError.md) rather than queued, so a client whose arrivals outrun the cap sheds load instead of growing a backlog that outlives the requests waiting on it. --- # /docs/typescript/api/index/interfaces/IndexerObservation [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerObservation # Interface: IndexerObservation Defined in: packages/sdk/src/observedReads.ts:133 Response-associated indexing watermark. This does not claim an entity changed at that block. ## Properties ### chainId > `readonly` **chainId**: `number` Defined in: packages/sdk/src/observedReads.ts:135 Configured owner chain. *** ### latestProcessedBlock > `readonly` **latestProcessedBlock**: `bigint` \| `null` Defined in: packages/sdk/src/observedReads.ts:137 Conservative minimum across successful data-bearing requests; null if any metadata is missing. *** ### startedAt > `readonly` **startedAt**: `number` \| `null` Defined in: packages/sdk/src/observedReads.ts:139 First contributing request start, in Unix milliseconds. Null for a result requiring no request. *** ### completedAt > `readonly` **completedAt**: `number` \| `null` Defined in: packages/sdk/src/observedReads.ts:141 Last contributing response completion, in Unix milliseconds. *** ### responseCount > `readonly` **responseCount**: `number` Defined in: packages/sdk/src/observedReads.ts:143 Successful data-bearing response count; rejected aggregate attempts do not count. *** ### independentHead > `readonly` **independentHead**: [`IndependentHead`](IndependentHead.md) Defined in: packages/sdk/src/observedReads.ts:145 Shared comparison observation, not an atomic historical snapshot. --- # /docs/typescript/api/index/interfaces/InsuranceFundState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / InsuranceFundState # Interface: InsuranceFundState Defined in: packages/sdk/src/perp/system.ts:89 The InsuranceFund's solvency picture. ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:93 The fund's address. *** ### maxTiers > **maxTiers**: `bigint` Defined in: packages/sdk/src/perp/system.ts:98 The maximum tier INDEX, not a count — the fund has `maxTiers + 1` addressable buckets, because tier 0 exists alongside coverage tiers `1..maxTiers`. *** ### totalBalance > **totalBalance**: `bigint` Defined in: packages/sdk/src/perp/system.ts:112 Sum across every tier including tier 0, raw collateral units — the contract's own `getTotalTierBalances`, which is the figure the INV-TIER accounting invariant is stated against. **Not "how much bad debt this stack can absorb"**, on two counts. Tier 0 is included here but never absorbs anything, so collateral parked there inflates the number without backing a single market. And each coverage tier is charged only its own pools' realized losses, capped at `min(funded, own loss)` and never subsidising another tier — so even the `1..maxTiers` sum is an upper bound that no single event can draw down in full. For absorption against a specific market, read that market's tier from [tiers](#tiers). *** ### tiers > **tiers**: [`InsuranceFundTier`](InsuranceFundTier.md)[] Defined in: packages/sdk/src/perp/system.ts:114 Per-tier balances and how many pools each backs, tier 0 first. --- # /docs/typescript/api/index/interfaces/InsuranceFundTier [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / InsuranceFundTier # Interface: InsuranceFundTier Defined in: packages/sdk/src/perp/system.ts:70 One tier of the InsuranceFund. ## Properties ### tier > **tier**: `number` Defined in: packages/sdk/src/perp/system.ts:77 Tier index. `0` is the general/unallocated bucket — a reserved sentinel that never absorbs bad debt and backs no pools (its [poolCount](#poolcount) is structurally zero, since tier 0 means "uncovered" and is not tracked). Coverage tiers run `1..maxTiers`. *** ### balance > **balance**: `bigint` Defined in: packages/sdk/src/perp/system.ts:79 Collateral held in this tier, raw units. *** ### poolCount > **poolCount**: `bigint` Defined in: packages/sdk/src/perp/system.ts:81 How many perp pools this tier backs. --- # /docs/typescript/api/index/interfaces/IsApprovedForPoolParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IsApprovedForPoolParams # Interface: IsApprovedForPoolParams Defined in: packages/sdk/src/spot/operatorGrants.ts:218 Identifies a per-pool grant slot to read — see [SomniaMarketsClient.isApprovedForPool](SomniaMarketsClient.md#isapprovedforpool). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:220 SpotPool the grant applies on. *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:222 Account that would have granted it (the signer of the grant). *** ### operator > **operator**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:224 Account acting on the owner's behalf. *** ### selector > **selector**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:226 4-byte function selector the operator wants to call. --- # /docs/typescript/api/index/interfaces/IsGloballyApprovedParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IsGloballyApprovedParams # Interface: IsGloballyApprovedParams Defined in: packages/sdk/src/spot/operatorGrants.ts:204 Identifies a global grant slot to read — see [SomniaMarketsClient.isGloballyApproved](SomniaMarketsClient.md#isgloballyapproved). ## Properties ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:206 Account that would have granted it (the signer of the grant). *** ### operator > **operator**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:208 Account acting on the owner's behalf. *** ### selector > **selector**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/operatorGrants.ts:210 4-byte function selector the operator wants to call. --- # /docs/typescript/api/index/interfaces/IsOperatorAuthorizedParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IsOperatorAuthorizedParams # Interface: IsOperatorAuthorizedParams Defined in: packages/sdk/src/spot/poolReads.ts:102 Identifies an operator grant to check — see [SomniaMarketsClient.isOperatorAuthorized](SomniaMarketsClient.md#isoperatorauthorized). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:104 SpotPool the grant applies on. *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:106 Account that would have granted it. *** ### operator > **operator**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:108 Account acting on the owner's behalf. *** ### selector > **selector**: `` `0x${string}` `` Defined in: packages/sdk/src/spot/poolReads.ts:110 4-byte function selector the operator wants to call (e.g. `placeOrderFor`). --- # /docs/typescript/api/index/interfaces/LendAccount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendAccount # Interface: LendAccount Defined in: packages/sdk/src/lend/types.ts:143 A whole SomniaLend account: the Pool's risk aggregate plus every non-empty per-reserve position, in one read. **Details** `healthFactor` is a wad (1e18): liquidation triggers below 1e18. The `*Base` aggregates are denominated in the oracle base currency (`baseCurrencyDecimals`, USD/8dp on this deployment). **Gotchas** A debt-free account reports `maxUint256` ("infinite") as its `healthFactor`. The `*Base` aggregates are cross-asset totals, not token amounts. ## Properties ### totalCollateralBase > **totalCollateralBase**: `bigint` Defined in: packages/sdk/src/lend/types.ts:145 Total collateral backing the account, base-currency units. *** ### totalDebtBase > **totalDebtBase**: `bigint` Defined in: packages/sdk/src/lend/types.ts:147 Total debt owed, base-currency units. *** ### availableBorrowsBase > **availableBorrowsBase**: `bigint` Defined in: packages/sdk/src/lend/types.ts:149 Remaining borrowing power, base-currency units. *** ### currentLiquidationThresholdBps > **currentLiquidationThresholdBps**: `number` Defined in: packages/sdk/src/lend/types.ts:151 Account-weighted liquidation threshold, bps. *** ### ltvBps > **ltvBps**: `number` Defined in: packages/sdk/src/lend/types.ts:153 Account-weighted max LTV, bps. *** ### healthFactor > **healthFactor**: `bigint` Defined in: packages/sdk/src/lend/types.ts:155 Health factor, wad (1e18); < 1e18 ⇒ liquidatable; maxUint256 ⇒ no debt. *** ### baseCurrencyDecimals > **baseCurrencyDecimals**: `number` Defined in: packages/sdk/src/lend/types.ts:157 Decimals of the base currency the `*Base` fields use. *** ### positions > **positions**: [`LendPosition`](LendPosition.md)[] Defined in: packages/sdk/src/lend/types.ts:159 Every reserve the account holds a supply or debt in (empty rows dropped). --- # /docs/typescript/api/index/interfaces/LendAddresses [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendAddresses # Interface: LendAddresses Defined in: packages/sdk/src/lend/types.ts:15 SomniaLend contract addresses (see docs.somnialend.finance/deployed-contracts). Set them on `config.addresses.lend`; every lend method throws a clear error when the address it needs is unset, like the rest of `SomniaMarketsAddresses`. ## Properties ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:17 The Pool proxy — every user action (supply/withdraw/borrow/repay) targets it. *** ### poolAddressesProvider? > `optional` **poolAddressesProvider?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:19 PoolAddressesProvider — the market id the UiPoolDataProvider reads are keyed by. *** ### uiPoolDataProvider? > `optional` **uiPoolDataProvider?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:21 UiPoolDataProviderV3 — the aggregated whole-market / whole-account reads. *** ### wrappedTokenGateway? > `optional` **wrappedTokenGateway?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:26 WrappedTokenGatewayV3 — native-SOMI wrap/unwrap periphery. Optional: only the `*Native` lender methods need it; they throw when it is unset. --- # /docs/typescript/api/index/interfaces/LendPosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendPosition # Interface: LendPosition Defined in: packages/sdk/src/lend/types.ts:111 One asset the account has supplied or borrowed, inside [LendAccount](LendAccount.md). ## Properties ### underlying > **underlying**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:113 The underlying ERC-20 of the reserve. *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/lend/types.ts:115 Underlying ticker (denormalized from the reserve row for display). *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/lend/types.ts:117 Underlying decimals (scales both balances below). *** ### aTokenBalance > **aTokenBalance**: `bigint` Defined in: packages/sdk/src/lend/types.ts:119 Current aToken balance incl. accrued interest, raw units. *** ### variableDebt > **variableDebt**: `bigint` Defined in: packages/sdk/src/lend/types.ts:121 Current variable debt incl. accrued interest, raw units. *** ### usageAsCollateralEnabled > **usageAsCollateralEnabled**: `boolean` Defined in: packages/sdk/src/lend/types.ts:123 Whether THIS account is using the supplied balance as collateral. --- # /docs/typescript/api/index/interfaces/LendRepayOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendRepayOptions # Interface: LendRepayOptions Defined in: packages/sdk/src/lend/lender.ts:76 Options for [Lender.repay](Lender.md#repay). ## Extends - [`LendWriteOptions`](LendWriteOptions.md) ## Properties ### approve? > `optional` **approve?**: `boolean` Defined in: packages/sdk/src/lend/lender.ts:44 Auto-approve the token pull when the allowance is short (default true) — same doctrine as the trader: one allowance read per (token, spender) pair, approve `maxUint256` once, cache the grant for the lender's lifetime. #### Inherited from [`LendWriteOptions`](LendWriteOptions.md).[`approve`](LendWriteOptions.md#approve) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/lend/lender.ts:46 Per-call gas ceiling override. #### Inherited from [`LendWriteOptions`](LendWriteOptions.md).[`gas`](LendWriteOptions.md#gas) *** ### onBehalfOf? > `optional` **onBehalfOf?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/lender.ts:78 Repay another address's debt (default: the signer's own). --- # /docs/typescript/api/index/interfaces/LendReserve [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendReserve # Interface: LendReserve Defined in: packages/sdk/src/lend/types.ts:47 One SomniaLend reserve (a listed asset), decoded from the UiPoolDataProvider aggregate — config, caps, live rates/indexes, liquidity, and the oracle price. **Details** Rates and indexes are Aave ray values (1e27) — convert a rate for display with [lendRayRateToApy](../functions/lendRayRateToApy.md). Token amounts (`availableLiquidity`, `totalVariableDebt`, `totalSupplied`) are raw `decimals`-scaled units, accrued to the read's block timestamp. **Gotchas** `borrowCap`/`supplyCap` are WHOLE tokens (Aave convention), not raw units — 0 means uncapped. ## Properties ### underlying > **underlying**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:49 The underlying ERC-20 the reserve lends (approve/supply/borrow this token). *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/lend/types.ts:51 Underlying token ticker, e.g. "USDso". *** ### name > **name**: `string` Defined in: packages/sdk/src/lend/types.ts:53 Underlying token full name. *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/lend/types.ts:55 Underlying token decimals (scales every raw amount on this row). *** ### aToken > **aToken**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:57 The interest-bearing aToken minted on supply (balance grows in place). *** ### variableDebtToken > **variableDebtToken**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/types.ts:59 The variable-debt token minted on borrow (balance grows with interest). *** ### ltvBps > **ltvBps**: `number` Defined in: packages/sdk/src/lend/types.ts:61 Max borrowing power per unit of this collateral, bps (8000 = 80%). *** ### liquidationThresholdBps > **liquidationThresholdBps**: `number` Defined in: packages/sdk/src/lend/types.ts:63 Collateral value threshold (bps) past which a position can be liquidated. *** ### liquidationBonusBps > **liquidationBonusBps**: `number` Defined in: packages/sdk/src/lend/types.ts:65 Liquidator bonus, bps over par (10500 = 5% bonus). *** ### reserveFactorBps > **reserveFactorBps**: `number` Defined in: packages/sdk/src/lend/types.ts:67 Slice of borrow interest diverted to the protocol treasury, bps. *** ### usageAsCollateralEnabled > **usageAsCollateralEnabled**: `boolean` Defined in: packages/sdk/src/lend/types.ts:69 Whether supplying this reserve can back borrows at all. *** ### borrowingEnabled > **borrowingEnabled**: `boolean` Defined in: packages/sdk/src/lend/types.ts:71 Whether the reserve can be borrowed. *** ### isActive > **isActive**: `boolean` Defined in: packages/sdk/src/lend/types.ts:73 Reserve is listed and operational (false ⇒ every action reverts). *** ### isFrozen > **isFrozen**: `boolean` Defined in: packages/sdk/src/lend/types.ts:75 Frozen: existing positions stand but new supplies/borrows revert. *** ### isPaused > **isPaused**: `boolean` Defined in: packages/sdk/src/lend/types.ts:77 Paused: every action on the reserve reverts. *** ### flashLoanEnabled > **flashLoanEnabled**: `boolean` Defined in: packages/sdk/src/lend/types.ts:79 Whether the reserve is flash-loanable. *** ### borrowCap > **borrowCap**: `bigint` Defined in: packages/sdk/src/lend/types.ts:81 Borrow cap in WHOLE tokens (0 = uncapped). *** ### supplyCap > **supplyCap**: `bigint` Defined in: packages/sdk/src/lend/types.ts:83 Supply cap in WHOLE tokens (0 = uncapped). *** ### availableLiquidity > **availableLiquidity**: `bigint` Defined in: packages/sdk/src/lend/types.ts:85 Un-borrowed underlying sitting in the aToken, raw units. *** ### totalVariableDebt > **totalVariableDebt**: `bigint` Defined in: packages/sdk/src/lend/types.ts:87 Total variable debt outstanding, raw units, accrued to the read time. *** ### totalSupplied > **totalSupplied**: `bigint` Defined in: packages/sdk/src/lend/types.ts:89 Total supplied (available + borrowed), raw units, accrued to the read time. *** ### liquidityRateRay > **liquidityRateRay**: `bigint` Defined in: packages/sdk/src/lend/types.ts:91 Annual supply rate, ray (1e27) — [lendRayRateToApy](../functions/lendRayRateToApy.md) for display. *** ### variableBorrowRateRay > **variableBorrowRateRay**: `bigint` Defined in: packages/sdk/src/lend/types.ts:93 Annual variable borrow rate, ray (1e27). *** ### liquidityIndexRay > **liquidityIndexRay**: `bigint` Defined in: packages/sdk/src/lend/types.ts:95 Supply index, ray — current aToken balance = scaled balance × this. *** ### variableBorrowIndexRay > **variableBorrowIndexRay**: `bigint` Defined in: packages/sdk/src/lend/types.ts:97 Variable borrow index, ray — current debt = scaled debt × this. *** ### lastUpdateTimestamp > **lastUpdateTimestamp**: `number` Defined in: packages/sdk/src/lend/types.ts:99 Unix seconds the reserve's stored rates/indexes were last written on-chain. *** ### priceInBaseCurrency > **priceInBaseCurrency**: `bigint` Defined in: packages/sdk/src/lend/types.ts:101 Oracle price of one whole token, in base-currency units ([baseCurrencyDecimals](#basecurrencydecimals)). *** ### baseCurrencyDecimals > **baseCurrencyDecimals**: `number` Defined in: packages/sdk/src/lend/types.ts:103 Decimals of the base currency (USD-denominated deployments use 8). --- # /docs/typescript/api/index/interfaces/LendSupplyOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendSupplyOptions # Interface: LendSupplyOptions Defined in: packages/sdk/src/lend/lender.ts:54 Options for [Lender.supply](Lender.md#supply). ## Extends - [`LendWriteOptions`](LendWriteOptions.md) ## Properties ### approve? > `optional` **approve?**: `boolean` Defined in: packages/sdk/src/lend/lender.ts:44 Auto-approve the token pull when the allowance is short (default true) — same doctrine as the trader: one allowance read per (token, spender) pair, approve `maxUint256` once, cache the grant for the lender's lifetime. #### Inherited from [`LendWriteOptions`](LendWriteOptions.md).[`approve`](LendWriteOptions.md#approve) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/lend/lender.ts:46 Per-call gas ceiling override. #### Inherited from [`LendWriteOptions`](LendWriteOptions.md).[`gas`](LendWriteOptions.md#gas) *** ### onBehalfOf? > `optional` **onBehalfOf?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/lender.ts:56 Credit the position to another address (default: the signer). --- # /docs/typescript/api/index/interfaces/LendWithdrawOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendWithdrawOptions # Interface: LendWithdrawOptions Defined in: packages/sdk/src/lend/lender.ts:64 Options for [Lender.withdraw](Lender.md#withdraw). ## Properties ### to? > `optional` **to?**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/lender.ts:66 Send the withdrawn tokens to another address (default: the signer). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/lend/lender.ts:68 Per-call gas ceiling override. --- # /docs/typescript/api/index/interfaces/LendWriteOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LendWriteOptions # Interface: LendWriteOptions Defined in: packages/sdk/src/lend/lender.ts:38 Options shared by the ERC-20 lend writes. ## Extended by - [`LendSupplyOptions`](LendSupplyOptions.md) - [`LendRepayOptions`](LendRepayOptions.md) ## Properties ### approve? > `optional` **approve?**: `boolean` Defined in: packages/sdk/src/lend/lender.ts:44 Auto-approve the token pull when the allowance is short (default true) — same doctrine as the trader: one allowance read per (token, spender) pair, approve `maxUint256` once, cache the grant for the lender's lifetime. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/lend/lender.ts:46 Per-call gas ceiling override. --- # /docs/typescript/api/index/interfaces/Lender [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Lender # Interface: Lender Defined in: packages/sdk/src/lend/lender.ts:104 Write surface for the SomniaLend money market, bound to one signer — built by `client.lend.createLender` on the owning client. **Details** Every method resolves once the tx is MINED, with its receipt. Amounts are raw underlying-token units. ERC-20 pulls (supply / repay) auto-approve by default; the `*Native` variants route native SOMI through the WrappedTokenGateway so the caller never touches WSOMI. **Gotchas** Every method throws `ContractRevertError` if the chain rejected the action — including a mined tx with `receipt.status: "reverted"`, whose reason is recovered by replaying the call at that block when the node still has the state — and `RpcError` when the send or the receipt read does not complete. A reverted lend action never resolves as success. The `*Native` variants need `wrappedTokenGateway` in the lend addresses. Borrowing is variable-rate only. Position/risk reads live on the lend client (`getAccount`), not here. ## Properties ### account > `readonly` **account**: `` `0x${string}` `` Defined in: packages/sdk/src/lend/lender.ts:106 The signer address the lender acts as. ## Methods ### supply() > **supply**(`asset`, `amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:124 Supply `amount` of `asset` to earn interest (and optionally back borrows). Auto-approves the Pool when the allowance is short. **Details** - `asset`: Underlying ERC-20 to supply (a [LendReserve](LendReserve.md).underlying). - `amount`: Raw underlying units. - `opts`: Approval/gas overrides, or supply on behalf of another address. **Example** (Supplying an ERC-20) ```ts const lender = client.lend.createLender({ privateKey }); await lender.supply(usdso, 1_000n * 10n ** 18n); ``` #### Parameters ##### asset `` `0x${string}` `` ##### amount `bigint` ##### opts? [`LendSupplyOptions`](LendSupplyOptions.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### withdraw() > **withdraw**(`asset`, `amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:129 Withdraw supplied `asset`. Pass `maxUint256` as `amount` to withdraw the full balance including accrued interest. See [Lender.supply](#supply). #### Parameters ##### asset `` `0x${string}` `` ##### amount `bigint` ##### opts? [`LendWithdrawOptions`](LendWithdrawOptions.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### borrow() > **borrow**(`asset`, `amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:134 Borrow `asset` against the account's collateral (variable rate). Reverts on-chain if the health factor would drop below 1. See [Lender.supply](#supply). #### Parameters ##### asset `` `0x${string}` `` ##### amount `bigint` ##### opts? ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### repay() > **repay**(`asset`, `amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:140 Repay variable-rate debt in `asset`. Pass `maxUint256` as `amount` to clear the full debt including accrued interest (requires balance ≥ debt; the contract only pulls what is owed). See [Lender.supply](#supply). #### Parameters ##### asset `` `0x${string}` `` ##### amount `bigint` ##### opts? [`LendRepayOptions`](LendRepayOptions.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setUseAsCollateral() > **setUseAsCollateral**(`asset`, `useAsCollateral`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:145 Toggle whether the supplied `asset` balance backs borrows. Disabling reverts on-chain if it would leave existing debt under-collateralized. #### Parameters ##### asset `` `0x${string}` `` ##### useAsCollateral `boolean` ##### opts? ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### supplyNative() > **supplyNative**(`amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:150 Supply native SOMI (wrapped to WSOMI by the gateway). Sibling of [Lender.supply](#supply); needs `addresses.lend.wrappedTokenGateway`. #### Parameters ##### amount `bigint` ##### opts? ###### onBehalfOf? `` `0x${string}` `` ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### withdrawNative() > **withdrawNative**(`amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:156 Withdraw the WSOMI position as native SOMI. `maxUint256` withdraws all. Auto-approves the gateway to pull the aWSOMI (an ERC-20 approve on the aToken). Sibling of [Lender.withdraw](#withdraw). #### Parameters ##### amount `bigint` ##### opts? [`LendWithdrawOptions`](LendWithdrawOptions.md) & `object` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### borrowNative() > **borrowNative**(`amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:162 Borrow native SOMI (variable rate) via the gateway. First-use grants the gateway credit delegation on the WSOMI variable-debt token (`approveDelegation`, cached like approvals). Sibling of [Lender.borrow](#borrow). #### Parameters ##### amount `bigint` ##### opts? ###### approve? `boolean` ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### repayNative() > **repayNative**(`amount`, `opts?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/lend/lender.ts:168 Repay WSOMI debt with native SOMI. `maxUint256` is not supported for the native path — pass a slight overpayment instead; the gateway refunds the excess. Sibling of [Lender.repay](#repay). #### Parameters ##### amount `bigint` ##### opts? ###### onBehalfOf? `` `0x${string}` `` ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### clearApprovalCache() > **clearApprovalCache**(): `void` Defined in: packages/sdk/src/lend/lender.ts:174 Drop the lender's in-memory approval/delegation grant cache (mirrors the trader's `clearApprovalCache`) — needed only if an approval was revoked out-of-band while this lender instance is alive. #### Returns `void` --- # /docs/typescript/api/index/interfaces/LinkPerpStopOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LinkPerpStopOrdersParams # Interface: LinkPerpStopOrdersParams Defined in: packages/sdk/src/trade.ts:1582 Inputs to [Trader.linkPerpStopOrders](Trader.md#linkperpstoporders) — pair two stops that already exist. The after-the-fact form of [PlacePerpStopOrderParams.pair](PlacePerpStopOrderParams.md#pair), and the way to re-pair a survivor: when one leg of a pair fires WITHOUT filling, the other stays armed and is unlinked, free to be paired with a fresh leg. ## Properties ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1584 The PerpStopOrderRegistry holding both orders. *** ### orderIdA > **orderIdA**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:1586 First order id (either operator; the pair is ordered by the registry). *** ### orderIdB > **orderIdB**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:1588 Second order id. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1594 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/LiquidationEngineConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiquidationEngineConfig # Interface: LiquidationEngineConfig Defined in: packages/sdk/src/perp/system.ts:123 The LiquidationEngine's CONFIGURED bounds — not its history, which is indexed as `LiquidationEvent`. ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:125 The engine's address. *** ### marginBank > **marginBank**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:127 The MarginBank it liquidates against — cross-check against the system config. *** ### penaltyBps > **penaltyBps**: `bigint` Defined in: packages/sdk/src/perp/system.ts:129 Penalty charged on a liquidation, bps. *** ### minSpreadBps > **minSpreadBps**: `bigint` Defined in: packages/sdk/src/perp/system.ts:131 Lower bound on the liquidation spread, bps. *** ### maxSpreadBps > **maxSpreadBps**: `bigint` Defined in: packages/sdk/src/perp/system.ts:133 Upper bound on the liquidation spread, bps. *** ### maxVolumePerBlock > **maxVolumePerBlock**: `bigint` Defined in: packages/sdk/src/perp/system.ts:135 Per-block cap on liquidated notional, raw quote units — the throughput throttle. *** ### bidderCount > **bidderCount**: `bigint` Defined in: packages/sdk/src/perp/system.ts:143 Registered stage-4 backstop bidders. Zero is a real operational signal, not just a statistic: with no bidders the takeover stage has nobody to take a position over, so the waterfall falls through to ADL sooner. --- # /docs/typescript/api/index/interfaces/ListLiquidationsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListLiquidationsOptions # Interface: ListLiquidationsOptions Defined in: packages/sdk/src/perp/history.ts:628 Filters and pagination for [client.listLiquidations](SomniaMarketsClient.md#listliquidations). Named rather than inline because this shape is declared twice - here and on the client member - and SDK-TYPE-005 exists so the two cannot drift as the API grows. ## Properties ### account? > `optional` **account?**: `string` Defined in: packages/sdk/src/perp/history.ts:630 Liquidated account. Case-insensitive: lowercased before the query. *** ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/perp/history.ts:632 Perp pool address. Case-insensitive: lowercased before the query. *** ### kind? > `optional` **kind?**: `"AutoDeleveraged"` \| `"CloseOutMarginSettled"` \| `"BadDebtAbsorbed"` \| `"PositionTransferred"` \| `"AccountLiquidated"` \| `"PositionLiquidated"` \| `"PositionTakenOver"` \| `"ResidualBadDebt"` \| `"ResidualBackedByOpenPnl"` \| `"AdlCapacityShortfall"` \| `"AdlPriceCapacityExhausted"` \| `"AdlSessionDiscarded"` \| `"PositionSkipped"` \| `"Throttled"` \| `"KeeperReward"` \| `"OrderPanicked"` \| `"CoverageDeclined"` Defined in: packages/sdk/src/perp/history.ts:638 A single stage to return. Matched EXACTLY as given and NOT lowercased, unlike the addresses above - it is the schema's own discriminator, so `"autodeleveraged"` would match nothing. A union rather than a `string` precisely because that miss is silent: an empty page reads as "no ADLs happened", so the typo has to be a compile error instead. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/perp/history.ts:640 Rows per page. Defaults to 50. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/perp/history.ts:648 Rows to skip. Defaults to 0. The query carries a TOTAL order (`timestamp`, then `blockNumber`, then the `id` primary key), so the sequence is STABLE between requests — two reads of an unchanged table agree, which `timestamp` alone did not guarantee for rows sharing a block. That fixes tie ordering; it does not make offset paging snapshot-consistent against a LIVE table. See the note on `listLiquidations`. --- # /docs/typescript/api/index/interfaces/ListLiveFundingPaymentsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListLiveFundingPaymentsOptions # Interface: ListLiveFundingPaymentsOptions Defined in: packages/sdk/src/liveTail.ts:349 Options for [SomniaMarketsClient.listLiveFundingPayments](SomniaMarketsClient.md#listlivefundingpayments). ## Extended by - [`UseLiveFundingPaymentsOptions`](../../react/interfaces/UseLiveFundingPaymentsOptions.md) ## Properties ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/liveTail.ts:351 Keep only settlements on this perp pool. *** ### account? > `optional` **account?**: `string` Defined in: packages/sdk/src/liveTail.ts:353 Keep only settlements for this account. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/liveTail.ts:355 Newest-first cap. Default 50. --- # /docs/typescript/api/index/interfaces/ListLiveLiquidationsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListLiveLiquidationsOptions # Interface: ListLiveLiquidationsOptions Defined in: packages/sdk/src/liveTail.ts:331 Options for [SomniaMarketsClient.listLiveLiquidations](SomniaMarketsClient.md#listliveliquidations). ## Extended by - [`UseLiveLiquidationsOptions`](../../react/interfaces/UseLiveLiquidationsOptions.md) ## Properties ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/liveTail.ts:337 Keep only legs on this perp pool. DROPS the account-level legs (`AccountLiquidated`, `ResidualBadDebt`, ...), which carry no pool — filter by `account` for the whole story of one liquidation. *** ### account? > `optional` **account?**: `string` Defined in: packages/sdk/src/liveTail.ts:339 Keep only legs keyed on this account (the liquidated side, never the counterparty). *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/liveTail.ts:341 Newest-first cap. Default 50. --- # /docs/typescript/api/index/interfaces/ListMarketReferenceLinksOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListMarketReferenceLinksOptions # Interface: ListMarketReferenceLinksOptions Defined in: packages/sdk/src/binary/settlement.ts:684 Filters and pagination for [client.listMarketReferenceLinks](SomniaMarketsClient.md#listmarketreferencelinks). ## Properties ### pending? > `optional` **pending?**: `boolean` Defined in: packages/sdk/src/binary/settlement.ts:691 Restrict to links whose resolution is (or is not) waiting on the reference question. `true` is the interesting set: a market that has its own oracle answer while the question it resolves AGAINST is not final yet. Omitted returns both. *** ### market? > `optional` **market?**: `string` Defined in: packages/sdk/src/binary/settlement.ts:693 Market id (lowercased bytes32). Case-insensitive: lowercased before the query. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/binary/settlement.ts:695 Rows per page. Defaults to 50. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/binary/settlement.ts:697 Rows to skip. Defaults to 0. Ordered by `timestamp` then the `id` primary key. --- # /docs/typescript/api/index/interfaces/ListMarketResolutionEventsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListMarketResolutionEventsOptions # Interface: ListMarketResolutionEventsOptions Defined in: packages/sdk/src/binary/settlement.ts:603 Filters and pagination for [client.listMarketResolutionEvents](SomniaMarketsClient.md#listmarketresolutionevents). Named rather than inline because this shape is declared twice — here and on the client member — and SDK-TYPE-005 exists so the two cannot drift. ## Properties ### market? > `optional` **market?**: `string` Defined in: packages/sdk/src/binary/settlement.ts:605 Market id (lowercased bytes32). Case-insensitive: lowercased before the query. *** ### kinds? > `optional` **kinds?**: readonly [`MarketResolutionKind`](../type-aliases/MarketResolutionKind.md)[] Defined in: packages/sdk/src/binary/settlement.ts:613 Kinds to return, matched with `_in`. Omitted returns every kind. Matched EXACTLY and NOT lowercased — it is the indexer's own discriminator. See [MarketResolutionKind](../type-aliases/MarketResolutionKind.md) for why this is a union and the row field is not. *** ### sinceTimestamp? > `optional` **sinceTimestamp?**: `number` Defined in: packages/sdk/src/binary/settlement.ts:620 Lower bound on `timestamp`, unix SECONDS, inclusive (`_gte`). Executes at the indexer against an indexed column, so a caller watching a rolling window pays for the window rather than over-fetching newest-first and discarding the tail. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/binary/settlement.ts:622 Rows per page. Defaults to 50. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/binary/settlement.ts:632 Rows to skip. Defaults to 0. The query carries a TOTAL order (`timestamp`, then `blockNumber`, then the `id` primary key), so the sequence is STABLE between requests. That fixes tie ordering; it does NOT make offset paging snapshot-consistent against a table the indexer is still writing to. Narrow with `sinceTimestamp` and raise `limit` when completeness matters more than a tidy page. --- # /docs/typescript/api/index/interfaces/ListPoolBindingsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListPoolBindingsOptions # Interface: ListPoolBindingsOptions Defined in: packages/sdk/src/pools.ts:115 Pagination for [client.listPoolBindings](SomniaMarketsClient.md#listpoolbindings). ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/pools.ts:117 Rows per page, from 1 to 1000. Defaults to 50. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/pools.ts:127 Rows to skip, from 0 to 2147483647 (GraphQL `Int`). Defaults to 0. Rows are ordered by `nonce`, newest first. The nonce is unique within a pool, so the order is total. The order is not a snapshot: when the pool opens new bindings between two requests, every older row moves down by that many positions and the next page repeats that many rows. Deduplicate on `id` when you page through the full history. --- # /docs/typescript/api/index/interfaces/ListVaultPayoutFallbacksOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListVaultPayoutFallbacksOptions # Interface: ListVaultPayoutFallbacksOptions Defined in: packages/sdk/src/binary/portfolio.ts:608 Filters, time window and pagination for [client.listVaultPayoutFallbacks](SomniaMarketsClient.md#listvaultpayoutfallbacks). Named rather than inline because the shape is declared twice - here and on the client member - and SDK-TYPE-005 exists so the two cannot drift. ## Properties ### owner? > `optional` **owner?**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:610 Credited owner. Case-insensitive: lowercased before the query. *** ### token? > `optional` **token?**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:612 Credited token. Case-insensitive: lowercased before the query. *** ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:614 The pool that emitted the credit. Case-insensitive: lowercased before the query. *** ### from? > `optional` **from?**: `number` \| `bigint` Defined in: packages/sdk/src/binary/portfolio.ts:616 Unix seconds, INCLUSIVE: rows at or after this time. Whole and non-negative. *** ### to? > `optional` **to?**: `number` \| `bigint` Defined in: packages/sdk/src/binary/portfolio.ts:618 Unix seconds, EXCLUSIVE: rows before this time. Whole and non-negative. *** ### order? > `optional` **order?**: `"asc"` \| `"desc"` Defined in: packages/sdk/src/binary/portfolio.ts:625 `"desc"` (the default) returns the NEWEST `limit` rows in the window. Pass `"asc"` to walk FORWARD from `from`; that is the mode a cursor needs, because under `"desc"` narrowing `from` changes the window, not which end a page comes from. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:627 Rows per page, an integer from 1 to 1000. Defaults to 50. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:629 Rows to skip, a non-negative safe integer. Defaults to 0. --- # /docs/typescript/api/index/interfaces/LiveFill [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiveFill # Interface: LiveFill Defined in: packages/sdk/src/store.ts:308 One fill in the live store, with indexer-compatible identifiers and raw units. **Details** Binary-side fields are enriched from the related live orders. Spot fills leave the binary-only fields undefined. **Gotchas** A just-received fill can temporarily omit maker, taker, or side data because the related order event can arrive later in the same transaction. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/store.ts:310 `${blockNumber}_${logIndex}` — matches the indexer Fill id *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/store.ts:317 Chain the row came from: the chain of the engine that produced it. The other identifiers are unique on one chain only, so a caller that merges rows from two engines keys on `(chainId, id)`. *** ### market\_id > **market\_id**: `string` Defined in: packages/sdk/src/store.ts:319 Id of the market the fill executed in (Hasura FK naming; joins [LiveMarket](../type-aliases/LiveMarket.md)). *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/store.ts:321 lowercased pool address (the log source) *** ### taker > **taker**: `` `0x${string}` `` \| `undefined` Defined in: packages/sdk/src/store.ts:327 Taker info is unresolved at OrderFilled emission time (the taker's OrderPlaced fires AFTER the fill in the same tx). Resolved via the takerOrder_id foreign key — enrichFill back-joins to LiveOrder. *** ### maker > **maker**: `` `0x${string}` `` \| `undefined` Defined in: packages/sdk/src/store.ts:332 Maker's address. Undefined until the maker's resting order is known — set when it was witnessed live, else back-joined from the order row via `makerOrder_id`. *** ### takerSide > **takerSide**: [`BinarySide`](../type-aliases/BinarySide.md) \| `undefined` Defined in: packages/sdk/src/store.ts:337 Taker's outcome side. Undefined on spot fills, and on binary fills until the taker order is joined (see `taker`). *** ### makerSide > **makerSide**: [`BinarySide`](../type-aliases/BinarySide.md) \| `undefined` Defined in: packages/sdk/src/store.ts:342 Maker's outcome side. Undefined on spot fills, and until the maker order is joined (see `maker`). *** ### kind > **kind**: [`BinaryFillKind`](../type-aliases/BinaryFillKind.md) \| `undefined` Defined in: packages/sdk/src/store.ts:347 How the fill settled (see [BinaryFillKind](../type-aliases/BinaryFillKind.md)). Undefined on spot fills, and on binary fills until BOTH sides are joined (classification needs both). *** ### takerIsBid > **takerIsBid**: `boolean` \| `undefined` Defined in: packages/sdk/src/store.ts:355 True when the taker bought the base/YES (the maker was the ask) — the tape's aggressor direction, valid on every market kind. Seeded from the indexer row on snapshot fills; on live fills derived at OrderFilled from the maker's resting side (undefined only when the maker order was never witnessed, until enrichFill joins the taker's OrderPlaced). *** ### takerOrder\_id > **takerOrder\_id**: `string` Defined in: packages/sdk/src/store.ts:357 Foreign keys to LiveOrder rows for join-side recovery. *** ### makerOrder\_id > **makerOrder\_id**: `string` Defined in: packages/sdk/src/store.ts:359 Maker-side counterpart of `takerOrder_id` (a [LiveOrder](LiveOrder.md) key). *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/store.ts:361 Raw quote/collateral units per whole base/outcome token. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/store.ts:366 Base/outcome tokens exchanged — raw units scaled by the market's `baseDecimals` (decimal string). *** ### quoteQuantity > **quoteQuantity**: `string` Defined in: packages/sdk/src/store.ts:368 quote value = quantity * fillPrice / 10^baseDecimals *** ### takerRemainingQuantity > **takerRemainingQuantity**: `string` Defined in: packages/sdk/src/store.ts:370 Taker order's unfilled size after this fill — raw base/outcome units (decimal string). *** ### makerRemainingQuantity > **makerRemainingQuantity**: `string` Defined in: packages/sdk/src/store.ts:372 Maker order's unfilled size after this fill — raw base/outcome units (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/store.ts:374 Block timestamp of the fill — unix seconds (decimal string). *** ### blockNumber > **blockNumber**: `number` Defined in: packages/sdk/src/store.ts:376 Block the fill landed in. *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/store.ts:378 Log index within the block — with `blockNumber`, the fill's tape position. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/store.ts:380 Transaction that produced the fill. --- # /docs/typescript/api/index/interfaces/LiveFundingUpdate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiveFundingUpdate # Interface: LiveFundingUpdate Defined in: packages/sdk/src/store.ts:263 A funding settlement observed by the live tail, shaped to splice onto the indexed `FundingRateUpdate` series. Deliberately NOT the full indexed row. The tail sees only what `FundingUpdated` carries, and two of the indexed fields are DERIVED from state the tail does not have: `intervalsAccrued` needs `n` from the funding-parameters epoch series, and the covered span needs the settlement anchor. Rather than guess them, they are absent here and arrive with the indexed row a moment later. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/store.ts:265 `${pool}_${blockNumber}_${logIndex}` — matches the indexer FundingRateUpdate id. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/store.ts:272 Chain the row came from: the chain of the engine that produced it. The other identifiers are unique on one chain only, so a caller that merges rows from two engines keys on `(chainId, id)`. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/store.ts:274 Perp pool (lowercased). *** ### fundingRate > **fundingRate**: `string` Defined in: packages/sdk/src/store.ts:276 Per-CALCULATION-WINDOW rate, 1e18-scaled, signed. Normalize with `fundingWindowSec`. *** ### cumulativeFundingPerUnit > **cumulativeFundingPerUnit**: `string` Defined in: packages/sdk/src/store.ts:278 Cumulative index AFTER this settlement (1e18 x quote per whole base, signed). *** ### indexPrice > **indexPrice**: `string` Defined in: packages/sdk/src/store.ts:279 *** ### markPrice > **markPrice**: `string` \| `null` Defined in: packages/sdk/src/store.ts:281 Null when the event's 0 sentinel fired for a stale mark feed. *** ### intervalsSettled > **intervalsSettled**: `string` Defined in: packages/sdk/src/store.ts:283 UNCLAMPED interval span, as emitted. Accrual is capped at n = window / interval. *** ### fundingWindowSec > **fundingWindowSec**: `number` \| `null` Defined in: packages/sdk/src/store.ts:285 Params as last known for the market; null before the first indexed funding row. *** ### fundingIntervalSec > **fundingIntervalSec**: `number` \| `null` Defined in: packages/sdk/src/store.ts:286 *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/store.ts:287 *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/store.ts:288 *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/store.ts:290 Log index within the block — with blockNumber, the settlement's position in the series. --- # /docs/typescript/api/index/interfaces/LiveOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiveOrder # Interface: LiveOrder Defined in: packages/sdk/src/store.ts:388 A resting/closed order (mirror of indexer Order). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/store.ts:390 `${pool}_${orderId}` *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/store.ts:397 Chain the row came from: the chain of the engine that produced it. The other identifiers are unique on one chain only, so a caller that merges rows from two engines keys on `(chainId, id)`. *** ### market\_id > **market\_id**: `string` Defined in: packages/sdk/src/store.ts:402 Id of the market the order was placed in. Pools are RECYCLED across markets (never concurrently), so book reads filter on this, not the pool alone. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/store.ts:404 Lowercased pool address hosting the order's book. *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/store.ts:406 On-chain order id, unique per pool (decimal string). *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/store.ts:408 Order owner's address (as emitted — compare case-insensitively). *** ### side > **side**: [`BinarySide`](../type-aliases/BinarySide.md) \| `undefined` Defined in: packages/sdk/src/store.ts:410 Binary outcome side. Undefined on spot orders (spot has no YES/NO). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/store.ts:415 Which side of the book's NATIVE terms the order rests on: true = bid. Native terms are YES terms for binary, quote-per-base for spot. *** ### userData > **userData**: `string` Defined in: packages/sdk/src/store.ts:420 Opaque caller bookkeeping from OrderPlaced, carried verbatim (uint256 decimal string) — never decoded; v2 takes the side from `BinaryOrderPlaced.kind` instead. *** ### price > **price**: `string` Defined in: packages/sdk/src/store.ts:425 Limit price in the book's native terms — raw quote/collateral units per whole base/outcome token (decimal string). *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/store.ts:427 Original size at placement — raw base/outcome units (decimal string). *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/store.ts:429 Unfilled size still resting — raw base/outcome units (decimal string). *** ### filledQuantity > **filledQuantity**: `string` Defined in: packages/sdk/src/store.ts:431 Cumulative size filled so far — raw base/outcome units (decimal string). *** ### expireTimestampNs > **expireTimestampNs**: `string` Defined in: packages/sdk/src/store.ts:437 Order expiry as a uint64 nanosecond timestamp (decimal string). GTC orders carry type(uint64).max, so they never expire; the matcher rejects a 0/past expiry at placement, so a resting order always has a real future ns value. *** ### status > **status**: [`OrderStatus`](../type-aliases/OrderStatus.md) Defined in: packages/sdk/src/store.ts:439 Lifecycle state (see [OrderStatus](../type-aliases/OrderStatus.md)). *** ### rested > **rested**: `boolean` Defined in: packages/sdk/src/store.ts:444 True once OrderRested landed — the order is ON the book. Only rested open orders count toward the materialized book levels. *** ### createdAt > **createdAt**: `string` Defined in: packages/sdk/src/store.ts:446 Placement block timestamp — unix seconds (decimal string). *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/store.ts:448 Transaction that placed the order. --- # /docs/typescript/api/index/interfaces/LivePrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LivePrice # Interface: LivePrice Defined in: packages/sdk/src/priceFeed/types.ts:52 The current price of one asset — the `Feed` singleton, parsed. This is what a live watch keeps current. ## Properties ### asset > **asset**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:54 Asset symbol this feed tracks (e.g. "BTC", "ETH"), uppercased. *** ### price > **price**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:59 Latest price, human units (raw / 1e18). Lossy past ~15 sig figs — use `raw` for exact math. *** ### ema > **ema**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:61 Latest EMA-smoothed mark price, human units (the feed's `mark`). *** ### blockNumber > **blockNumber**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:63 Block the latest tick landed in (chain time, monotonic). *** ### blockTimestamp > **blockTimestamp**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:68 Block timestamp of the latest tick — unix seconds, chain time. Use this as a series x-axis; it never drifts. *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:70 Price scale (Feed.decimals, always 18 today). *** ### raw > **raw**: `object` Defined in: packages/sdk/src/priceFeed/types.ts:75 Exact 1e18-scaled integer strings — never round-trip money through the `number` fields above. #### price > **price**: `string` Exact spot price — 1e18-scaled integer string. #### ema > **ema**: `string` Exact EMA mark — 1e18-scaled integer string. --- # /docs/typescript/api/index/interfaces/LockedBalance [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LockedBalance # Interface: LockedBalance Defined in: packages/sdk/src/spot/poolReads.ts:137 Base/quote amounts one owner has locked in resting orders. ## Properties ### lockedBase > **lockedBase**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:139 Base locked across the owner's resting asks, raw base units. *** ### lockedQuote > **lockedQuote**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:141 Quote locked across the owner's resting bids, raw quote units. --- # /docs/typescript/api/index/interfaces/LockedTokenBreakdown [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LockedTokenBreakdown # Interface: LockedTokenBreakdown Defined in: packages/sdk/src/spot/poolReads.ts:194 Book-wide lock state, per token — see [SomniaMarketsClient.getLockedTokenBreakdown](SomniaMarketsClient.md#getlockedtokenbreakdown). ## Properties ### base > **base**: [`TokenLockBreakdown`](TokenLockBreakdown.md) Defined in: packages/sdk/src/spot/poolReads.ts:195 *** ### quote > **quote**: [`TokenLockBreakdown`](TokenLockBreakdown.md) Defined in: packages/sdk/src/spot/poolReads.ts:196 --- # /docs/typescript/api/index/interfaces/MachineryStep [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MachineryStep # Interface: MachineryStep Defined in: packages/sdk/src/marketTypes/types.ts:17 One type-specific machinery onboarding step (rendered by a wizard; the preflight validators key off `id`). Descriptive only — no logic here. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/marketTypes/types.ts:19 Stable step id (e.g. "market-creator", "funding", "series"). *** ### label > **label**: `string` Defined in: packages/sdk/src/marketTypes/types.ts:21 Short human label. *** ### description > **description**: `string` Defined in: packages/sdk/src/marketTypes/types.ts:23 One-line description of what the operator does in this step. --- # /docs/typescript/api/index/interfaces/MarginAccount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarginAccount # Interface: MarginAccount Defined in: packages/sdk/src/perp/margin.ts:43 An account's cross-margin state in the MarginBank (collateral is the bank's single collateral token, e.g. USDso — raw units). ## Properties ### unlockedCollateralBalance > **unlockedCollateralBalance**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:45 Free collateral after locks (signed — settlement can drive it negative). *** ### lockedCollateral > **lockedCollateral**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:47 Collateral reserved for pending orders. *** ### activePerpPools > **activePerpPools**: `` `0x${string}` ``[] Defined in: packages/sdk/src/perp/margin.ts:49 Perp pools where the account holds an open position. *** ### equity > **equity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:51 Equity = collateral + unrealized PnL − pending funding (signed). *** ### withdrawable > **withdrawable**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:53 Collateral withdrawable right now (respects margin requirements). *** ### imReq > **imReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:55 Sum of notional × initialMarginBps / 10000 across all markets (raw). *** ### mmReq > **mmReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:57 Sum of notional × maintenanceMarginBps / 10000 across all markets (raw). *** ### cmReq > **cmReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:59 Sum of notional × closeOutMarginBps / 10000 across all markets (raw). *** ### marginStatus > **marginStatus**: [`MarginStatus`](../type-aliases/MarginStatus.md) Defined in: packages/sdk/src/perp/margin.ts:61 Health bucket derived from equity vs the requirements. --- # /docs/typescript/api/index/interfaces/MarkSources [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarkSources # Interface: MarkSources Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:173 Mark sources per market key, plus a fallback price for quiet markets. ## Properties ### series > **series**: `ReadonlyMap`\<`string`, [`MarkSeries`](../type-aliases/MarkSeries.md)\> Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:175 Candle-close series per market (oldest first). *** ### lastPrice > **lastPrice**: `ReadonlyMap`\<`string`, `number`\> Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:177 Last known price per market, used when a series has no sample yet. --- # /docs/typescript/api/index/interfaces/MarketCreatorAdmin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketCreatorAdmin # Interface: MarketCreatorAdmin Defined in: packages/sdk/src/marketCreatorAdmin.ts:326 The MarketCreator write + status surface — stamp out creators, register rolling series, fund/roll/tune them (see the module notes above). Built via `client.createMarketCreatorAdmin(config)` with a signer ([MarketCreatorAdminConfig](OracleHubAdminConfig.md)); every write sends one tx and resolves with its receipt after inclusion. Every write throws `ContractRevertError` when the chain rejects it — at simulation, at send, or as a mined receipt with `status: "reverted"` (the reason is recovered by replaying the call at that block while the node still has the state) — and `RpcError` when the send or the receipt read does not complete. A reverted write never resolves as if it had been confirmed. ## Methods ### createMarketCreator() > **createMarketCreator**(`p`): `Promise`\<[`CreateMarketCreatorResult`](CreateMarketCreatorResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:332 Stamp out a new MarketCreator (+ its policy) from the factory, bound to `(operatorId, venueId, core, adapter)` + a default book config. Resolves with the minted `creator` + `policy` (decoded from `MarketCreatorCreated`). #### Parameters ##### p [`CreateMarketCreatorParams`](CreateMarketCreatorParams.md) #### Returns `Promise`\<[`CreateMarketCreatorResult`](CreateMarketCreatorResult.md)\> *** ### fundMarketCreator() > **fundMarketCreator**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:337 Send native currency to a creator's `receive()` — it pays for reactivity rolls, so it must hold a balance on testnet/mainnet. #### Parameters ##### p [`FundMarketCreatorParams`](FundMarketCreatorParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### registerSeries() > **registerSeries**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:343 Register (or overwrite) a rolling-market series under a creator. Owner-only. `intervalSec` must be >= 60 and `asset` non-empty (the module reverts otherwise). #### Parameters ##### p [`RegisterSeriesParams`](RegisterSeriesParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### updateSeries() > **updateSeries**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:348 Overwrite an existing series — alias of [registerSeries](#registerseries) (the module upserts by `seriesId`). Provided for wizard clarity. #### Parameters ##### p [`RegisterSeriesParams`](RegisterSeriesParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### triggerRoll() > **triggerRoll**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:357 V1 ONLY: roll a series to its next market (owner-only). MarketCreatorV2 dropped `triggerRoll` — its one start path is [armFirstRoll](#armfirstroll) at a wall-clock boundary (restart = re-register + armFirstRoll), and stalls are handled by the permissionless [recoverSeries](#recoverseries). Calling this against a v2 creator reverts (selector absent). NOTE: calls the Somnia reactivity precompile — only succeeds on testnet/mainnet, not local anvil. #### Parameters ##### p [`TriggerRollParams`](TriggerRollParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### recoverSeries() > **recoverSeries**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:367 V2: PERMISSIONLESS last-resort recovery of a provably stalled series — covers dead subscriptions (out-of-funds auto-cancel / subscribe strand) and a refunded-but-comatose creator. Rate-limited on-chain (one attempt per backstop period per series); reverts `SeriesNotStalled` without evidence. The ops story after an out-of-funds incident: refuel the creator, call this once per stalled series. Touches the reactivity precompile → testnet/mainnet only. #### Parameters ##### p [`RecoverSeriesParams`](RecoverSeriesParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### armFirstRoll() > **armFirstRoll**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:374 A1: arm a series' FIRST roll at a future boundary WITHOUT minting now (owner-only) — the seamless-migration tool: start a fresh MC's series exactly at the outgoing MC's expiry. NOTE: touches the reactivity precompile — testnet/mainnet only. #### Parameters ##### p [`ArmFirstRollParams`](ArmFirstRollParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### reclaimOracleCredit() > **reclaimOracleCredit**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:380 A1: pull the creator's own accrued oracle surplus (payer credit) out of the hub into its native float. Runs automatically each roll cycle; this is the manual sweep of any leftovers. Permissionless. #### Parameters ##### p [`ReclaimOracleCreditParams`](ReclaimOracleCreditParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### adoptFrom() > **adoptFrom**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:390 In-place creator migration — PULL side (v2). `adoptFrom` inherits a quiesced predecessor's whole series set + each series' pending oracle qid onto the successor, so the next roll fires on the successor off the outgoing market's own answer (strike chain intact, no bootstrap). Reverts unless same operator/venue/owner, the predecessor is quiesced, and the successor's reactivity gas params are set. Touches the reactivity precompile → testnet/mainnet only. See docs/runbooks/migrating-market-creator.md. #### Parameters ##### p [`AdoptFromParams`](AdoptFromParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### handoffTo() > **handoffTo**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:397 In-place creator migration — PUSH side (v2). Retire the outgoing creator: tear down its subscriptions, sweep its native float to `successor`, and set `retired` (bricks rolling). Owner-only; the successor must share owner + venue. Touches the reactivity precompile → testnet/mainnet only. #### Parameters ##### p [`HandoffToParams`](HandoffToParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### swapCreator() > **swapCreator**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:403 Atomically flip a venue's `MarketCreatorPolicy` allowlist from `from` to `to` (policy-owner only) — the cutover switch paired with adoptFrom/handoffTo, so there is never a window where both or neither creator is authorized. #### Parameters ##### p [`SwapCreatorParams`](SwapCreatorParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setReactivityGasParams() > **setReactivityGasParams**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:405 Update the creator's reactivity gas params (owner-only). #### Parameters ##### p [`SetReactivityGasParamsParams`](SetReactivityGasParamsParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### getMarketCreatorOnchain() > **getMarketCreatorOnchain**(`creator`): `Promise`\<[`MarketCreatorOnchain`](MarketCreatorOnchain.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:410 One creator's live binding (core/adapter/operatorId/venueId/owner + default book params). On-chain point read. #### Parameters ##### creator `` `0x${string}` `` #### Returns `Promise`\<[`MarketCreatorOnchain`](MarketCreatorOnchain.md)\> *** ### getSeriesOnchain() > **getSeriesOnchain**(`creator`, `seriesId`): `Promise`\<[`SeriesOnchain`](SeriesOnchain.md)\> Defined in: packages/sdk/src/marketCreatorAdmin.ts:415 One series' live config under a creator. On-chain point read; the returned `intervalSec === 0` means the series was never registered. #### Parameters ##### creator `` `0x${string}` `` ##### seriesId `number` #### Returns `Promise`\<[`SeriesOnchain`](SeriesOnchain.md)\> --- # /docs/typescript/api/index/interfaces/MarketCreatorInfo [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketCreatorInfo # Interface: MarketCreatorInfo Defined in: packages/sdk/src/system.ts:19 On-chain state of the configured MarketCreator (part of [SystemInfo](SystemInfo.md)). Every field is a live read: a failed read throws, so each value here is something the chain actually answered. ## Properties ### marketCount > **marketCount**: `bigint` Defined in: packages/sdk/src/system.ts:21 Markets this creator has minted (`marketCount()`). *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/system.ts:23 Creator owner (`owner()`). *** ### reactivityGasLimit > **reactivityGasLimit**: `bigint` Defined in: packages/sdk/src/system.ts:25 Gas limit its reactivity roll callbacks run with. *** ### reactivityMaxFeePerGas > **reactivityMaxFeePerGas**: `bigint` Defined in: packages/sdk/src/system.ts:27 Reactivity-callback fee ceiling (wei per gas). *** ### reactivityPriorityFeePerGas > **reactivityPriorityFeePerGas**: `bigint` Defined in: packages/sdk/src/system.ts:29 Reactivity-callback tip (wei per gas). *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/system.ts:31 Origin operator id this creator's markets are attributed to. *** ### venueId > **venueId**: `string` Defined in: packages/sdk/src/system.ts:33 Origin venue id within the operator (bytes32 hex). --- # /docs/typescript/api/index/interfaces/MarketCreatorOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketCreatorOnchain # Interface: MarketCreatorOnchain Defined in: packages/sdk/src/marketCreatorAdmin.ts:274 One MarketCreator's live on-chain binding (the point read a wizard confirms). ## Properties ### core > **core**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:276 Core BinaryMarketsModule the creator schedules markets through (immutable). *** ### adapter > **adapter**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:278 Oracle adapter every series question resolves against (immutable). *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:280 Origin operator id the creator's markets are attributed to (immutable). *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:282 Origin venue id (within the operator) the markets are attributed to (immutable). *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:284 Current owner (can register series / trigger rolls). *** ### defaultBookParams > **defaultBookParams**: [`OrderBookParams`](OrderBookParams.md) Defined in: packages/sdk/src/marketCreatorAdmin.ts:286 Default order-book config applied to every market the creator deploys. --- # /docs/typescript/api/index/interfaces/MarketCreatorPreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketCreatorPreflightInput # Interface: MarketCreatorPreflightInput Defined in: packages/sdk/src/preflight.ts:270 Inputs for the creator-step preflight: the creator's native balance and whether the connected chain supports rolls. ## Properties ### balanceWei > **balanceWei**: `bigint` Defined in: packages/sdk/src/preflight.ts:272 The creator's native balance (wei) — it pays for reactivity rolls. *** ### precompileAvailable > **precompileAvailable**: `boolean` Defined in: packages/sdk/src/preflight.ts:277 Whether the connected chain has the Somnia reactivity precompile (false on local anvil — see [isLocalPrecompileUnavailable](../functions/isLocalPrecompileUnavailable.md)). --- # /docs/typescript/api/index/interfaces/MarketOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketOnchain # Interface: MarketOnchain Defined in: packages/sdk/src/markets.ts:1844 A BinaryMarket's wiring + live state, read straight from chain (works before the indexer has the market). ## Properties ### marketAddress > **marketAddress**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1846 The BinaryMarket contract address (resolved from the module record). *** ### outcomeToken > **outcomeToken**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1848 Protocol-level ERC-6909 outcome-token singleton (shared across all markets). *** ### yesId > **yesId**: `bigint` Defined in: packages/sdk/src/markets.ts:1850 This market's YES position id on the singleton. *** ### noId > **noId**: `bigint` Defined in: packages/sdk/src/markets.ts:1852 This market's NO position id on the singleton. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1859 The pool hosting (or that hosted) this market's CLOB. Settlement-extraction v2: a pool address is a TIME-VARYING binding — the same pool serves successive markets, so never key a market by pool address; `(pool, nonce)` identifies this market's slice of the pool's history. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/markets.ts:1861 The pool's market nonce for THIS market (part of the outcome-id encoding). *** ### collateral > **collateral**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1863 ERC-20 collateral token the market settles in (its `decimals` scale `backing`). *** ### status > **status**: `number` Defined in: packages/sdk/src/markets.ts:1865 MarketStatus enum: 0 Listed · 1 Trading · 2 Locked · 3 Settling · 4 Resolved · 5 Voided *** ### backing > **backing**: `bigint` Defined in: packages/sdk/src/markets.ts:1872 Live collateral backing. While trading this is the pool's `setBacking` (via `market.backing()`); once the market is FINALIZED onto the settlement singleton the pool reads 0, so this falls back to the settlement record's remaining NET backing (post fee-skim, decremented by each redemption). *** ### finalized > **finalized**: `boolean` Defined in: packages/sdk/src/markets.ts:1877 True once the market's backing + resolution snapshot were swept to the BinarySettlement singleton (redemption is served there from then on). *** ### expiry > **expiry**: `bigint` Defined in: packages/sdk/src/markets.ts:1879 Trading-close / settlement timestamp (seconds). *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/markets.ts:1881 Collateral token decimals. Falls back to DECIMALS (6) only if the token lacks the decimals() view; other read failures throw. *** ### winningOutcome > **winningOutcome**: `number` Defined in: packages/sdk/src/markets.ts:1887 Winning outcome (0 = YES, 1 = NO). Only meaningful when `isResolved` — the contract returns 0 by default which would otherwise read as a YES win on a market that hasn't resolved yet. *** ### isResolved > **isResolved**: `boolean` Defined in: packages/sdk/src/markets.ts:1889 Oracle has resolved the market to a concrete winning outcome. *** ### isVoided > **isVoided**: `boolean` Defined in: packages/sdk/src/markets.ts:1891 Oracle has voided the market (payout per the frozen void policy; see `voidPolicy`). *** ### voidPolicy > **voidPolicy**: `number` \| `null` Defined in: packages/sdk/src/markets.ts:1897 Void payout policy frozen at creation: 0 UNIFORM, 2 CLOB_SNAPSHOT (a void pays `[p, D-p]` at the closing YES price). `null` on pre-policy market clones, which lack the selector and always void uniform. --- # /docs/typescript/api/index/interfaces/MarketOnchainSources [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketOnchainSources # Interface: MarketOnchainSources Defined in: packages/sdk/src/markets.ts:1991 Module/settlement wiring `getMarketOnchain` resolves the market through. ## Properties ### module > **module**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1993 BinaryMarketsModule address (the on-chain market registry). *** ### settlement? > `optional` **settlement?**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1999 BinarySettlement singleton — enables the post-finalize backing fallback. Omit on pre-v2 deploys; `finalized` then stays false and `backing` is the raw `market.backing()` value. --- # /docs/typescript/api/index/interfaces/MarketOrderEstimate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketOrderEstimate # Interface: MarketOrderEstimate Defined in: packages/sdk/src/unified/quotes.ts:33 A market-order fill estimate from walking the book, human units. ## Properties ### averagePrice > **averagePrice**: `number` Defined in: packages/sdk/src/unified/quotes.ts:35 Volume-weighted average fill price (Σ quote / Σ base). *** ### baseFilled > **baseFilled**: `number` Defined in: packages/sdk/src/unified/quotes.ts:37 Base units the walk filled. *** ### quoteFilled > **quoteFilled**: `number` Defined in: packages/sdk/src/unified/quotes.ts:39 Quote units the walk exchanged (Σ qty·price). *** ### levelsConsumed > **levelsConsumed**: `number` Defined in: packages/sdk/src/unified/quotes.ts:45 Book levels the order crosses. Each matched level is a fill and execution gas scales with it — the signal for sizing a gas limit ahead of submission. --- # /docs/typescript/api/index/interfaces/MarketStats24h [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketStats24h # Interface: MarketStats24h Defined in: packages/sdk/src/derivedReads.ts:154 A market's trailing-24h activity, derived from OHLCV candle buckets. Prices are RAW quote units; volume is RAW quote (collateral) units. ## Properties ### volume24h > **volume24h**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:156 Σ quote volume over the window (raw collateral units). *** ### baseVolume24h > **baseVolume24h**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:158 Σ base/outcome-token volume over the window (raw base units). *** ### trades24h > **trades24h**: `number` Defined in: packages/sdk/src/derivedReads.ts:160 Σ trade count over the window. *** ### priceChange24h > **priceChange24h**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:165 closePrice(last) − openPrice(first) over the window (raw, signed). `0n` if fewer than one candle in-window. *** ### high24h > **high24h**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:167 Max high across the window (raw). `null` if no candles in-window. *** ### low24h > **low24h**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:169 Min low across the window (raw). `null` if no candles in-window. *** ### openPrice24h > **openPrice24h**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:171 openPrice of the first in-window candle (raw). `null` if none. --- # /docs/typescript/api/index/interfaces/MarketTypePlugin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketTypePlugin # Interface: MarketTypePlugin\ Defined in: packages/sdk/src/marketTypes/types.ts:33 A market-type plugin: the fee-param codec + machinery descriptor for one bytes4 `marketType`. `TParams` is the type's plain fee-param shape (e.g. [BinaryVenueParams](BinaryVenueParams.md) for BINARY_V1). ## Type Parameters ### TParams `TParams` = `unknown` ## Properties ### marketType > **marketType**: `` `0x${string}` `` Defined in: packages/sdk/src/marketTypes/types.ts:35 The bytes4 market-type id (e.g. `MARKET_TYPE_BINARY_V1`). *** ### label > **label**: `string` Defined in: packages/sdk/src/marketTypes/types.ts:37 Human label for the type. *** ### machinerySteps > **machinerySteps**: readonly [`MachineryStep`](MachineryStep.md)[] Defined in: packages/sdk/src/marketTypes/types.ts:39 The type-specific machinery onboarding steps, in order. ## Methods ### encodeVenueFeeParams() > **encodeVenueFeeParams**(`params`, `client`, `moduleAddress`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/marketTypes/types.ts:45 Encode plain fee params into a venue's opaque `feeParams` bytes — for binary this defers to the module's on-chain encoder (needs a client + the module address), so it is async. #### Parameters ##### params `TParams` ##### client ##### moduleAddress `` `0x${string}` `` \| `undefined` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### decodeVenueFeeParams() > **decodeVenueFeeParams**(`feeParams`): `TParams` \| `null` Defined in: packages/sdk/src/marketTypes/types.ts:50 Decode a venue's `feeParams` bytes back into plain params for display, or null if the bytes aren't this type's shape. Pure/local. #### Parameters ##### feeParams `` `0x${string}` `` #### Returns `TParams` \| `null` --- # /docs/typescript/api/index/interfaces/MintSetNativeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MintSetNativeParams # Interface: MintSetNativeParams Defined in: packages/sdk/src/trade.ts:2114 Params for [Trader.mintSetNative](Trader.md#mintsetnative) — mint a YES+NO set by paying in the chain's native coin. **When to use** Use when the market's collateral IS wrapped native: the router wraps `msg.value` for you, so the caller needs no prior approval and no wrap step. For ERC-20 collateral use [MintSetPermit2Params](MintSetPermit2Params.md) instead. **Gotchas** - Throws [ContractRevertError](../classes/ContractRevertError.md) `CollateralNotWNative` when the market's collateral is not wrapped native, or `ZeroAmount` when `amount` is 0. ## Extends - [`RouterMintBase`](RouterMintBase.md) ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2080 bytes32 market key the set is minted for (the market's `marketId`). #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`marketId`](RouterMintBase.md#marketid) *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/trade.ts:2082 Routing operator id (uint32) for attribution; 0 = none. #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`operatorId`](RouterMintBase.md#operatorid) *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2084 Routing venue id (bytes32 hex); 32-byte zero = none. #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`venueId`](RouterMintBase.md#venueid) *** ### router? > `optional` **router?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2089 CollateralRouter address; resolved from `config.addresses.collateralRouter` if omitted. Throws if neither is set (never sends to the zero address). #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`router`](RouterMintBase.md#router) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2095 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`gas`](RouterMintBase.md#gas) *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:2119 Native (SOMI/STT) amount to wrap → wNative and mint as `amount` YES + NO. Sent as `msg.value`; the target market's collateral must be wNative. --- # /docs/typescript/api/index/interfaces/MintSetParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MintSetParams # Interface: MintSetParams Defined in: packages/sdk/src/trade.ts:1625 Inputs to [Trader.mintSet](Trader.md#mintset) — deposit collateral, receive equal YES + NO. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1627 BinaryPool address — pool pulls collateral and mints YES+NO. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1629 Collateral amount → mints `amount` YES + `amount` NO to the signer. *** ### collateral? > `optional` **collateral?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1631 Collateral token; resolved from the live store (by pool) if omitted. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1633 Approve collateral → pool if allowance is short (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1639 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/MintSetPermit2Params [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MintSetPermit2Params # Interface: MintSetPermit2Params Defined in: packages/sdk/src/trade.ts:2138 Params for [Trader.mintSetPermit2](Trader.md#mintsetpermit2) — mint a YES+NO set from ERC-20 collateral pulled with a signed Permit2 permit. **When to use** Use as the sibling of [MintSetNativeParams](MintSetNativeParams.md), for markets whose collateral is a real ERC-20: one signature replaces the separate `approve` transaction. **Gotchas** - Throws [ContractRevertError](../classes/ContractRevertError.md) `PermitTokenMismatch` when `permit.permitted.token` is not the market's collateral, or `ZeroAmount` when `amount` is 0. ## Extends - [`RouterMintBase`](RouterMintBase.md) ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2080 bytes32 market key the set is minted for (the market's `marketId`). #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`marketId`](RouterMintBase.md#marketid) *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/trade.ts:2082 Routing operator id (uint32) for attribution; 0 = none. #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`operatorId`](RouterMintBase.md#operatorid) *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2084 Routing venue id (bytes32 hex); 32-byte zero = none. #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`venueId`](RouterMintBase.md#venueid) *** ### router? > `optional` **router?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2089 CollateralRouter address; resolved from `config.addresses.collateralRouter` if omitted. Throws if neither is set (never sends to the zero address). #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`router`](RouterMintBase.md#router) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2095 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`RouterMintBase`](RouterMintBase.md).[`gas`](RouterMintBase.md#gas) *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:2143 Collateral amount to pull via Permit2 and mint as `amount` YES + NO. Must match `permit.permitted.amount` semantics on the app side. *** ### permit > **permit**: [`Permit2TransferFrom`](Permit2TransferFrom.md) Defined in: packages/sdk/src/trade.ts:2145 Signed Permit2 permit whose `permitted.token` must equal the market collateral. *** ### signature > **signature**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2147 EIP-712 signature over `permit` by the signer. --- # /docs/typescript/api/index/interfaces/NetworkTapeOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / NetworkTapeOptions # Interface: NetworkTapeOptions Defined in: packages/sdk/src/networkTape.ts:46 Tuning knobs for [SomniaMarketsClient.createNetworkTape](SomniaMarketsClient.md#createnetworktape). All optional. ## Properties ### maxRows? > `optional` **maxRows?**: `number` Defined in: packages/sdk/src/networkTape.ts:48 Rows retained per column (bids / fills / asks). Default 60. *** ### ownerMapCap? > `optional` **ownerMapCap?**: `number` Defined in: packages/sdk/src/networkTape.ts:50 `(pool, orderId) → owner` entries retained for fill attribution. Default 20 000. --- # /docs/typescript/api/index/interfaces/NetworkTapeStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / NetworkTapeStatus # Interface: NetworkTapeStatus Defined in: packages/sdk/src/networkTape.ts:99 The tape's health + rolling event rates. ## Properties ### connected > **connected**: `boolean` Defined in: packages/sdk/src/networkTape.ts:100 *** ### lastBlock > **lastBlock**: `number` Defined in: packages/sdk/src/networkTape.ts:102 Highest block seen on the heads stream (0 until the first head). *** ### poolsSeen > **poolsSeen**: `number` Defined in: packages/sdk/src/networkTape.ts:104 Distinct pools that have emitted since the tape started. *** ### bidRate > **bidRate**: `number` Defined in: packages/sdk/src/networkTape.ts:106 Events per second over the tape's rolling 5s window, by column. *** ### fillRate > **fillRate**: `number` Defined in: packages/sdk/src/networkTape.ts:107 *** ### askRate > **askRate**: `number` Defined in: packages/sdk/src/networkTape.ts:108 --- # /docs/typescript/api/index/interfaces/ObservedReadResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadResult # Interface: ObservedReadResult\ Defined in: packages/sdk/src/observedReads.ts:148 Data keeps its legacy shape inside an immutable observation envelope. ## Type Parameters ### T `T` ## Properties ### data > `readonly` **data**: `T` Defined in: packages/sdk/src/observedReads.ts:149 *** ### observation > `readonly` **observation**: [`IndexerObservation`](IndexerObservation.md) Defined in: packages/sdk/src/observedReads.ts:150 --- # /docs/typescript/api/index/interfaces/ObservedReads [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReads # Interface: ObservedReads Defined in: packages/sdk/src/observedReads.ts:180 Owner-derived observations sharing one independent head. Create a new capability to refresh that head. Each read captures its own response metadata. Concurrent reads cannot replace older observations. Owner/caller cancellation retains its abort reason. The capability has no polling or separate transport. ## Properties ### independentHead > `readonly` **independentHead**: [`IndependentHead`](IndependentHead.md) Defined in: packages/sdk/src/observedReads.ts:182 The independently measured head shared by these reads. ## Methods ### read() > **read**\<`K`\>(`request`): `Promise`\<[`ObservedReadResult`](ObservedReadResult.md)\<`Awaited`\<`ReturnType`\<[`ObservedReadMethods`](../type-aliases/ObservedReadMethods.md)\[`K`\]\>\>\>\> Defined in: packages/sdk/src/observedReads.ts:194 Run one supported domain read with metadata from the same response. #### Type Parameters ##### K `K` *extends* [`ObservedReadOperation`](../type-aliases/ObservedReadOperation.md) #### Parameters ##### request [`ObservedReadRequest`](../type-aliases/ObservedReadRequest.md)\<`K`\> #### Returns `Promise`\<[`ObservedReadResult`](ObservedReadResult.md)\<`Awaited`\<`ReturnType`\<[`ObservedReadMethods`](../type-aliases/ObservedReadMethods.md)\[`K`\]\>\>\>\> #### Throws Indexer request or decoding failed. #### Throws Domain arguments or cursor are invalid. #### Throws A mixed-tier domain read needs missing chain configuration. #### Throws A mixed-tier chain read failed. #### Throws A mixed-tier contract read reverted. #### Throws A fill-page read needs a compatible reindexed producer. #### Throws A fill-page cursor belongs to another serving dataset or lacks a generation. #### Throws A domain invariant failed. *** ### batch() > **batch**\<`R`\>(`requests`): `Promise`\<\{ readonly \[P in string \| number \| symbol\]: ObservedReadResult\\>\> \}\> Defined in: packages/sdk/src/observedReads.ts:209 Run several reads concurrently, sharing the head but not a database transaction. Result order matches request order. Each result keeps its own watermark and span. #### Type Parameters ##### R `R` *extends* readonly [`ObservedReadRequest`](../type-aliases/ObservedReadRequest.md)\<[`ObservedReadOperation`](../type-aliases/ObservedReadOperation.md)\>[] #### Parameters ##### requests `R` #### Returns `Promise`\<\{ readonly \[P in string \| number \| symbol\]: ObservedReadResult\\>\> \}\> #### Throws A member's indexer request failed. #### Throws A member's arguments are invalid. #### Throws A member needs missing chain configuration. #### Throws A member's chain read failed. #### Throws A member's contract read reverted. #### Throws A fill-page member needs a compatible reindexed producer. #### Throws A fill-page member requires a page-one restart. #### Throws A domain invariant failed. --- # /docs/typescript/api/index/interfaces/OnchainOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OnchainOrder # Interface: OnchainOrder Defined in: packages/sdk/src/orders.ts:809 One resting order exactly as the pool holds it — raw units, `bigint` fields. Order ids are unique per POOL, not globally: always carry the pool alongside the id. ## Properties ### orderId > **orderId**: `bigint` Defined in: packages/sdk/src/orders.ts:811 The pool's order id (`OrderId`, a uint128). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/orders.ts:813 True for a bid (buy), false for an ask (sell). *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/orders.ts:815 The account the order rests for. *** ### userData > **userData**: `bigint` Defined in: packages/sdk/src/orders.ts:817 Caller-supplied tag echoed back by the book; 0 when unused. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/orders.ts:819 Limit price, raw quote/collateral units per whole base unit. *** ### fullQuantity > **fullQuantity**: `bigint` Defined in: packages/sdk/src/orders.ts:821 Quantity as originally placed, raw base units. *** ### quantityRemaining > **quantityRemaining**: `bigint` Defined in: packages/sdk/src/orders.ts:823 Quantity still resting, raw base units — what a cancel would return. *** ### expireTimestampNs > **expireTimestampNs**: `bigint` Defined in: packages/sdk/src/orders.ts:825 Expiry as a UNIX timestamp in NANOseconds; 0 means no expiry. --- # /docs/typescript/api/index/interfaces/OnchainResolutionPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OnchainResolutionPrice # Interface: OnchainResolutionPrice Defined in: packages/sdk/src/markets.ts:1906 A market's resolution price, read from the oracle adapter it was bound to — what `client.getOnchainResolutionPrice(marketId)` resolves. ## Properties ### numericValue > **numericValue**: `string` Defined in: packages/sdk/src/markets.ts:1908 Raw numeric answer as the adapter posted it, at [decimals](#decimals) scale. *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/markets.ts:1910 Scale of [numericValue](#numericvalue) — the adapter's `PRICE_DECIMALS`, or the fallback. *** ### voided > **voided**: `boolean` Defined in: packages/sdk/src/markets.ts:1912 The oracle voided the question rather than answering it. *** ### adapter > **adapter**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:1914 The adapter the answer was read from (markets bind to exactly one). *** ### oracleQuestionId > **oracleQuestionId**: `string` Defined in: packages/sdk/src/markets.ts:1916 The adapter-scoped question id the answer belongs to. --- # /docs/typescript/api/index/interfaces/OpenOrdersOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OpenOrdersOnchain # Interface: OpenOrdersOnchain Defined in: packages/sdk/src/orders.ts:979 One owner's resting orders across several pools, all read at one block. Read them with `client.getOpenOrdersOnchain(pools, owner)`. ## Properties ### orders > **orders**: [`OnchainOrder`](OnchainOrder.md) & `object`[] Defined in: packages/sdk/src/orders.ts:987 Every resting order, each tagged with the pool it rests on. Order ids are unique per pool, so the pool is part of a row's identity. Empty when no supplied pool holds an order for this owner. That is a successful empty result; a failed read throws. *** ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/orders.ts:989 The single block every read in the call quoted. --- # /docs/typescript/api/index/interfaces/OperatorAdmin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OperatorAdmin # Interface: OperatorAdmin Defined in: packages/sdk/src/operatorAdmin.ts:257 The MarketsCore control-plane write surface — register/update operators, create/update venues. Built via `client.createOperatorAdmin(config)` with a signer ([OperatorAdminConfig](OperatorAdminConfig.md)); every method sends one tx and resolves with its receipt after inclusion. Directory reads live on the client (indexer-backed `listOperators` / `listVenues` / `getOperator` / `getVenue`). Every write throws `ContractRevertError` when the chain rejects it — at simulation, at send, or as a mined receipt with `status: "reverted"` (the reason is recovered by replaying the call at that block while the node still has the state) — and `RpcError` when the send or the receipt read does not complete. A reverted write never resolves as if it had been confirmed. ## Methods ### registerOperator() > **registerOperator**(`p`): `Promise`\<[`RegisterOperatorResult`](RegisterOperatorResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:262 Permissionlessly claim a new operator identity. Resolves with the auto-assigned `operatorId` (decoded from `OperatorRegistered`). #### Parameters ##### p [`RegisterOperatorParams`](RegisterOperatorParams.md) #### Returns `Promise`\<[`RegisterOperatorResult`](RegisterOperatorResult.md)\> *** ### updateOperator() > **updateOperator**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:264 Update all mutable operator fields at once. Operator-owner only. #### Parameters ##### p [`UpdateOperatorParams`](UpdateOperatorParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setOperatorEnabled() > **setOperatorEnabled**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:266 Flip the operator's kill switch without touching other fields. #### Parameters ##### p [`SetOperatorEnabledParams`](SetOperatorEnabledParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### transferOperatorOwnership() > **transferOperatorOwnership**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:271 Stage a two-step operator-ownership transfer (or cancel a pending one by re-staging the current owner). #### Parameters ##### p [`TransferOperatorOwnershipParams`](TransferOperatorOwnershipParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### acceptOperatorOwnership() > **acceptOperatorOwnership**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:273 Complete a pending operator-ownership transfer. Caller must be the staged owner. #### Parameters ##### p [`AcceptOperatorOwnershipParams`](AcceptOperatorOwnershipParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### createVenue() > **createVenue**(`p`): `Promise`\<[`CreateVenueResult`](CreateVenueResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:278 Create a venue under an operator. Resolves with the contract-generated `venueId` (decoded from `VenueCreated`). #### Parameters ##### p [`CreateVenueParams`](CreateVenueParams.md) #### Returns `Promise`\<[`CreateVenueResult`](CreateVenueResult.md)\> *** ### updateVenue() > **updateVenue**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:280 Replace a venue's mutable config (`marketType` cannot change here). #### Parameters ##### p [`UpdateVenueParams`](UpdateVenueParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setVenueEnabled() > **setVenueEnabled**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/operatorAdmin.ts:282 Flip a venue's creation flag without touching other fields. #### Parameters ##### p [`SetVenueEnabledParams`](SetVenueEnabledParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> --- # /docs/typescript/api/index/interfaces/OperatorAdminConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OperatorAdminConfig # Interface: OperatorAdminConfig Defined in: packages/sdk/src/operatorAdmin.ts:33 Signer + target config for an [OperatorAdmin](OperatorAdmin.md) (reached via `client.createOperatorAdmin(config)`). Pass exactly one signer source: `walletClient`, `account`, or `privateKey`. ## Properties ### walletClient? > `optional` **walletClient?**: `object` Defined in: packages/sdk/src/operatorAdmin.ts:35 A pre-built signer (e.g. a browser/wagmi wallet over an injected provider). *** ### account? > `optional` **account?**: `` `0x${string}` `` \| `Account` Defined in: packages/sdk/src/operatorAdmin.ts:37 A local signing account (e.g. from viem's privateKeyToAccount). *** ### privateKey? > `optional` **privateKey?**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:39 Private key — the SDK derives the account. *** ### publicClient? > `optional` **publicClient?**: `object` Defined in: packages/sdk/src/operatorAdmin.ts:41 Read client for receipts. Defaults to the client's WebSocket client. *** ### marketsCore? > `optional` **marketsCore?**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:43 MarketsCore address override. Defaults to `config.addresses.marketsCore`. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:48 Default gas ceiling per tx. #### Default ```ts 10_000_000n ``` --- # /docs/typescript/api/index/interfaces/OperatorPreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OperatorPreflightInput # Interface: OperatorPreflightInput Defined in: packages/sdk/src/preflight.ts:84 The operator fields the operator-step preflight inspects (subset of [IndexedOperator](../type-aliases/IndexedOperator.md)). ## Properties ### caller > **caller**: `` `0x${string}` `` Defined in: packages/sdk/src/preflight.ts:86 The connected signer — must own the operator to run machinery under it. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/preflight.ts:88 The operator's current on-chain owner — a mismatch with `caller` blocks. *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/preflight.ts:90 The operator's kill switch — disabled blocks market creation under it. *** ### feeRecipient > **feeRecipient**: `string` Defined in: packages/sdk/src/preflight.ts:95 The operator's default fee recipient — the zero address only warns (fees fall to the zero address unless a venue overrides it). --- # /docs/typescript/api/index/interfaces/OracleHubAdmin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleHubAdmin # Interface: OracleHubAdmin Defined in: packages/sdk/src/oracleHub.ts:515 Admin handle for the OracleHub — the protocol's ONE governance-approved oracle adapter (Oracle v2 §8e, earmark-at-creation). Point reads (quotes, the earmark/credit accounts, dedup state, live status) plus the signed writes (schedule, credit-only withdrawals, funding, owner-gated gas/drain params, reactivity wiring). Built via `client.createOracleHubAdmin(config)`; needs `config.addresses.oracleHub` (and `binaryModule` for the approval reads). Every write throws `ContractRevertError` when the chain rejects it — at simulation, at send, or as a mined receipt with `status: "reverted"` (the reason is recovered by replaying the call at that block while the node still has the state) — and `RpcError` when the send or the receipt read does not complete. A reverted write never resolves as if it had been confirmed. ## Methods ### getSchedulingCost() > **getSchedulingCost**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:518 Marginal scheduling cost for `def` (0 = would dedup). #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> *** ### earmarkedOf() > **earmarkedOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:520 Native LOCKED for an operator's outstanding markets (wei; never withdrawable). #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### creditOf() > **creditOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:522 An operator's accrued WITHDRAWABLE surplus credit on the hub (wei). #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### outstandingOf() > **outstandingOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:524 Count of an operator's bound-but-unresolved markets. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### withdrawableOf() > **withdrawableOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:526 Wei an operator's owner may withdraw right now (== `creditOf`). #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### payerCreditOf() > **payerCreditOf**(`payer`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:531 A1: withdrawable surplus credited to a reserve-PAYER (open-venue creator or the autonomous MarketCreator), drawn by that account itself. #### Parameters ##### payer `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### payerOf() > **payerOf**(`marketId`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/oracleHub.ts:536 A1: the reserve-payer recorded for a market at onBind (surplus recipient); zero-address once settled + swept. #### Parameters ##### marketId `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### resolveReserve() > **resolveReserve**(): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:538 The per-market resolution reserve attached+locked at onBind (wei). #### Returns `Promise`\<`bigint`\> *** ### quoteCreateMarketValue() > **quoteCreateMarketValue**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:544 THE §8e create-market value rule: `getSchedulingCost(def) + resolveReserve()` (the reserve is attached to the create; attach exactly this to `scheduleAndCreateMarket`; excess refunds). #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> *** ### getQuestionState() > **getQuestionState**(`def`): `Promise`\<[`HubQuestionState`](HubQuestionState.md)\> Defined in: packages/sdk/src/oracleHub.ts:549 One definition's full dedup state: canonical key, the active question id it resolves to (0n = none), bind count, and the bound-market fan-out list. #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<[`HubQuestionState`](HubQuestionState.md)\> *** ### getQuestionIdByKey() > **getQuestionIdByKey**(`questionKey`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/oracleHub.ts:551 The ACTIVE question id for a canonical key (0n = never scheduled). #### Parameters ##### questionKey `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getBindCount() > **getBindCount**(`oracleQuestionId`): `Promise`\<`number`\> Defined in: packages/sdk/src/oracleHub.ts:553 Lifetime bind count for a question id. #### Parameters ##### oracleQuestionId `bigint` #### Returns `Promise`\<`number`\> *** ### getMarketsForQuestion() > **getMarketsForQuestion**(`oracleQuestionId`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/oracleHub.ts:555 Every marketId bound to a question id (the fan-out list). #### Parameters ##### oracleQuestionId `bigint` #### Returns `Promise`\<`` `0x${string}` ``[]\> *** ### isHubApproved() > **isHubApproved**(): `Promise`\<`boolean`\> Defined in: packages/sdk/src/oracleHub.ts:561 Whether the module has the hub approved (`approvedAdapters(hub)`) — the Oracle v2 equivalent of the old per-adapter `isAdapterApproved`. Needs `config.addresses.binaryModule`. #### Returns `Promise`\<`boolean`\> *** ### getHubStatus() > **getHubStatus**(): `Promise`\<[`HubStatus`](HubStatus.md)\> Defined in: packages/sdk/src/oracleHub.ts:566 The hub's full live status (owner / balance / approval / subscription / gas + drain params / resolveReserve + pending drain). #### Returns `Promise`\<[`HubStatus`](HubStatus.md)\> *** ### scheduleQuestion() > **scheduleQuestion**(`p`): `Promise`\<[`ScheduleQuestionResult`](ScheduleQuestionResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:575 Schedule a question through the hub (content-addressed: an identical template definition returns the EXISTING id and refunds the value). Resolves with the question id decoded from `QuestionScheduled` / `QuestionReused` and whether it deduplicated. #### Parameters ##### p [`ScheduleQuestionParams`](ScheduleQuestionParams.md) #### Returns `Promise`\<[`ScheduleQuestionResult`](ScheduleQuestionResult.md)\> *** ### withdraw() > **withdraw**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:582 Withdraw an operator's accrued WITHDRAWABLE surplus credit (credit-only; OWNER-gated on-chain: only the operator's owner, read from MarketsCore, may draw it, and only up to `withdrawableOf` — else `InsufficientCredit`). The earmark backing live markets is untouchable. #### Parameters ##### p [`WithdrawParams`](WithdrawParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### withdrawMyCredit() > **withdrawMyCredit**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:589 A1: withdraw the CALLER's own accrued payer credit (msg.sender-gated — the connected signer draws only its own surplus, up to `payerCreditOf(caller)`). This is how an open-venue creator claims their refund, and how the autonomous MarketCreator self-reclaims (via its own on-chain call). #### Parameters ##### p [`WithdrawMyCreditParams`](WithdrawMyCreditParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### fundHub() > **fundHub**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:594 Send native to the hub's `receive()` — funds the reactivity bond (hub float; NOT credited to any operator — resolution funding is per-market). #### Parameters ##### p [`FundHubParams`](FundHubParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setGasParams() > **setGasParams**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:599 Update the reactivity gas params (OWNER-only). `maxFeePerGas` also reprices `resolveReserve()` immediately. #### Parameters ##### p [`SetHubGasParams`](SetHubGasParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setDrainParams() > **setDrainParams**(`p`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:605 Update the bounded-drain metering params (OWNER-only): `perMarketResolveGas` sizes `resolveReserve`, `callbackBaseGas` is the attributed overhead term, `maxResolvesPerCallback` + `resolveGasReserve` bound one callback's work. #### Parameters ##### p [`SetHubDrainParams`](SetHubDrainParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### enableReactivity() > **enableReactivity**(`p?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:611 Register the Somnia reactivity subscription (OWNER-only, one-shot). NOTE: calls the reactivity precompile at 0x0100, which does NOT exist on local anvil — testnet/mainnet only. #### Parameters ##### p? [`EnableHubReactivityParams`](EnableHubReactivityParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### migrateSubscription() > **migrateSubscription**(`p?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/oracleHub.ts:616 Unsubscribe + re-subscribe with the current topic/gas params (OWNER-only; for upstream event-signature changes). Precompile — testnet/mainnet only. #### Parameters ##### p? [`EnableHubReactivityParams`](EnableHubReactivityParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> --- # /docs/typescript/api/index/interfaces/OracleHubAdminConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleHubAdminConfig # Interface: OracleHubAdminConfig Defined in: packages/sdk/src/machineryWriter.ts:46 Signer + read-client config shared by every machinery admin. Mirrors [OperatorAdminConfig](OperatorAdminConfig.md) — pass a `walletClient`, a local `account`, or a `privateKey`. ## Properties ### walletClient? > `optional` **walletClient?**: `object` Defined in: packages/sdk/src/machineryWriter.ts:48 A pre-built signer (e.g. a browser/wagmi wallet over an injected provider). *** ### account? > `optional` **account?**: `` `0x${string}` `` \| `Account` Defined in: packages/sdk/src/machineryWriter.ts:50 A local signing account (e.g. from viem's privateKeyToAccount). *** ### privateKey? > `optional` **privateKey?**: `` `0x${string}` `` Defined in: packages/sdk/src/machineryWriter.ts:52 Private key — the SDK derives the account. *** ### publicClient? > `optional` **publicClient?**: `object` Defined in: packages/sdk/src/machineryWriter.ts:54 Read client for receipts. Defaults to the client's WebSocket client. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/machineryWriter.ts:56 Default gas ceiling per tx. --- # /docs/typescript/api/index/interfaces/OrderBookParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderBookParams # Interface: OrderBookParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:33 Default CLOB order-book parameters a MarketCreator stamps onto each market it creates (mirror of the on-chain `OrderBookParameters` struct). All raw. ## Properties ### tickSize > **tickSize**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:35 Minimum price increment, in raw quote-token (collateral) units. *** ### minQuantity > **minQuantity**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:37 Minimum order quantity, in raw base-token (outcome-share) units. *** ### lotSize > **lotSize**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:39 Minimum quantity increment, in raw base-token (outcome-share) units. --- # /docs/typescript/api/index/interfaces/OrderFill [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderFill # Interface: OrderFill Defined in: packages/sdk/src/trade.ts:147 A single fill that occurred within a tx (decoded from the pool's OrderFilled). ## Properties ### takerOrderId > **takerOrderId**: `bigint` Defined in: packages/sdk/src/trade.ts:149 On-chain id of the taker (incoming) order. *** ### makerOrderId > **makerOrderId**: `bigint` Defined in: packages/sdk/src/trade.ts:151 On-chain id of the maker (resting) order that matched. *** ### quantityFilled > **quantityFilled**: `bigint` Defined in: packages/sdk/src/trade.ts:153 Quantity exchanged in this fill, raw units (outcome tokens on binary, base on spot). *** ### takerRemainingQuantity > **takerRemainingQuantity**: `bigint` Defined in: packages/sdk/src/trade.ts:155 Taker order's quantity still unfilled after this fill, raw units. *** ### makerRemainingQuantity > **makerRemainingQuantity**: `bigint` Defined in: packages/sdk/src/trade.ts:157 Maker order's quantity still resting after this fill, raw units. *** ### fillPrice > **fillPrice**: `bigint` Defined in: packages/sdk/src/trade.ts:162 Fill price — the YES price on a binary pool (raw collateral units per whole outcome token); raw quote units per whole base on a spot pool. --- # /docs/typescript/api/index/interfaces/OutcomePositionMark [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OutcomePositionMark # Interface: OutcomePositionMark Defined in: packages/sdk/src/derivedReads.ts:1385 An outcome position marked to a live price — one portfolio row's numbers. ## Properties ### value > **value**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:1387 Current position value in collateral (raw): `balance × mark`. *** ### upnl > **upnl**: `bigint` \| `null` Defined in: packages/sdk/src/derivedReads.ts:1389 Unrealized PnL in collateral (raw), or `null` when entry is unknown. *** ### upnlFraction > **upnlFraction**: `number` \| `null` Defined in: packages/sdk/src/derivedReads.ts:1391 Unrealized PnL as a signed fraction (0.12 = +12%), or `null`. --- # /docs/typescript/api/index/interfaces/Permit2TransferFrom [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Permit2TransferFrom # Interface: Permit2TransferFrom Defined in: packages/sdk/src/trade.ts:2059 A canonical Permit2 `PermitTransferFrom` — the signed authorization the Permit2 mint path forwards to the router (which relays it to Permit2). Build it (and the EIP-712 signature) with a Permit2 SDK on the app side. ## Properties ### permitted > **permitted**: `object` Defined in: packages/sdk/src/trade.ts:2061 Token + amount the signature authorizes. `token` must equal the market collateral. #### token > **token**: `` `0x${string}` `` The ERC-20 the signature authorizes — must equal the market's collateral token. #### amount > **amount**: `bigint` Max amount the signature authorizes, raw collateral units. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/trade.ts:2068 Unordered Permit2 nonce. *** ### deadline > **deadline**: `bigint` Defined in: packages/sdk/src/trade.ts:2070 Signature deadline (unix seconds). --- # /docs/typescript/api/index/interfaces/PerpFeedStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpFeedStatus # Interface: PerpFeedStatus Defined in: packages/sdk/src/perp/state.ts:263 Whether a perp pool's MARK feed is live, and how much open interest is riding on it. ## Properties ### markPriceOk > **markPriceOk**: `boolean` Defined in: packages/sdk/src/perp/state.ts:269 The pool's OWN verdict on its mark feed, from `tryGetMarkPrice`. Never re-derive it by comparing a timestamp: the staleness bound lives on `FundingParametersEpoch` per pool and moves per epoch, so an outside comparison can disagree with the pool. *** ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/state.ts:275 The mark itself, because `markPriceOk` is not the whole verdict: a feed can report ok and hand back 0, and a zero mark is never a real price for a live perp. Treat `markPriceOk && markPrice > 0n` as live — the same test [perpMarkForPnl](../functions/perpMarkForPnl.md) makes. *** ### openInterest > **openInterest**: `bigint` Defined in: packages/sdk/src/perp/state.ts:278 Total open interest in base units. What makes a stale mark dangerous rather than merely untidy: margin and liquidation prices are struck against the mark. *** ### indexUpdatedAt? > `optional` **indexUpdatedAt?**: `bigint` Defined in: packages/sdk/src/perp/state.ts:287 The INDEX oracle's timestamp (epoch seconds) — a DIFFERENT feed from the mark, so it corroborates a verdict rather than dating it. `undefined` when that leg reverted, which is the case this read exists to survive: it is diagnostic, and it must never take the verdict down with it. See the note on [client.getPerpFeedStatus](SomniaMarketsClient.md#getperpfeedstatus). --- # /docs/typescript/api/index/interfaces/PerpFundingPremium [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpFundingPremium # Interface: PerpFundingPremium Defined in: packages/sdk/src/perp/state.ts:340 A perp pool's funding-premium state — what the next settlement will charge, and the raw accumulator behind it. ## Properties ### timeWeightedPremium > **timeWeightedPremium**: `bigint` Defined in: packages/sdk/src/perp/state.ts:349 The premium the NEXT settlement will charge: the time-weighted average of the order-book premium over the interval so far, PRE-clamp, 1e18-scaled and signed. Positive means the perp is rich and longs pay. This is the value to build a predicted funding rate from. Do not read `lastObservedPremium` for that — see its note. *** ### lastObservedPremium > **lastObservedPremium**: `bigint` Defined in: packages/sdk/src/perp/state.ts:361 The standing INSTANTANEOUS sample, 1e18-scaled and signed. Exposed beside `timeWeightedPremium` because the contract's getter for this kept its signature and changed its meaning: before Wave 28 it WAS the premium the next settlement would charge. Anything still treating it that way is silently wrong, and a spot reading is the one number that looks most like the right one. Useful for "where is the book right now" and for reproducing the open segment. Not for predicting a charge. *** ### accumulator > **accumulator**: `bigint` Defined in: packages/sdk/src/perp/state.ts:363 Raw premium integral accumulated since `intervalStartNs`, for exact reproduction. *** ### intervalStartNs > **intervalStartNs**: `bigint` Defined in: packages/sdk/src/perp/state.ts:365 Start of the interval being averaged, in NANOseconds. Zero when un-armed — see `armed`. *** ### observedAtNs > **observedAtNs**: `bigint` Defined in: packages/sdk/src/perp/state.ts:367 When the standing sample was taken, in NANOseconds. *** ### validUntilNs > **validUntilNs**: `bigint` Defined in: packages/sdk/src/perp/state.ts:377 When the standing sample stops accruing credit, in NANOseconds. Every nanosecond past it is credited at ZERO, which is what makes a quote's weight its resting duration rather than its presence at one instant. It can legitimately sit BEHIND `observedAtNs`: a freeze writes the current time here, and an observation in the same block then advances `observedAtNs` to match. Do not subtract them without ordering them first. *** ### armed > **armed**: `boolean` Defined in: packages/sdk/src/perp/state.ts:387 Whether the time-weighted mechanism is running for this market yet. Derived from `intervalStartNs !== 0n`, which is the contract's own migration sentinel: it is armed by each market's FIRST settlement after the beacon upgrade. While this is `false` the pool still charges the point sample, so `timeWeightedPremium` equals `lastObservedPremium` and the accumulator is empty — correct, not missing, and it resolves on the market's next settlement. --- # /docs/typescript/api/index/interfaces/PerpLeverage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpLeverage # Interface: PerpLeverage Defined in: packages/sdk/src/perp/margin.ts:528 How levered an account is — measured at one position, and across the whole cross-margin account. Every ratio is **bps of 1x**: `10_000` is 1.00x, `25_000` is 2.5x, `200_000` is 20x. That is the protocol's own unit for every margin figure, so these compose with [PerpRiskParams](PerpRiskParams.md) without a rescale. ## Properties ### asOfBlock > **asOfBlock**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:530 The block every read was pinned to. *** ### size > **size**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:532 SIGNED position size in this market, raw base units (positive = long, 0 = flat). *** ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:534 Mark price the notionals were measured at, raw quote units per whole base. *** ### positionNotional > **positionNotional**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:536 This position's notional: `|size| × mark / oneBase`, raw collateral units. *** ### accountNotional > **accountNotional**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:546 Σ notional across EVERY market the account holds a position in, this one included, raw collateral units. Costs two extra reads per OTHER active market — the MarginBank exposes no aggregate notional view, and `imReq` cannot be inverted back into notional because each market applies its own OI-scaled IMF. So this grows with the account's footprint; a single-market account pays nothing extra. *** ### equity > **equity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:548 Account equity = collateral + Σ unrealized PnL − Σ pending funding (signed). *** ### positionLeverageBps > **positionLeverageBps**: `bigint` \| `null` Defined in: packages/sdk/src/perp/margin.ts:558 This position's notional over account equity, bps — "this position is Nx my equity". `null` when equity is ≤ 0, where the ratio has no meaning: an account with no equity left is not running infinite leverage, it is insolvent, and rendering an enormous number would say the wrong thing. Read [MarginStatus](../type-aliases/MarginStatus.md) for that state instead. *** ### accountLeverageBps > **accountLeverageBps**: `bigint` \| `null` Defined in: packages/sdk/src/perp/margin.ts:567 Total notional over account equity, bps. **The figure that actually governs risk here.** Margin is cross, so every position draws on the same collateral: a second position at the same notional doubles the account's leverage without changing the first one's [positionLeverageBps](#positionleveragebps). `null` on non-positive equity, as above. *** ### marketMaxLeverageBps > **marketMaxLeverageBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:578 The most leverage THIS MARKET will open a position at, bps — `10000² / effectiveImfBps`, using the OI-scaled IMF actually in force rather than the static `initialMarginBps`. A ceiling on new size, not a measurement of the position: it does not move when the position or the equity does. It DOES move when market-wide open interest does, which is why it is read per call rather than derived from [PerpRiskParams.initialMarginBps](PerpRiskParams.md#initialmarginbps). *** ### accountMaxLeverageX > **accountMaxLeverageX**: `number` Defined in: packages/sdk/src/perp/margin.ts:589 The account's OWN per-market cap as an integer multiplier, `0` when unset — what `trader.setPerpLeverage` writes, read back. A cap STRICTER than the market's effective IMF adds margin on top of the base requirement; that surcharge is quoted by `PerpOrderMarginPreview.leverageSurcharge`. Being a setting rather than a measurement, it can sit far above the position's actual [positionLeverageBps](#positionleveragebps). *** ### protocolMaxLeverageX > **protocolMaxLeverageX**: `number` Defined in: packages/sdk/src/perp/margin.ts:591 Protocol-wide ceiling that clamps the above, integer multiplier. *** ### creditFloor > **creditFloor**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:598 The account's non-withdrawable credit-voucher floor, raw collateral units. `0n` for an ordinary account, and the switch that arms the two fields below. Self-clearing: the confinement lifts on its own once the floor reaches zero. *** ### voucherLeverageCapX > **voucherLeverageCapX**: `number` Defined in: packages/sdk/src/perp/margin.ts:638 The protocol's voucher leverage cap, integer multiplier — what a voucher-holding account is confined to when it INCREASES a position. `0` means unset, which is a hard block rather than "no cap" (see [voucherMarketAllowed](#vouchermarketallowed)). Reported, not applied to [protocolMaxLeverageX](#protocolmaxleveragex), because it does not bound the position this call measures. `MarginBank._meetsIM` gates the whole voucher branch on `additionalSize > 0`, so it never touches a reduce or a close — a voucher holder can always close out, or place a stop, even on a market since removed from the allowlist. Folding it into the protocol ceiling would report a constraint on a reduce-only action that the chain does not apply. What it bounds is a NEW increase, and the composition is not a plain minimum: ``` // voucher inactive (creditFloor == 0n) // accountMaxLeverageX == 0 -> no leverage-derived requirement at all; // marketMaxLeverageBps is what binds // otherwise -> min(accountMaxLeverageX, protocolMaxLeverageX) // // voucher active and allowed // the cap REPLACES an unset or looser account setting, then the // protocol ceiling clamps the result: const confined = accountMaxLeverageX !== 0 && accountMaxLeverageX <= voucherLeverageCapX ? accountMaxLeverageX // a STRICTER user setting still wins : voucherLeverageCapX; const bindingX = Math.min(confined, protocolMaxLeverageX); ``` The load-bearing half is the first branch: a voucher turns an *unset* account cap into an enforced one. On an ordinary account `accountMaxLeverageX === 0` means "no cap set"; on a voucher account increasing a position it means "confined to `voucherLeverageCapX`". For whether a specific order passes, use [SomniaMarketsClient.previewPerpOrderMargin](SomniaMarketsClient.md#previewperpordermargin) — it applies all of this and reports `voucherBlocked` alongside the margin numbers. *** ### voucherMarketAllowed > **voucherMarketAllowed**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:650 Whether THIS market is on the voucher allowlist. Only consequential while [creditFloor](#creditfloor) is positive, and then it is a hard placement revert rather than an arithmetic clamp: an increase on a non-allowlisted market reverts `VoucherMarketNotAllowed`, and an unset [voucherLeverageCapX](#voucherleveragecapx) reverts `VoucherLeverageCapNotSet` — a deliberate fail safe, so an unconfigured cap never silently grants full leverage. Neither outcome is expressible as a leverage number, which is the other reason these are reported rather than folded in. --- # /docs/typescript/api/index/interfaces/PerpLiquidationPriceInputs [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpLiquidationPriceInputs # Interface: PerpLiquidationPriceInputs Defined in: packages/sdk/src/perp/margin.ts:388 Everything the maintenance-margin solve needs — and nothing that has to come from a particular block, so `perpLiquidationPrice` stays pure. ## Properties ### equity > **equity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:390 Account equity across every market (signed, raw collateral units). *** ### mmReq > **mmReq**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:392 Aggregate maintenance requirement across every market (raw collateral units). *** ### size > **size**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:394 SIGNED position size in THIS market, raw base units. Zero yields `null`. *** ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:396 This market's mark price, raw quote units per whole base. *** ### maintenanceMarginBps > **maintenanceMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:398 This market's maintenance-margin threshold, bps. *** ### oneBase > **oneBase**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:400 10^decimals of this market's synthetic base — the divisor for notional math. --- # /docs/typescript/api/index/interfaces/PerpMainFunding [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMainFunding # Interface: PerpMainFunding Defined in: packages/sdk/src/perp/linkedWallet.ts:112 The outstanding claim against a child, and who it is owed to. What a main funds can be BORROWED, NEVER WITHDRAWN: `withdraw` pays the child at most `balance - principal`, so a compromised child key can trade the money and lose it but cannot take it out. ## Properties ### principal > **principal**: `bigint` Defined in: packages/sdk/src/perp/linkedWallet.ts:122 Principal a main has funded and not yet recovered, in collateral units. Zero means nothing is outstanding. It is NOT a segregated bucket. The child's own money and its main's are one fungible balance, and the claim is clamped to `min(principal, balance)` at flat moments — so the child's own contribution is the JUNIOR tranche and a loss eats it first. A child that genuinely lost the money does not owe it forever. *** ### payer > **payer**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/linkedWallet.ts:131 The payer recorded AT FUNDING TIME, or zero when nothing is outstanding. Snapshotted deliberately: both routes home settle against this address, so an unlink or re-link between the pull and the repayment cannot misroute the money to whoever happens to be linked later. When this disagrees with the LIVE resolution ([PerpFundingPayer](../type-aliases/PerpFundingPayer.md)), THIS is who gets repaid. *** ### withdrawableFromPrincipal > `readonly` **withdrawableFromPrincipal**: `0n` Defined in: packages/sdk/src/perp/linkedWallet.ts:138 How much of `principal` the child could withdraw: always zero while a claim stands, and present as a field only so a caller does not have to re-derive the rule from prose. Included because "why can I not withdraw my balance" is the commonest question this surface has to answer. --- # /docs/typescript/api/index/interfaces/PerpOrderMarginQuote [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderMarginQuote # Interface: PerpOrderMarginQuote Defined in: packages/sdk/src/perp/margin.ts:1882 The placement gates and the lock they are measured against. ## Properties ### increasingQuantity > **increasingQuantity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1884 The part of the order that increases the position — the only part that locks. *** ### reducingQuantity > **reducingQuantity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1886 The part absorbed by existing exposure. Locks nothing. *** ### lockAmount > **lockAmount**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1888 Total collateral the pool will lock. *** ### initialMarginPortion > **initialMarginPortion**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1890 The initial-margin component of [lockAmount](#lockamount). *** ### adverseGapPortion > **adverseGapPortion**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1892 The adverse mark-to-entry component, zero on a favourable entry. *** ### leverageSurcharge > **leverageSurcharge**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1894 Extra margin a leverage cap stricter than the market's IMF demands. *** ### feeHeadroom > **feeHeadroom**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1912 The pool's worst-case fee reserve for this order (`PerpPool._feeHeadroom`). Not part of [lockAmount](#lockamount) and not charged — perps locks only initial margin and takes fees from the unlocked balance at fill. It exists solely as an auto-pull addend, so that pulling exactly the lock cannot leave a max-leverage open at `equity = IM − fees` against an `IM` requirement, i.e. in `MarginCall` at birth. The rate is an envelope, not a prediction: an order rests as a maker or crosses as a taker but never both, so it takes the larger of the two — with a negative (rebate) maker rate floored at zero first, since a rebate must not shrink the reserve below the taker case — plus the order's builder fee. Ceil-rounded, on the **full** order notional rather than the increasing leg, because fees are charged on the whole fill. Reported whatever [topUpRequired](#topuprequired) does, but it only enters the arithmetic when auto-pull is modelled. *** ### topUpRequired > **topUpRequired**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1933 What auto-pull would REQUEST in total (`MarginBank.quoteOrderTopUp`) — `0n` when [PerpOrderMarginQuoteInputs.wallet](PerpOrderMarginQuoteInputs.md#wallet) is omitted, i.e. when auto-pull is not being modelled at all. **Not the owner's wallet debit once a main is in play.** It is the requirement, and [ownWalletPull](#ownwalletpull) / [mainWalletPull](#mainwalletpull) are the two wallets that meet it. Showing this figure as the child's spend over-states it by exactly the main's leg. `lockAmount + feeHeadroom + leverageSurcharge` less the unlocked balance, floored at zero. **Order-local by design**: it excludes the initial margin of the account's positions in other markets, so it is exactly sufficient for a FLAT account and best-effort for one already carrying exposure — a pre-existing cross-market deficit still fails [meetsInitialMargin](#meetsinitialmargin). Auto-pull funds an ORDER, not an ACCOUNT. A `0n` is three different things, which is why it should be read beside the balance rather than alone: no pull needed, or one of the pool's three declines — a purely reducing order (closing never debits a wallet), an account already in debt (a pull would silently cure bad debt), or a voucher-blocked increase. *** ### walletCoversTopUp > **walletCoversTopUp**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1953 The funding wallets can together cover [topUpRequired](#topuprequired) — the owner's own balance and allowance, plus a linked main's capacity when one was supplied. Vacuously `true` when no pull is needed or auto-pull is not modelled. **What a `false` MEANS depends on whether a main is in play**, and the two are not the same outcome: - **No main.** The pool asks for a fixed `topUpRequired`, so the `transferFrom` inside `depositFor` reverts and the placement fails on the TOKEN's error rather than a margin gate — deliberate, because that error names the fix. This is a placement gate and it folds into [sufficient](#sufficient). - **With a main.** Both legs are `min(...)`-sized and neither can revert, so the pool pulls what it can and the margin gates judge the result. This is then INFORMATIONAL and does NOT fold into [sufficient](#sufficient): the order can be accepted with the lock funded and the fee reserve short, which is precisely what [feeHeadroom](#feeheadroom) exists to avoid. Read a `false` here as "the position may be born close to its own initial margin", not as "this will be rejected". *** ### ownWalletPull > **ownWalletPull**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1960 How much of [topUpRequired](#topuprequired) the OWNER's own wallet would supply. `min(topUpRequired, min(balance, allowance))`. The owner's wallet always pays first, so a child holding some collateral spends its own before it touches its main's. *** ### mainWalletPull > **mainWalletPull**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1976 How much of [topUpRequired](#topuprequired) a linked MAIN's wallet would supply — the residual the owner's own wallet could not cover, capped at [PerpOrderMarginQuoteInputs.mainWalletCapacity](PerpOrderMarginQuoteInputs.md#mainwalletcapacity). `0n` with no main, `0n` for an account that funds itself, and `0n` while [mainFundingBlocked](#mainfundingblocked). **Non-zero is the only proof another wallet is actually debited** — an eligible payer alone is not, since the order may need no top-up or the owner's own wallet may cover all of it. This is the number to show a trader before they sign. `ownWalletPull + mainWalletPull` is what the pull actually moves, and it is BELOW [topUpRequired](#topuprequired) exactly when [walletCoversTopUp](#walletcoverstopup) is `false` — neither leg reverts on a short wallet, so the shortfall surfaces at the margin gates instead. *** ### hasCollateralForLock > **hasCollateralForLock**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1984 Gate 1 — the unlocked balance covers the lock, **after any auto-pull**. With [PerpOrderMarginQuoteInputs.wallet](PerpOrderMarginQuoteInputs.md#wallet) supplied this is the real post-pull gate. Without it, the in-bank balance alone — conservative rather than wrong on the self-send path, since the pool tops up before `lockCollateral` runs. *** ### meetsInitialMargin > **meetsInitialMargin**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1998 Gate 2 — post-lock equity still meets the initial-margin requirement, **after any auto-pull** (the top-up lands in the unlocked balance that seeds equity). Note this is NOT monotone in quantity once auto-pull is modelled, and the reason is worth knowing: in the pulled regime the surcharge cancels from both sides and the gate reduces to `(equity − unlocked) + feeHeadroom ≥ imRequirement`, whose only quantity-dependent term GROWS. An account whose existing positions sit below their own initial margin can therefore be rejected at a middling size and accepted at a far larger one, whose headroom over-pulls enough to cover the deficit. `client.getMaxPerpOrderSize` deliberately does not offer sizes from that disconnected upper region. *** ### mainFundingBlocked > **mainFundingBlocked**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:2004 The main's leg was withheld because the account still owes a prior payer — see [PerpOrderMarginQuoteInputs.mainFundingBlocked](PerpOrderMarginQuoteInputs.md#mainfundingblocked). Placement is not blocked outright, only the main's contribution. *** ### voucherBlocked > **voucherBlocked**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:2006 The order would revert on the voucher allowlist / unset-cap guard. *** ### restrictedBlocked > **restrictedBlocked**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:2011 The market is close-only and this order has an increasing leg, so placement reverts `MarketRestricted`. Never blocks a pure reduce. *** ### isolationBlocked > **isolationBlocked**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:2017 The account is in isolated margin with a footprint in a DIFFERENT market, so placement reverts `IsolatedMarketBlocked`. Unlike every other gate here this blocks the reducing legs too — it is about which market may be traded, not about margin. *** ### sufficient > **sufficient**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:2019 Every gate passes. --- # /docs/typescript/api/index/interfaces/PerpOrderMarginQuoteInputs [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderMarginQuoteInputs # Interface: PerpOrderMarginQuoteInputs Defined in: packages/sdk/src/perp/margin.ts:1765 Everything the placement gates need, and nothing that has to come from a particular block — so `perpOrderMarginQuote` stays pure. ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1767 True = a buy. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1769 Order quantity, raw base units. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1771 Limit price, raw quote units per whole base. *** ### oneBase > **oneBase**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1773 10^decimals of the synthetic base. *** ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1775 Current mark, raw quote units per whole base. *** ### effectiveImfBps > **effectiveImfBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1777 The OI-scaled IMF in force, bps. *** ### positionSize > **positionSize**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1779 SIGNED existing position size, raw base units. *** ### effectiveReducingCapacity > **effectiveReducingCapacity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1781 Reducing capacity resting orders have not already spoken for, raw base units. *** ### equity > **equity**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1783 Account equity, signed. *** ### imRequirement > **imRequirement**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1785 Aggregate initial-margin requirement. *** ### unlockedCollateral > **unlockedCollateral**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1787 Unlocked collateral balance, signed. *** ### accountMaxLeverageX > **accountMaxLeverageX**: `number` Defined in: packages/sdk/src/perp/margin.ts:1789 The account's own per-market cap, `0` when unset. *** ### protocolMaxLeverageX > **protocolMaxLeverageX**: `number` Defined in: packages/sdk/src/perp/margin.ts:1791 Protocol-wide ceiling. *** ### creditFloor > **creditFloor**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1793 The account's credit-voucher floor. *** ### voucherLeverageCapX > **voucherLeverageCapX**: `number` Defined in: packages/sdk/src/perp/margin.ts:1795 The protocol's voucher leverage cap, `0` when unset. *** ### voucherMarketAllowed > **voucherMarketAllowed**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1797 Whether this market is voucher-allowlisted. *** ### wallet? > `optional` **wallet?**: `object` Defined in: packages/sdk/src/perp/margin.ts:1814 The owner's wallet, which turns auto-pull (T70) modelling ON. Supply it **only when the transaction sender will be the order owner**, because that is the pool's entire gate: `PerpPool._autoPullMargin` returns early unless `msg.sender == order.owner`, deliberately narrower than spot's, which also admits registry-approved operators. Routing through `placeOrderFor`, an operator grant, a router, or the stop registry means no pull — omit this and the gates fall back to the in-bank balance, which is what those paths actually face. `balance` is the owner's collateral-token balance and `allowance` their approval to the **MarginBank** (the same one `deposit` already needs — the pool reaches the wallet through `depositFor`). Both bind: the pull is an ordinary `transferFrom`, so whichever is smaller is the ceiling, and an insufficient one reverts from the TOKEN rather than being swallowed. #### balance > **balance**: `bigint` #### allowance > **allowance**: `bigint` *** ### mainWalletCapacity? > `optional` **mainWalletCapacity?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1835 A linked MAIN's spendable capacity — `MarginBank.quoteWalletCapacity(payer)`, which is `min(balance, allowance)` in one number. Omit it when the account has no main. This is the SECOND funding leg, and without it a linked child's placement reads as underfunded when it is not. `PerpPool._reserveAndPullMargin` spends the owner's own wallet first and takes the residual from the main, so the two legs add: the pull succeeds when `ownCapacity + mainWalletCapacity` covers [PerpOrderMarginQuote.topUpRequired](PerpOrderMarginQuote.md#topuprequired). It only participates when [wallet](#wallet) is also supplied, because the whole pull — both legs — is gated on `msg.sender == order.owner`. A main never funds an operator-routed or stop-triggered order. One number rather than a balance/allowance pair on purpose: the bank exposes only the minimum for another wallet, and reading the pair separately would let the SDK's sizing disagree with the contract's. The cost is that a main-side shortfall does not say which of the two bound — a caller that needs to know reads the main's token balance and allowance directly. *** ### mainFundingBlocked? > `optional` **mainFundingBlocked?**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1851 The main's leg cannot be spent because the account still owes a DIFFERENT payer. Defaults to `false`. `MarginBank.depositForFromMain` allows one payer at a time: while `mainFundedPrincipal` is outstanding it reverts `PriorFundingPayerOutstanding` unless the live payer IS the recorded one. A child funded by main A, unlinked, and re-linked to main B is exactly that state, and `quoteFundingPayer` names B — so counting B's capacity would quote an executable order that reverts. While `true` the main's leg is treated as zero, whatever [mainWalletCapacity](#mainwalletcapacity) says. The account can still place whatever its own wallet and bank balance fund. The fix is to clear the old claim with `trader.repayPerpMainFunding`, not to fund either main. *** ### takerFeeBpsTimes1k? > `optional` **takerFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1856 The pool's taker fee, `BPS_TIMES_1K`. Feeds [PerpOrderMarginQuote.feeHeadroom](PerpOrderMarginQuote.md#feeheadroom) only; the lock itself is fee-free. Defaults to `0n`. *** ### makerFeeBpsTimes1k? > `optional` **makerFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1858 The pool's maker fee, `BPS_TIMES_1K` and SIGNED — negative is a rebate. Defaults to `0n`. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1860 The builder fee attached to this order, `BPS_TIMES_1K`. Defaults to `0n`. *** ### restricted? > `optional` **restricted?**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1867 The market is in close-only mode (`PerpPool.isRestricted()`). Defaults to `false`. Rejects any order with an increasing leg outright — no arithmetic involved — so it behaves like the voucher block rather than like a margin gate. *** ### isolationAllowsMarket? > `optional` **isolationAllowsMarket?**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1874 `MarginBank.isolationAllowsMarket(account, pool)`. Defaults to `true`. `false` rejects the WHOLE order, reducing legs included — the one placement gate that does, because it is a market-selection rule rather than a margin one. --- # /docs/typescript/api/index/interfaces/PerpPosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPosition # Interface: PerpPosition Defined in: packages/sdk/src/perp/state.ts:451 An account's position in one perp pool (from the MarginBank). `size` is signed base units: positive = long, negative = short, zero = flat. ## Properties ### size > **size**: `bigint` Defined in: packages/sdk/src/perp/state.ts:456 Signed position size in raw base units: positive = long, negative = short, zero = flat. *** ### avgEntryPrice > **avgEntryPrice**: `bigint` Defined in: packages/sdk/src/perp/state.ts:458 Volume-weighted average entry price (raw quote units per whole base). *** ### entryFundingIndex > **entryFundingIndex**: `bigint` Defined in: packages/sdk/src/perp/state.ts:460 Cumulative funding index at open / last settlement (1e18-scaled, signed). *** ### lastUpdatedTimestampNs > **lastUpdatedTimestampNs**: `bigint` Defined in: packages/sdk/src/perp/state.ts:462 Last position update (nanoseconds). --- # /docs/typescript/api/index/interfaces/PerpPositionAnalyticsInputs [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPositionAnalyticsInputs # Interface: PerpPositionAnalyticsInputs Defined in: packages/sdk/src/perp/margin.ts:797 Everything the per-position arithmetic needs, and nothing that has to come from a particular block — so `perpPositionAnalytics` stays pure and testable. The last six all arrive together from one `tryGetHealthSnapshot`; the first three are the stored `Position`. ## Properties ### size > **size**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:799 SIGNED position size, raw base units (positive = long, negative = short). *** ### avgEntryPrice > **avgEntryPrice**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:801 Volume-weighted average entry price, raw quote units per whole base. *** ### entryFundingIndex > **entryFundingIndex**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:803 Cumulative funding index stamped at open / last settlement (1e18-scaled, signed). *** ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:805 Current mark price, raw quote units per whole base. *** ### projectedCumulativeFunding > **projectedCumulativeFunding**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:807 Cumulative funding per unit INCLUDING unsettled intervals (1e18-scaled, signed). *** ### oneBase > **oneBase**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:809 10^decimals of the synthetic base asset. *** ### effectiveImfBps > **effectiveImfBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:811 The OI-scaled IMF actually in force, bps. *** ### maintenanceMarginBps > **maintenanceMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:813 Maintenance threshold, bps. *** ### closeOutMarginBps > **closeOutMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:815 Close-out / takeover threshold, bps. --- # /docs/typescript/api/index/interfaces/PerpPositionMetrics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPositionMetrics # Interface: PerpPositionMetrics Defined in: packages/sdk/src/perp/margin.ts:823 One position, marked to the current mark and funding index. ## Properties ### size > **size**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:825 SIGNED size, raw base units — echoed so a result stands alone. *** ### notional > **notional**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:827 `|size| × mark / oneBase`, raw collateral units. Zero when flat. *** ### unrealizedPnl > **unrealizedPnl**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:835 Mark-to-market PnL on price alone, signed: `(mark − entry) × size / oneBase`. **Excludes funding**, deliberately — see [accruedFunding](#accruedfunding). Truncates toward zero, matching `PerpMath.unrealizedPnl`'s plain `int256` division, which is NOT the rounding the funding leg uses. *** ### accruedFunding > **accruedFunding**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:853 Funding **owed** since the position's entry index, signed and raw collateral units. **Positive means the account pays**; negative means it receives. Sign is the contract's, not a display convention, and it is the opposite of [unrealizedPnl](#unrealizedpnl)'s: this is a payment, so it is SUBTRACTED to reach [equityContribution](#equitycontribution). Rendering it beside PnL without flipping it shows a cost as a gain. Includes unsettled intervals, because it is computed against the pool's *projected* cumulative index rather than its last settled one — settlement is permissionless and lazy, so the settled index can lag by hours, and a position measured against it under-reports what the account already owes. Ceils toward +∞ (`divCeilInt`), so a payer pays at least what is owed and a receiver receives at most it. *** ### equityContribution > **equityContribution**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:861 This position's contribution to account equity: `unrealizedPnl − accruedFunding`. The figure the MarginBank actually sums. Across every active market these add to `equity − collateral`, exactly — which is the invariant that makes this a port of the contract rather than a re-derivation of it. *** ### initialMarginRequirement > **initialMarginRequirement**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:876 This position's share of the account's initial-margin requirement: `ceil(notional × effectiveImfBps / 10000)`. **This is "position margin" in the only sense the protocol defines one.** Margin is cross, so no collateral is segregated per position and there is nothing to read; what a position *does* have is the requirement it adds to the account. Note it uses the market's IMF only. An account leverage setting stricter than the market's IMF raises the bar for a NEW order (`MarginBank._meetsIM`) but does not appear here, because `_marketHealthFromSnapshot` does not apply it — health, liquidation and equity are all measured without it. Use [SomniaMarketsClient.previewPerpOrderMargin](SomniaMarketsClient.md#previewperpordermargin) for the order-gating figure. *** ### maintenanceMarginRequirement > **maintenanceMarginRequirement**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:878 `ceil(notional × maintenanceMarginBps / 10000)` — the liquidation threshold's share. *** ### closeOutMarginRequirement > **closeOutMarginRequirement**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:880 `ceil(notional × closeOutMarginBps / 10000)` — the takeover threshold's share. *** ### returnOnMarginBps > **returnOnMarginBps**: `bigint` \| `null` Defined in: packages/sdk/src/perp/margin.ts:897 [equityContribution](#equitycontribution) over [initialMarginRequirement](#initialmarginrequirement), in bps — "this position has returned N% of the margin it ties up". **Net of funding**, because funding is a real cost of holding the position and a gross figure flatters a position that is up on price and bleeding carry. For the price-only ratio, use `unrealizedPnl × 10000n / initialMarginRequirement`. `null` whenever [initialMarginRequirement](#initialmarginrequirement) is zero and the ratio is therefore undefined — not `0n`, which would read as a real break-even. That is a flat position in the ordinary case, and also a dust one whose [notional](#notional) floors to zero, which the protocol likewise asks no margin for. Floors (toward −∞) rather than truncating, so a loss never rounds toward looking smaller than it is. --- # /docs/typescript/api/index/interfaces/PerpPositionRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPositionRef # Interface: PerpPositionRef Defined in: packages/sdk/src/perp/state.ts:474 Identifies one account's position in one perp pool — the (bank, account, pool) triple every per-position read keys on. Shared by `getPerpPosition` and `getLiquidationPrice` (perp/margin.ts); one object instead of three positional `Address` args (which compiled fine with any two swapped). ## Properties ### marginBank > **marginBank**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/state.ts:476 The MarginBank holding the position — comes off the `PerpMarket` row. *** ### account > **account**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/state.ts:478 The position's owner. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/state.ts:480 The perp pool the position is in. --- # /docs/typescript/api/index/interfaces/PerpRiskParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpRiskParams # Interface: PerpRiskParams Defined in: packages/sdk/src/perp/margin.ts:155 A perp market's RISK CONFIG — the static parameters frozen on the pool, read straight from `getPerpPoolParameters`. Never reverts, so this is the dependable source for maintenance margin even when the mark feed is down. All bps values are standard basis points (100 = 1%) EXCEPT the two fee fields, which are bps × 1000 (the pool's own unit — 1500 = 1.5 bps = 0.015%). ## Properties ### initialMarginBps > **initialMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:162 The initial-margin curve's FLOOR, bps — not necessarily what an order is charged. When dynamic IMF is enabled the pool scales this up with open interest; read `effectiveImfBps` off [PerpHealthSnapshot](../type-aliases/PerpHealthSnapshot.md) for the rate actually in force. Equal to the effective IMF only when dynamic IMF is off. *** ### maintenanceMarginBps > **maintenanceMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:169 Maintenance-margin threshold, bps — the level below which a position is liquidatable. Unlike initial margin this does **not** scale with open interest, deliberately: the liquidation threshold must not move under a position because the market's OI grew. *** ### closeOutMarginBps > **closeOutMarginBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:171 Close-out / takeover threshold, bps. Strictly below maintenance. *** ### maxOpenInterest > **maxOpenInterest**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:173 Market-wide open-interest cap, raw base units. *** ### maxPositionSize > **maxPositionSize**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:175 Per-position size cap, raw base units. *** ### takerFeeBpsTimes1k > **takerFeeBpsTimes1k**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:177 Taker fee, bps × 1000. *** ### makerFeeBpsTimes1k > **makerFeeBpsTimes1k**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:179 Maker fee, bps × 1000 — SIGNED, because a negative value is a maker rebate. *** ### insuranceFundShareBps > **insuranceFundShareBps**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:181 Share of collected fees routed to the Insurance Fund, bps. --- # /docs/typescript/api/index/interfaces/PerpSideHolders [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpSideHolders # Interface: PerpSideHolders Defined in: packages/sdk/src/perp/margin.ts:1155 One side of one perp market's complete holder set, as of one block. ## Properties ### holders > **holders**: `` `0x${string}` ``[] Defined in: packages/sdk/src/perp/margin.ts:1161 Every account holding an open position on the requested side. Ordering is UNSPECIFIED by the contract and can change on any close — treat it as a set, never as a stable sequence. Empty when nobody holds that side. *** ### asOfBlock > **asOfBlock**: `bigint` Defined in: packages/sdk/src/perp/margin.ts:1168 The block height every page was read at. Feed it into the reads that take a block pin — `getBankruptcyPrice`'s `opts.blockNumber`, and a sibling call for the other side — to keep a sweep on one consistent snapshot. (The other position/health reads answer at head only.) --- # /docs/typescript/api/index/interfaces/PerpSideHoldersRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpSideHoldersRef # Interface: PerpSideHoldersRef Defined in: packages/sdk/src/perp/margin.ts:1122 Identifies one side of one perp market in the MarginBank — the (bank, pool, side) triple the holder-enumeration read keys on. ## Properties ### marginBank > **marginBank**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/margin.ts:1124 The MarginBank holding the positions — comes off the `PerpMarket` row. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/margin.ts:1126 The perp pool whose holders to enumerate. *** ### isLong > **isLong**: `boolean` Defined in: packages/sdk/src/perp/margin.ts:1128 True for the long side, false for the short side. --- # /docs/typescript/api/index/interfaces/PerpStateOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStateOnchain # Interface: PerpStateOnchain Defined in: packages/sdk/src/perp/state.ts:22 A perp pool's live pricing/funding state, read straight from chain in one pipelined fan-out. Fresher than the indexed Market row (funding fields there only update when FundingUpdated fires, i.e. per settlement window). ## Properties ### markPrice > **markPrice**: `bigint` Defined in: packages/sdk/src/perp/state.ts:24 EMA-smoothed oracle mark price (raw quote units per whole base). *** ### markPriceOk > **markPriceOk**: `boolean` Defined in: packages/sdk/src/perp/state.ts:29 Whether the mark feed is live. When false, `markPrice` is not meaningful — the FundingUpdated event signals the same condition with a 0 sentinel. *** ### indexPrice > **indexPrice**: `bigint` Defined in: packages/sdk/src/perp/state.ts:31 Unsmoothed oracle index price (raw quote units per whole base). *** ### indexUpdatedAt > **indexUpdatedAt**: `bigint` Defined in: packages/sdk/src/perp/state.ts:33 Index price oracle timestamp (seconds). *** ### fundingRate > **fundingRate**: `bigint` Defined in: packages/sdk/src/perp/state.ts:35 Current funding rate per settlement window (1e18-scaled fraction, signed). *** ### cumulativeFundingPerUnit > **cumulativeFundingPerUnit**: `bigint` Defined in: packages/sdk/src/perp/state.ts:37 Settled cumulative funding per base unit (1e18-scaled, signed). *** ### projectedCumulativeFundingPerUnit > **projectedCumulativeFundingPerUnit**: `bigint` Defined in: packages/sdk/src/perp/state.ts:39 Cumulative funding projected to now (unsettled accrual included). *** ### openInterest > **openInterest**: `bigint` Defined in: packages/sdk/src/perp/state.ts:47 TOTAL open interest in base units. Replaces `longOpenInterest` / `shortOpenInterest`: the contract keeps ONE counter because the short side is provably equal in a matched CLOB, and the two-field form did not match the deployed ABI at all — it made every `getPerpState` call throw. *** ### fundingWindowSec > **fundingWindowSec**: `number` Defined in: packages/sdk/src/perp/state.ts:53 The rate's DENOMINATOR in seconds (`fundingCalculationWindowSec`), 28800 on every live pool. `fundingRate` is per THIS window — not per settlement interval and not annualized. Normalize with it; never with a hardcoded constant. *** ### fundingIntervalSec > **fundingIntervalSec**: `number` Defined in: packages/sdk/src/perp/state.ts:60 Settlement cadence in seconds. **3600 on every live pool**, so `fundingWindowSec / fundingIntervalSec` is 8. It has been 300 (n = 96), and the same emitted rate means a 12x different per-interval accrual across that boundary — which is why this is read per pool and never assumed. Indexed history still spans it. *** ### lastFundingUpdateAt > **lastFundingUpdateAt**: `bigint` Defined in: packages/sdk/src/perp/state.ts:62 Last settlement, unix seconds (the chain stores nanoseconds). *** ### nextFundingAt > **nextFundingAt**: `bigint` Defined in: packages/sdk/src/perp/state.ts:64 When the next settlement becomes due. Settlement is LAZY, so it may pass unmet. *** ### emaPremium > **emaPremium**: `bigint` Defined in: packages/sdk/src/perp/state.ts:86 EMA'd premium driving the rate, and NOT mark vs index — expect it to disagree with `(mark - index) / index`, which is a different quantity by design. Since DEX-2252 the underlying premium is Binance's impact-price shape rather than a book midpoint: `[max(0, impactBid - index) - max(0, index - impactAsk)] / index`, where each impact price is the quantity-weighted price of filling a configured impact notional on that side, counting only orders that pass a fillability check, and time-weighted across the settlement interval. Three consequences: - **There is a deadband.** An index sitting anywhere inside the impact spread prices exactly zero, so a merely wide book is no longer charged funding for its spread. - **Zero does not mean an empty book.** A side that cannot show the impact notional of fillable depth drops out and the other side stands alone, so a ONE-SIDED book can carry a non-zero premium. Only a book with nothing priceable on either side is reliably zero. - **It lags the book**, because it is an average over the interval rather than a reading at an instant. Not recoverable from events, so this read is the only source. *** ### oracle > **oracle**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/state.ts:96 The pool's aggregator oracle contract. This is the address the pool itself reads prices from, so it is the head of the chain that produces `markPrice` and `indexPrice` — the aggregator chains to the sim-controlled oracle and then to the agent EMA feed. It is a per-pool address: every live pool reports a different one, so it cannot be substituted with a per-network constant such as the deployment config's `oracleHub`. --- # /docs/typescript/api/index/interfaces/PerpStopOrderLeg [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderLeg # Interface: PerpStopOrderLeg Defined in: packages/sdk/src/trade.ts:1490 One leg of a perp stop order — the terms shared by a single stop and by each half of a linked pair. ## Extended by - [`PlacePerpStopOrderParams`](PlacePerpStopOrderParams.md) ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:1492 True = the triggered order buys, false = sells. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:1502 Base quantity to trade at trigger, raw base units. ZERO is a sentinel meaning "the whole position at trigger time" — the size is resolved against the live position when it fires, so the stop keeps covering a position that GREW after it was armed. A non-zero quantity is fixed at creation and only ever clamped DOWN. Rejected for `"opening"` intent, where it has no meaning. *** ### triggerPrice > **triggerPrice**: `bigint` Defined in: packages/sdk/src/trade.ts:1504 Mark price that arms the trigger (raw collateral units per whole base). *** ### triggerOperator > **triggerOperator**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1506 0 = GTE (fires when mark ≥ triggerPrice), 1 = LTE (mark ≤ triggerPrice). *** ### stopOrderType > **stopOrderType**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1508 0 = LIMIT (uses limitPrice), 1 = MARKET (slippage-bounded by the registry). *** ### limitPrice? > `optional` **limitPrice?**: `bigint` Defined in: packages/sdk/src/trade.ts:1510 Limit price for a LIMIT stop (raw collateral per whole base). Must be 0 for MARKET. *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1512 Builder to tag on the triggered order. Omit for none. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:1514 Builder fee in bps x 1000 (so 1500 = 1.5bps). Requires `builder`. --- # /docs/typescript/api/index/interfaces/PerpSystemConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpSystemConfig # Interface: PerpSystemConfig Defined in: packages/sdk/src/perp/system.ts:36 How the perps stack is wired, straight from `MarginBank.getSystemConfig`. This is the address book. Every other contract in the plane is reachable from here, so a consumer never hardcodes one per chain — and the bank's own view of them is the authoritative one, since these are the addresses it will actually call. ## Properties ### marginBank > **marginBank**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:38 The MarginBank reporting this config (echoed back). *** ### collateralToken > **collateralToken**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:40 The single collateral token every perp market is quoted in. *** ### perpPoolFactory > **perpPoolFactory**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:42 The factory that deploys PerpPools. *** ### liquidationEngine > **liquidationEngine**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:44 The LiquidationEngine — the PROXY, which is what to call. *** ### insuranceFund > **insuranceFund**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:46 The tiered InsuranceFund that absorbs bad debt. *** ### feeRecipient > **feeRecipient**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/system.ts:48 Where protocol fees are routed. *** ### maxLeverageLimit > **maxLeverageLimit**: `number` Defined in: packages/sdk/src/perp/system.ts:50 Protocol-wide ceiling on per-account leverage; clamps a stricter user setting. *** ### fullyWired > **fullyWired**: `boolean` Defined in: packages/sdk/src/perp/system.ts:62 Whether the factory, liquidation engine and insurance fund are all set. **`feeRecipient` is NOT part of it**, despite sitting in the same struct — the contract's flag covers three of the five addresses above. A go-live check that read this as "everything is configured" would sign off a stack whose fee routing is still unset, so check [feeRecipient](#feerecipient) separately. False means some part of the stack is half-configured, which is the state in which liquidation or settlement paths degrade silently rather than reverting. --- # /docs/typescript/api/index/interfaces/PerpVoucher [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpVoucher # Interface: PerpVoucher Defined in: packages/sdk/src/perp/voucher.ts:121 One account's voucher state. ## Properties ### claimed > **claimed**: `boolean` Defined in: packages/sdk/src/perp/voucher.ts:123 Whether this address has ever claimed from the live distributor. *** ### floor > **floor**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:131 The non-withdrawable house money in the account, in raw collateral units. `withdraw` frees at most `balance - floor`. After a loss, the bank lowers the floor to the balance the next time it settles the account while it is flat (on a deposit, for example). It never raises the floor. `0n` means no house money remains. *** ### expiresAt > **expiresAt**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:136 Unix seconds when the floor becomes sweepable, or `0n` when no voucher is active. A claimed account reads `0n` after a sweep. --- # /docs/typescript/api/index/interfaces/PerpVoucherCampaign [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpVoucherCampaign # Interface: PerpVoucherCampaign Defined in: packages/sdk/src/perp/voucher.ts:38 The live credit-voucher campaign behind one MarginBank. Every amount is in raw collateral units and every time is Unix seconds. ## Properties ### distributor > **distributor**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/voucher.ts:40 The VoucherDistributor the bank accepts credit from. Pass it to `claimPerpVoucher` to skip resolution. *** ### collateralToken > **collateralToken**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/voucher.ts:42 The collateral token the grant is paid in. *** ### grantAmount > **grantAmount**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:44 What one claim credits, in raw collateral units. *** ### expiryDurationSec > **expiryDurationSec**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:49 Seconds after a claim before the grant can be swept back. A sweep happens only when the account holds no positions or resting orders; it never forces a close. *** ### startsAt > **startsAt**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:51 Unix seconds when claims open. Inclusive. *** ### endsAt > **endsAt**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:53 Unix seconds when claims close. Exclusive. *** ### budgetRemaining > **budgetRemaining**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:58 The distributor's collateral balance. This is the hard cap on claims: when it falls below `grantAmount`, every claim reverts until someone funds it. *** ### claimsRemaining > **claimsRemaining**: `bigint` Defined in: packages/sdk/src/perp/voucher.ts:60 How many more claims the budget covers: `budgetRemaining / grantAmount`, rounded down. *** ### leverageCapX > **leverageCapX**: `number` Defined in: packages/sdk/src/perp/voucher.ts:66 The leverage a voucher account is confined to when it increases a position. `0` blocks every increase; it does not mean "uncapped". Each market's own initial margin still applies, so the effective limit is the lower of the two. --- # /docs/typescript/api/index/interfaces/PerpWalletLinkTarget [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpWalletLinkTarget # Interface: PerpWalletLinkTarget Defined in: packages/sdk/src/trade.ts:1068 How a linked-wallet consent write finds its `LinkedWalletRegistry` — the resolution triple every one of the four registry writes shares. Supply ONE of the three. `registry` is used as given. Otherwise the SDK reads `getLinkedWalletRegistry()` off the bank, because the bank is what decides which registry is authoritative — a registry nobody armed is inert. `pool` resolves the bank first. A bank holding no registry throws [NotConfiguredError](../classes/NotConfiguredError.md): the rail is dormant on that deployment. Pass `registry` to reach a registry anyway; the consent writes still work, they just fund nothing until the bank is armed. ## Extended by - [`ProposePerpWalletLinkParams`](ProposePerpWalletLinkParams.md) - [`AcceptPerpWalletLinkParams`](AcceptPerpWalletLinkParams.md) - [`CancelPerpWalletLinkProposalParams`](CancelPerpWalletLinkProposalParams.md) - [`UnlinkPerpWalletParams`](UnlinkPerpWalletParams.md) ## Properties ### registry? > `optional` **registry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1070 The LinkedWalletRegistry. Skips resolution entirely. *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1072 MarginBank address — its `getLinkedWalletRegistry()` is read (never cached). *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1074 A PerpPool — its `marginBank()` is read (and cached), then the registry. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1080 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PerpWalletLinkage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpWalletLinkage # Interface: PerpWalletLinkage Defined in: packages/sdk/src/perp/linkedWallet.ts:153 A link group, with the maturity the raw graph does not carry. `maturesAt` matters for a reason worth stating: ADL netting is gated on maturity so that a link armed in reaction to an impending auto-deleveraging cannot buy netting credit. The FUNDING rail deliberately reads the raw graph instead, because the main proposed the link and owns the allowance, and there is no analogous surprise. So a link can be fundable and not yet mature — do not use `maturesAt` to decide whether a pull will happen. ## Properties ### main > **main**: `` `0x${string}` `` Defined in: packages/sdk/src/perp/linkedWallet.ts:155 The group's main. Zero when the wallet is unlinked. *** ### members > **members**: readonly `` `0x${string}` ``[] Defined in: packages/sdk/src/perp/linkedWallet.ts:157 The main plus every child. Empty when the wallet is unlinked. *** ### linkedAt > **linkedAt**: `bigint` Defined in: packages/sdk/src/perp/linkedWallet.ts:159 Unix seconds the link was formed, or 0. *** ### maturesAt > **maturesAt**: `bigint` Defined in: packages/sdk/src/perp/linkedWallet.ts:161 Unix seconds the link becomes mature FOR ADL NETTING, or 0. Not a funding gate. *** ### isChild > **isChild**: `boolean` Defined in: packages/sdk/src/perp/linkedWallet.ts:163 Convenience: whether this wallet is a child (has a main that is not itself). *** ### isMain > **isMain**: `boolean` Defined in: packages/sdk/src/perp/linkedWallet.ts:165 Convenience: whether this wallet is a main with at least one child. --- # /docs/typescript/api/index/interfaces/PlaceOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceOrderParams # Interface: PlaceOrderParams Defined in: packages/sdk/src/trade.ts:216 Inputs to [Trader.placeOrder](Trader.md#placeorder) — a binary YES/NO limit or market order on a BinaryPool. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:218 BinaryPool address. *** ### side > **side**: [`BinarySide`](../type-aliases/BinarySide.md) Defined in: packages/sdk/src/trade.ts:223 Side + outcome ("BUY_YES" | "SELL_YES" | "BUY_NO" | "SELL_NO") — mapped onto the pool's OrderKind enum. Buys escrow collateral, sells escrow outcome tokens. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:225 YES limit price as raw collateral units per whole outcome token (price × 10^decimals). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:227 Outcome-token quantity, raw units. *** ### outcomeToken? > `optional` **outcomeToken?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:232 Outcome-token singleton + this pool's YES/NO ids. Resolved from the pool (IBinaryPool.outcomeToken/yesId/noId) if omitted. *** ### yesId? > `optional` **yesId?**: `bigint` Defined in: packages/sdk/src/trade.ts:234 This pool's YES position id on the singleton; resolved from the pool if omitted. *** ### noId? > `optional` **noId?**: `bigint` Defined in: packages/sdk/src/trade.ts:236 This pool's NO position id on the singleton; resolved from the pool if omitted. *** ### collateral? > `optional` **collateral?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:238 Collateral (buy-side escrow) token; resolved from the pool if omitted. *** ### expireTimestampNs? > `optional` **expireTimestampNs?**: `bigint` Defined in: packages/sdk/src/trade.ts:252 Order expiry in ns. Defaults to the POOL'S MARKET EXPIRY, not to a far future — a binary order must satisfy `0 < expireNs <= pool.marketExpiryNs` or the pool rejects it with `OrderExpiryBeyondMarket`, which keeps the book drainable by the expiry sweeps once the market locks. So an order left to default stops resting when its market expires. On a rolling series that is hours, not decades. There is no GTC here; ~50y is the spot and perp default, where there is no market expiry to outlive. A value already in the past reverts (`OrderAlreadyExpired`) — a deliberate choice is honoured verbatim rather than silently clamped. *** ### orderType? > `optional` **orderType?**: `number` Defined in: packages/sdk/src/trade.ts:258 OrderBook OrderType (see [ORDER\_TYPE](../variables/ORDER_TYPE.md)): 0 NormalOrder (rest), 1 FillOrKill, 2 ImmediateOrCancel, 3 PostOnly. Defaults to 0. A market order is an IOC (2) placed at the price extreme so it crosses immediately and cancels the remainder. *** ### selfMatchingOption? > `optional` **selfMatchingOption?**: `number` Defined in: packages/sdk/src/trade.ts:263 Self-match behaviour when this order crosses your OWN resting order, default 0 (`CANCEL_TAKER`). See [SELF\_MATCHING\_OPTION](../variables/SELF_MATCHING_OPTION.md). *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:265 Approve the escrow token to the pool if allowance is short (default true). *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:271 Routing/builder frontend address to attribute the order to. Requires the trader to have opted this builder in via [Trader.approveBuilder](Trader.md#approvebuilder). Omit (or zero) for no routing fee. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:276 Per-order builder/routing fee in the pool's native bps×1000 unit (≤ the venue's frozen `maxBuilderFee` ceiling AND ≤ the trader's approval). 0 = none. *** ### userData? > `optional` **userData?**: `bigint` Defined in: packages/sdk/src/trade.ts:282 Opaque market-maker bookkeeping tag (v2). Forwarded verbatim to the pool (stored on the order + emitted in `OrderPlaced`); the SDK never interprets it and the pool no longer uses it for side derivation. Default 0. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:288 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlaceOrderResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceOrderResult # Interface: PlaceOrderResult Defined in: packages/sdk/src/trade.ts:203 Base result of a confirmed write — the SDK waits for the receipt before resolving. ## Extends - [`TxResult`](TxResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### orderId? > `optional` **orderId?**: `bigint` Defined in: packages/sdk/src/trade.ts:205 The resting order's on-chain id, if the order rested (OrderPlaced emitted). *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/trade.ts:207 Fills that executed in this tx (empty for a cleanly-resting limit order). --- # /docs/typescript/api/index/interfaces/PlacePerpOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlacePerpOrderParams # Interface: PlacePerpOrderParams Defined in: packages/sdk/src/trade.ts:808 Inputs to [Trader.placePerpOrder](Trader.md#placeperporder) — a perp limit or market order on a PerpPool. Margin is locked from the signer's MarginBank balance (no escrow transfer in this tx) — [Trader.depositMargin](Trader.md#depositmargin) first. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:810 PerpPool address. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:812 True = buy/long the synthetic base; false = sell/short. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:817 Limit price — raw quote (collateral) units per whole base. For a MARKET order pass a crossing price; it bounds the margin lock. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:819 Base quantity, raw base units. *** ### expireTimestampNs? > `optional` **expireTimestampNs?**: `bigint` Defined in: packages/sdk/src/trade.ts:821 Order expiry in ns. Defaults to ~50y (GTC). *** ### orderType? > `optional` **orderType?**: `number` Defined in: packages/sdk/src/trade.ts:823 0 limit (default) or 2 market (IOC). See [ORDER\_TYPE](../variables/ORDER_TYPE.md). *** ### selfMatchingOption? > `optional` **selfMatchingOption?**: `number` Defined in: packages/sdk/src/trade.ts:828 Self-match behaviour when this order crosses your OWN resting order, default 0 (`CANCEL_TAKER`). See [SELF\_MATCHING\_OPTION](../variables/SELF_MATCHING_OPTION.md). *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:834 Routing/builder frontend address to attribute the order to. Requires the trader to have opted this builder in via [Trader.approveBuilder](Trader.md#approvebuilder) on this pool. Omit (or zero) for no routing fee. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:841 Per-order builder/routing fee in the pool's native bps×1000 unit (≤ the pool's `maxBuilderFee` ceiling AND ≤ the trader's approval). 0 = none. The ceiling is owner-updatable on a PerpPool, so read it rather than caching it indefinitely. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:847 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlacePerpStopOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlacePerpStopOrderParams # Interface: PlacePerpStopOrderParams Defined in: packages/sdk/src/trade.ts:1529 Inputs to [Trader.placePerpStopOrder](Trader.md#placeperpstoporder) — a take-profit / stop-loss (or, with `intent: "opening"`, a stop-entry) that the PerpStopOrderRegistry holds pending and places on the PerpPool when the MARK price crosses the trigger. Pass `pair` to arm two legs as a linked one-cancels-other set in a single transaction, at 2x the SOMI payment. There is no separate "place linked" method on purpose: a pair is the same order with a second leg, and splitting it would give callers two ways to say one thing. ## Extends - [`PerpStopOrderLeg`](PerpStopOrderLeg.md) ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:1492 True = the triggered order buys, false = sells. #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`isBid`](PerpStopOrderLeg.md#isbid) *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:1502 Base quantity to trade at trigger, raw base units. ZERO is a sentinel meaning "the whole position at trigger time" — the size is resolved against the live position when it fires, so the stop keeps covering a position that GREW after it was armed. A non-zero quantity is fixed at creation and only ever clamped DOWN. Rejected for `"opening"` intent, where it has no meaning. #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`quantity`](PerpStopOrderLeg.md#quantity) *** ### triggerPrice > **triggerPrice**: `bigint` Defined in: packages/sdk/src/trade.ts:1504 Mark price that arms the trigger (raw collateral units per whole base). #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`triggerPrice`](PerpStopOrderLeg.md#triggerprice) *** ### triggerOperator > **triggerOperator**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1506 0 = GTE (fires when mark ≥ triggerPrice), 1 = LTE (mark ≤ triggerPrice). #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`triggerOperator`](PerpStopOrderLeg.md#triggeroperator) *** ### stopOrderType > **stopOrderType**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1508 0 = LIMIT (uses limitPrice), 1 = MARKET (slippage-bounded by the registry). #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`stopOrderType`](PerpStopOrderLeg.md#stopordertype) *** ### limitPrice? > `optional` **limitPrice?**: `bigint` Defined in: packages/sdk/src/trade.ts:1510 Limit price for a LIMIT stop (raw collateral per whole base). Must be 0 for MARKET. #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`limitPrice`](PerpStopOrderLeg.md#limitprice) *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1512 Builder to tag on the triggered order. Omit for none. #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`builder`](PerpStopOrderLeg.md#builder) *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:1514 Builder fee in bps x 1000 (so 1500 = 1.5bps). Requires `builder`. #### Inherited from [`PerpStopOrderLeg`](PerpStopOrderLeg.md).[`builderFeeBpsTimes1k`](PerpStopOrderLeg.md#builderfeebpstimes1k) *** ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1531 PerpStopOrderRegistry address (one per PerpPool). *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1533 The PerpPool the registry places on — needed for the operator-auth check. *** ### operatorRegistry? > `optional` **operatorRegistry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1538 Shared OperatorPermissionsRegistry where the one-time global approval is granted. Resolved from the live config (addresses.operatorPermissionsRegistry) if omitted. *** ### intent? > `optional` **intent?**: [`PerpStopIntent`](../type-aliases/PerpStopIntent.md) Defined in: packages/sdk/src/trade.ts:1543 Reduce-only (default) or opening. Omit and existing callers keep the behaviour they always had. *** ### pair? > `optional` **pair?**: [`PerpStopOrderLeg`](PerpStopOrderLeg.md) Defined in: packages/sdk/src/trade.ts:1554 A second leg, armed atomically and LINKED to the first: when one fires and fills, the other is cancelled and its SOMI refunded. The pair must be a coherent TP/SL set — same side, OPPOSITE trigger operators, and straddling (the GTE leg's trigger above the LTE leg's) — or the registry rejects it. Both legs are reduce-only; an opening leg cannot be paired, because a bracket whose children activate on the parent's FILL is not expressible (the pool does not notify the registry on fill). *** ### somiPayment? > `optional` **somiPayment?**: `bigint` Defined in: packages/sdk/src/trade.ts:1559 SOMI to fund the reactivity trigger gas, PER LEG. Read from registry.somiPaymentPerOrder() if omitted; a pair sends twice this. *** ### skipOperatorApproval? > `optional` **skipOperatorApproval?**: `boolean` Defined in: packages/sdk/src/trade.ts:1564 Skip the one-time operator-approval check/tx (default false). Set true if you know the registry is already operator-approved for this owner. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1570 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlacePerpStopOrderResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlacePerpStopOrderResult # Interface: PlacePerpStopOrderResult Defined in: packages/sdk/src/trade.ts:188 [Trader.placePerpStopOrder](Trader.md#placeperpstoporder)'s result: the tx plus the registry id(s). Both ids come from `PendingOrderCreated`, because the function's return value is unreadable from a receipt. ## Extends - [`TxResult`](TxResult.md) ## Other ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### stopOrderId? > `optional` **stopOrderId?**: `bigint` Defined in: packages/sdk/src/trade.ts:194 The id of the leg described by the call's own top-level fields — pass to [Trader.cancelPerpStopOrder](Trader.md#cancelperpstoporder). Undefined only if the event wasn't found in the receipt (an ABI/deployment drift, not a normal path). ## trading ### pairedStopOrderId? > `optional` **pairedStopOrderId?**: `bigint` Defined in: packages/sdk/src/trade.ts:200 The `pair` leg's id, when one was placed. Undefined for a single stop. --- # /docs/typescript/api/index/interfaces/PlaceSpotOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceSpotOrderParams # Interface: PlaceSpotOrderParams Defined in: packages/sdk/src/trade.ts:461 Inputs to [Trader.placeSpotOrder](Trader.md#placespotorder) — a spot limit or market order on a SpotPool. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:463 SpotPool address. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:465 True = buy the base asset (pay quote); false = sell base (pay base/native). *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:470 Limit price — raw quote units per whole base token. For a MARKET order pass a crossing price (best opposite level ± slippage); it bounds the escrow. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:472 Base quantity, raw base units. *** ### ~~baseDecimals?~~ > `optional` **baseDecimals?**: `number` Defined in: packages/sdk/src/trade.ts:479 Base-token decimals. The pool now reports its exact funding requirement, so the SDK no longer uses this value. #### Deprecated Retained for source compatibility. New calls can omit it. *** ### quoteToken > **quoteToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:481 Quote token (approved on a buy). *** ### baseToken > **baseToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:483 Base token (approved on a non-native sell). *** ### baseIsNative? > `optional` **baseIsNative?**: `boolean` Defined in: packages/sdk/src/trade.ts:491 True when the base asset is native SOMI. A sell then pays via `msg.value` instead of an approval — the pool's exact vault shortfall, fee headroom included, read from `getAutoPullRequirement` (one `eth_call`) right before the order is encoded. The bare quantity would revert `InvalidMsgValue` on any fee-bearing pool. *** ### expireTimestampNs? > `optional` **expireTimestampNs?**: `bigint` Defined in: packages/sdk/src/trade.ts:507 Order expiry in ns. Defaults to ~50y (GTC). A spot pool has no market expiry to outlive, so the binary verb's `OrderExpiryBeyondMarket` cap does not apply here. Two traps: - A timestamp already in the PAST reverts with `OrderAlreadyExpired`. It used to be accepted silently — the pool skipped the placement and returned no order id, so the transaction succeeded having placed nothing — but the current protocol rejects it outright. - An expired order does NOT auto-return its escrow, and this one IS silent. The funds stay locked in the pool until someone sweeps it — [Trader.cancelExpiredOrders](Trader.md#cancelexpiredorders) reclaims them, and is callable by anyone, not only the owner. *** ### orderType? > `optional` **orderType?**: `number` Defined in: packages/sdk/src/trade.ts:509 0 limit (default) or 2 market (IOC). See [ORDER\_TYPE](../variables/ORDER_TYPE.md). *** ### selfMatchingOption? > `optional` **selfMatchingOption?**: `number` Defined in: packages/sdk/src/trade.ts:514 Self-match behaviour when this order crosses your OWN resting order, default 0 (`CANCEL_TAKER`). See [SELF\_MATCHING\_OPTION](../variables/SELF_MATCHING_OPTION.md). *** ### userData? > `optional` **userData?**: `bigint` Defined in: packages/sdk/src/trade.ts:516 Opaque market-maker bookkeeping tag, forwarded verbatim. Default 0. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:518 Approve the escrow token if allowance is short (default true). *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:524 Routing/builder frontend address to attribute the order to. Requires the trader to have opted this builder in via [Trader.approveBuilder](Trader.md#approvebuilder) on this pool. Omit (or zero) for no routing fee. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:531 Per-order builder/routing fee in the pool's native bps×1000 unit (≤ the pool's `maxBuilderFee` ceiling AND ≤ the trader's approval). 0 = none. The ceiling is owner-updatable on a SpotPool, so read it rather than caching it indefinitely. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:537 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlaceSpotOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceSpotOrdersParams # Interface: PlaceSpotOrdersParams Defined in: packages/sdk/src/trade.ts:589 Inputs to [Trader.placeSpotOrders](Trader.md#placespotorders) — place several orders on ONE SpotPool in a single transaction. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:591 SpotPool address every order in this batch targets. *** ### orders > **orders**: [`SpotOrderRequest`](SpotOrderRequest.md)[] Defined in: packages/sdk/src/trade.ts:593 The orders to place, in the order the results come back. *** ### ~~baseDecimals?~~ > `optional` **baseDecimals?**: `number` Defined in: packages/sdk/src/trade.ts:600 Base-token decimals. The pool now reports each order's exact funding requirement, so the SDK no longer uses this value. #### Deprecated Retained for source compatibility. New calls can omit it. *** ### quoteToken > **quoteToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:602 Quote token (approved once for the batch's total buy-side escrow). *** ### baseToken > **baseToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:604 Base token (approved once for the batch's total sell-side quantity). *** ### baseIsNative? > `optional` **baseIsNative?**: `boolean` Defined in: packages/sdk/src/trade.ts:611 True when the base asset is native SOMI. Batch writes are NON-payable, so a native-base sell here funds from the pool's vault balance — pre-deposit native to the vault first (the batch cannot send `msg.value`, and nothing is approved for a native base). *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:613 Approve the escrow tokens if allowance is short (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:619 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlaceSpotOrdersResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceSpotOrdersResult # Interface: PlaceSpotOrdersResult Defined in: packages/sdk/src/trade.ts:643 Result of [Trader.placeSpotOrders](Trader.md#placespotorders). ## Extends - [`TxResult`](TxResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### outcomes > **outcomes**: [`BatchPlaceOutcome`](BatchPlaceOutcome.md)[] Defined in: packages/sdk/src/trade.ts:649 Per-request outcomes, index-aligned with the `orders` input. Reconstructed from the receipt's `OrderPlaced` events (a transaction's return data is not readable by an EOA). *** ### fills > **fills**: [`OrderFill`](OrderFill.md)[] Defined in: packages/sdk/src/trade.ts:651 Fills that executed in this tx, across every request in the batch. --- # /docs/typescript/api/index/interfaces/PlaceSpotStopOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceSpotStopOrderParams # Interface: PlaceSpotStopOrderParams Defined in: packages/sdk/src/trade.ts:1379 Inputs to [Trader.placeSpotStopOrder](Trader.md#placespotstoporder) — a stop-loss / take-profit order the SpotStopOrderRegistry holds pending and places on the pool when the mark price crosses the trigger. Funded by SOMI `msg.value` for the trigger gas. ## Properties ### registry > **registry**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1381 SpotStopOrderRegistry address (the per-pool registry). *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1386 The SpotPool the registry trades on — needed for the operator-auth check, the ERC-20 escrow approval, and the native vault pre-load math. *** ### operatorRegistry? > `optional` **operatorRegistry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1391 Shared OperatorPermissionsRegistry where the one-time global approval is granted. Resolved from the live config (addresses.operatorPermissionsRegistry) if omitted. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:1393 True = buy stop (escrows quote at trigger); false = sell stop (escrows base/native). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:1395 Base quantity to trade at trigger, raw base units. *** ### triggerPrice > **triggerPrice**: `bigint` Defined in: packages/sdk/src/trade.ts:1397 Mark price that arms the trigger (raw quote per whole base). *** ### triggerOperator > **triggerOperator**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1399 0 = GTE (trigger when mark ≥ triggerPrice), 1 = LTE (mark ≤ triggerPrice). *** ### stopOrderType > **stopOrderType**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1401 0 = LIMIT (uses limitPrice), 1 = MARKET (slippage-bounded). *** ### limitPrice? > `optional` **limitPrice?**: `bigint` Defined in: packages/sdk/src/trade.ts:1403 Limit price for a LIMIT stop order (raw quote per whole base). *** ### quoteToken > **quoteToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1405 Quote token — the input escrow on a buy stop. *** ### baseToken > **baseToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1407 Base token — the input escrow on a (non-native) sell stop. *** ### baseIsNative? > `optional` **baseIsNative?**: `boolean` Defined in: packages/sdk/src/trade.ts:1409 True when the base asset is native SOMI (sell stops pre-load the pool vault). *** ### somiPayment? > `optional` **somiPayment?**: `bigint` Defined in: packages/sdk/src/trade.ts:1414 SOMI to fund the reactivity subscription gas. Read from registry.somiPaymentPerOrder() if omitted. *** ### skipOperatorApproval? > `optional` **skipOperatorApproval?**: `boolean` Defined in: packages/sdk/src/trade.ts:1419 Skip the one-time operator-approval check/tx (default false). Set true if you know the registry is already operator-approved for this owner. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1421 Approve the ERC-20 escrow token to the pool if allowance is short (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1427 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PlaceStopOrderResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PlaceStopOrderResult # Interface: PlaceStopOrderResult Defined in: packages/sdk/src/trade.ts:171 [Trader.placeSpotStopOrder](Trader.md#placespotstoporder)'s result: the tx plus the registry id. ## Extends - [`TxResult`](TxResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) *** ### stopOrderId? > `optional` **stopOrderId?**: `bigint` Defined in: packages/sdk/src/trade.ts:177 The pending order's id on the registry (from `PendingOrderCreated`) — pass to [Trader.cancelStopOrder](Trader.md#cancelstoporder). Undefined only if the event wasn't found in the receipt (an ABI/deployment drift, not a normal path). --- # /docs/typescript/api/index/interfaces/PnLEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PnLEvent # Interface: PnLEvent Defined in: packages/sdk/src/derivedReads.ts:353 One position-affecting event for the PnL fold, in the account's perspective, RAW units. Buys/sells are per-outcome; a mint/merge touches BOTH outcomes. ## Properties ### kind > **kind**: `"buy"` \| `"sell"` \| `"mint"` \| `"merge"` Defined in: packages/sdk/src/derivedReads.ts:355 Order-book buy/sell of one outcome, or a router mint/merge of a complete set. *** ### outcomeIndex > **outcomeIndex**: `0` \| `1` Defined in: packages/sdk/src/derivedReads.ts:357 0 = YES, 1 = NO. Ignored for mint/merge (they touch both). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:359 Token quantity (raw). For mint/merge this is the pair (set) amount. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/derivedReads.ts:361 Fill price for the fill's own outcome, raw. Ignored for mint/merge. --- # /docs/typescript/api/index/interfaces/PnlBucket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PnlBucket # Interface: PnlBucket Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:224 One PnL bucket: the PnL attributed to (prevSample, t]. ## Properties ### t > **t**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:226 Bucket end time (ms). *** ### pnlUsd > **pnlUsd**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:228 Signed PnL attributed to the bucket, USD. --- # /docs/typescript/api/index/interfaces/PokeOracleParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PokeOracleParams # Interface: PokeOracleParams Defined in: packages/sdk/src/trade.ts:1972 Permissionless oracle retry: ask the module to re-pull the answer for one oracle question. ## Properties ### oracleQuestionId > **oracleQuestionId**: `bigint` Defined in: packages/sdk/src/trade.ts:1978 The ORACLE QUESTION id to retry — not a market id. The module fans out to every market bound to this question; read it from a market row's `oracleQuestion` or the module's market record. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1980 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1986 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/PoolBindingRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PoolBindingRecord # Interface: PoolBindingRecord Defined in: packages/sdk/src/pools.ts:81 One interval in a pool's life during which it was bound 1:1 to a single market (indexer `PoolBinding`; id = `${pool}_${nonce}`). `MarketCreated` OPENS a binding; `PoolReleased` or the next `MarketCreated` on the same pool CLOSES it. An open binding (`toBlock` null) is the pool's current market. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/pools.ts:83 `${poolAddress}_${nonce}` *** ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/pools.ts:85 Lowercased pool address. *** ### marketId > **marketId**: `string` Defined in: packages/sdk/src/pools.ts:87 Lowercased bytes32 marketId this binding served. *** ### nonce > **nonce**: `string` Defined in: packages/sdk/src/pools.ts:89 Pool market nonce for this binding (decimal string). *** ### fromBlock > **fromBlock**: `string` Defined in: packages/sdk/src/pools.ts:91 Block the binding opened in (the MarketCreated; decimal string). *** ### fromLogIndex > **fromLogIndex**: `number` Defined in: packages/sdk/src/pools.ts:93 Log index of the opening event within its block. *** ### fromTimestamp > **fromTimestamp**: `string` Defined in: packages/sdk/src/pools.ts:95 Timestamp (unix seconds) the binding opened. *** ### toBlock > **toBlock**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:97 Null while the binding is open (the pool's current market). *** ### toLogIndex > **toLogIndex**: `number` \| `null` Defined in: packages/sdk/src/pools.ts:99 Log index of the closing event; null while the binding is open. *** ### toTimestamp > **toTimestamp**: `string` \| `null` Defined in: packages/sdk/src/pools.ts:101 Timestamp (unix seconds) the binding closed; null while open. *** ### closedBy > **closedBy**: `"Released"` \| `"Rotated"` \| `null` Defined in: packages/sdk/src/pools.ts:106 How the binding closed: `"Released"` (PoolReleased) | `"Rotated"` (the next MarketCreated recycled the pool onward); null while open. --- # /docs/typescript/api/index/interfaces/PoolMarketBinding [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PoolMarketBinding # Interface: PoolMarketBinding Defined in: packages/sdk/src/markets.ts:2117 The chain-only binding between a binary pool and the market it currently hosts. Read it with `client.getPoolMarketBinding(pool)`. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:2119 The pool the binding was read for, echoed back exactly as supplied. *** ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:2121 The module id of the market this pool currently hosts (bytes32 hex). *** ### marketAddress > **marketAddress**: `` `0x${string}` `` Defined in: packages/sdk/src/markets.ts:2123 The BinaryMarket contract address the pool points at. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/markets.ts:2129 The pool's market nonce at the read block. `(pool, nonce)` identifies this market's slice of the pool's history: the nonce increments on every recycle, so a caller holding an older nonce holds a stale binding. *** ### finalized > **finalized**: `boolean` Defined in: packages/sdk/src/markets.ts:2136 True once the market's backing and resolution snapshot were swept to the settlement singleton. It does NOT mean the pool was released: a finalized pool can still hold resting orders, and it stays bound to its last market until the next recycle. *** ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/markets.ts:2138 The single block both reads were made at. --- # /docs/typescript/api/index/interfaces/PoolSeedStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PoolSeedStatus # Interface: PoolSeedStatus Defined in: packages/sdk/src/store.ts:104 One pool's own seed status, unaffected by any other watched pool. [TailStatus](TailStatus.md) reports the same four facts for the MOST RECENT seed only, so with several watched pools its values cannot be attributed to a pool. Read this for a per-pool answer; read `TailStatus` for "what did the last seed do". ## Properties ### seedSource > **seedSource**: [`SeedSource`](../type-aliases/SeedSource.md) Defined in: packages/sdk/src/store.ts:109 Where THIS pool took its book seed: `"indexer"` for the indexer snapshot, `"chain"` for a `seed: "chain"` watch. *** ### seedBlock > **seedBlock**: `number` Defined in: packages/sdk/src/store.ts:111 Block THIS pool's seed was consistent to. *** ### seedTruncated > **seedTruncated**: `boolean` Defined in: packages/sdk/src/store.ts:116 Whether THIS pool's chain seed hit its page budget and read a shallow book. Always false for an indexer seed. *** ### fillsLoaded > **fillsLoaded**: `boolean` Defined in: packages/sdk/src/store.ts:122 Whether fill history was loaded for THIS pool. `false` plus an empty `getLiveFills` means "never loaded"; `true` plus an empty result means "genuinely no fills in the loaded range" (SDK-IO-002). --- # /docs/typescript/api/index/interfaces/PortfolioAnalytics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioAnalytics # Interface: PortfolioAnalytics Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:236 The computed metrics plane — mirrors what a portfolio page renders. ## Properties ### timeframe > **timeframe**: [`PortfolioTimeframe`](../type-aliases/PortfolioTimeframe.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:237 *** ### asOf > **asOf**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:239 Upper bound of the series (ms). *** ### equity > **equity**: [`EquityPoint`](EquityPoint.md)[] Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:241 Cumulative window PnL over time, oldest first; first point is 0. *** ### holdings > **holdings**: [`HoldingsPoint`](HoldingsPoint.md)[] Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:272 Marked value of the traded book over time, oldest first, on the same sample grid as [PortfolioAnalytics.equity](#equity). The first point is the carried-in book valued at the window start, not zero. This series is a LEVEL, where `equity` is a change. It sums `qty × mark` over every open position at each sample, before the cost basis is taken off. It sums SIGNED position value. Every book this fold keeps today is long-only, because `applyTrade` floors each market's quantity at zero, so today the sum cannot go below zero. Do not lock a chart axis to that. The module note above commits this fold to taking the perp plane as new event kinds, a perp book is signed, and a short marks negative. The marks are the caller's, and this fold does not validate them. A negative price carries into this value unchanged, exactly as it already carries into the PnL and MWRR figures. A position the sample cannot price is left OUT of the value rather than guessed at, and [HoldingsPoint.unpricedMarkets](HoldingsPoint.md#unpricedmarkets) counts what was left out. Check it before presenting a sample as the whole book. It measures the TRADED BOOK, not the wallet. A token that arrived without a fill — bridged in, transferred in, minted — is not in the book, so it is not in this value. Idle quote balance is not a position, so it is not included either. [PortfolioFundingEvent](PortfolioFundingEvent.md)s refine the capital base only, so a deposit inside the window does not step this curve. Read balances from the chain when you need what the wallet itself is worth. *** ### pnl > **pnl**: `object` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:273 #### totalUsd > **totalUsd**: `number` Signed total PnL over the timeframe, USD (== last equity point). #### buckets > **buckets**: [`PnlBucket`](PnlBucket.md)[] *** ### mwrr > **mwrr**: `object` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:278 #### return > **return**: `number` \| `null` Period money-weighted return as a fraction: [gainUsd](#mwrr) over [weightedCapitalUsd](#mwrr). Not annualized. Null when the capital base is not meaningfully positive — at or below one US cent, which includes a base driven negative by withdrawals or by an account extracting more than it put in. Null is not zero: the other fields stay readable so a caller can present the window another way. On the funding basis this can exceed 100% in either direction, because capital at risk for only part of the window is weighted down while the gain covers all of it. That is what a money-weighted period rate states, so it is reported rather than withheld. Read [weightedCapitalUsd](#mwrr) to see how much capital the figure measures against before presenting it as a headline. #### gainUsd > **gainUsd**: `number` Signed money gained over the period, USD. #### depositedUsd > **depositedUsd**: `number` Unweighted capital base: carried-in position value + the window's net flows, per [capitalBasis](#mwrr). On the trades basis, buys deploy capital and the MATCHED proceeds of sells return it — proceeds of tokens never bought on the venue are scored nowhere, so an external seller reads 0 rather than a negative base. Signed. #### weightedCapitalUsd > **weightedCapitalUsd**: `number` The denominator the return divides by. On the funding basis this is the Modified Dietz base: carried-in value plus each external movement weighted by the fraction of the window remaining after it. On the trades basis it equals [depositedUsd](#mwrr), because a trade moves capital already inside the account and weighting it would collapse the base for an account that merely rearranged what it held. Signed. #### capitalBasis > **capitalBasis**: `"trades"` \| `"funding"` Which definition produced the capital figures. `"funding"` when the caller supplied [PortfolioFundingEvent](PortfolioFundingEvent.md)s that fall inside the window, else `"trades"` — the proxy, which cannot see capital that never passed through a trade. Funding that predates the window does not select the funding basis: it contributes no in-window flow, and any capital it left invested is already in the carried-in position's value, which both bases count. Branch on this rather than on the package version. *** ### volume > **volume**: `object` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:326 #### periodUsd > **periodUsd**: `number` Trading volume over the timeframe, USD. #### lifetimeUsd > **lifetimeUsd**: `number` Volume across every supplied event, USD. #### sessionUsd? > `optional` **sessionUsd?**: `number` Volume since `sessionSince`, when supplied. *** ### feesSaved > **feesSaved**: `object` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:334 #### cexRateBps > **cexRateBps**: `number` The comparison taker rate (bps) the savings are computed against. #### periodUsd > **periodUsd**: `number` Volume × rate over the timeframe, USD. #### lifetimeUsd > **lifetimeUsd**: `number` Volume × rate across every supplied event, USD. --- # /docs/typescript/api/index/interfaces/PortfolioAnalyticsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioAnalyticsOptions # Interface: PortfolioAnalyticsOptions Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:410 Options for [computePortfolioAnalytics](../functions/computePortfolioAnalytics.md). ## Properties ### timeframe > **timeframe**: [`PortfolioTimeframe`](../type-aliases/PortfolioTimeframe.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:411 *** ### asOf > **asOf**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:413 Upper bound of the series (ms) — the caller's clock. *** ### marks > **marks**: [`MarkSources`](MarkSources.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:415 Marks for unrealized valuation. *** ### sessionSince? > `optional` **sessionSince?**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:417 Session start (ms) for `volume.sessionUsd`. *** ### cexRateBps? > `optional` **cexRateBps?**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:423 Comparison taker rate, bps. #### Default [DEFAULT\_CEX\_RATE\_BPS](../variables/DEFAULT_CEX_RATE_BPS.md) --- # /docs/typescript/api/index/interfaces/PortfolioFundingEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioFundingEvent # Interface: PortfolioFundingEvent Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:86 External capital entering or leaving the wallet — a bridge delivery, a transfer from another wallet, a withdrawal. Funding events refine the MWRR capital base ONLY. They never touch the equity curve, PnL, or volume: moving money into an account is not profit, and it is not a trade. Venue fills are NOT funding. A trade's settlement transfer is an internal rearrangement the trade event already carries, so a caller sourcing funding from raw token transfers MUST exclude transfers whose counterparty is a venue contract (pool, router, settlement) or the same capital is counted twice. These are caller-supplied because the SDK cannot derive them: the indexer has no wallet token-transfer entity, and the public Somnia RPC caps `eth_getLogs` at 1,000 blocks. Source them from app records, bridge history, or a private RPC scan, valued in USD at the event time. ## Properties ### kind > **kind**: `"funding"` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:88 Event kind. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:90 Event time (ms). *** ### direction > **direction**: `"in"` \| `"out"` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:92 Whether capital entered or left the wallet. *** ### valueUsd > **valueUsd**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:94 Absolute value moved, human USD units (positive). *** ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:102 Numeric chain id the movement happened on. Set it, with `transferId` and `counterpartyChainId`, on a BRIDGE leg so a multi-chain exchange can pair the origin and destination legs of one transfer between its own chains and drop both — see [netInternalTransfers](../functions/netInternalTransfers.md). Optional; a plain deposit or withdrawal leaves all three unset. *** ### transferId? > `optional` **transferId?**: `string` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:108 The bridge transfer both legs belong to (the warp-route message id, or any id the app assigns to one transfer). Legs with the same id and opposite `direction` are one transfer. *** ### counterpartyChainId? > `optional` **counterpartyChainId?**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:110 The chain the other leg of a bridge transfer lands on (out) or came from (in). --- # /docs/typescript/api/index/interfaces/PortfolioTradeEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioTradeEvent # Interface: PortfolioTradeEvent Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:50 A trade the account took part in, human USD-quote units. ## Properties ### kind > **kind**: `"trade"` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:52 Event kind. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:54 Event time (ms). *** ### market > **market**: `string` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:56 The market the event belongs to (any stable key; symbol works). *** ### side > **side**: `"buy"` \| `"sell"` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:58 Trade direction from the account's perspective. *** ### baseAmount > **baseAmount**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:60 Base size exchanged, human units (positive). *** ### quoteAmount > **quoteAmount**: `number` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:62 Quote value exchanged, human USD units (positive). --- # /docs/typescript/api/index/interfaces/PreflightResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PreflightResult # Interface: PreflightResult Defined in: packages/sdk/src/preflight.ts:31 The uniform result every validator returns. `ok` is `blockers.length === 0`. ## Properties ### ok > **ok**: `boolean` Defined in: packages/sdk/src/preflight.ts:33 True when there are no blockers (`blockers.length === 0`); warnings don't affect it. *** ### blockers > **blockers**: `string`[] Defined in: packages/sdk/src/preflight.ts:38 Conditions that STOP the step — the on-chain write would revert or produce a dead market. Human-readable, ready to render as-is. *** ### warnings > **warnings**: `string`[] Defined in: packages/sdk/src/preflight.ts:40 Advisory notices — the step can proceed, but the operator should know. --- # /docs/typescript/api/index/interfaces/PreparedAccountAuthorization [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PreparedAccountAuthorization # Interface: PreparedAccountAuthorization Defined in: packages/sdk/src/smartAccounts.ts:52 An account authorization with the payload its owner signs: hand `typedData` to any EIP-712 signer (a wallet client, an executor's `signTypedData`), then pass `authorization` + the signature to [SmartAccountsClient.buildCreateAccounts](SmartAccountsClient.md#buildcreateaccounts). ## Properties ### authorization > `readonly` **authorization**: `AccountAuthorization` Defined in: packages/sdk/src/smartAccounts.ts:54 What the owner authorizes: which accounts, which owners, until when. *** ### typedData > `readonly` **typedData**: `MessageDefinition` Defined in: packages/sdk/src/smartAccounts.ts:56 The EIP-712 payload to sign. Its domain deliberately omits the chain id — one signature settles on every chain. --- # /docs/typescript/api/index/interfaces/PreparedAccountExecution [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PreparedAccountExecution # Interface: PreparedAccountExecution Defined in: packages/sdk/src/smartAccounts.ts:88 A prepared account execution for the sign-now-send-later flow: the signer signs `typedData` (or `digest`) HERE, and `toCall(signature)` is the finished call ANY funded sender may broadcast — your backend, a relayer, a different key. Nothing about it is bound to this client's transport. **Details** Send the resulting call with at least `gasFloor` gas: safe frames run nested, and EIP-150 makes the execution need a floor of gas REMAINING that no estimate of gas spent supplies. Assert the receipt's `status` yourself — a hand-rolled send has no writer to do it. ## Properties ### typedData > `readonly` **typedData**: `MessageDefinition` Defined in: packages/sdk/src/smartAccounts.ts:94 The EIP-712 payload to sign: the account's own Safe transaction when the signer owns it directly, or the outermost parent's `SafeMessage` envelope when `through` names parents. Chain-bound either way. *** ### digest > `readonly` **digest**: `` `0x${string}` `` Defined in: packages/sdk/src/smartAccounts.ts:96 The same thing as 32 bytes, for a signer that will not render the payload. *** ### signer > `readonly` **signer**: `` `0x${string}` `` Defined in: packages/sdk/src/smartAccounts.ts:98 The address the signature must recover to. *** ### gasFloor > `readonly` **gasFloor**: `bigint` Defined in: packages/sdk/src/smartAccounts.ts:100 The least gas the broadcast must carry. A floor, not an estimate. ## Methods ### toCall() > **toCall**(`signature`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:102 Turn the signature into the call. Aimed at the account; any funded sender may broadcast it. #### Parameters ##### signature `` `0x${string}` `` #### Returns [`UnsignedCall`](UnsignedCall.md) --- # /docs/typescript/api/index/interfaces/PriceCandle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceCandle # Interface: PriceCandle Defined in: packages/sdk/src/priceFeed/types.ts:127 One OHLC candle — a `Candle` row, parsed to human units. ## Properties ### asset > **asset**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:129 Asset symbol this candle rolls up (e.g. "BTC"), uppercased. *** ### resolution > **resolution**: [`PriceCandleResolution`](../type-aliases/PriceCandleResolution.md) Defined in: packages/sdk/src/priceFeed/types.ts:131 Rollup bucket width — see [PriceCandleResolution](../type-aliases/PriceCandleResolution.md). *** ### bucketStart > **bucketStart**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:133 Bucket start — unix seconds, chain time. *** ### open > **open**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:135 Spot price at the first tick in the bucket, human units (raw / 1e18). *** ### high > **high**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:137 Highest spot price in the bucket, human units. *** ### low > **low**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:139 Lowest spot price in the bucket, human units. *** ### close > **close**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:141 Spot price at the last tick in the bucket, human units. *** ### emaClose > **emaClose**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:143 EMA mark at bucket close (the feed's `markClose`). *** ### count > **count**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:145 Number of feed ticks in the bucket (update density — NOT trade volume). --- # /docs/typescript/api/index/interfaces/PriceFeedConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceFeedConfig # Interface: PriceFeedConfig Defined in: packages/sdk/src/config.ts:195 The realtime price-feed endpoint — the standalone EMA price-feed indexer (Hasura GraphQL). ONE endpoint serves every tracked asset (BTC/USDC, ETH/USDC, …); callers select an asset by filter. Snapshot + history read over HTTP; live prices stream over a Hasura WebSocket subscription. ## Properties ### url > **url**: `string` Defined in: packages/sdk/src/config.ts:197 HTTP GraphQL endpoint (snapshot + history + candles, all assets). *** ### wsUrl? > `optional` **wsUrl?**: `string` Defined in: packages/sdk/src/config.ts:202 WebSocket GraphQL endpoint for live subscriptions. Derived from `url` (http→ws, https→wss) when omitted. *** ### quote? > `optional` **quote?**: `string` Defined in: packages/sdk/src/config.ts:223 Quote asset to pin every read to (e.g. `"USDC"`), case-insensitive. The feed indexes SEVERAL quotes per base (`BTC/USDC`, `BTC/USDT`), so `base` alone is no longer a unique feed key: leaving this unset matches every quote, which double-counts a base that trades against more than one quote — duplicate candle buckets (a hard error in charting libs that require strictly ascending, unique timestamps), an arbitrary `Feed`/tick row per push. **Required for a live watch.** `watchPrice`/`watchPrices` (and the price hooks and `SomniaMarkets.watchPrice`, which go through them) reject with a `NotConfiguredError` naming `config.priceFeed.quote` when it is unset. The tick tape streams on a `requestId` cursor, and one oracle request prices every symbol in the tick, so across quotes that cursor is not unique: a batch boundary between two rows sharing one would advance past the second and lose it. Unpinned reads double-count; an unpinned watch would drop data. The one-shot reads (`fetchPrice`, `fetchPriceHistory`, `fetchPriceOHLCV`, `fetchPrices`, `listPriceFeeds`) still work unset, where double-counting is the only cost. Both shipped feed constants are pinned to USDC already. --- # /docs/typescript/api/index/interfaces/PriceFeedInfo [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceFeedInfo # Interface: PriceFeedInfo Defined in: packages/sdk/src/priceFeed/types.ts:153 Feed metadata + current price for one asset — the `Feed` singleton, parsed. ## Properties ### asset > **asset**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:155 Asset key (the pair's base, e.g. `BTC`), uppercased. *** ### decimals > **decimals**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:157 Price scale (Feed.decimals — always 18 today; raw values are 10^decimals-scaled). *** ### symbol > **symbol**: `string` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:159 The feed's on-chain pair symbol, e.g. `BTC/USDT`. *** ### base > **base**: `string` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:161 Base asset, e.g. `BTC`. *** ### quote > **quote**: `string` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:163 Quote asset, e.g. `USDT`. *** ### description > **description**: `string` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:165 Free-form feed description from the scheduler, or null when unset. *** ### updatedAtMs > **updatedAtMs**: `number` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:176 When the oracle last WROTE this feed — unix **milliseconds**, or null if unknown. This is the freshness signal to judge a price by: the feed ticks ~1/s, so an age beyond a few seconds means the asset has stalled. A live subscription does NOT keep this moving on a stalled asset — a feed that stops updating simply stops pushing, so the value freezes and its age grows. Compute age against a local clock (`Date.now() - updatedAtMs`) and re-render on a timer; do not wait for a data event that will never arrive. *** ### sourceUpdatedAtMs > **sourceUpdatedAtMs**: `number` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:184 When the underlying market data was timestamped at the SOURCE — unix milliseconds, or null if unknown. Compare against [updatedAtMs](#updatedatms) to separate "the oracle stopped writing" from "the oracle is writing, but with stale source data": a large `updatedAtMs - sourceUpdatedAtMs` gap means the price was already old when it landed on chain. *** ### resynced > **resynced**: `boolean` \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:189 Whether the last write was a resync (a correction/backfill rather than a routine tick), or null if unknown. *** ### latest > **latest**: [`LivePrice`](LivePrice.md) \| `null` Defined in: packages/sdk/src/priceFeed/types.ts:194 Current price (same value a live watch keeps current), or null if the feed has no observations yet. --- # /docs/typescript/api/index/interfaces/PricePoint [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PricePoint # Interface: PricePoint Defined in: packages/sdk/src/priceFeed/types.ts:89 One raw tick — a `PricePoint` row (one feed tick: the spot median + its EMA mark), parsed. `price` is the spot index; `ema` is the EMA-smoothed mark. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:91 Indexer row id (`-`). *** ### asset > **asset**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:93 Asset symbol this tick prices (e.g. "BTC"), uppercased. *** ### price > **price**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:98 Spot index at this tick, human units (raw / 1e18). Lossy past ~15 sig figs — use `raw` for exact math. *** ### ema > **ema**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:100 EMA-smoothed mark at this tick, human units (the feed's `mark`). *** ### requestId > **requestId**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:106 Somnia-Agents batch request that produced this tick (provenance). One request prices every symbol in the tick, so all of a tick's rows share it. Decimal string (uint256). *** ### blockNumber > **blockNumber**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:108 Block the tick landed in (chain time, monotonic). *** ### blockTimestamp > **blockTimestamp**: `number` Defined in: packages/sdk/src/priceFeed/types.ts:110 Block timestamp of the tick — unix seconds, chain time. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/priceFeed/types.ts:112 Transaction that delivered the tick. *** ### raw > **raw**: `object` Defined in: packages/sdk/src/priceFeed/types.ts:114 Exact 1e18-scaled integer strings for precise math. #### price > **price**: `string` Exact spot price — 1e18-scaled integer string. #### ema > **ema**: `string` Exact EMA mark — 1e18-scaled integer string. --- # /docs/typescript/api/index/interfaces/PriceWatchHandle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceWatchHandle # Interface: PriceWatchHandle Defined in: packages/sdk/src/priceFeed/priceFeed.ts:41 A live price watch. `stop()` releases it (idempotent); the underlying subscriptions are shared and torn down when the last handle stops. ## Methods ### stop() > **stop**(): `void` Defined in: packages/sdk/src/priceFeed/priceFeed.ts:51 Release this handle's reference on the asset's watch (idempotent — extra calls are no-ops). Handles on the same asset share one subscription; stopping the LAST one tears the asset down after a short linger (which absorbs unmount/remount without re-snapshotting): the asset's subscriptions end, its rows are purged, and live price reads for it return null/empty again. The socket is shared by every watched asset on the endpoint; it closes when the last asset on it is torn down. #### Returns `void` --- # /docs/typescript/api/index/interfaces/ProposePerpWalletLinkParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ProposePerpWalletLinkParams # Interface: ProposePerpWalletLinkParams Defined in: packages/sdk/src/trade.ts:1092 Inputs to [Trader.proposePerpWalletLink](Trader.md#proposeperpwalletlink) — offer a child wallet a link to the signer as its main. The signer is the prospective MAIN. Half of a two-sided handshake: the child must then send [Trader.acceptPerpWalletLink](Trader.md#acceptperpwalletlink). ## Extends - [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md) ## Properties ### registry? > `optional` **registry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1070 The LinkedWalletRegistry. Skips resolution entirely. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`registry`](PerpWalletLinkTarget.md#registry) *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1072 MarginBank address — its `getLinkedWalletRegistry()` is read (never cached). #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`marginBank`](PerpWalletLinkTarget.md#marginbank) *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1074 A PerpPool — its `marginBank()` is read (and cached), then the registry. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`pool`](PerpWalletLinkTarget.md#pool) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1080 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`gas`](PerpWalletLinkTarget.md#gas) *** ### child > **child**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1094 The prospective child. Must not be the signer, and must not already be linked. --- # /docs/typescript/api/index/interfaces/QueryKeyChainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QueryKeyChainOptions # Interface: QueryKeyChainOptions Defined in: packages/sdk/src/queryKeys.ts:68 Trailing chain scope of a query-key factory. Pass the chain of the engine that serves the read. Omit it in a single-chain app: the key is then the same key the factory produced before it took a chain. A key with a chain is the key without one plus a last `{ chainId }` element. So a key without a chain, used as a prefix filter (TanStack Query's default for invalidation), also matches every chain's entry. A key with a chain never matches an entry stored without one, even on the primary chain. On a multi-chain exchange, pass `chainId` on every key. ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/queryKeys.ts:70 Numeric chain id of the engine that serves the read. --- # /docs/typescript/api/index/interfaces/QuestionDefinitionInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QuestionDefinitionInput # Interface: QuestionDefinitionInput Defined in: packages/sdk/src/oracleHub.ts:112 Full question definition — the input to `scheduleQuestion` / `getSchedulingCost` / `questionKeyOf`. Mirrors the on-chain `QuestionDefinition` struct field-for-field. ## Properties ### questionText > **questionText**: `string` Defined in: packages/sdk/src/oracleHub.ts:117 Free-form question text. EXCLUDED from the dedup key for template (all-JSON-source) definitions — the sources determine the answer. *** ### sources > **sources**: [`QuestionSourceInput`](QuestionSourceInput.md)[] Defined in: packages/sdk/src/oracleHub.ts:119 Answer sources the oracle fetches; all-JSON definitions dedup content-addressed. *** ### validAnswers > **validAnswers**: [`ValidAnswersInput`](ValidAnswersInput.md) Defined in: packages/sdk/src/oracleHub.ts:121 The answer space the question resolves within. *** ### resolutionTime > **resolutionTime**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:123 Unix-seconds the oracle answers at. *** ### minAgreement > **minAgreement**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:125 Minimum count of sources that must agree for the oracle to resolve (else void). *** ### subcommitteeSize > **subcommitteeSize**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:127 Oracle subcommittee nodes assigned to answer the question. *** ### subcommitteeThreshold > **subcommitteeThreshold**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:129 Subcommittee nodes that must concur on the answer. --- # /docs/typescript/api/index/interfaces/QuestionIntervalInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QuestionIntervalInput # Interface: QuestionIntervalInput Defined in: packages/sdk/src/oracleHub.ts:82 Inclusive numeric interval (`low <= value <= high` matches the bucket). ## Properties ### low > **low**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:84 Lower bound (inclusive), scaled by `numericDecimals`. *** ### high > **high**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:86 Upper bound (inclusive), scaled by `numericDecimals`. --- # /docs/typescript/api/index/interfaces/QuestionSourceInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QuestionSourceInput # Interface: QuestionSourceInput Defined in: packages/sdk/src/oracleHub.ts:70 One answer source (website URL / JSON URL / on-chain contract) with its encoded params. ## Properties ### sourceType > **sourceType**: `number` Defined in: packages/sdk/src/oracleHub.ts:72 [QUESTION\_SOURCE\_TYPE](../variables/QUESTION_SOURCE_TYPE.md) value (uint8 on the wire). *** ### params > **params**: `` `0x${string}` `` Defined in: packages/sdk/src/oracleHub.ts:74 Source-type-specific encoded params. --- # /docs/typescript/api/index/interfaces/RecallPerpMainFundingParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RecallPerpMainFundingParams # Interface: RecallPerpMainFundingParams Defined in: packages/sdk/src/trade.ts:1176 Inputs to [Trader.recallPerpMainFunding](Trader.md#recallperpmainfunding) — the PAYER pulls principal back out of a child. Signed by the payer. Same clamped accounting as [Trader.repayPerpMainFunding](Trader.md#repayperpmainfunding), and the same destination. ## Extends - [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md) ## Properties ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1148 MarginBank address (from the PerpMarket row), or pass `pool` to resolve it. #### Inherited from [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md).[`marginBank`](RepayPerpMainFundingParams.md#marginbank) *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1150 A PerpPool — its `marginBank()` is read (and cached) when `marginBank` is omitted. #### Inherited from [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md).[`pool`](RepayPerpMainFundingParams.md#pool) *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1158 Principal to return, raw units. Over-asking is SAFE and does not revert: the bank returns `min(amount, outstanding, present balance)`. Pass the outstanding principal from `client.getPerpMainFunding` to repay in full. #### Inherited from [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md).[`amount`](RepayPerpMainFundingParams.md#amount) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1164 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md).[`gas`](RepayPerpMainFundingParams.md#gas) *** ### child > **child**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1178 The child to recall from. The signer must be its recorded payer. --- # /docs/typescript/api/index/interfaces/ReclaimOracleCreditParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ReclaimOracleCreditParams # Interface: ReclaimOracleCreditParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:215 Params for [MarketCreatorAdmin.reclaimOracleCredit](MarketCreatorAdmin.md#reclaimoraclecredit). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:217 The MarketCreator whose oracle credit is swept (permissionless). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:219 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/RecoverSeriesParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RecoverSeriesParams # Interface: RecoverSeriesParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:160 Params for [MarketCreatorAdmin.recoverSeries](MarketCreatorAdmin.md#recoverseries). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:162 The MarketCreatorV2 owning the series. Permissionless — any caller. *** ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:164 The provably stalled series to recover. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:166 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/RedeemAuthorization [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemAuthorization # Interface: RedeemAuthorization Defined in: packages/sdk/src/trade.ts:1773 A signed authorization the position OWNER produces so a relayer can call [Trader.redeemFor](Trader.md#redeemfor) on their behalf. The on-chain payout is hard-pinned to `owner` (never the relayer), so this is a pure gas sponsorship — the signer keeps every cent of the proceeds. Produced by [Trader.signRedeemAuth](Trader.md#signredeemauth), consumed by [Trader.redeemFor](Trader.md#redeemfor). ## Properties ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1775 The position owner (the signer). The payout is paid here on-chain. *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/trade.ts:1777 Routing operator id (uint32) for attribution; part of the signed struct. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1779 Routing venue id (bytes32 hex); part of the signed struct. *** ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1781 bytes32 marketId the redemption targets. *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1783 Outcome the owner holds (0 = YES, 1 = NO). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1785 Outcome-token amount to burn for collateral. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/trade.ts:1787 Per-owner replay nonce (module tracks `(owner, nonce)`); any unused value. *** ### deadline > **deadline**: `bigint` Defined in: packages/sdk/src/trade.ts:1789 Signature deadline (unix seconds). The module rejects a stale authorization. *** ### signature > **signature**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1791 The EIP-712 signature over the authorization (65-byte r‖s‖v hex). --- # /docs/typescript/api/index/interfaces/RedeemDirectParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemDirectParams # Interface: RedeemDirectParams Defined in: packages/sdk/src/trade.ts:1862 Low-level direct redemption against the BinarySettlement singleton — bypasses the module (no operator attribution). Burns the caller's outcome tokens and pays `to`. Prefer the module-routed [RedeemParams](RedeemParams.md) for normal trading; use this for keeper/tooling paths that hold the raw outcome id. ## Properties ### outcomeId > **outcomeId**: `bigint` Defined in: packages/sdk/src/trade.ts:1864 The ERC-6909 outcome id to redeem (encodes pool + nonce + index). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1866 Outcome-token quantity to burn. *** ### to? > `optional` **to?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1868 Recipient of the released collateral (default: the trader's own address). *** ### settlement? > `optional` **settlement?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1873 BinarySettlement address; resolved from `config.addresses.binarySettlement` when omitted. Throws if neither is set. *** ### outcomeToken? > `optional` **outcomeToken?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1878 Outcome-token singleton (for the operator grant). Resolved from the settlement's `outcomeToken()` when omitted. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1880 Ensure the settlement is an operator on the outcome-token singleton (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1886 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RedeemForParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemForParams # Interface: RedeemForParams Defined in: packages/sdk/src/trade.ts:1837 Relayer path: submit a position owner's pre-signed [RedeemAuthorization](RedeemAuthorization.md) so THEY pay the gas while the OWNER receives the payout. The caller (relayer) need not be the owner; the module recovers the signature to `owner` and pays `owner` directly. ## Properties ### authorization > **authorization**: [`RedeemAuthorization`](RedeemAuthorization.md) Defined in: packages/sdk/src/trade.ts:1839 The owner's signed authorization (from [Trader.signRedeemAuth](Trader.md#signredeemauth)). *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1845 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. Must match the `verifyingContract` the authorization was signed against. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1851 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RedeemManyParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemManyParams # Interface: RedeemManyParams Defined in: packages/sdk/src/trade.ts:1733 Claim winnings from several settled markets in ONE transaction — the batch form of [RedeemParams](RedeemParams.md). Each entry is redeemed independently for the signer (settlement pays each straight to their wallet); all-or-nothing. ## Properties ### entries > **entries**: `object`[] Defined in: packages/sdk/src/trade.ts:1735 Per-market redemptions. `outcomeIdx` is required per entry (0 = YES, 1 = NO). #### marketId > **marketId**: `` `0x${string}` `` bytes32 marketId of the market to redeem on. #### outcomeIdx > **outcomeIdx**: `0` \| `1` Which outcome's tokens to redeem (0 = YES, 1 = NO). #### amount > **amount**: `bigint` Outcome tokens to redeem, raw units (collateral decimals). *** ### operatorId? > `optional` **operatorId?**: `number` Defined in: packages/sdk/src/trade.ts:1744 Routing operator id (uint32) for attribution; 0 = none (default). *** ### venueId? > `optional` **venueId?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1746 Routing venue id (bytes32 hex); 32-byte zero = none (default). *** ### outcomeToken? > `optional` **outcomeToken?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1751 Outcome-token singleton to grant the module operator on (one grant covers all ids). Resolved from the settlement singleton when omitted. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1753 BinaryMarketsModule address; resolved from `config.addresses.binaryModule`. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1755 Ensure the module is an operator on the outcome-token singleton (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1761 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RedeemNativeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemNativeParams # Interface: RedeemNativeParams Defined in: packages/sdk/src/trade.ts:2156 Inputs to [Trader.redeemNative](Trader.md#redeemnative) — redeem winning outcome tokens for a NATIVE payout via the CollateralRouter (unwraps wNative → native). ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2158 bytes32 market key redeemed against; its collateral must be wNative. *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:2164 Outcome the caller holds (0 = YES, 1 = NO). The router is type-blind — it forwards this to the core, which the pool prices (winner 1:1, void 1/N per side). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:2166 Amount of that outcome's tokens to redeem for a native payout. *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/trade.ts:2168 Routing operator id (uint32) for attribution; 0 = none. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2170 Routing venue id (bytes32 hex); 32-byte zero = none. *** ### router? > `optional` **router?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2175 CollateralRouter address; resolved from `config.addresses.collateralRouter` if omitted. Throws if neither is set. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2181 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RedeemOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemOptions # Interface: RedeemOptions Defined in: packages/sdk/src/unified/exchange.ts:463 Optional leg selection for [SomniaMarkets.redeem](../classes/SomniaMarkets.md#redeem). ## Properties ### outcomeIdx? > `optional` **outcomeIdx?**: `0` \| `1` Defined in: packages/sdk/src/unified/exchange.ts:469 Leg to redeem (0 = YES, 1 = NO). Omit it on a resolved market to let the SDK verify the terminal state and read the winner on-chain. A voided market requires the leg because both can redeem. --- # /docs/typescript/api/index/interfaces/RedeemParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RedeemParams # Interface: RedeemParams Defined in: packages/sdk/src/trade.ts:1673 Inputs to [Trader.redeem](Trader.md#redeem) — burn winning outcome tokens for collateral on a resolved/voided market (module-routed redemption). ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1679 bytes32 marketId the module keys the redemption on (settlement-extraction v2: redemption is module-routed — the module pulls the caller's winning tokens, finalizes-if-needed, and redeems through the BinarySettlement singleton). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1681 Outcome-token amount to burn for collateral. *** ### outcomeIdx? > `optional` **outcomeIdx?**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1695 Outcome leg to redeem (0 = YES, 1 = NO). When omitted, the SDK first confirms `market.isResolved()`, then derives the leg from the finalized one-hot payout vector. This needs `market`; otherwise pass `outcomeIdx` explicitly. Settlement v3 stores a payout vector — `winningOutcome()` was removed and reverts on the deployed contract. The lookup is RESOLUTION-ONLY. An unresolved market throws instead of guessing from an unfinished vector. A voided market has no winner — both legs are redeemable — so redeem throws [InvalidInputError](../classes/InvalidInputError.md) rather than picking one. Pass the leg you hold, or use [RedeemManyParams](RedeemManyParams.md) with one entry per leg to claim both in one transaction. *** ### market? > `optional` **market?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1701 BinaryMarket address — only needed to auto-look-up `outcomeIdx` / `outcomeToken` when those are omitted. The `outcomeIdx` lookup reads the terminal flags first, then the finalized payout vector and denominator. *** ### operatorId? > `optional` **operatorId?**: `number` Defined in: packages/sdk/src/trade.ts:1703 Routing operator id (uint32) for attribution; 0 = none (default). *** ### venueId? > `optional` **venueId?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1705 Routing venue id (bytes32 hex); 32-byte zero = none (default). *** ### outcomeToken? > `optional` **outcomeToken?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1710 Outcome-token singleton the winning position lives on (for the operator grant). Looked up via `market.outcomeToken()` when omitted. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1715 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. Throws if neither is set. *** ### autoApprove? > `optional` **autoApprove?**: `boolean` Defined in: packages/sdk/src/trade.ts:1717 Ensure the module is an operator on the outcome-token singleton (default true). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1723 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ReduceOrderParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ReduceOrderParams # Interface: ReduceOrderParams Defined in: packages/sdk/src/trade.ts:340 Shrink a resting order's remaining quantity IN PLACE — keeps its price-time queue priority (unlike [Trader.placeOrder](Trader.md#placeorder) + amend, which re-queues at the back). Works on spot AND binary pools: BinaryPool implements the reduce-refund hook, so the freed escrow (collateral for a buy, outcome tokens for a sell) is returned to the owner. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:342 BinaryPool (or SpotPool) address hosting the resting order. *** ### orderId > **orderId**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:344 uint128 OrderId of the resting order to shrink (decimal string or bigint). *** ### newQuantityRemaining > **newQuantityRemaining**: `bigint` Defined in: packages/sdk/src/trade.ts:351 The order's NEW remaining quantity. Must be a `lotSize` multiple, `>= minQuantity`, and strictly less than the current remaining. Reverts on-chain (`ExpiredOrderMustBeCancelled`) if the order has already expired — use [Trader.cancelOrder](Trader.md#cancelorder) to recover an expired order's funds. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:357 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ReduceOrderRequest [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ReduceOrderRequest # Interface: ReduceOrderRequest Defined in: packages/sdk/src/trade.ts:772 One reduction inside a [Trader.reduceOrders](Trader.md#reduceorders) batch. ## Properties ### orderId > **orderId**: `string` \| `bigint` Defined in: packages/sdk/src/trade.ts:774 uint128 OrderId of the resting order to shrink (decimal string or bigint). *** ### newQuantityRemaining > **newQuantityRemaining**: `bigint` Defined in: packages/sdk/src/trade.ts:779 The order's NEW remaining quantity. Must be a `lotSize` multiple, `>= minQuantity`, and strictly less than the current remaining. --- # /docs/typescript/api/index/interfaces/ReduceOrdersParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ReduceOrdersParams # Interface: ReduceOrdersParams Defined in: packages/sdk/src/trade.ts:788 Inputs to [Trader.reduceOrders](Trader.md#reduceorders) — shrink several resting orders on ONE pool in a single transaction. Works on spot AND binary pools. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:790 SpotPool (or BinaryPool) address hosting the resting orders. *** ### reductions > **reductions**: [`ReduceOrderRequest`](ReduceOrderRequest.md)[] Defined in: packages/sdk/src/trade.ts:792 The reductions to apply. Any invalid entry reverts the whole batch. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:798 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RegisterOperatorParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RegisterOperatorParams # Interface: RegisterOperatorParams Defined in: packages/sdk/src/operatorAdmin.ts:91 Params for [OperatorAdmin.registerOperator](OperatorAdmin.md#registeroperator). ## Properties ### feeRecipient > **feeRecipient**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:93 Default recipient of the operator's venue fees (a venue can override it). *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:98 Whether the operator starts live; flip later via [OperatorAdmin.setOperatorEnabled](OperatorAdmin.md#setoperatorenabled). *** ### policy > **policy**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:100 IVenuePolicy address; zero for none (operator-wide gate is optional). *** ### context? > `optional` **context?**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:102 Opaque metadata bytes attached to the operator; empty (`0x`) by default. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:104 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/RegisterOperatorResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RegisterOperatorResult # Interface: RegisterOperatorResult Defined in: packages/sdk/src/operatorAdmin.ts:112 Result of [OperatorAdmin.registerOperator](OperatorAdmin.md#registeroperator) — carries the id the contract assigned, which every later operator call keys on. ## Extends - [`TxResult`](TxResult.md) ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:114 The auto-assigned operator id (decoded from `OperatorRegistered`). *** ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) --- # /docs/typescript/api/index/interfaces/RegisterSeriesParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RegisterSeriesParams # Interface: RegisterSeriesParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:115 Params for [MarketCreatorAdmin.registerSeries](MarketCreatorAdmin.md#registerseries) / [MarketCreatorAdmin.updateSeries](MarketCreatorAdmin.md#updateseries). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:117 The MarketCreator to register the series under. Caller must be its owner. *** ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:122 Series key within the creator; re-registering the same id overwrites the config and resets the series' oracle reference. *** ### collateral > **collateral**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:124 Per-series collateral ERC-20. *** ### asset > **asset**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:130 Display ticker (e.g. "BTC" — NOT a pair). Doubles as the exchange base symbol for the USDC-quoted candle sources built per roll, so it must match the spot listing on the source exchanges (Binance/OKX/…). *** ### numericDecimals > **numericDecimals**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:132 Decimal precision of the oracle's numeric price answer. *** ### intervalSec > **intervalSec**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:134 Roll interval in seconds; the module rejects < 60 (`InvalidSeriesConfig`). *** ### settlementWindow > **settlementWindow**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:136 Post-expiry settlement window in seconds. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:138 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/RegistrySweep [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RegistrySweep # Interface: RegistrySweep Defined in: packages/sdk/src/markets.ts:989 A registry sweep with the silent drop made visible — see [SomniaMarketsClient.listRegistryMarketsChecked](SomniaMarketsClient.md#listregistrymarketschecked). ## Properties ### markets > **markets**: [`Market`](../type-aliases/Market.md)[] Defined in: packages/sdk/src/markets.ts:991 The markets that parsed, exactly what `listRegistryMarkets` returns. *** ### dropped > **dropped**: `number` Defined in: packages/sdk/src/markets.ts:997 Rows the indexer served that the SDK could not parse, and so are absent from `markets`. Zero means the sweep is complete: every row the registry holds is in hand. --- # /docs/typescript/api/index/interfaces/ReleasePoolParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ReleasePoolParams # Interface: ReleasePoolParams Defined in: packages/sdk/src/trade.ts:1953 Permissionless keeper entry: release a finalized, drained pool back to its creator's free list for recycle onto the next market. ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1955 bytes32 marketId whose (finalized, book-empty) pool to release. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1957 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1963 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RepayPerpMainFundingParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RepayPerpMainFundingParams # Interface: RepayPerpMainFundingParams Defined in: packages/sdk/src/trade.ts:1146 Inputs to [Trader.repayPerpMainFunding](Trader.md#repayperpmainfunding) — the CHILD returns principal its main funded. Signed by the child. The money goes to the payer the bank snapshotted at funding time, not to whoever is linked now. ## Extended by - [`RecallPerpMainFundingParams`](RecallPerpMainFundingParams.md) ## Properties ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1148 MarginBank address (from the PerpMarket row), or pass `pool` to resolve it. *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1150 A PerpPool — its `marginBank()` is read (and cached) when `marginBank` is omitted. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1158 Principal to return, raw units. Over-asking is SAFE and does not revert: the bank returns `min(amount, outstanding, present balance)`. Pass the outstanding principal from `client.getPerpMainFunding` to repay in full. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1164 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ResolveParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ResolveParams # Interface: ResolveParams Defined in: packages/sdk/src/trade.ts:2208 Inputs to [Trader.resolve](Trader.md#resolve) — resolve a market via the FakeOracle (demo/dev resolver only). ## Properties ### market > **market**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2210 BinaryMarket address to resolve. *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:2212 The outcome to resolve to (0 = YES wins, 1 = NO wins). *** ### fakeOracle? > `optional` **fakeOracle?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2214 FakeOracle address; defaults to the configured one. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2220 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/RevertContext [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RevertContext # Interface: RevertContext Defined in: packages/sdk/src/revert.ts:26 Where the failing call was aimed — carried onto the error for diagnosis. ## Properties ### address? > `optional` **address?**: `string` Defined in: packages/sdk/src/revert.ts:28 The contract that was called, when known. *** ### functionName? > `optional` **functionName?**: `string` Defined in: packages/sdk/src/revert.ts:30 The function that was called, when known. --- # /docs/typescript/api/index/interfaces/RollPreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RollPreflightInput # Interface: RollPreflightInput Defined in: packages/sdk/src/preflight.ts:352 Inputs for the roll-step preflight: the series exists on-chain (its `intervalSec > 0`), the creator is funded, and the chain supports rolls. ## Properties ### seriesIntervalSec > **seriesIntervalSec**: `number` Defined in: packages/sdk/src/preflight.ts:354 The series' on-chain `intervalSec` (0 ⇒ never registered). *** ### creatorBalanceWei > **creatorBalanceWei**: `bigint` Defined in: packages/sdk/src/preflight.ts:359 The MarketCreator's native balance (wei) — 0 blocks (the roll can't pay its reactivity gas). *** ### precompileAvailable > **precompileAvailable**: `boolean` Defined in: packages/sdk/src/preflight.ts:364 Whether the connected chain has the Somnia reactivity precompile (false on local anvil — see [isLocalPrecompileUnavailable](../functions/isLocalPrecompileUnavailable.md)). --- # /docs/typescript/api/index/interfaces/RouterMintBase [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RouterMintBase # Interface: RouterMintBase Defined in: packages/sdk/src/trade.ts:2078 Shared inputs for the CollateralRouter complete-set entry points. ## Extended by - [`MintSetNativeParams`](MintSetNativeParams.md) - [`MintSetPermit2Params`](MintSetPermit2Params.md) ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2080 bytes32 market key the set is minted for (the market's `marketId`). *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/trade.ts:2082 Routing operator id (uint32) for attribution; 0 = none. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2084 Routing venue id (bytes32 hex); 32-byte zero = none. *** ### router? > `optional` **router?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2089 CollateralRouter address; resolved from `config.addresses.collateralRouter` if omitted. Throws if neither is set (never sends to the zero address). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2095 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/ScheduleQuestionParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ScheduleQuestionParams # Interface: ScheduleQuestionParams Defined in: packages/sdk/src/oracleHub.ts:356 Parameters for [OracleHubAdmin.scheduleQuestion](OracleHubAdmin.md#schedulequestion). ## Properties ### def > **def**: [`QuestionDefinitionInput`](QuestionDefinitionInput.md) Defined in: packages/sdk/src/oracleHub.ts:358 The question to schedule (deduped content-addressed for template definitions). *** ### valueWei? > `optional` **valueWei?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:363 Native value to attach. Defaults to the live `getSchedulingCost(def)` quote (the marginal price — 0 for a dedup reuse). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:365 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/ScheduleQuestionResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ScheduleQuestionResult # Interface: ScheduleQuestionResult Defined in: packages/sdk/src/oracleHub.ts:382 Result of [OracleHubAdmin.scheduleQuestion](OracleHubAdmin.md#schedulequestion). **Details** Scheduling is idempotent by question DEFINITION: an identical definition deduplicates onto the existing question instead of creating a second one. **Gotchas** Because of that deduplication, check `reused` before assuming this call is what created the id. ## Extends - [`TxResult`](TxResult.md) ## Properties ### oracleQuestionId > **oracleQuestionId**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:384 Oracle-assigned (or deduplicated) question id. *** ### reused > **reused**: `boolean` Defined in: packages/sdk/src/oracleHub.ts:389 True when the definition deduplicated onto an EXISTING question (`QuestionReused` — the caller was charged nothing). *** ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. #### Inherited from [`TxResult`](TxResult.md).[`hash`](TxResult.md#hash) *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). #### Inherited from [`TxResult`](TxResult.md).[`receipt`](TxResult.md#receipt) *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. #### Inherited from [`TxResult`](TxResult.md).[`executionTimeMicros`](TxResult.md#executiontimemicros) --- # /docs/typescript/api/index/interfaces/SeedOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SeedOptions # Interface: SeedOptions Defined in: packages/sdk/src/liveTail.ts:87 Options for a chain-seeded watch. ## Properties ### seed > **seed**: `"chain"` Defined in: packages/sdk/src/liveTail.ts:102 Seed source; `"chain"` selects the indexer-free path. ONE POOL PER CALL. N pools means N `watchMarket` calls, because a `(pool, marketId)` binding is 1:1 at any instant and this option carries one id. The N calls share one tail and one subscription set, so they hydrate independently and each pool keeps its own seed status — read it with `getSeedStatus(pool)`, not `getLiveStatus()`, which reports the most recent seed only. Read cost per pool, worst case: `2 × maxPages` contract reads, one drain per side, plus the module read for the market row. At the defaults that is 80 reads per pool, and it stops early on a side that runs out of orders. *** ### marketId > **marketId**: `string` Defined in: packages/sdk/src/liveTail.ts:110 Market id the pool currently serves — book reads filter on it. Read it from chain with `getPoolMarketBinding(pool)` when the indexer is unreachable; the seed rejects an id whose on-chain record names a different pool. *** ### maxCount? > `optional` **maxCount?**: `number` Defined in: packages/sdk/src/liveTail.ts:112 Orders per drained page. Defaults to 500. *** ### maxPages? > `optional` **maxPages?**: `number` Defined in: packages/sdk/src/liveTail.ts:120 Page budget per side. Defaults to 40, so the default drain covers 20,000 resting orders per side. Reaching the budget is reported as `getSeedStatus(pool).seedTruncated`, not thrown. Prefer that per-pool read over `getLiveStatus().seedTruncated`, which another pool's later seed overwrites. --- # /docs/typescript/api/index/interfaces/SeriesOnchain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SeriesOnchain # Interface: SeriesOnchain Defined in: packages/sdk/src/marketCreatorAdmin.ts:294 One Series' live on-chain config (mirror of the `Series` struct). ## Properties ### collateral > **collateral**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:296 Per-series collateral ERC-20. *** ### asset > **asset**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:302 Display ticker (e.g. "BTC" — NOT a pair). Doubles as the exchange base symbol for the USDC-quoted candle sources built per roll, so it must match the spot listing on the source exchanges (Binance/OKX/…). *** ### numericDecimals > **numericDecimals**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:304 Decimal precision of the oracle's numeric price answer. *** ### intervalSec > **intervalSec**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:306 Roll interval in seconds; `0` means the series was never registered. *** ### settlementWindow > **settlementWindow**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:308 Post-expiry settlement window in seconds. --- # /docs/typescript/api/index/interfaces/SeriesPreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SeriesPreflightInput # Interface: SeriesPreflightInput Defined in: packages/sdk/src/preflight.ts:309 The series fields the series-step preflight inspects. ## Properties ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/preflight.ts:311 The series id to register — 0 blocks (the module rejects it as UnknownSeries). *** ### asset > **asset**: `string` Defined in: packages/sdk/src/preflight.ts:313 The series' asset label (e.g. "BTC/USDT") — empty blocks. *** ### intervalSec > **intervalSec**: `number` Defined in: packages/sdk/src/preflight.ts:318 The roll interval in seconds — below [MIN\_SERIES\_INTERVAL\_SEC](../variables/MIN_SERIES_INTERVAL_SEC.md) blocks (InvalidSeriesConfig). *** ### collateral > **collateral**: `` `0x${string}` `` Defined in: packages/sdk/src/preflight.ts:320 The venue's collateral token — the zero address blocks. --- # /docs/typescript/api/index/interfaces/SetAdapterApprovedParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetAdapterApprovedParams # Interface: SetAdapterApprovedParams Defined in: packages/sdk/src/governanceAdmin.ts:24 Params for [GovernanceAdmin.setAdapterApproved](GovernanceAdmin.md#setadapterapproved). ## Properties ### adapter > **adapter**: `` `0x${string}` `` Defined in: packages/sdk/src/governanceAdmin.ts:26 The oracle adapter to approve or revoke on BinaryMarketsModule. *** ### approved > **approved**: `boolean` Defined in: packages/sdk/src/governanceAdmin.ts:28 `true` approves (adapter can back new markets); `false` revokes. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/governanceAdmin.ts:30 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/SetHubDrainParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetHubDrainParams # Interface: SetHubDrainParams Defined in: packages/sdk/src/oracleHub.ts:469 Parameters for [OracleHubAdmin.setDrainParams](OracleHubAdmin.md#setdrainparams) (OWNER-only). ## Properties ### perMarketResolveGas > **perMarketResolveGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:474 Gas budgeted per market resolve — sizes `resolveReserve()` (`perMarketResolveGas × maxFeePerGas`). *** ### callbackBaseGas > **callbackBaseGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:479 Callback overhead gas explicitly attributed across the markets resolved in it (the metering overhead term). *** ### maxResolvesPerCallback > **maxResolvesPerCallback**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:481 Belt-and-suspenders cap on markets resolved per callback. *** ### resolveGasReserve > **resolveGasReserve**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:483 Remaining-gas floor at which the drain loop breaks to the next block. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:485 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/SetHubGasParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetHubGasParams # Interface: SetHubGasParams Defined in: packages/sdk/src/oracleHub.ts:450 Parameters for [OracleHubAdmin.setGasParams](OracleHubAdmin.md#setgasparams) (OWNER-only). ## Properties ### priorityFeePerGas > **priorityFeePerGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:452 New reactivity-callback tip (wei per gas). *** ### maxFeePerGas > **maxFeePerGas**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:457 New reactivity-callback fee ceiling (wei per gas) — also reprices `resolveReserve()` immediately. *** ### gasLimit > **gasLimit**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:459 New gas limit each reactivity callback runs with. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:461 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/SetManualVaultModeParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetManualVaultModeParams # Interface: SetManualVaultModeParams Defined in: packages/sdk/src/trade.ts:1294 Inputs to [Trader.setManualVaultMode](Trader.md#setmanualvaultmode) — flip a SpotPool's auto-pull opt-out for the signer. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1296 SpotPool the mode applies to. Scoped per user PER POOL. *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/trade.ts:1298 True to draw only on vault balance; false to restore wallet auto-pull. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1304 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/SetOperatorApprovalForPoolParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetOperatorApprovalForPoolParams # Interface: SetOperatorApprovalForPoolParams Defined in: packages/sdk/src/trade.ts:1346 Inputs to [Trader.setOperatorApprovalForPool](Trader.md#setoperatorapprovalforpool) — admit an operator on ONE SpotPool (the tighter default). ## Extends - `OperatorApprovalParamsBase` ## Properties ### operator > **operator**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1310 Account being admitted to act for the signer (a bot, a router, a helper contract). #### Inherited from `OperatorApprovalParamsBase.operator` *** ### selectors > **selectors**: readonly `` `0x${string}` ``[] Defined in: packages/sdk/src/trade.ts:1316 4-byte selectors the operator may call. Grant only what it needs — [PLACE\_ORDER\_FOR\_SELECTOR](../variables/PLACE_ORDER_FOR_SELECTOR.md) to place, [CANCEL\_ORDER\_FOR\_SELECTOR](../variables/CANCEL_ORDER_FOR_SELECTOR.md) to cancel. Must not be empty. #### Inherited from `OperatorApprovalParamsBase.selectors` *** ### approved > **approved**: `boolean` Defined in: packages/sdk/src/trade.ts:1318 True to grant, false to revoke. #### Inherited from `OperatorApprovalParamsBase.approved` *** ### operatorRegistry? > `optional` **operatorRegistry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1323 OperatorPermissionsRegistry address. #### Default `addresses.operatorPermissionsRegistry` #### Inherited from `OperatorApprovalParamsBase.operatorRegistry` *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1329 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from `OperatorApprovalParamsBase.gas` *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1348 SpotPool the grant applies on. --- # /docs/typescript/api/index/interfaces/SetOperatorApprovalGlobalParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetOperatorApprovalGlobalParams # Interface: SetOperatorApprovalGlobalParams Defined in: packages/sdk/src/trade.ts:1338 Inputs to [Trader.setOperatorApprovalGlobal](Trader.md#setoperatorapprovalglobal) — admit an operator across every registered pool (what `SpotRouter` requires). ## Extends - `OperatorApprovalParamsBase` ## Properties ### operator > **operator**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1310 Account being admitted to act for the signer (a bot, a router, a helper contract). #### Inherited from `OperatorApprovalParamsBase.operator` *** ### selectors > **selectors**: readonly `` `0x${string}` ``[] Defined in: packages/sdk/src/trade.ts:1316 4-byte selectors the operator may call. Grant only what it needs — [PLACE\_ORDER\_FOR\_SELECTOR](../variables/PLACE_ORDER_FOR_SELECTOR.md) to place, [CANCEL\_ORDER\_FOR\_SELECTOR](../variables/CANCEL_ORDER_FOR_SELECTOR.md) to cancel. Must not be empty. #### Inherited from `OperatorApprovalParamsBase.selectors` *** ### approved > **approved**: `boolean` Defined in: packages/sdk/src/trade.ts:1318 True to grant, false to revoke. #### Inherited from `OperatorApprovalParamsBase.approved` *** ### operatorRegistry? > `optional` **operatorRegistry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1323 OperatorPermissionsRegistry address. #### Default `addresses.operatorPermissionsRegistry` #### Inherited from `OperatorApprovalParamsBase.operatorRegistry` *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1329 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from `OperatorApprovalParamsBase.gas` --- # /docs/typescript/api/index/interfaces/SetOperatorEnabledParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetOperatorEnabledParams # Interface: SetOperatorEnabledParams Defined in: packages/sdk/src/operatorAdmin.ts:143 Params for [OperatorAdmin.setOperatorEnabled](OperatorAdmin.md#setoperatorenabled). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:145 The operator to flip. Caller must be its owner. *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:147 New enabled flag (the operator-wide kill switch). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:149 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/SetPerpLeverageParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetPerpLeverageParams # Interface: SetPerpLeverageParams Defined in: packages/sdk/src/trade.ts:1357 Inputs to [Trader.setPerpLeverage](Trader.md#setperpleverage) — cap the signer's max leverage on one perp pool (the MarginBank sizes positions against margin with it). ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1359 PerpPool the leverage cap applies to. *** ### leverageX > **leverageX**: `number` Defined in: packages/sdk/src/trade.ts:1361 Max leverage multiplier (e.g. 10 = 10x), bounded by the protocol limit. *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1363 MarginBank address; read (and cached) from `pool.marginBank()` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1369 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/SetReactivityGasParamsParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetReactivityGasParamsParams # Interface: SetReactivityGasParamsParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:174 Params for [MarketCreatorAdmin.setReactivityGasParams](MarketCreatorAdmin.md#setreactivitygasparams). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:176 The MarketCreator to update. Caller must be its owner. *** ### priorityFeePerGas > **priorityFeePerGas**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:178 Priority fee per gas (wei) the reactivity callback bids. *** ### maxFeePerGas > **maxFeePerGas**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:180 Max fee per gas (wei) the reactivity callback bids. *** ### gasLimit > **gasLimit**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:182 Gas limit reserved per reactivity subscription (gas units). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:184 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/SetVenueEnabledParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SetVenueEnabledParams # Interface: SetVenueEnabledParams Defined in: packages/sdk/src/operatorAdmin.ts:231 Params for [OperatorAdmin.setVenueEnabled](OperatorAdmin.md#setvenueenabled). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:233 The operator owning the venue. Caller must be its owner. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:235 The venue to flip (within the operator). *** ### creationEnabled > **creationEnabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:237 New creation flag; trading on existing markets is unaffected. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:239 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/SettlementRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SettlementRecord # Interface: SettlementRecord Defined in: packages/sdk/src/trade.ts:2020 A market's settlement record on the BinarySettlement singleton (the permanent redemption home). Mirrors the on-chain `MarketSettlement` struct. ## Properties ### collateralToken > **collateralToken**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2022 The ERC-20 collateral the net backing is held in. *** ### backing > **backing**: `bigint` Defined in: packages/sdk/src/trade.ts:2027 The NET collateral held for this market (post fee-skim on resolution), decremented by each redemption's payout. *** ### finalized > **finalized**: `boolean` Defined in: packages/sdk/src/trade.ts:2029 True once the pool's backing + snapshot have been swept in. Gates redemption. *** ### voided > **voided**: `boolean` Defined in: packages/sdk/src/trade.ts:2031 True if the market voided (each side redeems against the stored payout vector — a half per side under `UNIFORM`, `[p, D−p]` on a captured `CLOB_SNAPSHOT` void; never a settlement fee). *** ### winningOutcome > **winningOutcome**: `number` Defined in: packages/sdk/src/trade.ts:2036 The winning outcome index (0 = YES, 1 = NO); derived as argmax of `payoutNumerators`. Meaningful only when `!voided`. *** ### payoutNumerators > **payoutNumerators**: `bigint`[] Defined in: packages/sdk/src/trade.ts:2041 Settlement v3 fee-scaled payout VECTOR (denominator 10_000_000). Redemption of outcome `i` pays `amount × payoutNumerators[i] / 10_000_000`. *** ### settlementFeeBpsTimes1k > **settlementFeeBpsTimes1k**: `bigint` Defined in: packages/sdk/src/trade.ts:2043 The one-time settlement-fee rate skimmed at finalize (bps×1000; retained for audit). *** ### feeRecipient > **feeRecipient**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2045 The address the settlement fee was skimmed to at finalize. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2047 The pool that finalized this market (the address encoded in the outcome ids). *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/trade.ts:2049 The pool's market nonce for this record. --- # /docs/typescript/api/index/interfaces/SignRedeemAuthParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SignRedeemAuthParams # Interface: SignRedeemAuthParams Defined in: packages/sdk/src/trade.ts:1802 Inputs to [Trader.signRedeemAuth](Trader.md#signredeemauth) — everything in the signed struct EXCEPT the signature (which the call produces). Signed by the connected signer (the position owner); the resulting [RedeemAuthorization](RedeemAuthorization.md) is handed to a relayer to submit via [Trader.redeemFor](Trader.md#redeemfor). ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1804 bytes32 marketId the redemption targets. *** ### outcomeIdx > **outcomeIdx**: `0` \| `1` Defined in: packages/sdk/src/trade.ts:1806 Outcome the owner holds (0 = YES, 1 = NO). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1808 Outcome-token amount to burn for collateral. *** ### nonce > **nonce**: `bigint` Defined in: packages/sdk/src/trade.ts:1810 Per-owner replay nonce; any value not yet consumed for this owner. *** ### deadline > **deadline**: `bigint` Defined in: packages/sdk/src/trade.ts:1812 Signature deadline (unix seconds). *** ### operatorId? > `optional` **operatorId?**: `number` Defined in: packages/sdk/src/trade.ts:1814 Routing operator id (uint32) for attribution; 0 = none (default). *** ### venueId? > `optional` **venueId?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1816 Routing venue id (bytes32 hex); 32-byte zero = none (default). *** ### owner? > `optional` **owner?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1821 Owner the payout is pinned to; defaults to the connected signer's address. Must be the address whose signer produces the signature. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1826 BinaryMarketsModule address — the EIP-712 `verifyingContract`; resolved from `config.addresses.binaryModule` when omitted. --- # /docs/typescript/api/index/interfaces/SmartAccountSigner [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SmartAccountSigner # Interface: SmartAccountSigner Defined in: packages/sdk/src/executor/smartAccount.ts:76 The owner key that authorizes a smart account's transaction when the sending actor's presence is not authority enough — a sponsored send, or an account reached `through` parents. **Details** What the signer is asked to sign is the payload the accounts SDK prepares: the account's own Safe transaction when the signer owns it directly, or the outermost parent's `SafeMessage` envelope when `through` names a chain of accounts. Either way the payload binds the chain, so a wallet on the wrong network refuses it. ## Properties ### address > `readonly` **address**: `` `0x${string}` `` Defined in: packages/sdk/src/executor/smartAccount.ts:81 The address the signature must recover to: an owner of the account, or — with `through` — an owner of the OUTERMOST parent. *** ### signTypedData > `readonly` **signTypedData**: [`TypedDataSigner`](../type-aliases/TypedDataSigner.md) Defined in: packages/sdk/src/executor/smartAccount.ts:83 Signs the prepared EIP-712 payload as [SmartAccountSigner.address](#address). --- # /docs/typescript/api/index/interfaces/SmartAccountsClient [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SmartAccountsClient # Interface: SmartAccountsClient Defined in: packages/sdk/src/smartAccounts.ts:143 The smart-accounts capability — the factory account model of `@somnia-chain/accounts-sdk`, bound to one markets client's chain and transport. Reached as `client.accounts`. **Details** Reads go through the owning client's chain transport. The `build*` members return [UnsignedCall](UnsignedCall.md)s (or [UnsignedAccountCreation](UnsignedAccountCreation.md)s carrying their gas) for any executor to send — creation by whoever pays, owner management and transfers through the account's own smart-account executor (`client.createExecutor({ smartAccount, inner })`), so the account administers itself. Every member is refused with [InvalidInputError](../classes/InvalidInputError.md) on a chain the accounts SDK has no deployment for (Somnia mainnet 5031, Somnia testnet 50312 and Hideki testnet 50383 are covered; the factory sits at the same address on each). ## Methods ### addressOf() > **addressOf**(`accountId`, `index`): `` `0x${string}` `` Defined in: packages/sdk/src/smartAccounts.ts:157 The address `(accountId, index)` derives to on this chain — the same on every covered chain, deployed or not. Pure; no read. **Gotchas** The factory is upgradeable, so this is a prediction: fine for a screen, but read [SmartAccountsClient.find](#find) (or the accounts SDK's authoritative read) before publishing a deposit address. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### accountId `` `0x${string}` `` ##### index `bigint` #### Returns `` `0x${string}` `` *** ### find() > **find**(`accountId`, `options?`): `Promise`\<`AccountScan`\> Defined in: packages/sdk/src/smartAccounts.ts:168 Scan which of `accountId`'s derived accounts are deployed, from index 0 upward. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, or the range is empty or wider than the accounts SDK's scan cap. - Throws [RpcError](../classes/RpcError.md) - the transport failed outright; `cause` has the original. A single index that did not answer is reported inside the scan instead. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### accountId `` `0x${string}` `` ##### options? ###### maxIndex? `bigint` #### Returns `Promise`\<`AccountScan`\> *** ### nextFreeIndex() > **nextFreeIndex**(`accountId`, `options?`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/smartAccounts.ts:178 The lowest index with no deployed account, for creating the next one. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - no read answered — the accounts SDK refuses to hand out a possibly-taken index. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### accountId `` `0x${string}` `` ##### options? ###### from? `bigint` #### Returns `Promise`\<`bigint`\> *** ### ownersOf() > **ownersOf**(`account`): `Promise`\<`OwnerSet`\> Defined in: packages/sdk/src/smartAccounts.ts:187 An account's owner set: each owner classified as a key or another account, plus the threshold. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### account `` `0x${string}` `` #### Returns `Promise`\<`OwnerSet`\> *** ### custodyChain() > **custodyChain**(`account`, `options?`): `Promise`\<`CustodyChain`\> Defined in: packages/sdk/src/smartAccounts.ts:197 Walk DOWN from an account to the keys that ultimately control it, across accounts owning accounts. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. An unreadable branch is skipped and reported in the result instead. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### account `` `0x${string}` `` ##### options? ###### maxDepth? `number` #### Returns `Promise`\<`CustodyChain`\> *** ### authorityPath() > **authorityPath**(`account`, `signer`, `options?`): `Promise`\ Defined in: packages/sdk/src/smartAccounts.ts:208 Walk UP from a signer: the parent accounts between it and `account`, nearest first — exactly what the smart-account executor spec takes as `through`. `null` when the signer has no authority over the account (a real answer, not an error). Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### account `` `0x${string}` `` ##### signer `` `0x${string}` `` ##### options? ###### maxDepth? `number` #### Returns `Promise`\ *** ### tree() > **tree**(`root`, `options?`): `Promise`\<`AccountTree`\> Defined in: packages/sdk/src/smartAccounts.ts:217 The tree of accounts under one root — every deployed account derived from it, and from those, recursively. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### root `` `0x${string}` `` ##### options? ###### maxIndex? `bigint` ###### indices? readonly `bigint`[] ###### maxDepth? `number` #### Returns `Promise`\<`AccountTree`\> *** ### holdings() > **holdings**(`account`, `tokens?`): `Promise`\<`Holdings`\> Defined in: packages/sdk/src/smartAccounts.ts:230 An account's native balance and the balances of the tokens asked about. A balance is `undefined` where the read did not answer — never silently zero. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### account `` `0x${string}` `` ##### tokens? readonly `` `0x${string}` ``[] #### Returns `Promise`\<`Holdings`\> *** ### health() > **health**(`account`): `Promise`\<`HealthReport`\> Defined in: packages/sdk/src/smartAccounts.ts:240 Evaluate an account's setup against the factory's canonical shape: singleton, fallback handler, owners, threshold, modules — each finding with a severity. Chain read (current to head). - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. - Throws [RpcError](../classes/RpcError.md) - the transport failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### account `` `0x${string}` `` #### Returns `Promise`\<`HealthReport`\> *** ### buildExecution() > **buildExecution**(`args`): `Promise`\<[`PreparedAccountExecution`](PreparedAccountExecution.md)\> Defined in: packages/sdk/src/smartAccounts.ts:256 Prepare an execution whose signer is NOT the sender — the sign-now-send-later flow: the owner signs here, and the finished call goes to whoever pays (your backend, a relayer). The executor path (`createExecutor({ smartAccount, … })`) is the right tool when the same process signs and sends; this is for when it is not. One nonce read through this client, skipped when `nonce` is given — an account's FIRST action can be prepared and signed before the account is deployed, at nonce 0. Chain read (current to head) unless `nonce` is given. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, `calls` is empty, or a call names another chain. - Throws [RpcError](../classes/RpcError.md) - the nonce read failed; `cause` has the original. The complete union is [SmartAccountsReadError](../type-aliases/SmartAccountsReadError.md). #### Parameters ##### args ###### account `` `0x${string}` `` The account that acts. ###### calls readonly [`UnsignedCall`](UnsignedCall.md)[] What it does. Several calls batch into one account transaction. ###### signer `` `0x${string}` `` The address that will sign — an owner of the account, or of the outermost parent. ###### through? readonly `` `0x${string}` ``[] The parent accounts between the signer and `account`, nearest first. ###### nonce? `bigint` The account's nonce, when the caller already knows it — no read is performed. `0n` prepares an undeployed account's first action. #### Returns `Promise`\<[`PreparedAccountExecution`](PreparedAccountExecution.md)\> *** ### buildCreateAccount() > **buildCreateAccount**(`accountId`, `index`): [`UnsignedAccountCreation`](UnsignedAccountCreation.md) Defined in: packages/sdk/src/smartAccounts.ts:280 Build the call that deploys `(accountId, index)`'s account on this chain. Permissionless and idempotent: no signature from anybody — the owner is forced out of the CREATE3 salt, so a sponsor cannot inject one. Send as `executor.execute([r.call], { gas: r.gas })`. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### accountId `` `0x${string}` `` ##### index `bigint` #### Returns [`UnsignedAccountCreation`](UnsignedAccountCreation.md) *** ### buildAccountAuthorization() > **buildAccountAuthorization**(`args`): [`PreparedAccountAuthorization`](PreparedAccountAuthorization.md) Defined in: packages/sdk/src/smartAccounts.ts:293 Build the authorization one owner signature settles: several accounts, optional additional owners (a session key) and threshold, valid on EVERY covered chain — the domain deliberately omits the chain id. Sign `typedData` with any EIP-712 signer, then hand the pair to [SmartAccountsClient.buildCreateAccounts](#buildcreateaccounts) (or the exchange-level fan-out). Pure; no read. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, no index is named, or the validity window exceeds what every chain accepts. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### args ###### accountId `` `0x${string}` `` The address the accounts derive from — the EOA (or account) that signs. ###### indices readonly `bigint`[] Which indices to create. At least one. ###### additionalOwners? readonly `` `0x${string}` ``[] Extra owners installed at creation — typically one session key. ###### threshold? `bigint` Signature threshold for the created accounts. Default 1. ###### window? `bigint` Seconds the signature stays valid. Default 900, max 18,000. ###### now? `bigint` Unix seconds "now". Defaults to the system clock. #### Returns [`PreparedAccountAuthorization`](PreparedAccountAuthorization.md) *** ### buildCreateAccounts() > **buildCreateAccounts**(`authorization`, `signature`): [`UnsignedAccountCreation`](UnsignedAccountCreation.md) Defined in: packages/sdk/src/smartAccounts.ts:316 Turn a signed authorization into this chain's creation call. Any funded actor may send it; the accounts the authorization names that already exist are skipped, not reverted. For every covered chain at once, use the exchange-level `exchange.accounts.buildCreateAccounts`. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### authorization `AccountAuthorization` ##### signature `` `0x${string}` `` #### Returns [`UnsignedAccountCreation`](UnsignedAccountCreation.md) *** ### buildAddOwner() > **buildAddOwner**(`account`, `owner`, `threshold`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:325 Build the call that adds an owner (typically a session key) to an account, setting the threshold. Execute it THROUGH the account itself: `client.createExecutor({ smartAccount: account, inner })`. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### account `` `0x${string}` `` ##### owner `` `0x${string}` `` ##### threshold `bigint` #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildSwapOwner() > **buildSwapOwner**(`account`, `owners`, `oldOwner`, `newOwner`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:335 Build the call that swaps one owner for another. `owners` is the account's CURRENT owner list ([SmartAccountsClient.ownersOf](#ownersof)) — Safe's owner list is linked, so the call names the predecessor. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, or `oldOwner` is not in `owners`. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### account `` `0x${string}` `` ##### owners readonly `` `0x${string}` ``[] ##### oldOwner `` `0x${string}` `` ##### newOwner `` `0x${string}` `` #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildRemoveOwner() > **buildRemoveOwner**(`account`, `owners`, `owner`, `threshold`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:344 Build the call that removes an owner, setting the threshold. `owners` is the account's CURRENT owner list. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, or `owner` is not in `owners`. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### account `` `0x${string}` `` ##### owners readonly `` `0x${string}` ``[] ##### owner `` `0x${string}` `` ##### threshold `bigint` #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildChangeThreshold() > **buildChangeThreshold**(`account`, `threshold`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:351 Build the call that changes the account's signature threshold. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### account `` `0x${string}` `` ##### threshold `bigint` #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildTransfer() > **buildTransfer**(`args`): readonly [`UnsignedCall`](UnsignedCall.md)[] Defined in: packages/sdk/src/smartAccounts.ts:361 Build the calls that move native value and/or ERC-20 amounts OUT of an account. Execute them through that account's smart-account executor — the account holding the funds is the one that sends. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the chain is not covered, or nothing is being moved. The complete union is [SmartAccountsBuildError](../type-aliases/SmartAccountsBuildError.md). #### Parameters ##### args ###### to `` `0x${string}` `` The recipient. ###### native? `bigint` Wei of native value to move. ###### tokens? readonly `TokenAmount`[] ERC-20 amounts to move, in raw token units. #### Returns readonly [`UnsignedCall`](UnsignedCall.md)[] --- # /docs/typescript/api/index/interfaces/SomniaLendClient [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaLendClient # Interface: SomniaLendClient Defined in: packages/sdk/src/lend/client.ts:22 The SomniaLend client — reads over the deployed Aave-v3-fork contracts plus the [Lender](Lender.md) write factory, bound to one markets client's chain transport. Reached as `client.lend`. ## Methods ### listReserves() > **listReserves**(): `Promise`\<[`LendReserve`](LendReserve.md)[]\> Defined in: packages/sdk/src/lend/client.ts:41 Every SomniaLend reserve — config, caps, live rates/indexes, liquidity, and the oracle price, in one aggregated eth_call. Chain read (current to head). **Details** Rates come back as ray bigints; convert for display with [lendRayRateToApy](../functions/lendRayRateToApy.md). See [LendReserve](LendReserve.md) for the unit conventions. **Example** (Displaying reserve APY) ```ts const reserves = await client.lend.listReserves(); for (const r of reserves) { console.log(r.symbol, `supply APY ${(lendRayRateToApy(r.liquidityRateRay) * 100).toFixed(2)}%`); } ``` #### Returns `Promise`\<[`LendReserve`](LendReserve.md)[]\> *** ### getAccount() > **getAccount**(`account`): `Promise`\<[`LendAccount`](LendAccount.md)\> Defined in: packages/sdk/src/lend/client.ts:46 A whole SomniaLend account: health factor, borrowing power, and every non-empty supplied/borrowed position. Chain read (current to head). #### Parameters ##### account `` `0x${string}` `` #### Returns `Promise`\<[`LendAccount`](LendAccount.md)\> *** ### createLender() > **createLender**(`config`): [`Lender`](Lender.md) Defined in: packages/sdk/src/lend/client.ts:52 Build a [Lender](Lender.md) bound to a signer — the write surface (supply / withdraw / borrow / repay, ERC-20 and native, auto-approving). Same signer doctrine as every SDK write factory (privateKey / local account / walletClient). #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`Lender`](Lender.md) --- # /docs/typescript/api/index/interfaces/SomniaMarketsAccount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsAccount # Interface: SomniaMarketsAccount Defined in: packages/sdk/src/account.ts:59 An account for a multi-chain [SomniaMarkets](../classes/SomniaMarkets.md): one address, and the executor that acts as it on each configured chain. **Details** Pass it as `account` in [SomniaMarketsConfig](../type-aliases/SomniaMarketsConfig.md). Portfolio reads (`fetchBalance`, `fetchPositions`, …) use `address` on every chain; a write for a market on chain N goes through `executors[N]`. A chain with no executor is read-only: a write there throws [NotConfiguredError](../classes/NotConfiguredError.md) naming the chain. **Gotchas** Every executor's `actor` must equal `address`, or the SDK would read allowances for one account and send as another. The facade checks this at construction and throws [InvalidInputError](../classes/InvalidInputError.md) on a mismatch. The account's `inner` executors sign locally, as in the example. An executor from `createExecutor({ sessionSeed })` sends its seed to the node on every write, so the smart-account spec refuses it as `inner`. Use one sending mode per address: local and node-side sends from the same address share one nonce space. **Example** (One smart account on two chains) ```ts const exchange = new SomniaMarkets({ chains: [l1, hideki], account: { address: ACCOUNT, executors: { [l1.chain.id]: l1Engine.createExecutor({ smartAccount: ACCOUNT, inner: l1Engine.createExecutor({ privateKey: sessionKey }), }), [hideki.chain.id]: l2Engine.createExecutor({ smartAccount: ACCOUNT, inner: l2Engine.createExecutor({ privateKey: sessionKey }), }), }, }, }); ``` ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/account.ts:61 The account's address — the same on every chain. *** ### executors > **executors**: `Partial`\<`Record`\<`number`, [`Executor`](Executor.md)\>\> Defined in: packages/sdk/src/account.ts:63 The executor that acts as `address` on each chain, keyed by chain id. --- # /docs/typescript/api/index/interfaces/SomniaMarketsAddresses [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsAddresses # Interface: SomniaMarketsAddresses Defined in: packages/sdk/src/config.ts:16 Protocol contract addresses (all optional — features degrade if unset). ## Properties ### fakeOracle? > `optional` **fakeOracle?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:18 FakeOracle resolver (demo resolve/void). *** ### collateral? > `optional` **collateral?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:24 Per-venue collateral ERC-20 (the venue's quote/collateral token; on test environments this is the faucet-capable TestUSDC). Preferred over `testUsdc`, which remains as the legacy/fallback alias. *** ### testUsdc? > `optional` **testUsdc?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:29 TestUSDC collateral (faucet + balances). Legacy/fallback alias for [SomniaMarketsAddresses.collateral](#collateral). *** ### binaryModule? > `optional` **binaryModule?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:35 BinaryMarketsModule — the binary product's core module (complete-set mint/redeem, market creation, adapter approval). Needed by the trader writes, the hub-approval reads, and /system diagnostics. *** ### marketCreator? > `optional` **marketCreator?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:40 MarketCreator factory. When set, the live tail watches MarketCreated and picks up new binary markets the block they deploy — no indexer round-trip. *** ### clobFactory? > `optional` **clobFactory?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:45 ClobFactory — /system-diagnostics fallback when the module's live `clobFactory()` read fails; a live/config mismatch is flagged. *** ### binaryPoolImpl? > `optional` **binaryPoolImpl?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:53 BinaryPool implementation behind the fleet (distinct from the factory's `binaryMarketImpl`). On beacon-generation deploys this is the impl the [SomniaMarketsAddresses.binaryPoolBeacon](#binarypoolbeacon) points at; on pre-beacon deploys it is the EIP-1167 master copy the factory cloned. Not read by the SDK itself, but surfaced to apps — the explorer's system overview renders it. *** ### binaryPoolBeacon? > `optional` **binaryPoolBeacon?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:60 The fleet's `UpgradeableBeacon` (beacon generation onwards). Every pool the factory deploys is a `BeaconProxy` against it, so upgrading the beacon moves the whole fleet at once. Absent on pre-beacon manifests, where pools are independent clones of [SomniaMarketsAddresses.binaryPoolImpl](#binarypoolimpl). *** ### binarySettlement? > `optional` **binarySettlement?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:68 The permanent BinarySettlement singleton (settlement-extraction v2). Every pool finalizes its markets into it and every redemption routes through it, so a pool can be recycled onto the next market. Needed by the low-level `redeemDirect` / `claimOwed` / `getSettlement` trader methods, which throw if it is unset. Absent on pre-v2 (pool-redeem) deploys. *** ### operatorPermissionsRegistry? > `optional` **operatorPermissionsRegistry?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:73 Shared OperatorPermissionsRegistry — users operator-approve a SpotStopOrderRegistry here (once, globally) so it can place their stop order via the pool at trigger time. *** ### marketsCore? > `optional` **marketsCore?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:79 MarketsCore — the control-plane registry of operators, typed venues, and the module binding per market type. Needed by the operator/venue admin reads + `createOperatorAdmin` writes. *** ### collateralRouter? > `optional` **collateralRouter?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:86 CollateralRouter periphery — the native-token (wrap/unwrap) + Permit2 entry over BinaryMarketsModule's complete-set flow. May be absent for an environment where only the plain-ERC-20 path is deployed; the router-based trader methods throw if it is unset rather than sending to the zero address. *** ### marketCreatorFactory? > `optional` **marketCreatorFactory?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:92 MarketCreatorFactory — stamps out per-operator/venue MarketCreator (+ its policy) instances, the operator "market machinery" layer. Needed by `createMarketCreatorAdmin` writes; the admin throws if it is unset. *** ### marketCreatorFactoryV2? > `optional` **marketCreatorFactoryV2?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:101 v2 sibling of [SomniaMarketsAddresses.marketCreatorFactory](#marketcreatorfactory) — stamps out `MarketCreatorV2` (interval/bucket-mode rolling series) instances. Additive: coexists with the v1 factory. Not read by `createMarketCreatorAdmin` automatically — pass it explicitly via that call's `factory` override to mint a v2 creator instead of v1. Undefined on deploys that predate it. *** ### oracleHub? > `optional` **oracleHub?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:112 The OracleHub proxy (Oracle v2 §8e) — the protocol's ONE governance-approved oracle adapter. Every market creation binds through it (content-addressed `scheduleQuestion` dedup, earmark-at-creation resolution funding + bounded-drain exact metering, payout-vector delivery). Needed by the OracleHub reads (`quoteCreateMarketValue`, `getSchedulingCost`, `earmarkedOf`, `resolveReserve`) and the `createOracleHubAdmin` writes; those throw if it is unset. Also the default `adapter` for `createMarketCreatorAdmin.createMarketCreator`. *** ### ~~oracleAdapterFactory?~~ > `optional` **oracleAdapterFactory?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:120 Legacy OracleAdapterFactory address retained for source compatibility. #### Deprecated LEGACY (pre-oracle-v2): OracleAdapterFactory. The factory contract was deleted in Oracle v2 — use [SomniaMarketsAddresses.oracleHub](#oraclehub). Kept only so old configs keep type-checking; nothing in the SDK reads it. *** ### ~~sharedOracleAdapter?~~ > `optional` **sharedOracleAdapter?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:128 Legacy shared oracle-adapter address retained for source compatibility. #### Deprecated LEGACY (pre-oracle-v2): the shared ProphecyOracleAdapter proxy. Replaced by [SomniaMarketsAddresses.oracleHub](#oraclehub). Kept only so old configs keep type-checking; nothing in the SDK reads it. *** ### perpPoolFactory? > `optional` **perpPoolFactory?**: `` `0x${string}` `` Defined in: packages/sdk/src/config.ts:157 PerpPoolFactory — the on-chain authority on which perp markets exist. Unnecessary ONLY while the indexer carries at least one perp row. [SomniaMarkets.loadMarkets](../classes/SomniaMarkets.md#loadmarkets) finds the factory from such a row: it carries its `marginBank`, and `MarginBank.getSystemConfig()` reports the factory the bank actually calls. That is the better source — it is the deployment's own view of its wiring, so it cannot drift from a stale config the way a hardcoded address can. Set this for the one case the bootstrap cannot cover: an indexer with NO perp rows at all, where there is no `marginBank` to ask. That happens on a fresh reindex, and while an indexer is catching up below the factory's first deploy block. Without it, `loadMarkets` does not look for perps at all and returns an empty perp set with every error accessor clean; [SomniaMarkets.perpDiscoverySkipped](../classes/SomniaMarkets.md#perpdiscoveryskipped) is what reports that state. When set it takes precedence, so it also serves as an override while a bank's reported factory is being rotated. `SOMNIA_TESTNET_ADDRESSES` and `SOMNIA_HIDEKI_TESTNET_ADDRESSES` set it, so a binding with either preset lists its perps without an indexer. `SOMNIA_MAINNET_ADDRESSES` does not set it. Because a set value takes precedence, these presets do not use the bank's factory. The preset value is fixed when the SDK version is released, so it can become stale after a perps redeploy. To use the bank's factory, pass a copy of the preset without this field. *** ### lend? > `optional` **lend?**: [`LendAddresses`](LendAddresses.md) Defined in: packages/sdk/src/config.ts:184 SomniaLend money-market addresses — a THIRD-PARTY Aave v3 fork (docs.somnialend.finance), so unlike the first-party fields above these are NOT in the deployments manifests. Set `SOMNIA_MAINNET_LEND` or `SOMNIA_TESTNET_LEND` (from the root entry) for the published deployments. Backs the `client.lend` namespace; its methods throw a clear error when the address they need is unset. **Gotchas** This is the ONLY way to point the lend surface at a deployment — and the addresses must belong to this client's `chain`. A testnet deployment needs a testnet client; there is no way to graft one chain's lend addresses onto another chain's socket. **Example** (Configuring SomniaLend) ```ts const exchange = new SomniaMarkets({ ...config, addresses: { lend: SOMNIA_MAINNET_LEND }, }); const account = await exchange.client.lend.getAccount(me); console.log(`health factor ${account.healthFactor}`); ``` --- # /docs/typescript/api/index/interfaces/SomniaMarketsChainFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsChainFilter # Interface: SomniaMarketsChainFilter Defined in: packages/sdk/src/unified/exchange.ts:335 Restricts a multi-chain account read to one chain. **Details** An account read with no `chainId` and no market reads every chain the exchange spans. It fails closed: when one chain fails, the read throws, and an `IndexerError` or `RpcError` names that chain in its `chainId`. A read with `chainId` reads only that chain, so a caller can still read the chains that answer. This includes the market load before the read: on an exchange that has not loaded markets yet, it loads only that chain. Together with a market ref, `chainId` must name the market's chain, else the read throws `InvalidInputError`. A chain the exchange does not span throws `NotConfiguredError`. ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:337 Read only this chain. Omit it to read every chain. --- # /docs/typescript/api/index/interfaces/SomniaMarketsChainsConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsChainsConfig # Interface: SomniaMarketsChainsConfig Defined in: packages/sdk/src/unified/exchange.ts:161 The multi-chain form of [SomniaMarketsConfig](../type-aliases/SomniaMarketsConfig.md): one [ChainBinding](../type-aliases/ChainBinding.md) per chain the exchange spans. Each binding builds its own engine — its own socket, indexer connection, nonce lane and fee envelope. Chain ids and indexer URLs must be distinct across bindings. ## Properties ### chains > **chains**: [`ClientConfig`](ClientConfig.md)[] Defined in: packages/sdk/src/unified/exchange.ts:163 One engine configuration per chain, in the order `chainIds` reports them. The first is the primary. --- # /docs/typescript/api/index/interfaces/SomniaMarketsClient [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClient # Interface: SomniaMarketsClient Defined in: packages/sdk/src/somniaMarketsClient.ts:516 An SDK client — the single handle for all protocol I/O. This is the raw engine tier, reached through the exchange (`new SomniaMarkets(config)` → `exchange.client`). Each exchange's engine is fully isolated: its own config, live store, and (lazily opened) chain WebSocket, so several can coexist in one process without sharing state. The read surface has three tiers — pick by freshness need: 1. **Live store** (`getLive*`, synchronous): zero round-trips, updates the moment an event lands on-chain. Requires a watch ([watchMarket](#watchmarket) / [watchMarkets](#watchmarkets)) covering the market you read. 2. **Chain** (`getBinaryOrderBook`, `getMarketOnchain`, …): one `eth_call` round-trip, current to head. Works without any watch. 3. **Indexer** (`listMarkets`, `getPortfolio`, …): history and aggregates; lags the chain slightly. Works without any watch or the socket. ## Extended by - [`SomniaMarketsClientWithObservations`](SomniaMarketsClientWithObservations.md) ## Properties ### config > `readonly` **config**: [`ClientConfig`](ClientConfig.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:518 The config this client was built with. *** ### lend > `readonly` **lend**: [`SomniaLendClient`](SomniaLendClient.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:569 The SomniaLend namespace — reads (`lend.listReserves()`, `lend.getAccount()`) and the `lend.createLender()` write factory for the third-party Aave v3 money market on Somnia (mainnet + testnet). Lazily bound to `config.addresses.lend` (set `SOMNIA_MAINNET_LEND` / `SOMNIA_TESTNET_LEND` from the root entry); its methods throw a clear error when those addresses are unset. The root entry also publishes its types, deployment constants, ray-math helpers and ABIs; this namespace is the only way to call it, so a lend read always rides the client's own chain transport. *** ### accounts > `readonly` **accounts**: [`SmartAccountsClient`](SmartAccountsClient.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:579 The smart-accounts capability — the factory account model of `@somnia-chain/accounts-sdk` on this client's chain: derive and discover accounts, walk ownership, build creation / owner-management / transfer calls for an executor to send, and read holdings and health. Built lazily; reads ride this client's own chain transport. See [SmartAccountsClient](SmartAccountsClient.md), and `createExecutor({ smartAccount, inner })` for sending AS an account. ## Methods ### getViemClient() > **getViemClient**(): `object` Defined in: packages/sdk/src/somniaMarketsClient.ts:556 This client's underlying viem client, undecorated — viem's own behaviour, over the socket this client already has. **When to use** Use to reach a contract or RPC method the SDK does not model: your own contracts, or plain calls like `getBalance` / `getCode` / `waitForTransactionReceipt`. Reads through it keep VIEM's error contract, so `e instanceof ContractFunctionRevertedError` and the rest of your existing viem error handling still work. Building your own client instead would open a second WebSocket; this one shares the SDK's. **Details** - Returns: The undecorated viem `PublicClient` for this client's chain. **Gotchas** Reads through this client do NOT get the SDK's decoded protocol errors — a revert arrives as viem's error, not a [ContractRevertError](../classes/ContractRevertError.md) with an `errorName`. That is the point of the accessor, but it means you should prefer the SDK's own methods for protocol contracts, where the decoding is the value. The two clients are deliberately different: everything reachable from this interface uses the decoded one. Calling this opens the WebSocket if it is not already open, and throws [NotConfiguredError](../classes/NotConfiguredError.md) on a client built without `wsRpcUrl`. The returned client belongs to this client's current connection. After `stopLive()` or the owner's `close()`, its requests reject with viem's `SocketClosedError`, and it never opens a socket again. Call `getViemClient()` again after `stopLive()` to get a working client. #### Returns `object` *** ### watchMarket() > **watchMarket**(`pool`, `opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:657 Watch one market: hydrate a consistent snapshot of it (market row, recent fills, its full resting order book) and stream its events — order-book activity plus, for a binary market, its lifecycle/status events. While the watch is active, every `getLive*` read for this pool is current to the last block at zero round-trip cost. Watches are **ref-counted**: watching the same pool twice shares one subscription and one snapshot; each handle's `stop()` releases one reference, and the scope is torn down (subscription dropped, heavy rows purged) shortly after the last release — a brief linger absorbs quick re-watches (navigation, React remounts) without re-snapshotting. Resolves once the seam is sealed (snapshot + backfill + buffered replay) — i.e. once reads are live. Rejects (and releases the reference) if hydration fails; the socket dropping later is healed automatically by reconnect + chain backfill. The React data hooks call this automatically while mounted. **Details** `opts` opts INTO a chain seed. Omit it and the watch seeds from the indexer snapshot exactly as before, and `getLiveStatus().snapshotBlock` keeps its existing meaning. Pass `{ seed: "chain", marketId }` and the book is drained from the pool contract at one pinned block instead, so the watch starts with the indexer unreachable. Supply the `marketId` the pool currently serves: pools are recycled across markets and book reads filter on it. A chain seed also reads the market's row from the BinaryMarketsModule, so `config.addresses.binaryModule` must be set — the row is what every later order and fill event attributes through. It carries what the module answers (collateral, decimals, nonce, lifecycle state); indexer-only fields such as the question text, `strike`/`mode` and the creation history stay empty or null and STAY that way — a seeded pool is never re-hydrated, and the row outlives `stop()` until cold-market eviction drops it (see [getLiveMarkets](#getlivemarkets)). Read the indexer directly ([getBinaryMarket](#getbinarymarket)) when those fields are needed. A chain seed covers exactly ONE pool. N pools means N calls, which is the supported way to seed several: they share one tail and one subscription set, and each pool keeps its own seed status. Read that with [getSeedStatus](#getseedstatus), NOT [getLiveStatus](#getlivestatus), whose seed fields report the most recent seed only and are overwritten by the next pool's. The worst-case read cost is `2 × maxPages` contract reads per pool, 80 at the defaults, plus one module read for the market row. A chain seed has no per-scope order cap, unlike the indexer snapshot, whose budget is shared across the scope's pools and drops the OLDEST resting orders first. `getSeedStatus(pool).seedTruncated` is `true` only if that pool's drain hit its own page budget. **Gotchas** A chain seed loads NO fill history — the chain cannot answer fills from before the seam. The tape loads on a detached lane, so `getLiveFills` may be empty while the book is complete. Branch on `getSeedStatus(pool).fillsLoaded`, not on the tape being empty: `false` means never loaded, `true` with `[]` means genuinely no fills. The global `getLiveStatus().fillsLoaded` turns true when ANY pool's lane lands, so it cannot answer for one pool. A failed tape read sets `failure.operation` to `"fill-history"` and does not reject this promise. Seeded orders carry an empty `createdAt`/`txHash`: placement history is indexer-only and the seed does not invent it. `userOrders` sorts on `createdAt`, so they sort last until a snapshot dates them. #### Parameters ##### pool `string` ##### opts? [`SeedOptions`](SeedOptions.md) #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Throws [IndexerError](../classes/IndexerError.md) If the indexer snapshot fails (default seed only). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If a chain seed is requested with no `addresses.binaryModule`, or the indexer does not index the client's chain. #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.maxCount`/`opts.maxPages` is not a positive safe integer, or `opts.marketId` is not a bytes32 id. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If a chain-seed page read reverts. #### Throws [RpcError](../classes/RpcError.md) If a chain read or the subscription fails at the transport. *** ### watchMarkets() > **watchMarkets**(`opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:685 Watch every market whose book or lifecycle can still change — the whole-protocol tail for list views and multi-market bots. Prefer [watchMarket](#watchmarket) scoped to what you actually trade or render: this variant's cost grows with the protocol (snapshot size, subscription filter width, event volume). **Details** The watch selects markets by lifecycle, not by age. It hydrates every SPOT and PERP market and every BINARY market that is not finalized, which includes Locked, Settling, Resolved and Voided markets that still wait for settlement events. A finalized BINARY market is left out: its status is terminal, its book holds no live order, and its pool can serve a later market. Its redemption ledger (`netBacking`) keeps moving on the settlement contract, so read it with [getBinaryMarket](#getbinarymarket). [watchMarket](#watchmarket) applies no lifecycle filter, but it selects the market its pool serves now: it hydrates a finalized market only until the pool is recycled. One snapshot hydrates at most 500 eligible markets, newest first, so that the whole set shares one seam. When more eligible markets exist, `getLiveStatus().allMarketsTruncated` is `true` while this watch is active, and the oldest eligible markets are not watched. Watch those with [watchMarket](#watchmarket). - `opts.discover`: Also watch the MarketCreator factory so markets created AFTER this call join the watch live, in their creation block (requires `config.addresses.marketCreator`). Off by default. #### Parameters ##### opts? ###### discover? `boolean` #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> *** ### watchUser() > **watchUser**(`user`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:696 Hydrate one account's order/fill **history** (one indexer fetch) so [getLiveUserFills](#getliveuserfills) / [getLiveUserOrders](#getliveuserorders) have depth predating your watches. This does not subscribe to anything by itself: live events are attributed to every account automatically, but only within markets covered by an active [watchMarket](#watchmarket) / [watchMarkets](#watchmarkets) — an account's activity in unwatched markets stays at snapshot state. Ref-counted like market watches; supports multiple accounts at once. #### Parameters ##### user `string` #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> *** ### watchPerpMarkets() > **watchPerpMarkets**(`opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:732 Watch the perp **plane**: hydrate the recent liquidation waterfall legs and per-account funding settlements, then stream both live — the same snapshot-then-live guarantee [watchMarket](#watchmarket) gives a book. ONE scope covers every perp market, and that is forced rather than chosen. MarginBank and LiquidationEngine are singletons, so the log subscription is one stream whatever the caller asks for — and the account-level waterfall legs (`AccountLiquidated`, `ResidualBadDebt`, ...) carry no pool at all, so a per-pool scope would either drop them or attach them to every pool. Filter at read time with [listLiveLiquidations](#listliveliquidations) / [listLiveFundingPayments](#listlivefundingpayments) instead. Independent of [watchMarket](#watchmarket): watching a perp pool gives you its book, funding RATE and open interest; this gives you liquidations and funding SETTLEMENT. Neither implies the other, and a UI showing both wants both watches. Ref-counted and lingered like the other watches. Resolves once the seam is sealed; a later socket drop is healed by reconnect and chain backfill, with no second indexer touch. **Details** - `opts.marginBank`: The MarginBank to read the plane's wiring from. Normally UNNECESSARY — the address is taken from an indexed perp market row, and `MarginBank.getSystemConfig()` reports the LiquidationEngine from there. Pass it for the one case that cannot cover: an indexer with no perp rows at all, where there is nothing to ask. It is a FALLBACK, never an override: it is used when the indexer names no bank, including on a scope a read hook acquired moments earlier with no hint to give, and it is ignored when the indexer named one — the hydrated rows are that bank's plane, so streaming another one would splice two venues into one feed. #### Parameters ##### opts? [`WatchPerpMarketsOptions`](WatchPerpMarketsOptions.md) #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Throws InvalidInputError when `opts.marginBank` is not an address. #### Throws IndexerError when the plane snapshot fails. #### Throws RpcError when the MarginBank wiring read or the seam's head read fails — the liquidation half cannot be watched without the wiring, and watching the bank alone would stream funding settlements and no liquidations, which reads as a venue with none. #### Throws ContractRevertError when the resolved MarginBank — indexed, or supplied via `opts.marginBank` — reverts on `getSystemConfig()`, i.e. it is not a MarginBank the SDK can read. #### Throws NotConfiguredError on a client built without `wsRpcUrl` or `indexerUrl`, or whose indexer does not index its chain. *** ### getWatchStatus() > **getWatchStatus**(`pool`): [`WatchStatus`](../type-aliases/WatchStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:740 Per-market watch state: `"unwatched"` (no active watch — `getLive*` reads return empty for this pool, which is how you distinguish "empty book" from "not watching"), `"hydrating"` (watch registered; snapshot, seam backfill, or reconnect in progress), or `"live"`. #### Parameters ##### pool `string` #### Returns [`WatchStatus`](../type-aliases/WatchStatus.md) *** ### getPerpPlaneStatus() > **getPerpPlaneStatus**(): [`WatchStatus`](../type-aliases/WatchStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:746 Perp-plane watch state, in the same three values [getWatchStatus](#getwatchstatus) uses — so `"unwatched"` distinguishes "no liquidations happened" from "not watching". #### Returns [`WatchStatus`](../type-aliases/WatchStatus.md) *** ### stopLive() > **stopLive**(): `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:763 Tear down every watch, subscription, timer, and socket this client opened (tests, shutdown), including the chain WebSocket — so a Node process that has touched the chain exits on its own afterwards. The store keeps its last state; `getLive*` and `listLive*` reads keep answering (stale), and a later chain read reopens a connection that the next `stopLive()` releases in turn. An indexer read already on the wire stays active, but one still QUEUED for an in-flight slot, or sleeping out a retry backoff, is rejected with [IndexerUnavailableError](../classes/IndexerUnavailableError.md) (`reason: "live-reset"`), so nothing sends after the stop. The client stays usable. Existing observed-read capabilities are invalidated; create a new one before observing again. Each client owns its own chain socket, even when several use the same `wsRpcUrl`, so stopping one never closes another's. #### Returns `void` *** ### subscribeLive() > **subscribeLive**(`listener`): () => `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:775 Fire `listener` after every batch of store changes — the "something changed, re-read" signal (the React hooks subscribe to exactly this). Re-read with any `getLive*` method; their results are memoized per store version, so re-reading without a change returns the same reference. **Details** - Returns: An unsubscribe function. #### Parameters ##### listener () => `void` #### Returns () => `void` *** ### getLiveStatus() > **getLiveStatus**(): [`TailStatus`](TailStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:783 The tail's global health: mode (`"init"` until the first watch hydrates, then `"tailing"`), the last seam block, the last locally-materialized block, the chain head, socket state, and the active watch count. For one market's state, use [getWatchStatus](#getwatchstatus). #### Returns [`TailStatus`](TailStatus.md) *** ### getSeedStatus() > **getSeedStatus**(`pool`): [`PoolSeedStatus`](PoolSeedStatus.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:811 One watched pool's OWN seed status, or `null` when the pool is not hydrated. **When to use** Use it whenever more than one pool is watched. [getLiveStatus](#getlivestatus) reports `seedSource`, `seedBlock`, `seedTruncated` and `fillsLoaded` for the MOST RECENT seed only, so with several pools those values cannot be attributed to a pool: a later seed writes `seedTruncated: false` over an earlier `true`, and `fillsLoaded` turns true when any pool's lane lands. **Gotchas** `null` means this pool has no hydrated watch — never that its seed was complete. Check [getWatchStatus](#getwatchstatus) to tell an unwatched pool from one still hydrating. A released watch drops its entry, so a rewatched pool cannot read the previous watch's truncation or fill-lane result. ```ts const seed = client.getSeedStatus(pool); if (seed && !seed.fillsLoaded) console.log("tape not loaded for", pool); ``` #### Parameters ##### pool `string` #### Returns [`PoolSeedStatus`](PoolSeedStatus.md) \| `null` *** ### isTailing() > **isTailing**(): `boolean` Defined in: packages/sdk/src/somniaMarketsClient.ts:814 True once at least one watch is live (`mode === "tailing"`). #### Returns `boolean` *** ### getLiveMarkets() > **getLiveMarkets**(): [`Market`](../type-aliases/Market.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:829 Every market the store retains (spot + binary, as the discriminated [Market](../type-aliases/Market.md) union), from any watch, past or present. Synchronous, memoized. The store always keeps a market that a pool is bound to or that a retained fill or order names. It keeps other markets (released or replaced) as metadata up to a fixed allowance of 500 rows and evicts the earliest-discovered ones after that. So the list does not grow with session age. An evicted market is also absent from [getLiveMarketByAddress](#getlivemarketbyaddress), and its late settlement events do not change the live store. Read it with [getMarket](#getmarket) or [getBinaryMarket](#getbinarymarket). #### Returns [`Market`](../type-aliases/Market.md)[] *** ### getLiveMarketByPool() > **getLiveMarketByPool**(`pool`): [`Market`](../type-aliases/Market.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:832 One market by its pool address (either kind), or null if unknown. #### Parameters ##### pool `string` #### Returns [`Market`](../type-aliases/Market.md) \| `null` *** ### getLiveMarketByAddress() > **getLiveMarketByAddress**(`marketAddress`): [`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:838 One binary market by its BinaryMarket contract address, or null. (Spot markets have no market contract — they are identified by pool.) #### Parameters ##### marketAddress `string` #### Returns [`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null` *** ### getLiveFills() > **getLiveFills**(`pool`, `opts?`): [`LiveFill`](LiveFill.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:848 The most recent fills on one pool, newest first — the live trade tape. Maker/taker owner + side are back-joined from the order map where known. **Details** - `opts.limit`: Max rows (default 40; the store retains ~400 per pool). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns [`LiveFill`](LiveFill.md)[] *** ### getLiveFundingUpdates() > **getLiveFundingUpdates**(`pool`, `opts?`): [`LiveFundingUpdate`](LiveFundingUpdate.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:866 Funding settlements the live tail has seen for a perp pool, OLDEST FIRST. The tail's counterpart to [listFundingRateHistory](#listfundingratehistory): splice these onto a one-shot query to extend a funding chart past the snapshot block, instead of only seeing the latest value on the market row. Deduped on (block, logIndex), so a reorg replay overwrites rather than appending a phantom point. Carries less than an indexed row, deliberately: `intervalsAccrued` needs `n` from the parameter-epoch series and the covered span needs the settlement anchor, neither of which the tail has. Both arrive with the indexed row a moment later. **Details** - `opts.limit`: Max rows (default 500). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns [`LiveFundingUpdate`](LiveFundingUpdate.md)[] *** ### listLiveLiquidations() > **listLiveLiquidations**(`opts?`): [`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:891 Liquidation waterfall legs the tail has seen, newest first — the live counterpart to [getLiquidations](#getliquidations), and the SAME [LiquidationEvent](../type-aliases/LiquidationEvent.md) rows, so the two merge without translation. The live window is hydrated from the newest indexed rows, so it OVERLAPS the newest indexed page: merge by `id`, never by concatenation, or legs and their amounts are counted twice. Requires an active [watchPerpMarkets](#watchperpmarkets). Without one this returns empty, except after [stopLive](#stoplive), which keeps the store: the last rows stay readable but stale. Check [getPerpPlaneStatus](#getperpplanestatus) rather than treating a non-empty result as current. One liquidation is SEVERAL rows sharing a `txHash` — stages of one waterfall, not repetitions of one event. Read `kind` first, and read the field TSDoc on [LiquidationEvent](../type-aliases/LiquidationEvent.md) before aggregating anything: only `insuranceCovered` and `coverageDeclined` are flows, while `badDebt` and `deficit` are levels that double-count when summed. **Details** - `opts.pool`: Restrict to one pool. This DROPS the account-level legs, which carry no pool — the same partial view the indexed read's nullable `pool` column gives. Filter by `account` for the whole story. - `opts.account`: Restrict to the LIQUIDATED account. An account assigned into an ADL as the profitable counterparty has no row of its own; it appears in `counterparty` instead. - `opts.limit`: Max rows (default 50; the store retains ~1000 plane rows). #### Parameters ##### opts? [`ListLiveLiquidationsOptions`](ListLiveLiquidationsOptions.md) #### Returns [`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[] *** ### listLiveFundingPayments() > **listLiveFundingPayments**(`opts?`): [`FundingPayment`](../type-aliases/FundingPayment.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:909 Per-account funding settlements the tail has seen, newest first — the live counterpart to [getFundingPayments](#getfundingpayments), and the same [FundingPayment](../type-aliases/FundingPayment.md) rows. Requires an active [watchPerpMarkets](#watchperpmarkets). After [stopLive](#stoplive) the last rows stay readable but stale; check [getPerpPlaneStatus](#getperpplanestatus). Distinct from [getLiveFundingUpdates](#getlivefundingupdates), which is the per-pool RATE series: this is what each account actually paid or received. `amount` is signed, and **positive is what the account pays**. **Details** - `opts.pool`: Restrict to one pool. - `opts.account`: Restrict to one account. - `opts.limit`: Max rows (default 50; the store retains ~1000 plane rows). #### Parameters ##### opts? [`ListLiveFundingPaymentsOptions`](ListLiveFundingPaymentsOptions.md) #### Returns [`FundingPayment`](../type-aliases/FundingPayment.md)[] *** ### getLiveUserFills() > **getLiveUserFills**(`pool`, `user`, `opts?`): [`LiveFill`](LiveFill.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:919 Fills `user` participated in (as maker or taker), newest first. **Details** - `pool`: Restrict to one pool, or null for all pools. - `opts.limit`: Max rows (default 50). #### Parameters ##### pool `string` \| `null` ##### user `string` ##### opts? ###### limit? `number` #### Returns [`LiveFill`](LiveFill.md)[] *** ### getLiveUserOrders() > **getLiveUserOrders**(`pool`, `user`, `opts?`): [`LiveOrder`](LiveOrder.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:943 `user`'s orders on one pool, newest first — every lifecycle state (open, filled, cancelled, expired), so filter by `status === "Open"` for a working-orders view. Keeps every unexpired open order, recent terminal transitions, and terminal orders needed to attribute retained fills. An `Open` order past its expiry at the latest chain head is history, not liquidity: from that head it counts toward the terminal cap. Its status stays `Open`, because on chain it holds its escrow until a cancel or a sweep, and removal from the live store does not mean a refund. An active [watchUser](#watchuser) keeps all of its user's expired open orders until the watch is released. Older terminal history is available from [getOrders](#getorders); terminal history remains bounded even after a long watch. Accepted indexed `Closed` rows count toward the cap at hydration. A live `Closed` row waits for a later block from its pool so a delayed same-block `OrderRested` can promote it. An active [watchUser](#watchuser) also retains its seeded orders until that watch is released. Rows retained after a market watch ends remain account history, not book liquidity. **Details** - `opts.limit`: Max rows (default 100). #### Parameters ##### pool `string` ##### user `string` ##### opts? ###### limit? `number` #### Returns [`LiveOrder`](LiveOrder.md)[] *** ### getLiveBinaryOrderBook() > **getLiveBinaryOrderBook**(`pool`, `opts?`): [`BinaryOrderBook`](BinaryOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:957 The locally-materialized resting book of a **binary** pool, 4-sided (`yesBids`/`yesAsks` plus the NO sides derived as `1 − yesPrice`) — the event-derived book with a per-scope applied-event watermark. Heads alone do not advance `blockNumber`. Expiry uses the local wall clock. Use the pinned chain read for an exact as-of snapshot. Synchronous; safe to call every render (memoized per store version). **Details** - `opts.depth`: Price levels per side (default 10). #### Parameters ##### pool `string` ##### opts? ###### depth? `number` #### Returns [`BinaryOrderBook`](BinaryOrderBook.md) *** ### getLiveBinaryOrderBookByMarket() > **getLiveBinaryOrderBookByMarket**(`marketId`, `opts?`): [`BinaryOrderBook`](BinaryOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:974 The locally-materialized resting book of a **binary** market, resolved by its `marketId` rather than its pool address. Because a BinaryPool is RECYCLED across markets (one pool serves successive markets, never concurrently), a page keyed on a `marketId` must never render the pool's NEXT market's orders once its own market has ended. This read resolves the market's current pool and, if `marketId` is no longer the pool's current binding (stale/ended), returns an EMPTY book — so a stale page renders nothing rather than the successor market's liquidity. Prefer this over [getLiveBinaryOrderBook](#getlivebinaryorderbook) when you hold a `marketId` (not a live pool). **Details** - `opts.depth`: Price levels per side (default 10). #### Parameters ##### marketId `string` ##### opts? ###### depth? `number` #### Returns [`BinaryOrderBook`](BinaryOrderBook.md) *** ### getLiveSpotOrderBook() > **getLiveSpotOrderBook**(`pool`, `opts?`): [`SpotOrderBook`](SpotOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:984 The locally-materialized resting book of a **spot** pool (`bids`/`asks`, best price first) — the zero-round-trip mirror of [getSpotOrderBook](#getspotorderbook). **Details** - `opts.depth`: Price levels per side (default 12). #### Parameters ##### pool `string` ##### opts? ###### depth? `number` #### Returns [`SpotOrderBook`](SpotOrderBook.md) *** ### quoteBinaryOrder() > **quoteBinaryOrder**(`params`): [`BinaryOrderQuote`](BinaryOrderQuote.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:1006 Preview a MARKET order against the live binary book — "you'll pay ~$X, average Y, slippage Z". Pure over the live store (synchronous); key it by `pool` (a live pool) or `marketId` (recycle-safe — a stale market quotes against an empty book). Crossing side: BUY_YES/BUY_NO consume the asks, SELL_YES/SELL_NO the bids; NO prices are the YES book inverted (`oneCollateral − yesPrice`). `cost` is raw collateral paid (buy) / received (sell); `avgPrice` the volume-weighted fill price; `wouldRest` the unfilled remainder that would rest as a maker order. **Details** - `params.quantity`: Order size in raw outcome-token units. - `params.depth`: Book levels to walk per side (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinarySide`](../type-aliases/BinarySide.md) ###### quantity `bigint` ###### depth? `number` #### Returns [`BinaryOrderQuote`](BinaryOrderQuote.md) *** ### getBinaryBookParams() > **getBinaryBookParams**(`pool`): `Promise`\<[`BinaryBookParams`](BinaryBookParams.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1021 A BinaryPool's on-chain order-book grid (`tickSize`/`lotSize`/`minQuantity`) — the increments the pool validates every order against. One `eth_call`, cached per pool for the client's lifetime (the grid is admin-retunable but never changes per-order). [quoteBinaryStake](#quotebinarystake) and [quoteBinarySell](#quotebinarysell) read it through this cache. #### Parameters ##### pool `string` #### Returns `Promise`\<[`BinaryBookParams`](BinaryBookParams.md)\> *** ### getClosingPrice() > **getClosingPrice**(`pool`): `Promise`\<[`ClosingPriceState`](ClosingPriceState.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1040 A BinaryPool's captured closing price and close state — the snapshot a `CLOB_SNAPSHOT` venue's void pays out against (`[p, D−p]` at the closing YES price instead of the uniform half-refund). One `eth_call`. Resolves `null` when the pool predates the capture surface: the selector doubles as the capability probe, mirroring how the module resolves a market's void policy at creation. `state` is `"OPEN"` until [Trader.captureClose](Trader.md#captureclose) (or a normal resolution) has run. `null` is that capability answer and nothing else. A failed read throws: `RpcError` on a transport failure, `ContractRevertError` on a revert that names an error or a reason. #### Parameters ##### pool `string` #### Returns `Promise`\<[`ClosingPriceState`](ClosingPriceState.md) \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The pool declares `closingPrice()` and rejected the call. *** ### quoteBinaryStake() > **quoteBinaryStake**(`params`): `Promise`\<[`BinaryStakeQuote`](BinaryStakeQuote.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1066 Size a stake-denominated market BUY against the live binary book — "bet $50 on Up" → the shares, protective limit, and escrow the order will actually use. The inverse of [quoteBinaryOrder](#quotebinaryorder): that prices a quantity; this sizes a quantity from a collateral budget, walking the asks cheapest-first while the escrow at the worst level touched stays within the stake. The protective limit is padded with a slippage cushion (so the IOC still crosses a moving book), tick-aligned, and the quantity re-fit and lot-aligned so the escrow never exceeds the stake. Live store + one cached chain read ([getBinaryBookParams](#getbinarybookparams)); needs an active watch for the book. The result feeds straight into `trader.placeOrder({ pool, side, price: yesPrice, quantity, orderType: ORDER_TYPE.MARKET })`. Resolves `null` when nothing is fillable (empty book, or a stake too small to buy a single lot). **Details** - `params.side`: "BUY_YES" (Up) or "BUY_NO" (Down). - `params.stake`: Collateral budget in raw units — the max loss. - `params.depth`: Book levels to sweep (default 10). - `params.slippageBps`: Protective-limit cushion in bps (default 300 = 3%). - `params.slippageMinTicks`: Minimum cushion in ticks (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinaryBuySide`](../type-aliases/BinaryBuySide.md) ###### stake `bigint` ###### depth? `number` ###### slippageBps? `bigint` ###### slippageMinTicks? `bigint` #### Returns `Promise`\<[`BinaryStakeQuote`](BinaryStakeQuote.md) \| `null`\> *** ### quoteBinarySell() > **quoteBinarySell**(`params`): `Promise`\<[`BinarySellQuote`](BinarySellQuote.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1093 Build a market SELL that unwinds an outcome position by crossing the resting bids, with a tick-aligned slippage cushion below the best bid — the sell-side sibling of [quoteBinaryStake](#quotebinarystake) (see it for the family's mental model and tiering). Resolves `null` when there's no bid to cross or nothing to sell — disable the Sell control rather than sending a doomed order. The quote's `fillableQuantity`/`estProceeds` report what the crossable bids can actually absorb — warn on a partial unwind before submitting. **Details** - `params.side`: "SELL_YES" (Up position) or "SELL_NO" (Down position). - `params.quantity`: Outcome tokens to sell, raw units (lot-aligned down). - `params.depth`: Book levels to resolve (default 10). - `params.slippageBps`: Protective-floor cushion in bps (default 300 = 3%). - `params.slippageMinTicks`: Minimum cushion in ticks (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinarySellSide`](../type-aliases/BinarySellSide.md) ###### quantity `bigint` ###### depth? `number` ###### slippageBps? `bigint` ###### slippageMinTicks? `bigint` #### Returns `Promise`\<[`BinarySellQuote`](BinarySellQuote.md) \| `null`\> *** ### getMarketStats24h() > **getMarketStats24h**(`target`): `Promise`\<[`MarketStats24h`](MarketStats24h.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1109 A market's trailing-24h stats (volume, trades, price change, high/low/open), summed from 1h OHLCV candle buckets — cheaper than scanning fills. Key it by `pool` or `marketId`. Prices are raw quote units; volume is raw collateral. One indexer round-trip. #### Parameters ##### target ###### pool? `string` ###### marketId? `string` #### Returns `Promise`\<[`MarketStats24h`](MarketStats24h.md)\> *** ### getBinaryPositionPnL() > **getBinaryPositionPnL**(`account`, `marketId`): `Promise`\<[`BinaryPositionPnL`](BinaryPositionPnL.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1147 An account's position + cost basis + PnL in one binary market, RAW units. Reconstructs cost basis (weighted-average) from the account's order-book fills on the market folded with complete-set mints/merges, marks the CURRENT balances to the book-clamped last price (see `markYesPrice`; the settlement payout once resolved), and realizes sells against the running average. Best-effort over indexed fills; see [BinaryPositionPnL](BinaryPositionPnL.md) for the accounting assumptions. One fan-out of indexer reads plus one top-of-book `eth_call` (skipped, falling back to `lastPrice` alone, when no chain client is configured). Every money field is BLENDED across both outcomes; `outcomes.yes` / `outcomes.no` carry each book on its own. Both are needed for a wallet holding YES and NO, where the blend can read `0` while the legs are large and opposite. RAW units throughout — format with `market.quoteDecimals`. A market that has never traded has NO price to mark against, so every mark-derived field is `null`: `markValue` and `unrealizedPnl`, and `markPrice` / `markValue` / `unrealizedPnl` on each leg. Show those as unknown; do NOT treat them as zero. `balance`, `costBasis`, `avgCost` and `realizedPnl` never depend on a mark and stay exact. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the account is unusable. - Throws [InvalidInputError](../classes/InvalidInputError.md) - no binary market with that id, or a voided market carrying a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [IndexerError](../classes/IndexerError.md) - a fills, actions or balances read did not complete, OR an indexed fill or router action is malformed: an `id` that is not `` `${blockNumber}_${logIndex}` ``, or a `quantity`, `fillPrice` or mint/merge `amount` that is not an unsigned decimal number. This method fetches those rows itself, so a row it cannot read is corrupt indexed data, never a bad argument; the specific parse failure is on `cause`. - Throws [RpcError](../classes/RpcError.md) - the top-of-book `eth_call` did not complete (only with a chain client configured; a failed read is never marked on `lastPrice` as if it had succeeded). - Throws [ContractRevertError](../classes/ContractRevertError.md) - the pool rejected the top-of-book read. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` ##### marketId `string` #### Returns `Promise`\<[`BinaryPositionPnL`](BinaryPositionPnL.md)\> *** ### getOpenPositionsWithPnL() > **getOpenPositionsWithPnL**(`account`): `Promise`\<[`OpenPositionPnL`](../type-aliases/OpenPositionPnL.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1185 PnL for ALL of an account's open binary positions in one call — the batched, positions-list companion to [getBinaryPositionPnL](#getbinarypositionpnl). Each entry is a [OpenPositionPnL](../type-aliases/OpenPositionPnL.md): the position's market joined with its reliable avg-cost PnL (`costBasis` / `avgCost` / `markValue` / `unrealizedPnl` / `realizedPnl`, marked to the book-clamped price), computed identically to `getBinaryPositionPnL` per market. Prefer this over deriving PnL from book stats. Fetched in a bounded number of indexer round-trips (fills + router actions + top-of-book batched across every open market), not a per-position loop. Empty array when the account holds nothing. Still ONE entry per market, with both books on it. To render a row per outcome, read `row.outcomes.yes` / `row.outcomes.no` and keep the legs whose `balance > 0n` — the top-level money fields are blended across the two and belong to neither. A market that has never traded has NO price to mark against, so its `markValue` and `unrealizedPnl` are `null`, as are the same fields on each leg. Show those as unknown; do NOT treat them as zero. A positions list routinely mixes priced and unpriced markets, so handle `null` per row. **Errors** - Throws [IndexerError](../classes/IndexerError.md) when the positions, fills, router actions, or top-of-book request does not complete. - Throws [InvalidInputError](../classes/InvalidInputError.md) when a voided position carries a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [IndexerError](../classes/IndexerError.md) when an indexed fill or router action is malformed — an `id` that is not `` `${blockNumber}_${logIndex}` ``, or a `quantity`, `fillPrice` or mint/merge `amount` that is not an unsigned decimal number. This method fetches those rows itself, so a row it cannot read is corrupt indexed data, never a bad argument; the specific parse failure is on `cause`. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) when the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` #### Returns `Promise`\<[`OpenPositionPnL`](../type-aliases/OpenPositionPnL.md)[]\> *** ### getClaimable() > **getClaimable**(`account`): `Promise`\<[`ClaimablePosition`](ClaimablePosition.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1208 An account's redeemable positions across all SETTLED (resolved/voided) binary markets, each shaped to feed straight into `trader.redeemMany({ entries })`. Winners get `amount × (1 − settlementFee)`; a voided market pays each side against the payout vector it stored — a half per side under the `UNIFORM` void policy, `[p, D−p]` on a `CLOB_SNAPSHOT` void that captured a two-sided close, and never a settlement fee. Loser-side and still-trading positions are omitted. One portfolio read, then one settlement-fee read per unique winning market, with at most eight fee reads in flight at a time. **Errors** - Throws [IndexerError](../classes/IndexerError.md) when the portfolio or settlement-fee request does not complete. After a fee read fails, no new fee read starts. - Throws [InvalidInputError](../classes/InvalidInputError.md) when a voided position carries a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) when the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` #### Returns `Promise`\<[`ClaimablePosition`](ClaimablePosition.md)[]\> *** ### watchPrice() > **watchPrice**(`asset`): `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1235 Watch one asset's price (e.g. `"BTC"`, `"ETH"`): hydrate a snapshot (feed metadata + current price + recent ticks) to get roughly up to speed, then stream live over a Hasura WebSocket subscription. While active, every `getLivePrice`/`getLivePriceTicks` read for this asset is current to the last pushed tick at zero round-trip cost. Ref-counted like [watchMarket](#watchmarket): watching the same asset twice shares one subscription and one snapshot; each handle's `stop()` releases one reference, and a brief linger absorbs quick re-watches. Different assets share transport in this client: one price-feed socket per endpoint, and one batched snapshot request (up to 10 assets) for watches started in the same tick. Each asset keeps its own ticks, cursor and status. Requires `config.priceFeed`, INCLUDING its `quote`: a live watch rejects with a `NotConfiguredError` naming `config.priceFeed.quote` when the feed is unpinned, because the tick tape's cursor is only unique within one quote (see [PriceFeedConfig.quote](PriceFeedConfig.md#quote)). The one-shot `fetchPrice*` reads still work unpinned. Rejects (and releases the ref) in either case. #### Parameters ##### asset `string` #### Returns `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> *** ### watchPrices() > **watchPrices**(`assets`): `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1247 Watch a batch of assets at once (e.g. `["BTC", "ETH"]`). Returns a single handle whose `stop()` releases all of them; each asset is independently ref-counted, so this composes with per-asset [watchPrice](#watchprice) calls. The assets hydrate in batched snapshot requests and stream on one shared socket. If a snapshot request fails, this rejects and releases every asset. Requires a quote-pinned `config.priceFeed` for the same reason [watchPrice](#watchprice) does. #### Parameters ##### assets `string`[] #### Returns `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> *** ### getPriceStatus() > **getPriceStatus**(`asset`): [`PriceFeedStatus`](../type-aliases/PriceFeedStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:1255 Per-asset price-watch state: `"unwatched"`, `"hydrating"`, `"live"`, or `"error"`. Check it before rendering a live price — on `"error"` the reads still answer, but with values that have stopped updating. See [PriceFeedStatus](../type-aliases/PriceFeedStatus.md). #### Parameters ##### asset `string` #### Returns [`PriceFeedStatus`](../type-aliases/PriceFeedStatus.md) *** ### subscribePrices() > **subscribePrices**(`listener`): () => `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:1268 Fire `listener` after every batch of price-store changes (React hooks subscribe to exactly this). Re-read with `getLivePrice`/`getLivePriceTicks`. Each read keeps its reference until that asset's own data changes, so a change to another asset does not give a new value. Independent of [subscribeLive](#subscribelive) (prices are a separate store/service). **Details** - Returns: An unsubscribe function. #### Parameters ##### listener () => `void` #### Returns () => `void` *** ### getLivePrice() > **getLivePrice**(`asset`): [`LivePrice`](LivePrice.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:1274 The current price of a watched asset (from the live store), or null if unwatched / not yet hydrated. Synchronous, memoized. #### Parameters ##### asset `string` #### Returns [`LivePrice`](LivePrice.md) \| `null` *** ### getLivePrices() > **getLivePrices**(`assets`): ([`LivePrice`](LivePrice.md) \| `null`)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:1280 Current prices for a batch of watched assets, aligned to `assets` (each entry null if that asset is unwatched / not yet hydrated). Synchronous. #### Parameters ##### assets `string`[] #### Returns ([`LivePrice`](LivePrice.md) \| `null`)[] *** ### getLivePriceTicks() > **getLivePriceTicks**(`asset`, `opts?`): [`PricePoint`](PricePoint.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:1292 The recent tick tape of a watched asset, newest first. Synchronous. The returned array keeps its reference until this asset receives new ticks. An asset with no ticks returns one shared empty array. Readers share the array, so it is frozen: copy it before you sort or reverse it. **Details** - `opts.limit`: Max ticks (default 100; the store retains ~1000). #### Parameters ##### asset `string` ##### opts? ###### limit? `number` #### Returns [`PricePoint`](PricePoint.md)[] *** ### getLivePriceFeedInfo() > **getLivePriceFeedInfo**(`asset`): [`PriceFeedInfo`](PriceFeedInfo.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:1298 Feed metadata + current price for a watched asset (from the live store), or null if unwatched. For a one-shot read without a watch use [fetchPriceFeedInfo](#fetchpricefeedinfo). #### Parameters ##### asset `string` #### Returns [`PriceFeedInfo`](PriceFeedInfo.md) \| `null` *** ### fetchPriceFeedInfo() > **fetchPriceFeedInfo**(`asset`): `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1301 One-shot feed metadata + current price (one HTTP round-trip; no watch needed). #### Parameters ##### asset `string` #### Returns `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)\> *** ### fetchPrice() > **fetchPrice**(`asset`): `Promise`\<[`LivePrice`](LivePrice.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1307 One-shot current price (one HTTP round-trip), or null if the feed has no observations yet. #### Parameters ##### asset `string` #### Returns `Promise`\<[`LivePrice`](LivePrice.md) \| `null`\> *** ### fetchPrices() > **fetchPrices**(`assets?`): `Promise`\<[`LivePrice`](LivePrice.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1314 One-shot current prices for a batch of assets, or ALL tracked assets when `assets` is omitted — the multi-asset "price wall" in one request. Assets with no observations yet are omitted from the result. #### Parameters ##### assets? `string`[] #### Returns `Promise`\<[`LivePrice`](LivePrice.md)[]\> *** ### listPriceFeeds() > **listPriceFeeds**(): `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1320 One-shot feed catalog — metadata + current price for every tracked asset (discovery). One HTTP round-trip; no watch needed. #### Returns `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)[]\> *** ### fetchPriceHistory() > **fetchPriceHistory**(`asset`, `opts?`): `Promise`\<[`PricePoint`](PricePoint.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1326 Historic ticks for one asset, newest first — window with `from`/`to` (unix seconds, chain time), page with `limit` (default 500). #### Parameters ##### asset `string` ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`PricePoint`](PricePoint.md)[]\> *** ### fetchPriceCandles() > **fetchPriceCandles**(`asset`, `resolution`, `opts?`): `Promise`\<[`PriceCandle`](PriceCandle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1332 OHLC candles for one asset + resolution (`"M1"`/`"H1"`/`"D1"`), oldest first (chart-ready). Window with `from`/`to` (unix seconds); page with `limit`. #### Parameters ##### asset `string` ##### resolution [`PriceCandleResolution`](../type-aliases/PriceCandleResolution.md) ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`PriceCandle`](PriceCandle.md)[]\> *** ### listMarkets() > **listMarkets**(`opts?`): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1352 List markets, newest first, as the discriminated `Market = SpotMarket | BinaryMarket` union. **Details** - `opts.marketType`: Filter to `"SPOT"` or `"BINARY"`; omit for both. - `opts.limit`: Max rows (default 50). - `opts.offset`: Row offset for pagination (default 0). #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> *** ### listRegistryMarkets() > **listRegistryMarkets**(): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1360 Registry sweep for the unified tier: every non-binary market plus the binary series that are still live (not finalized), paged until exhausted. Finalized series accumulate without bound; resolve those by pool via the raw-tier lookups instead. #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> *** ### listRegistryMarketsChecked() > **listRegistryMarketsChecked**(): `Promise`\<[`RegistrySweep`](RegistrySweep.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1375 [listRegistryMarkets](#listregistrymarkets) with the rows the SDK could not parse COUNTED, as `{ markets, dropped }`. A malformed row is dropped silently rather than failing the page, so a caller that treats the sweep as exhaustive — a monitor publishing coverage over it, say — cannot tell a short answer from a complete one. `dropped > 0` says the registry holds markets this read did not return. #### Returns `Promise`\<[`RegistrySweep`](RegistrySweep.md)\> #### Throws [IndexerError](../classes/IndexerError.md) The indexed read did not complete. The complete union is [SomniaMarketsClientListRegistryMarketsCheckedError](../type-aliases/SomniaMarketsClientListRegistryMarketsCheckedError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. *** ### countMarkets() > **countMarkets**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1383 Server-side COUNT of markets (optionally one type) for pagination totals. Needs the privileged `_aggregate` role (server-only), like [countBinaryMarkets](#countbinarymarkets). Without it the count is a row scan capped at 10,000 and a larger total reads as exactly `10000` — [countMarketsBounded](#countmarketsbounded) reports whether it did. #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) #### Returns `Promise`\<`number`\> *** ### countMarketsBounded() > **countMarketsBounded**(`opts?`): `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1389 [countMarkets](#countmarkets) with the truncation reported: `truncated: true` means the public-role scan hit its cap and `count` is a lower bound. #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) #### Returns `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> *** ### getMarket() > **getMarket**(`id`): `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1395 One market by primary key (bytes32 marketId for binary, pool address for spot), or null if the indexer doesn't have it. #### Parameters ##### id `string` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> *** ### listBinaryMarkets() > **listBinaryMarkets**(`opts?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1398 [listMarkets](#listmarkets) pre-narrowed to binary markets. #### Parameters ##### opts? [`BinaryMarketFilter`](../type-aliases/BinaryMarketFilter.md) & `object` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> *** ### listLiveBinaryMarkets() > **listLiveBinaryMarkets**(`filter?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1406 Currently-live binary markets (`expiry > now`), soonest-to-expire first. Call with no argument for all live markets, or pass a [LiveBinaryMarketsFilter](../type-aliases/LiveBinaryMarketsFilter.md) to narrow by `operatorId` / `venueId` / `asset` / `intervalSec` / `status` (e.g. `{ venueId: "0x4d41494e" }`). #### Parameters ##### filter? [`LiveBinaryMarketsFilter`](../type-aliases/LiveBinaryMarketsFilter.md) #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> *** ### listBinaryVenueIds() > **listBinaryVenueIds**(): `Promise`\<`object`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1413 Distinct (operatorId, venueId) pairs across binary markets — the cheap server-side source for operator/venue filter options (so a UI never fetches every market just to enumerate origins). Excludes null attribution. #### Returns `Promise`\<`object`[]\> *** ### listBinaryAssets() > **listBinaryAssets**(): `Promise`\<`string`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1426 Distinct asset symbols across binary markets — the cheap server-side source for an asset filter's options. #### Returns `Promise`\<`string`[]\> *** ### countBinaryMarkets() > **countBinaryMarkets**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1435 Server-side COUNT of binary markets matching a filter, optionally split by lifecycle phase (`"live"` / `"past"`; omit `phase` to count both) — a total without fetching rows (Hasura `_aggregate`). On the public role this is a row scan capped at 10,000, which `Market` passes in production during 2026 — [countBinaryMarketsBounded](#countbinarymarketsbounded) says which. #### Parameters ##### opts? [`BinaryMarketCountOptions`](../type-aliases/BinaryMarketCountOptions.md) #### Returns `Promise`\<`number`\> *** ### countBinaryMarketsBounded() > **countBinaryMarketsBounded**(`opts?`): `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1442 [countBinaryMarkets](#countbinarymarkets) with the truncation reported: `truncated: true` means the public-role scan hit its cap and `count` is a lower bound, so a `rows.length < count` pagination gate would stop early. #### Parameters ##### opts? [`BinaryMarketCountOptions`](../type-aliases/BinaryMarketCountOptions.md) #### Returns `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> *** ### listPastBinaryMarkets() > **listPastBinaryMarkets**(`opts?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1448 Past binary markets (`expiry ≤ now`), most-recently-expired first, paginated with `limit` + `offset`. #### Parameters ##### opts? [`PastBinaryMarketsOptions`](../type-aliases/PastBinaryMarketsOptions.md) #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> *** ### getBinaryMarket() > **getBinaryMarket**(`id`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1454 One binary market by bytes32 marketId, or null (also null if the id resolves to a spot market). #### Parameters ##### id `string` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> *** ### getBinaryMarketByAddress() > **getBinaryMarketByAddress**(`marketAddress`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1460 One binary market by its on-chain BinaryMarket ADDRESS (the Market PK is the bytes32 marketId, so an address-keyed caller must resolve through this). Newest first for recycled/rebound addresses; null if not yet indexed. #### Parameters ##### marketAddress `string` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> *** ### getMarketFees() > **getMarketFees**(`id`): `Promise`\<[`MarketFees`](../type-aliases/MarketFees.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1465 Fee config frozen into the market's pool at creation (origin venue attribution + rates in bpsTimes1k), or null without attribution. #### Parameters ##### id `string` #### Returns `Promise`\<[`MarketFees`](../type-aliases/MarketFees.md) \| `null`\> *** ### listSpotMarkets() > **listSpotMarkets**(`opts?`): `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1471 [listMarkets](#listmarkets) pre-narrowed to spot markets. Pass a [SpotMarketFilter](../type-aliases/SpotMarketFilter.md) (+ `limit`) to narrow by base/quote symbol. #### Parameters ##### opts? [`SpotMarketFilter`](../type-aliases/SpotMarketFilter.md) & `object` #### Returns `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md)[]\> *** ### getSpotMarket() > **getSpotMarket**(`id`): `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1474 One spot market by pool address, or null (also null if not spot). #### Parameters ##### id `string` #### Returns `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md) \| `null`\> *** ### getMarketStatusHistory() > **getMarketStatusHistory**(`marketId`): `Promise`\<[`MarketStatusUpdate`](../type-aliases/MarketStatusUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1480 A market's status-transition history (Trading→Locked→Settling→Resolved…), oldest-first — the resolution/lock timeline for a market page. #### Parameters ##### marketId `string` #### Returns `Promise`\<[`MarketStatusUpdate`](../type-aliases/MarketStatusUpdate.md)[]\> *** ### listPerpMarkets() > **listPerpMarkets**(`opts?`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1486 [listMarkets](#listmarkets) pre-narrowed to perp markets. Pass a [PerpMarketFilter](../type-aliases/PerpMarketFilter.md) (+ `limit`) to narrow by base/quote symbol. #### Parameters ##### opts? [`PerpMarketFilter`](../type-aliases/PerpMarketFilter.md) & `object` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)[]\> *** ### getPerpMarket() > **getPerpMarket**(`id`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1492 One perp market by pool address, or null (also null if the id resolves to another market kind). #### Parameters ##### id `string` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md) \| `null`\> *** ### getCandles() > **getCandles**(`poolAddress`, `intervalSeconds`, `opts?`): `Promise`\<[`Candle`](../type-aliases/Candle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1504 OHLCV candles for one pool + interval, oldest first (chart-ready). **Details** - `intervalSeconds`: Bucket size — one of the indexer's rollup intervals. - `opts.limit`: Max buckets (default 500). - `opts.from`: Only buckets at/after this unix-seconds timestamp. - `opts.to`: Only buckets at/before this unix-seconds timestamp. #### Parameters ##### poolAddress `string` ##### intervalSeconds `number` ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`Candle`](../type-aliases/Candle.md)[]\> *** ### getMarketActivity() > **getMarketActivity**(`market`, `opts?`): `Promise`\<[`MarketActivity`](../type-aliases/MarketActivity.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1537 One market's activity, newest first — trades interleaved with complete-set mints and merges, redemptions, oracle resolution and lifecycle transitions. This is the market's transaction history. Every row names the transaction it landed in, so a caller can follow any row to the chain. Narrow a row on its `kind` ([MarketActivity](../type-aliases/MarketActivity.md)). Use this for a market page's activity panel. It is the one-shot INDEXER read, so it carries the history the panel needs on first paint, and it does not update itself. For trades arriving with no round-trip, read [getLiveFills](#getlivefills) as well and merge on the trade rows' `id`, which is `TRADE:` followed by the fill id — FIELD BY FIELD, preferring whichever source has a value. Neither is a superset of the other: the tail leaves `taker`/`takerSide` undefined on the fills it hydrates, and the indexer's `takerIsBid` is null until its taker bridge lands. Preferring one source wholesale drops what the other knew. A spot or perp market returns `TRADE` rows only — the other kinds come from binary-only entities, so asking for them there is not an error, just empty. One round-trip. Page backwards with `until`, not an offset (see [MarketActivityOptions](../type-aliases/MarketActivityOptions.md)). #### Parameters ##### market `string` The market's bytes32 marketId (case-insensitive). On spot and perp this is the pool address. ##### opts? [`MarketActivityOptions`](../type-aliases/MarketActivityOptions.md) #### Returns `Promise`\<[`MarketActivity`](../type-aliases/MarketActivity.md)[]\> *** ### getTransactionActivity() > **getTransactionActivity**(`txHash`, `opts?`): `Promise`\<[`TransactionActivity`](../type-aliases/TransactionActivity.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1562 Everything the protocol did in ONE transaction — trades, complete-set mints and merges, redemptions, oracle resolution, lifecycle transitions, the orders it placed and the fees it paid ([TransactionActivity](../type-aliases/TransactionActivity.md)). The read behind a transaction detail view, and the counterpart to [getTradeContext](#gettradecontext): that starts from a trade and shows its transaction as context, this starts from a transaction and shows every trade in it. `events` is the same union [getMarketActivity](#getmarketactivity) returns, with the same row ids, so one component renders both — but in LOG order, earliest first, because a transaction reads forwards. A hash the indexer has nothing for returns empty collections and a null `blockNumber` rather than throwing: an unknown hash and a transaction that touched no protocol contract are both absence. Indexer first. The client asks the chain for the transaction's block only when the indexer has no event for the hash and `opts.anchor` is unset. That lookup is best-effort: if the chain cannot place the hash, the read probes the indexer's order table instead. #### Parameters ##### txHash `string` Transaction hash (case-insensitive). ##### opts? [`TransactionActivityOptions`](../type-aliases/TransactionActivityOptions.md) #### Returns `Promise`\<[`TransactionActivity`](../type-aliases/TransactionActivity.md)\> *** ### getBlockActivity() > **getBlockActivity**(`blockNumber`, `opts?`): `Promise`\<[`BlockActivity`](../type-aliases/BlockActivity.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1585 What the protocol traded in one block, grouped by market — the level above [getTransactionActivity](#gettransactionactivity). The block's own timestamp anchors every read, because no block column in the indexer schema is indexed. Resolving it is a chain read, and this client owns the transport, so it happens here: a caller never needs a second client. Reach for [getViemClient](#getviemclient) only for chain work the SDK does not model. A block with no markets activity — the common case, since only ~42% of blocks carry any — returns an empty `markets` array rather than throwing. Order rows carry no `status`: `Order` is mutable, so its status is as-of-now and would show a state from the block's future. Use `touch`. `truncated` reports a stream that came back full; page with `opts.offset`. #### Parameters ##### blockNumber `bigint` Block to read. ##### opts? [`BlockActivityOptions`](../type-aliases/BlockActivityOptions.md) Rows per stream and the offset to page from. #### Returns `Promise`\<[`BlockActivity`](../type-aliases/BlockActivity.md)\> *** ### getLatestActiveBlock() > **getLatestActiveBlock**(): `Promise`\<\{ `blockNumber`: `bigint`; `timestamp`: `bigint`; \} \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1595 The newest block the indexer has markets activity for, or null when it has none at all. The entry point for a block view: the chain head runs ahead of the indexer, and most blocks carry no markets activity, so the head is usually a blank page. Pair with [getBlockActivity](#getblockactivity). #### Returns `Promise`\<\{ `blockNumber`: `bigint`; `timestamp`: `bigint`; \} \| `null`\> *** ### getAdjacentActiveBlocks() > **getAdjacentActiveBlocks**(`blockNumber`, `opts?`): `Promise`\<\{ `prev`: `bigint` \| `null`; `next`: `bigint` \| `null`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1610 The closest blocks with markets activity below and above one block. The read behind a block view's prev/next: most blocks carry no markets activity, so stepping by n±1 lands on a blank page more often than not. Either side is null when no active block was found within the bounded scan. Anchored the same way as [getBlockActivity](#getblockactivity), and for the same reason resolves that anchor itself. #### Parameters ##### blockNumber `bigint` The block being viewed; excluded from both answers. ##### opts? [`BlockActivityOptions`](../type-aliases/BlockActivityOptions.md) Rows per stream per direction. #### Returns `Promise`\<\{ `prev`: `bigint` \| `null`; `next`: `bigint` \| `null`; \}\> *** ### getFills() > **getFills**(`pool`, `opts?`): `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1624 Recent fills on one pool, newest first. Bound the tape with `since`/`until` in seconds, or with `sinceBlock` to resume from a processed block ([FillsOptions](../type-aliases/FillsOptions.md)). #### Parameters ##### pool `string` ##### opts? [`FillsOptions`](../type-aliases/FillsOptions.md) #### Returns `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> #### Throws The pool or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getTradeContext() > **getTradeContext**(`id`): `Promise`\<[`TradeContext`](../type-aliases/TradeContext.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1644 ONE fill IN CONTEXT, by id — the trade, its market, both sides' orders resolved, the fees it paid, and the other fills its transaction produced ([TradeContext](../type-aliases/TradeContext.md)). [getFill](#getfill) is the cheaper sibling: one query, the fill and its market, no surrounding context. Prefer it when a caller only renders the trade. The read behind a trade detail view. `getFills` and [getMarketActivity](#getmarketactivity) are the list reads that produce the id; this is the drill-down from one of their rows. Returns `null` when no fill has this id — a stale or mistyped link, not a failure. Two round-trips: the transaction's siblings and fees are anchored on the fill's own timestamp, so the fill has to resolve first. #### Parameters ##### id `string` Fill id, `${blockNumber}_${logIndex}`. #### Returns `Promise`\<[`TradeContext`](../type-aliases/TradeContext.md) \| `null`\> *** ### getUserFills() > **getUserFills**(`account`, `opts?`): `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1662 Fills a user participated in (maker OR taker), newest first — the one-shot indexer counterpart to [getLiveUserFills](#getliveuserfills). Optionally scope to one market and/or pool, a `since`/`until` window, and a `sinceBlock` bound ([FillsScope](../type-aliases/FillsScope.md)). Use `sinceBlock` to resume from a processed block: blocks can share a timestamp, so a seconds bound repeats or skips them. On binary, scope by `market` rather than `pool` for one market's tape: a pool is recycled by successive markets, so `pool` also returns the fills of that pool's earlier lives. Both predicates run at the indexer, so `limit` applies to the rows you asked for. #### Parameters ##### account `string` ##### opts? [`FillsScope`](../type-aliases/FillsScope.md) #### Returns `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> #### Throws The account, a scope value or a block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getUserFillsPage() > **getUserFillsPage**(`account`, `options?`): `Promise`\<[`UserFillsPage`](../type-aliases/UserFillsPage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1714 Read one historical fill page through this owner's indexer. Prefer this to offset paging when new fills can arrive between reads. Numeric timestamp, block number and log index define a total descending order. Self-trades appear once. Existing fill fields and account-side interpretation are unchanged. The default limit is 50; valid limits are integers from 1 to 1000. A sentinel row establishes continuation without returning it. Null continuation means no further row was observed, not that indexing or historical coverage is complete. Cursors bind account, chain, configured endpoint, normalized filters, sort, and the serving Fill dataset generation. A replacement behind the same URL rejects continuation with [FillHistoryRestartRequiredError](../classes/FillHistoryRestartRequiredError.md). A legacy cursor without a generation also requires a restart. Discard all accumulated pages and restart without a cursor. The generation comes from the serving indexer database, so it survives Hasura replica restarts. A fresh replay with changed hashed producer inputs rotates it; an identical replay does not. A code-only resume preserves the old identity and therefore cannot roll out a handler change that affects stored fills. An endpoint without this producer contract fails closed. Newer inserts belong to a fresh first-page read; a page is not a complete-history coverage guarantee. Cancellation through the configured owner's signal preserves the caller's abort reason rather than converting it to an IndexerError. #### Parameters ##### account `string` Wallet participating as maker or taker. ##### options? [`GetUserFillsPageOptions`](../type-aliases/GetUserFillsPageOptions.md) Market/pool, market kind (`marketType`), inclusive time and source-block filters, bounded limit and cursor. Omit `marketType` to read every kind. The cursor is scoped to the normalized filters, including `sinceBlock` and `marketType`. #### Returns `Promise`\<[`UserFillsPage`](../type-aliases/UserFillsPage.md)\> The dataset generation, existing fill rows and the next cursor, or null when this read has no next row. #### Throws [InvalidInputError](../classes/InvalidInputError.md) For invalid input or malformed/foreign cursors. #### Throws [IndexerError](../classes/IndexerError.md) When the read fails or returned position scalars are invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Throws [IndexerUnavailableError](../classes/IndexerUnavailableError.md) When local backpressure or the circuit breaker refuses the read. #### Throws [FillHistoryUnavailableError](../classes/FillHistoryUnavailableError.md) When the serving indexer has not initialized its dataset generation. #### Throws [FillHistoryRestartRequiredError](../classes/FillHistoryRestartRequiredError.md) When the cursor's generation differs from the serving dataset, or a legacy cursor lacks a generation. #### Example ```ts const first = await exchange.client.getUserFillsPage(account, { limit: 100 }); try { if (first.nextCursor !== null) { const next = await exchange.client.getUserFillsPage(account, { limit: 100, cursor: first.nextCursor }); console.log(next.fills); } } catch (error) { if (error instanceof FillHistoryRestartRequiredError) { const restarted = await exchange.client.getUserFillsPage(account, { limit: 100 }); console.log(restarted.fills); } else throw error; } ``` *** ### getFillsPage() > **getFillsPage**(`options`): `Promise`\<[`FillsPage`](../type-aliases/FillsPage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1760 Every fill of one MARKET KIND in an inclusive block range, across every pool of that kind, oldest first — the read behind a published trade feed. Takes no pool, unlike [getFills](#getfills): a feed indexes the whole venue and must not enumerate its pools. The block range is what bounds the read. Use blocks, not `since`/`until` seconds, whenever successive reads must tile the chain exactly. Several Somnia blocks can share a timestamp, so a seconds window drops or repeats the fills in them at every seam. Both bounds here are inclusive and `(blockNumber, logIndex)` is a total order, so `[a, b]` then `[b + 1, c]` covers every fill once. Pages default to 500 rows. The cursor names the last row returned and binds the chain, endpoint, kind and both bounds, so a cursor from one range is rejected by another. A full page always returns a cursor, so a range that ends on a page boundary costs one empty final page. Drain a range until `nextCursor` is null; a null cursor means this read saw no further row IN THE RANGE, not that indexing is complete — [getLatestFillBlock](#getlatestfillblock) is what reports how far the fill data reaches. Amounts stay raw strings, as everywhere on [FillRow](../type-aliases/FillRow.md). Do not route a published feed through the human-unit market reads. #### Parameters ##### options [`FillsPageOptions`](../type-aliases/FillsPageOptions.md) Kind, inclusive block range, page size and continuation. #### Returns `Promise`\<[`FillsPage`](../type-aliases/FillsPage.md)\> #### Throws A bound, the kind, the limit or the cursor is unusable. #### Throws The read did not complete, or returned unusable block positions. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Example ```ts let cursor: string | undefined; do { const page = await exchange.client.getFillsPage({ marketType: "SPOT", sinceBlock: 441_000_000n, toBlock: 441_010_000n, cursor, }); console.log(page.fills.length); cursor = page.nextCursor ?? undefined; } while (cursor !== undefined); ``` *** ### getLatestFillBlock() > **getLatestFillBlock**(`marketType`): `Promise`\<[`LatestFillBlock`](../type-aliases/LatestFillBlock.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1779 The newest block carrying an indexed fill of one market kind, with that block's timestamp — the head marker to poll before asking for a range. Taken from the fill data rather than from the indexer's processed-block watermark, so the marker can never name a block [getFillsPage](#getfillspage) cannot yet serve. Returns `null` when no fill of that kind is indexed — a fresh deployment or one still replaying, not a failure. [getLatestActiveBlock](#getlatestactiveblock) is the wider question: the newest block with ANY markets activity, fills included. #### Parameters ##### marketType [`MarketType`](../type-aliases/MarketType.md) Market kind to report on. #### Returns `Promise`\<[`LatestFillBlock`](../type-aliases/LatestFillBlock.md) \| `null`\> #### Throws The market kind is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getFill() > **getFill**(`id`): `Promise`\<[`FillDetail`](../type-aliases/FillDetail.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1786 One fill by its id (`${blockNumber}_${logIndex}`) with both parties' order linkage and the market it executed on — the single lookup behind a fill detail view. Null when not indexed (a just-executed fill can lag a beat). #### Parameters ##### id `string` #### Returns `Promise`\<[`FillDetail`](../type-aliases/FillDetail.md) \| `null`\> *** ### getOrderFills() > **getOrderFills**(`pool`, `orderId`, `opts?`): `Promise`\<[`OrderFillRow`](../type-aliases/OrderFillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1798 Every fill one order participated in — either side, newest first. `(pool, orderId)` names exactly one order forever (ids never reuse). This bounded whole-history lookup accepts only `limit`; use `getFills` or `getUserFills` with `sinceBlock` to resume a pool or account tape. #### Parameters ##### pool `string` ##### orderId `string` \| `bigint` ##### opts? ###### limit? `number` #### Returns `Promise`\<[`OrderFillRow`](../type-aliases/OrderFillRow.md)[]\> #### Throws The pool identifier or order id is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getOrder() > **getOrder**(`pool`, `orderId`): `Promise`\<[`OrderDetail`](../type-aliases/OrderDetail.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1805 One order by `(pool, orderId)` — the indexer's view, including owner and full lifecycle attribution (status, cancelReason, amend chain). Null when not indexed; for chain-head truth use [getOrderOnchain](#getorderonchain). #### Parameters ##### pool `string` ##### orderId `string` \| `bigint` #### Returns `Promise`\<[`OrderDetail`](../type-aliases/OrderDetail.md) \| `null`\> *** ### listMarketsByPool() > **listMarketsByPool**(`pool`, `opts?`): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1812 Every market a pool has hosted, newest first — one row for SPOT/PERP, the full recycle history for a BINARY pool. First row = the current market. The one-row shortcut is [getMarketByPool](#getmarketbypool). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> *** ### getOpenOrders() > **getOpenOrders**(`owner`, `opts?`): `Promise`\<[`OpenOrder`](../type-aliases/OpenOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1827 `owner`'s currently-OPEN orders, newest first. Pass [OrdersOptions](../type-aliases/OrdersOptions.md) (minus `status` — always "Open" here) to scope by `pool`/`pools`/`market`/ `markets`/`side`/`userData`/`sinceBlock` and page. Each row carries the placement's own `userData` tag, so a caller can match a row to the order it sent. NOTE: this lags the chain — for a trading loop prefer [getLiveUserOrders](#getliveuserorders) (or track the `orderId`s your own `placeOrder` calls return). For non-open history use [getOrders](#getorders). #### Parameters ##### owner `string` ##### opts? `Omit`\<[`OrdersOptions`](../type-aliases/OrdersOptions.md), `"status"`\> #### Returns `Promise`\<[`OpenOrder`](../type-aliases/OpenOrder.md)[]\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getOrders() > **getOrders**(`owner`, `opts?`): `Promise`\<[`OrderRow`](../type-aliases/OrderRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1842 `owner`'s orders across ALL statuses (Open/Filled/Cancelled/Expired/Closed), newest first — the order-history counterpart to [getOpenOrders](#getopenorders). Each row carries its lifecycle `status`, fill progress and the placement's own `userData` tag. Filter by `status`/`side`/`pool`/`pools`/`market`/ `markets`/`userData`/`sinceBlock` and page via [OrdersOptions](../type-aliases/OrdersOptions.md). `sinceBlock` bounds the PLACEMENT block, so it does not report later changes to older orders. #### Parameters ##### owner `string` ##### opts? [`OrdersOptions`](../type-aliases/OrdersOptions.md) #### Returns `Promise`\<[`OrderRow`](../type-aliases/OrderRow.md)[]\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### listSweepableOrders() > **listSweepableOrders**(`opts?`): `Promise`\<[`SweepableOrder`](../type-aliases/SweepableOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1863 Orders past expiry that are STILL RESTING, across the whole book — the work-list for a permissionless expired-order sweep. Not scoped to an account. Works on every market kind; scope with `pool` and/or `marketType`. Each row carries exactly what the sweep verbs need: `orderId` for `trader.cancelExpiredOrders`, and `isBid` + `price` for `trader.sweepExpiredAtLevel`. **This is not `status: "Expired"`.** That status is written when the chain emits `OrderExpired` — i.e. once an order has ALREADY been removed. The sweepable set is the opposite: `status = "Open"` and `expireTimestampNs < now`, orders the book still holds because nobody has cleaned them up. They are NOT matched against — the matcher skips an expired maker — but each costs a warm SLOAD per traversal and holds a priority-index slot. Longest-overdue first. GTC excludes itself because this SDK writes it as now + 50 years, not via any contract sentinel. #### Parameters ##### opts? ###### pool? `string` ###### marketType? [`MarketType`](../type-aliases/MarketType.md) ###### owner? `string` ###### asOfSec? `number` \| `bigint` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`SweepableOrder`](../type-aliases/SweepableOrder.md)[]\> *** ### getOutcomeBalances() > **getOutcomeBalances**(`account`, `marketAddress`): `Promise`\<[`OutcomeBalances`](../type-aliases/OutcomeBalances.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1877 Indexed YES/NO outcome-token balances of `account` in one binary market ("0" when unseen). Display-grade: to gate a write, read the tokens' on-chain balances via [getErc20Balance](#geterc20balance) instead. #### Parameters ##### account `string` ##### marketAddress `string` #### Returns `Promise`\<[`OutcomeBalances`](../type-aliases/OutcomeBalances.md)\> *** ### getPortfolio() > **getPortfolio**(`account`, `opts?`): `Promise`\<[`Portfolio`](../type-aliases/Portfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1885 A wallet's whole binary portfolio in one round-trip once the registry is warm (a cold call resolves the market-type scope first): non-zero outcome positions, open orders, and recent trades (each with market context). Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page orders/trades or window trades. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`Portfolio`](../type-aliases/Portfolio.md)\> *** ### getSpotPortfolio() > **getSpotPortfolio**(`account`, `opts?`): `Promise`\<[`SpotPortfolio`](../type-aliases/SpotPortfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1892 A wallet's spot activity: open orders, pending stop orders, and recent trades. Token holdings are NOT here — spot balances are plain ERC-20 / native balances; read them on-chain. Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`SpotPortfolio`](../type-aliases/SpotPortfolio.md)\> *** ### getSpotStopOrders() > **getSpotStopOrders**(`account`, `opts?`): `Promise`\<[`SpotStopOrder`](../type-aliases/SpotStopOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1901 A wallet's spot stop orders — PENDING by default (list + cancel via `trader.cancelStopOrder`). Pass `status` to see triggered/failed/cancelled history, `pool` to scope to one market, `limit` to page. Rows don't include a LIMIT stop's limit price. See [SpotStopOrder](../type-aliases/SpotStopOrder.md). #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### status? [`StopOrderStatus`](../type-aliases/StopOrderStatus.md) ###### limit? `number` #### Returns `Promise`\<[`SpotStopOrder`](../type-aliases/SpotStopOrder.md)[]\> *** ### getPerpPortfolio() > **getPerpPortfolio**(`account`, `opts?`): `Promise`\<[`PerpPortfolio`](../type-aliases/PerpPortfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1912 A wallet's perp activity as indexed: open perp orders + recent perp trades. Positions/collateral live in the MarginBank — read them on-chain with [getPerpPosition](#getperpposition) / [getMarginAccount](#getmarginaccount). Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`PerpPortfolio`](../type-aliases/PerpPortfolio.md)\> *** ### listPerpStopOrders() > **listPerpStopOrders**(`opts?`): `Promise`\<[`PerpStopOrder`](../type-aliases/PerpStopOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1935 Perp take-profit / stop-loss orders, newest first — the read that makes TP/SL usable at all. The PerpStopOrderRegistry keeps pending orders in private storage behind no enumeration getter, so there is no chain read that answers "what stops do I have". Creation and triggering both work; without this a trader cannot see, price or cancel what they created, which is why the feature shipped gated. Every scope comes from the same call: `{ account }` for a trader's working stops (default status `PENDING`), `{ pool }` with no account for a market's whole pending book, and `status` for history. `account` is optional deliberately — a market-wide view of what will fire is a legitimate monitoring read. Read `dropReason` before calling a `TRIGGER_FAILED` order a failure: a reduce-only drop means the stop was overtaken by events, which is ordinary; only `PlacementFailed` is a rejection. Rows don't include `limitPrice`. Fetch it for live stops with [getPerpStopOrders](#getperpstoporders). #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### status? [`StopOrderStatus`](../type-aliases/StopOrderStatus.md)[] ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpStopOrder`](../type-aliases/PerpStopOrder.md)[]\> *** ### getPerpStopOrder() > **getPerpStopOrder**(`ref`): `Promise`\<[`PerpStopOrderOnChain`](../type-aliases/PerpStopOrderOnChain.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1960 One pending stop read straight from its registry — the chain tier [listPerpStopOrders](#listperpstoporders) does not have. The only way to read a LIMIT stop's `limitPrice`, its linked `siblingOrderId` and its `intent`: no event carries them, so [PerpStopOrder](../type-aliases/PerpStopOrder.md) cannot. Cannot enumerate — list ids there, then enrich each here. `null` when the id is not live. **Do not infer liveness from the terms**: a dead id keeps plausible values until its slot is recycled, so `live` is the only truth. #### Parameters ##### ref [`PerpStopOrderRef`](../type-aliases/PerpStopOrderRef.md) #### Returns `Promise`\<[`PerpStopOrderOnChain`](../type-aliases/PerpStopOrderOnChain.md) \| `null`\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) The order id is not a valid uint128 integer. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The owner has no chain WebSocket endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) The registry read failed before it returned a contract result. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The registry rejected the read. *** ### getPerpStopOrders() > **getPerpStopOrders**(`refs`): `Promise`\ Defined in: packages/sdk/src/somniaMarketsClient.ts:1994 Enrich known perp stop ids with one ordered chain batch. Use [listPerpStopOrders](#listperpstoporders) to discover ids. Each result belongs to the input ref at the same index. `absent` means the registry confirmed that the stop is not live. `failed` means only that member was unreadable. The configured chain uses Multicall3 when available. Other chains use a bounded point-read fallback. Both paths pin every result to one chain head. A contract revert or RPC failure for a member is returned as `failed`. #### Parameters ##### refs readonly [`PerpStopOrderRef`](../type-aliases/PerpStopOrderRef.md)[] #### Returns `Promise`\ #### Throws [InvalidInputError](../classes/InvalidInputError.md) An order id is not a canonical unsigned uint128 decimal. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The owner has no chain WebSocket endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) The head could not be pinned or the batch result was malformed. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The Multicall3 aggregate rejected the batch. #### Example ```ts const indexed = await client.listPerpStopOrders({ account: owner }); const refs = indexed.map((stop) => { if (!isAddress(stop.registry)) throw new Error(`Invalid registry ${stop.registry}`); return { registry: stop.registry, orderId: stop.orderIdRaw }; }); const reads = await client.getPerpStopOrders(refs); for (const [index, read] of reads.entries()) { const stop = indexed[index]; if (stop === undefined) throw new Error(`Missing indexed stop ${index}`); if (read.status === "present") console.log(stop.id, read.order); if (read.status === "absent") console.log(stop.id, "no longer live"); if (read.status === "failed") console.error(stop.id, read.error); } ``` *** ### getPerpStopOrderSomiPayment() > **getPerpStopOrderSomiPayment**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2000 SOMI a perp stop registry charges per pending order, in wei. Send exactly this with a create or it reverts; refunded on cancel, consumed on a fire. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getUnclaimedPerpStopSomi() > **getUnclaimedPerpStopSomi**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2008 SOMI a perp stop registry owes `account`, in wei, claimable with `trader.claimPerpStopSomi`. Credited when a cancel's direct refund fails (a contract owner with no payable receiver) OR when the registry is wound down, which credits every owner — **including EOAs**. #### Parameters ##### ref ###### registry `` `0x${string}` `` ###### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### listPerpOrderHistory() > **listPerpOrderHistory**(`account`, `opts?`): `Promise`\<[`PerpOrderHistoryRow`](../type-aliases/PerpOrderHistoryRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2026 An account's FINISHED perp orders, most-recently-ended first — the history tab behind [getPerpPortfolio](#getperpportfolio)'s open-orders list. `getPerpPortfolio` hard-filters `status = "Open"`, so before this there was no way to see a filled, cancelled or expired perp order at all. Excludes working orders by default (`status != "Open"`); pass `status` to narrow to particular outcomes. Ordered by when each order ENDED, not when it was placed — a long-resting order that just filled belongs at the top of a history view, not buried at its placement date. Note `Closed` is terminal, not transitional: an IOC that partially filled without resting stays `Closed` forever, so treating it as "still working" would show a finished order as live. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### status? [`TerminalOrderStatus`](../type-aliases/TerminalOrderStatus.md)[] ###### orderBy? `"placed"` \| `"ended"` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpOrderHistoryRow`](../type-aliases/PerpOrderHistoryRow.md)[]\> *** ### getSyncStatus() > **getSyncStatus**(`chainId`): `Promise`\<[`IndexerSyncStatus`](../type-aliases/IndexerSyncStatus.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2046 Read the indexer's own metadata without chain RPC. A missing row for another chain returns null. For the client's own chain, a missing row fails the first read's binding check with NotConfiguredError; a row that goes missing after the check passed still returns null. Use the concrete owner's getIndexerFreshness for an independent comparison. #### Parameters ##### chainId `number` #### Returns `Promise`\<[`IndexerSyncStatus`](../type-aliases/IndexerSyncStatus.md) \| `null`\> #### Throws A query variable is invalid. #### Throws The metadata request failed. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### waitForIndexedBlock() > **waitForIndexedBlock**(`chainId`, `block`, `opts?`): `Promise`\<[`IndexedBlockWait`](../type-aliases/IndexedBlockWait.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2083 Wait until the indexer has processed `block` on `chainId`, then resolve with what the wait observed. The step between a confirmed write and an indexer read of that write: every indexer-backed read answers from the processed height, so a read issued before the block is indexed correctly reports the row as absent. Resolving means a read issued afterwards sees what that block wrote. Polls `chain_metadata` every `pollMs` (default 500) until `timeoutMs` (default 30,000). Pass `signal` to abort; the caller's abort reason is rethrown unchanged. For the client's own chain, the wait reads the RPC head once when it would resolve. An indexer more than 10,000 blocks past that head follows an earlier genesis of the same chain id, so the wait rejects instead of resolving. A client with no chain endpoint skips this read. **Example** (Read your own write) ```ts const receipt = await exchange.client.getViemClient().waitForTransactionReceipt({ hash }); await exchange.client.waitForIndexedBlock(exchange.client.config.chain.id, receipt.blockNumber); const orders = await exchange.client.getOpenOrders(owner, { userData: 7n }); ``` #### Parameters ##### chainId `number` ##### block `number` \| `bigint` ##### opts? [`WaitForIndexedBlockOptions`](../type-aliases/WaitForIndexedBlockOptions.md) #### Returns `Promise`\<[`IndexedBlockWait`](../type-aliases/IndexedBlockWait.md)\> #### Throws The block height, `timeoutMs` or `pollMs` is not a usable whole number. #### Throws The deadline passed with the indexer still behind the block. #### Throws A metadata read failed, or the indexer serves no row for this chain. #### Throws The client has no indexer, its indexer does not serve its own chain, or its indexer is more than 10,000 blocks past the RPC head. #### Throws The RPC head read failed. The complete union is [SomniaMarketsClientWaitForIndexedBlockError](../type-aliases/SomniaMarketsClientWaitForIndexedBlockError.md). *** ### getMarketByPool() > **getMarketByPool**(`pool`): `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2093 Resolve a market by its pool address (one query; no live watch), or null. Binary markets are keyed by bytes32 marketId, so this is the by-pool lookup. #### Parameters ##### pool `string` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> *** ### countOrders() > **countOrders**(`owner`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2109 Server-side COUNT of `owner`'s orders matching an [OrdersOptions](../type-aliases/OrdersOptions.md) filter — the total for an order-history page. Privileged `_aggregate` role (server-only), with a bounded row-count fallback on the public role. WITHOUT THAT HEADER THE RESULT IS A LOWER BOUND, returned as if exact: the fallback scan stops at 10,000 rows and reports 10,000, and `Order` is far past that in production. There is no bounded variant of this method yet — [countMarketsBounded](#countmarketsbounded) is the shape to copy. #### Parameters ##### owner `string` ##### opts? [`OrdersOptions`](../type-aliases/OrdersOptions.md) #### Returns `Promise`\<`number`\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The count did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### countUserFills() > **countUserFills**(`account`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2127 Server-side COUNT of the fills `account` participated in (maker OR taker), optionally scoped by market and/or pool + a `since`/`until` window or inclusive `sinceBlock` source-block bound ([FillsScope](../type-aliases/FillsScope.md)) — a history-page total. WITHOUT THE PRIVILEGED `_aggregate` HEADER THE RESULT IS A LOWER BOUND, returned as if exact: the fallback scan stops at 10,000 rows and reports 10,000, and `Fill` is the deepest counted table in production. There is no bounded variant of this method yet — [countMarketsBounded](#countmarketsbounded) is the shape to copy. #### Parameters ##### account `string` ##### opts? [`FillsScope`](../type-aliases/FillsScope.md) #### Returns `Promise`\<`number`\> #### Throws The account, a scope value or a block bound is unusable. #### Throws The count did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. *** ### getRouterActions() > **getRouterActions**(`account`, `opts?`): `Promise`\<[`RouterActionRecord`](../type-aliases/RouterActionRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2138 An account's RouterMinter action history (redeem / mint / merge), newest first — optionally scoped to one `market` (or several via `markets`) and/or `kind`, paginated ([RouterActionsOptions](../type-aliases/RouterActionsOptions.md)). Mint and merge move a position's cost basis, so scope this the same way you scope the fills you fold it against: an account-wide capped read drops the OLDEST rows, which are the ones that set the basis. #### Parameters ##### account `string` ##### opts? [`RouterActionsOptions`](../type-aliases/RouterActionsOptions.md) #### Returns `Promise`\<[`RouterActionRecord`](../type-aliases/RouterActionRecord.md)[]\> *** ### getMarketResolution() > **getMarketResolution**(`marketId`): `Promise`\<\{ `events`: [`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]; `reference`: [`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md) \| `null`; `closingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `openingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `oracleAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2148 Everything the indexer knows about how a market resolves: lifecycle events, the oracle reference link, and the posted oracle answers. `closingAnswer` is the market's own resolution answer (the CLOSING price for a reference-mode up/down market); `openingAnswer` is the reference-question answer (the OPENING price it resolves against, null for fixed-strike markets). Any piece may be absent. `oracleAnswer` is a deprecated alias of `closingAnswer`. #### Parameters ##### marketId `string` #### Returns `Promise`\<\{ `events`: [`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]; `reference`: [`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md) \| `null`; `closingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `openingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `oracleAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; \}\> *** ### listMarketResolutionEvents() > **listMarketResolutionEvents**(`opts?`): `Promise`\<[`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2188 Market-resolution lifecycle events across markets, newest first — filter by `market`, `kinds` and/or `sinceTimestamp`, paginate ([ListMarketResolutionEventsOptions](ListMarketResolutionEventsOptions.md)). The cross-market counterpart to [getMarketResolution](#getmarketresolution), which reports one market in full. One row per delivery ATTEMPT and append-only, so a monitor watching for `"Skipped"` / `"Failed"` wants `sinceTimestamp` — without a lower bound this returns every failure the deployment has ever recorded, and a count over it only ever grows. #### Parameters ##### opts? [`ListMarketResolutionEventsOptions`](ListMarketResolutionEventsOptions.md) #### Returns `Promise`\<[`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]\> #### Throws The indexer request failed or returned an error. An empty page is `[]`. *** ### listMarketReferenceLinks() > **listMarketReferenceLinks**(`opts?`): `Promise`\<[`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2206 Reference-question links, oldest first — filter by `pending` and/or `market`, paginate ([ListMarketReferenceLinksOptions](ListMarketReferenceLinksOptions.md)). `pending: true` is the set worth sweeping: markets holding their own oracle answer while the question they resolve AGAINST is not final. They stay unresolved with no on-chain retry until `pokeOracle` lands the reference or `voidExpired` backstops them. Only reference-resolved markets have a link, so this never lists fixed-strike markets. Oldest first, because the rows are live state rather than a trail: the first row is the market that has been stuck longest. #### Parameters ##### opts? [`ListMarketReferenceLinksOptions`](ListMarketReferenceLinksOptions.md) #### Returns `Promise`\<[`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md)[]\> #### Throws The indexer request failed or returned an error. An empty page is `[]`. *** ### getOpeningPrices() > **getOpeningPrices**(`marketIds`): `Promise`\<`Record`\<`string`, `string` \| `null`\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2214 Batch opening (reference-question) prices for many markets in one pair of round-trips — for list views. Map of lowercased marketId → raw oracle `numericValue` (null when no reference answer yet). Format with the market's oracle price scale. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, `string` \| `null`\>\> *** ### getResolutionPrices() > **getResolutionPrices**(`marketIds`): `Promise`\<`Record`\<`string`, `string` \| `null`\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2222 Batch RESOLUTION (settlement) prices for many markets in one pair of round-trips — the settlement counterpart to [getOpeningPrices](#getopeningprices). Map of lowercased marketId → raw oracle `numericValue`, null where unresolved. Joins each market's OWN question, so fixed-strike markets are covered too. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, `string` \| `null`\>\> *** ### getOnchainResolutionPrice() > **getOnchainResolutionPrice**(`marketId`): `Promise`\<[`OnchainResolutionPrice`](OnchainResolutionPrice.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2232 A market's RESOLUTION price read straight from CHAIN — the fallback for a settled market whose answer the indexer never saw, because its oracle adapter is not the one whose events the indexer ingests. Resolves the market's bound adapter through the module, so it works for any adapter. Null while the question is not final. Carries its own `decimals` (adapters differ — do NOT assume a scale). #### Parameters ##### marketId `string` #### Returns `Promise`\<[`OnchainResolutionPrice`](OnchainResolutionPrice.md) \| `null`\> *** ### getBookTops() > **getBookTops**(`marketIds`): `Promise`\<`Record`\<`string`, [`BookTop`](../type-aliases/BookTop.md)\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2242 Batch top of book (best resting bid/ask + mid) for many markets in one round-trip — for list views that want a book-derived price without an N+1 per-pool fan-out. EVERY market kind: spot and perp pool addresses and binary market ids are all valid, and may be mixed in one call. Map of lowercased marketId → [BookTop](../type-aliases/BookTop.md), whose prices are raw and in each market's own terms; empty-book markets are absent. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, [`BookTop`](../type-aliases/BookTop.md)\>\> *** ### listProtocolFees() > **listProtocolFees**(`opts?`): `Promise`\<[`ProtocolFeeRecord`](../type-aliases/ProtocolFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2249 Realized protocol-fee records, newest first — filter by `recipient` / `market` / `pool` / `payer`, paginate. The per-fill stream behind [getMarketFees](#getmarketfees)'s running total. #### Parameters ##### opts? ###### recipient? `string` ###### market? `string` ###### pool? `string` ###### payer? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`ProtocolFeeRecord`](../type-aliases/ProtocolFeeRecord.md)[]\> *** ### listBuilderFees() > **listBuilderFees**(`opts?`): `Promise`\<[`BuilderFeeRecord`](../type-aliases/BuilderFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2262 Realized builder/routing-fee records, newest first — filter by `builder` / `market` / `payer`, paginate. #### Parameters ##### opts? ###### builder? `string` ###### market? `string` ###### payer? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`BuilderFeeRecord`](../type-aliases/BuilderFeeRecord.md)[]\> *** ### listSettlementFees() > **listSettlementFees**(`opts?`): `Promise`\<[`SettlementFeeRecord`](../type-aliases/SettlementFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2274 Realized settlement-fee records, newest first — filter by `market` / `recipient`, paginate. #### Parameters ##### opts? ###### market? `string` ###### recipient? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`SettlementFeeRecord`](../type-aliases/SettlementFeeRecord.md)[]\> *** ### listBuilderApprovals() > **listBuilderApprovals**(`opts?`): `Promise`\<[`BuilderApproval`](../type-aliases/BuilderApproval.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2286 Builder-approval directory, newest-updated first — filter by `user` and/or `builder`, paginate. The directory complement to the on-chain point read [getBuilderApproval](#getbuilderapproval). #### Parameters ##### opts? ###### user? `string` ###### builder? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`BuilderApproval`](../type-aliases/BuilderApproval.md)[]\> *** ### getVaultPayoutFallbacks() > **getVaultPayoutFallbacks**(`owner`, `opts?`): `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2298 An owner's vault-credit fallback history (append-only), newest first — optionally scoped to one `token`, paginated. The live claimable balance is the chain read [getVaultBalance](#getvaultbalance). #### Parameters ##### owner `string` ##### opts? ###### token? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> *** ### listVaultPayoutFallbacks() > **listVaultPayoutFallbacks**(`opts?`): `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2335 Vault-credit fallbacks across EVERY owner, newest first by default — filter by `owner`, `token` and/or `pool`, window with `from`/`to`, paginate. [getVaultPayoutFallbacks](#getvaultpayoutfallbacks) is the per-owner view of the same log; this is the operator's: every payout that could not reach a wallet and was credited to a pool vault instead, without knowing the owners in advance. Each row names the `pool` whose vault holds the credit; the live claimable amount is the chain read [getVaultBalance](#getvaultbalance) with that pool as the `vault`. The sort is a TOTAL order — `timestamp`, then the `id` primary key — so the sequence is stable between requests. The table is live and append-only, so offset paging is approximate; to follow the log forward pass `order: "asc"` with `from` at the last row's timestamp and skip the ids already seen there. Returns one [VaultPayoutFallback](../type-aliases/VaultPayoutFallback.md) per indexed credit, an empty array when none matches. An INDEXED read: as current as the indexer's processed block, never ahead of it (see the read tiers reference). Usage is shown in the binary markets guide under "Vault credits". #### Parameters ##### opts? [`ListVaultPayoutFallbacksOptions`](ListVaultPayoutFallbacksOptions.md) #### Returns `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, `opts.offset` is not a non-negative safe integer, or `opts.from` / `opts.to` are not whole, non-negative unix seconds. Checked before the request: `NaN` and `Infinity` are ordinary `number` values that would serialize to `null` and lift the page bound, or reach the indexer as an invalid numeric and come back as its failure. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. #### Throws [IndexerUnavailableError](../classes/IndexerUnavailableError.md) Local backpressure or the circuit breaker refused the read before it was sent. The union is [SomniaMarketsClientListVaultPayoutFallbacksError](../type-aliases/SomniaMarketsClientListVaultPayoutFallbacksError.md). *** ### getFundingPayments() > **getFundingPayments**(`account`, `opts?`): `Promise`\<[`FundingPayment`](../type-aliases/FundingPayment.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2341 An account's funding-payment history, newest first — optionally scoped to one `pool`, paginated. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`FundingPayment`](../type-aliases/FundingPayment.md)[]\> *** ### getMarginEvents() > **getMarginEvents**(`account`, `opts?`): `Promise`\<[`MarginEvent`](../type-aliases/MarginEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2350 An account's margin-account movement history (deposits/withdraws/locks), newest first — paginated. #### Parameters ##### account `string` ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`MarginEvent`](../type-aliases/MarginEvent.md)[]\> *** ### listLiquidations() > **listLiquidations**(`opts?`): `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2369 Liquidation events, newest first — filter by `account`, `pool` and/or `kind`, paginate. `kind` matters more than it looks: the rows are stages of one mechanism, so one cascade produces many rows and an unfiltered `limit` is spent mostly on stages the caller did not ask about. See [LiquidationEvent.kind](../type-aliases/LiquidationEvent.md#kind). The sort is a TOTAL order — `timestamp`, then `blockNumber`, then the `id` primary key — so the sequence is stable between requests. That fixes tie ordering only: these are live rows, and an event indexed ahead of your offset still repeats a row while a reorg that removes one still skips a row. Offset paging here is approximate, not snapshot-consistent. #### Parameters ##### opts? [`ListLiquidationsOptions`](ListLiquidationsOptions.md) #### Returns `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> #### Throws [IndexerError](../classes/IndexerError.md) The indexed read did not complete. The complete union is [SomniaMarketsClientListLiquidationsError](../type-aliases/SomniaMarketsClientListLiquidationsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. *** ### ~~getLiquidations()~~ > **getLiquidations**(`opts?`): `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2381 Liquidation events, newest first. #### Parameters ##### opts? [`ListLiquidationsOptions`](ListLiquidationsOptions.md) #### Returns `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> #### Deprecated Renamed to [listLiquidations](#listliquidations), per SDK-TYPE-006. Forwards verbatim. #### Throws [IndexerError](../classes/IndexerError.md) As [SomniaMarketsClient.listLiquidations](#listliquidations). The union is [SomniaMarketsClientGetLiquidationsError](../type-aliases/SomniaMarketsClientGetLiquidationsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. *** ### listFundingRateHistory() > **listFundingRateHistory**(`pool`, `opts?`): `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2395 A perp pool's funding-rate history, newest first by default. `from`/`to` are unix SECONDS and are what a chart should use — settlement is hourly (24 rows per pool per day, and 288 across the retired 300s cadence still in indexed history), so paging by offset to reach a date is both slow and fragile. Normalize each row with its OWN `fundingWindowSec`. Pass `order: "asc"` to make `from` a forward CURSOR. Under the default `"desc"` a page always comes off the newest end, so `from = last.timestamp + 1` re-reads the tail instead of advancing. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` ###### order? `"asc"` \| `"desc"` #### Returns `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> *** ### listFundingRateCandles() > **listFundingRateCandles**(`pool`, `intervalSeconds`, `opts?`): `Promise`\<[`FundingRateCandle`](../type-aliases/FundingRateCandle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2417 A perp pool's funding-rate ROLLUPS at one resolution (3600 | 14400 | 86400), newest first — for ranges the raw series is too dense for. Buckets can be ABSENT where no settlement's span reached them: zero-fill those grid slots as `{ avgFundingRate8h: 0, coverage: 0 }` and never carry the previous rate forward. Past buckets also get REVISED when a catch-up settlement reaches backwards. Pages NEWEST-first against a default `limit` of 500, so a month of hourly buckets (720) silently returns its newest 500 — treat `rows.length === limit` as truncated. #### Parameters ##### pool `string` ##### intervalSeconds `number` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` #### Returns `Promise`\<[`FundingRateCandle`](../type-aliases/FundingRateCandle.md)[]\> *** ### listPerpFees() > **listPerpFees**(`opts?`): `Promise`\<[`PerpFeeRecord`](../type-aliases/PerpFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2431 Realized perp fees / rebates / builder credits, newest first — the perps fee rail off MarginBank, distinct from the binary/spot `listBuilderFees`. `insurancePortion` is a component OF `amount`, not an addition to it: a fee total is `SUM(amount)`, an insurance inflow is `SUM(insurancePortion)`, and adding the two double-counts. `amount` is unsigned — `isRebate` carries the direction. #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### builder? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpFeeRecord`](../type-aliases/PerpFeeRecord.md)[]\> *** ### listPerpOrderRejections() > **listPerpOrderRejections**(`opts?`): `Promise`\<[`PerpOrderRejection`](../type-aliases/PerpOrderRejection.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2452 Orders refused inside a BATCH placement, newest first. `placeOrders` / `placeOrdersFor` only — the singular entry points revert, and a revert discards its logs, so a singular placement leaves no row here. Nothing here has an `Order` row either: a rejected request never rested and never filled. Map a row back to what was sent with `requestIndex`. `reason` is the decoded name and is null for a member this SDK version does not know; `reasonRaw` always carries the index. The `reason` FILTER takes the index, so a caller can select a reason this SDK cannot yet name. #### Parameters ##### opts? ###### owner? `string` ###### pool? `string` ###### reason? `number` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpOrderRejection`](../type-aliases/PerpOrderRejection.md)[]\> *** ### ~~getFundingRateHistory()~~ > **getFundingRateHistory**(`pool`, `opts?`): `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2465 Lists funding-rate history through the compatibility alias. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` #### Returns `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> #### Deprecated Use [listFundingRateHistory](#listfundingratehistory) instead. This alias forwards verbatim. *** ### getOpenInterestHistory() > **getOpenInterestHistory**(`pool`, `opts?`): `Promise`\<[`OpenInterestSnapshot`](../type-aliases/OpenInterestSnapshot.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2471 A perp pool's open-interest history, newest first — paginated. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OpenInterestSnapshot`](../type-aliases/OpenInterestSnapshot.md)[]\> *** ### listPerpPositions() > **listPerpPositions**(`account`, `opts?`): `Promise`\<[`IndexedPerpPosition`](../type-aliases/IndexedPerpPosition.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2486 An account's perp positions across every pool, newest-updated first — ONE round-trip, replacing a chain read per market. A snapshot as of each row's `updatedAtBlock`, NOT marked to market: unrealized PnL, liquidation price and margin health all still need a chain read. `entryFundingIndex` is not selected — the deployed Hasura schema does not carry it yet — so anything funding-sensitive belongs on [getPerpPosition](#getperpposition). Size-0 (fully closed) rows are excluded unless `includeFlat` — upserted rows are never deleted, so closed positions linger forever. An empty array means the indexer has no rows, not that the account is flat. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### includeFlat? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedPerpPosition`](../type-aliases/IndexedPerpPosition.md)[]\> *** ### getBinaryOrderBook() > **getBinaryOrderBook**(`pool`, `opts?`): `Promise`\<[`BinaryOrderBook`](BinaryOrderBook.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2533 Read a binary pool's resting book from the contract (`getBookLevels`, both sides in one pipelined round-trip), 4-sided like the live variant. Use when the tail isn't running or as a checksum. A live watch can serve render and quote paths without another chain read. A binary pool can be recycled onto another market. This pool-keyed read has no `marketId` guard, so an address saved for an older market can return the next market's book. If you hold a `marketId` and have an active watch, use [getLiveBinaryOrderBookByMarket](#getlivebinaryorderbookbymarket) to avoid showing that book. For a chain-only snapshot, read the selected market with `getMarketOnchain`, compare its pool's binding with the selected id, and pass that binding's `blockNumber` plus the market's collateral `decimals` to this read. Return no book when the binding is absent or differs: ```ts const market = await client.getMarketOnchain(marketId); const binding = await client.getPoolMarketBinding(market.pool); const book = binding?.marketId.toLowerCase() === marketId.toLowerCase() ? await client.getBinaryOrderBook(market.pool, { blockNumber: binding.blockNumber, decimals: market.decimals, }) : null; ``` **Details** - `opts.depth`: Price levels per side (default 10). - `opts.decimals`: Price scale decimals for the NO-side inversion (default 6). - `opts.blockNumber`: Pin both sides to this block. Omitted: select one head. Successful empty books retain the pin. This is an exact chain snapshot. #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetBinaryOrderBookOptions`](GetBinaryOrderBookOptions.md) #### Returns `Promise`\<[`BinaryOrderBook`](BinaryOrderBook.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If depth or the block pin is invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If selecting the head or reading either side fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects either read. *** ### getSpotOrderBook() > **getSpotOrderBook**(`pool`, `opts?`): `Promise`\<[`SpotOrderBook`](SpotOrderBook.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2550 Read a spot OR perp pool's resting book from the contract (both ride the shared OrderBook base). Live variant: [getLiveSpotOrderBook](#getlivespotorderbook). **Details** - `opts.depth`: Levels per side (default 12). - `opts.blockNumber`: Pin both sides to this block. Omitted: select one head. Successful empty books retain the pin. #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetSpotOrderBookOptions`](GetSpotOrderBookOptions.md) #### Returns `Promise`\<[`SpotOrderBook`](SpotOrderBook.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If depth or the block pin is invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If selecting the head or reading either side fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects either read. *** ### getOrderOnchain() > **getOrderOnchain**(`pool`, `orderId`, `opts?`): `Promise`\<[`OnchainOrder`](OnchainOrder.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2595 One order's state at chain head, by `(pool, orderId)` — ids are unique per pool. Reads your own writes: answers from the block a placement landed in, while the indexed [getOrders](#getorders) may still lag. `null` when the pool has no ACTIVE order for that id (never assigned, filled, cancelled, expired-and-swept, or replaced by an amend, which re-places under a NEW id; a `reduceOrder` keeps its id and stays active) - the indexer is the surface that keeps history. `opts.blockNumber` reads at the end of that block instead - historical order state, for a consumer decoding `OrderFilled` from chain logs. That event carries the fill's own `fillPrice` (which IS the maker's resting price), `quantityFilled` and `makerRemainingQuantity`, so take those from the event; what it does not carry is the maker's SIDE, and the fill removes the maker order in the same transaction, so the last height holding it is `fill.blockNumber - 1n`. That read is exact for the maker's identity - `isBid`, `owner`, `userData`, `expireTimestampNs`, none of which any fill log carries - and BLOCK-LEVEL for BOTH quantities: an earlier transaction in the fill's own block may have filled this maker, or reduced it (`reduceOrder` decrements `fullQuantity` and `quantityRemaining` together, under the same id), and no block read sees between transactions. Two edges answer plausibly rather than failing: a PARTIAL fill leaves the order in place with a smaller `quantityRemaining`, so reading at the fill's own block succeeds with different numbers; and an order placed and filled inside ONE block is absent at `blockNumber - 1n`, so that read is `null` and the placement has to come from the same block's `OrderPlaced`. A pinned read far behind head needs archive state. ```ts // A fill's side, for a maker this process never saw rest. const maker = await client.getOrderOnchain(pool, makerOrderId, { blockNumber: fillBlock - 1n }); // `null` is an UNRESOLVED side, not a sell: an order placed and filled inside one // block has no state one block earlier, and its side is in that block's OrderPlaced. const takerBought = maker === null ? null : !maker.isBid; ``` #### Parameters ##### pool `` `0x${string}` `` ##### orderId `bigint` ##### opts? [`GetOrderOnchainOptions`](GetOrderOnchainOptions.md) #### Returns `Promise`\<[`OnchainOrder`](OnchainOrder.md) \| `null`\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If the read fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects the read for any reason other than the id having no active order. *** ### getBookTopsOnchain() > **getBookTopsOnchain**(`markets`, `opts?`): `Promise`\<[`BookTopsOnchain`](BookTopsOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2617 Top of book for many markets, read from POOL STATE at ONE pinned block — the chain-sourced sibling of [getBookTops](#getbooktops). Prefer this wherever a quote must not lag: a board, a selector, a mark for open positions. [getBookTops](#getbooktops) stays the cheaper read (one indexed round-trip, no chain dependency) for an unbounded list that tolerates indexer lag. Pass the market rows a view already holds — each supplies its own `poolAddress`, so nothing is resolved twice. `tops` is keyed by lowercased market id and omits empty-book markets, exactly as [getBookTops](#getbooktops) does, so the two are comparable key for key. Cost is two reads per market where the chain declares no Multicall3; keep the set to what a view shows. #### Parameters ##### markets `object`[] ##### opts? [`GetBookTopsOnchainOptions`](GetBookTopsOnchainOptions.md) #### Returns `Promise`\<[`BookTopsOnchain`](BookTopsOnchain.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If the read fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If a pool rejects the read. *** ### getOwnOpenOrdersOnchain() > **getOwnOpenOrdersOnchain**(`pool`, `owner`, `opts?`): `Promise`\<`bigint`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2629 An owner's open order ids at chain head, or at a pinned block. Any address may be asked about — the pool's view reads `msg.sender` and this impersonates via the `eth_call` sender, so no signer is involved. Indexed counterpart, with human units and history: [getOpenOrders](#getopenorders). For the full rows rather than the ids, use [getOpenOrdersOnchain](#getopenordersonchain). #### Parameters ##### pool `` `0x${string}` `` ##### owner `` `0x${string}` `` ##### opts? [`GetOwnOpenOrdersOnchainOptions`](GetOwnOpenOrdersOnchainOptions.md) #### Returns `Promise`\<`bigint`[]\> *** ### getOpenOrdersOnchain() > **getOpenOrdersOnchain**(`pools`, `owner`, `opts?`): `Promise`\<[`OpenOrdersOnchain`](OpenOrdersOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2647 One owner's full open-order rows across several pools, read from chain at ONE pinned block. This is the outage-resilient companion to [getOpenOrders](#getopenorders), which is an indexer read: it throws `IndexerError` while the indexer is unreachable and lists stale rows while it lags. Point a bot that must know what it has resting at this read instead of wrapping the indexed one in a catch. The caller supplies the pool list; there is no discovery, because resolving pools by symbol is itself an indexer read. Rows carry `isBid` and no YES/NO side, no market or symbol, and no history — see the function's own TSDoc for why the binary side is not derivable. A pool with no resting orders contributes no rows. A failed read throws. #### Parameters ##### pools `` `0x${string}` ``[] ##### owner `` `0x${string}` `` ##### opts? [`GetOpenOrdersOnchainOptions`](GetOpenOrdersOnchainOptions.md) #### Returns `Promise`\<[`OpenOrdersOnchain`](OpenOrdersOnchain.md)\> *** ### getAllOpenOrdersOnchain() > **getAllOpenOrdersOnchain**(`pool`, `opts`): `Promise`\<\{ `orders`: [`OnchainOrder`](OnchainOrder.md)[]; `hasMore`: `boolean`; `nextCursor`: `bigint`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2670 One page of every open order on one side, at chain head — the per-order detail the aggregated book reads ([getBinaryOrderBook](#getbinaryorderbook), [getSpotOrderBook](#getspotorderbook)) collapse into levels. The pool accepts this view only from the zero address, so a configured signer is never forwarded. Loop while `hasMore`, feeding `nextCursor` back as `cursor`; pin a block if pages must be mutually consistent. **Details** - `opts.maxCount`: Orders per page (default 100). - `opts.blockNumber`: Read at that exact block instead of the current head, so every page of a multi-page snapshot sees one book. Sample a head with `getBlockNumber` and pass it to every page. #### Parameters ##### pool `` `0x${string}` `` ##### opts ###### isBid `boolean` ###### maxCount? `number` ###### cursor? `bigint` ###### blockNumber? `bigint` #### Returns `Promise`\<\{ `orders`: [`OnchainOrder`](OnchainOrder.md)[]; `hasMore`: `boolean`; `nextCursor`: `bigint`; \}\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. *** ### getPerpState() > **getPerpState**(`pool`): `Promise`\<[`PerpStateOnchain`](PerpStateOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2680 A perp pool's live mark/index price, funding rate + cumulative index, and open interest in one pipelined fan-out — fresher than the indexed row (which only updates on funding settlements). #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpStateOnchain`](PerpStateOnchain.md)\> *** ### getPerpFeedStatus() > **getPerpFeedStatus**(`pool`): `Promise`\<[`PerpFeedStatus`](PerpFeedStatus.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2705 Is a perp pool's mark feed live, and how much open interest is riding on it — the pair a mark-feed monitor needs, with the index timestamp as best-effort corroboration. Prefer this to [getPerpState](#getperpstate) for MONITORING a feed. That read is all-or-nothing and one of its legs is a bare `IOracle.getPrice()`, so a dead oracle rejects the whole call and the mark verdict is lost in exactly the case it is wanted. Here the verdict cannot be taken down by the oracle: `tryGetMarkPrice` reports staleness rather than reverting, open interest consults no oracle, and only the index timestamp — which arrives `undefined` instead — is allowed to fail. Read [getPerpState](#getperpstate) instead when you want the full pricing and funding picture and a dead oracle is a legitimate reason to fail the call. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpFeedStatus`](PerpFeedStatus.md)\> #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) No WebSocket endpoint is configured — `wsRpcUrl`, or a chain whose `rpcUrls` carry one. Raised when this read resolves its client, before any request goes out. #### Throws [RpcError](../classes/RpcError.md) A chain read did not complete — the block pin included. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The pool rejected the mark or open-interest read. A reverting INDEX read is NOT among these: it is swallowed by design and surfaces as an absent `indexUpdatedAt`. The complete union is [SomniaMarketsClientGetPerpFeedStatusError](../type-aliases/SomniaMarketsClientGetPerpFeedStatusError.md). *** ### getPerpFundingPremium() > **getPerpFundingPremium**(`pool`): `Promise`\<[`PerpFundingPremium`](PerpFundingPremium.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2720 A perp pool's funding-premium state: what the next settlement will charge, the standing instantaneous sample, and the raw accumulator behind them. Separate from [getPerpState](#getperpstate) on purpose — these getters arrived with Wave 28 and do not exist on an older pool implementation, and `getPerpState` batches with `allowFailure: false`, so folding them in would let one un-upgraded pool take a core read down. Read `timeWeightedPremium` for a predicted funding rate, never `lastObservedPremium` — the contract getter behind the latter kept its signature and changed its meaning. Check `armed` before calling the figure an average. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpFundingPremium`](PerpFundingPremium.md)\> *** ### getPerpPosition() > **getPerpPosition**(`ref`): `Promise`\<[`PerpPosition`](PerpPosition.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2726 An account's position in one perp pool, from the MarginBank (signed size: positive = long). `ref.marginBank` comes off the [PerpMarket](../type-aliases/PerpMarket.md) row. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpPosition`](PerpPosition.md)\> *** ### getMarginAccount() > **getMarginAccount**(`marginBank`, `account`): `Promise`\<[`MarginAccount`](MarginAccount.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2735 An account's cross-margin state (free/locked collateral, equity, withdrawable, active pools) from the MarginBank — now including the account health (`imReq`/`mmReq`/`cmReq`) and `marginStatus`. The client samples the chain head once and pins every component read to that block, so all fields describe one chain state. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`MarginAccount`](MarginAccount.md)\> *** ### getAccountHealth() > **getAccountHealth**(`marginBank`, `account`): `Promise`\<[`AccountHealth`](AccountHealth.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2742 An account's cross-margin health alone (equity vs IM/MM/CM + the derived status) — a lighter read than [getMarginAccount](#getmarginaccount) when only health matters. The health tuple and status are pinned to one sampled chain block. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`AccountHealth`](AccountHealth.md)\> *** ### getLiquidationPrice() > **getLiquidationPrice**(`ref`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2754 Estimated liquidation price for an account's position in one perp pool (raw quote units per whole base), or null when flat. Solves `equity == mmReq` with BOTH sides moving against the mark — see `perpLiquidationPrice` — over the cross-margin equity/mmReq, so it is the price at which this pool's move alone trips maintenance. Throws on a stale mark anywhere in the account. This is where liquidation *triggers*. For the contract's own figure of where a position's equity is *exhausted*, see [getBankruptcyPrice](#getbankruptcyprice). #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<`bigint` \| `null`\> *** ### getPerpLeverage() > **getPerpLeverage**(`ref`): `Promise`\<[`PerpLeverage`](PerpLeverage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2769 An account's realized leverage at one position and across the whole cross-margin account, plus every ceiling that bounds it — the market's IMF-implied max, the account's own cap, the protocol limit, and the credit-voucher confinement. Ratios are bps of 1x. Derived, not read: the MarginBank exposes only leverage *caps*, never a measurement of a position. The ceilings are returned as stored and do not compose by taking a minimum — see [PerpLeverage.voucherLeverageCapX](PerpLeverage.md#voucherleveragecapx). For whether a specific order passes, use `previewPerpOrderMargin`. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpLeverage`](PerpLeverage.md)\> *** ### getPerpPositionAnalytics() > **getPerpPositionAnalytics**(`ref`): `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2785 One position, marked — unrealized PnL, accrued funding, notional, the three margin requirements it contributes, and its return on margin. Two reads, pinned to one block. The split `getAccountHealth` cannot give you: that returns one equity figure for the whole account, with every market's PnL and funding already summed and netted, so a two-position trader cannot see which one carries the loss and cannot see funding at all. `accruedFunding` is **owed** — positive means the account pays. Returns `{ priceable: false }` on a stale mark rather than throwing, because in a positions table one dead feed must degrade one row, not the page. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)\> *** ### listPerpPositionAnalytics() > **listPerpPositionAnalytics**(`p`): `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2798 Every position the account holds, each marked — the positions-table read. `1 + 2n` reads for `n` active markets, all pinned to ONE block, which is the point of having it rather than looping the single read: unpinned, the rows come from different heights and their `equityContribution`s do not re-sum to any equity the account ever had. Scoped to the bank's own `activePerpPools`, so a closed position does not linger the way it does on the indexed rows. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)[]\> *** ### getMaxPerpOrderSize() > **getMaxPerpOrderSize**(`p`): `Promise`\<[`PerpMaxOrderSize`](../type-aliases/PerpMaxOrderSize.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2819 The largest order this account can place at `price` — what a **Max** button should call. The inverse of `previewPerpOrderMargin`, and the protocol has no such view. Does not re-derive the sizing rule: it binary-searches the forward one, so the two cannot disagree. A hand-rolled `equity / (price × imf)` drops the adverse mark-to-entry term, which is the usual reason a "max" order is rejected. `maxQuantity` is aligned down to the pool's lot grid. **Check `placeable`** — a size below the pool's `minQuantity` is a revert, not a small order. `limitedBy` says which gate bound it. Market-wide `maxOpenInterest` and book depth are deliberately not modelled. **Pass `autoPull` when the transaction sender will be the order owner.** That is the pool's whole gate for topping the account up from its wallet (T70), and with it on, an account with an empty bank and a funded, approved wallet goes from a max of `0n` to whatever the wallet funds. Leave it off for `placeOrderFor`, an operator grant or the stop registry, where no pull happens. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### price `bigint` ###### autoPull? `boolean` ###### builderFeeBpsTimes1k? `bigint` #### Returns `Promise`\<[`PerpMaxOrderSize`](../type-aliases/PerpMaxOrderSize.md)\> *** ### previewPerpClosePnl() > **previewPerpClosePnl**(`p`): `Promise`\<[`PerpClosePreview`](../type-aliases/PerpClosePreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2842 What closing a position — all of it or part — would actually realise. Backs a close modal. Two things it gets right that a hand-derived figure usually does not, both silent: the close is **aligned down to the lot grid** first, so a "close all" on a position that is not a lot multiple leaves a remainder open; and funding settles on the **whole** position rather than the closed share, because `settleTrade` settles before it touches the position. `netProceeds` is the number to show — `realizedPnl − fundingSettled − fee`. `fundingSettled` is positive when the account pays. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### quantity? `bigint` ###### price? `bigint` ###### asMaker? `boolean` #### Returns `Promise`\<[`PerpClosePreview`](../type-aliases/PerpClosePreview.md)\> *** ### previewPerpLiquidationPrice() > **previewPerpLiquidationPrice**(`p`): `Promise`\<[`PerpLiquidationPreview`](../type-aliases/PerpLiquidationPreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2861 Where a proposed order would leave the liquidation price if it filled in full at its limit price, alongside where it sits now — the projection an order form needs, which [getLiquidationPrice](#getliquidationprice) cannot give for an order not yet placed. Ports all four of `MarginBank.settleTrade`'s cases (open / increase / reduce / flip) and charges the fill's fee, so a reduce and an add move the answer in opposite directions. Whether the order is ACCEPTED is [previewPerpOrderMargin](#previewperpordermargin)'s question, not this one. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### quantity `bigint` ###### price `bigint` ###### asMaker? `boolean` #### Returns `Promise`\<[`PerpLiquidationPreview`](../type-aliases/PerpLiquidationPreview.md)\> *** ### getPerpSideHolders() > **getPerpSideHolders**(`ref`, `opts?`): `Promise`\<[`PerpSideHolders`](PerpSideHolders.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2893 Every account holding an open position on one side of one perp market, from the MarginBank's own per-(pool, side) holder array — the read that lets a liquidation keeper find its watch set from head state alone, no off-chain indexer. Chain tier. Pages through the bank's bounded slice view (many holders per round-trip, never one call per holder), with every page pinned to ONE block — `opts.blockNumber`, or the head sampled once — so a holder entering or leaving mid-walk can neither be missed nor double-counted. The result carries `asOfBlock`; feed it into [getBankruptcyPrice](#getbankruptcyprice)'s `opts.blockNumber` (and the other side's call) to keep a sweep on one consistent snapshot — the other position/health reads answer at head only. The indexed counterpart, [listPerpPositions](#listperppositions), answers the inverse question (one account's positions across pools) and lags head. **Details** - `opts.blockNumber`: pin to this block instead of the current head - `opts.pageSize`: holders per contract call (default 1000) #### Parameters ##### ref [`PerpSideHoldersRef`](PerpSideHoldersRef.md) ##### opts? [`GetPerpSideHoldersOptions`](GetPerpSideHoldersOptions.md) #### Returns `Promise`\<[`PerpSideHolders`](PerpSideHolders.md)\> *** ### getBankruptcyPrice() > **getBankruptcyPrice**(`ref`, `opts?`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2914 The MarginBank's OWN bankruptcy price for an account's position in one perp pool (raw quote units per whole base) — the contract-computed price at which the position's allocated equity is exhausted. What a liquidation keeper prices a bankrupt position against. A different quantity from [getLiquidationPrice](#getliquidationprice), not a better version of it: that is the SDK's client-side estimate of where liquidation *triggers* (use it for UI/monitoring); this is the contract's figure for where there is nothing left (use it for anything that settles or bids). Reverts rather than returning a sentinel — a [ContractRevertError](../classes/ContractRevertError.md) with `errorName: "NoOpenPosition"` when the account is flat in that pool (branch on `errorName`, never message text). **Details** - `opts.blockNumber`: read at this block instead of head. Pricing an enumerated holder? Pass the enumeration's `asOfBlock` — at head, a holder that closed after the snapshot reverts `NoOpenPosition`. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) ##### opts? [`GetBankruptcyPriceOptions`](GetBankruptcyPriceOptions.md) #### Returns `Promise`\<`bigint`\> *** ### getPerpSystemConfig() > **getPerpSystemConfig**(`marginBank`): `Promise`\<[`PerpSystemConfig`](PerpSystemConfig.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2929 How the perps stack is wired — the address book for every other contract in the plane (collateral token, pool factory, liquidation engine, insurance fund, fee recipient), plus the protocol-wide leverage ceiling and a `fullyWired` flag. Read this first: the addresses here are what the other protocol-state reads should be pointed at, so nothing is hardcoded per chain, and they are the bank's own view — the addresses it will actually call. `liquidationEngine` is the PROXY. An implementation address answers reads with unset defaults (zero bidders, zero penalty), which looks like a configured-but-idle engine rather than the wrong address. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<[`PerpSystemConfig`](PerpSystemConfig.md)\> *** ### getInsuranceFundState() > **getInsuranceFundState**(`fund`): `Promise`\<[`InsuranceFundState`](InsuranceFundState.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2935 The InsuranceFund's per-tier balances and the total bad debt it can absorb. Point it at `insuranceFund` from [getPerpSystemConfig](#getperpsystemconfig). #### Parameters ##### fund `` `0x${string}` `` #### Returns `Promise`\<[`InsuranceFundState`](InsuranceFundState.md)\> *** ### listPerpInsuranceFundEvents() > **listPerpInsuranceFundEvents**(`opts?`): `Promise`\<[`PerpInsuranceFundEvent`](../type-aliases/PerpInsuranceFundEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2946 The InsuranceFund's tier ledger, newest first — how each tier reached the balance [getInsuranceFundState](#getinsurancefundstate) reports. Indexer tier; the chain keeps no history. **Do not sum `amount` bare.** It is populated on inflows, outflows and the internal `TierAllocated` move alike, so a plain total is turnover rather than a balance — fold it by `kind`. `covered` on a `BadDebtAuthorised` row restates the `TierDebited` rows beside it, and `TierCredited` restates the fee plane's `insurancePortion`. #### Parameters ##### opts? ###### kind? `string` ###### tier? `number` \| `bigint` ###### account? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpInsuranceFundEvent`](../type-aliases/PerpInsuranceFundEvent.md)[]\> *** ### getLiquidationEngineConfig() > **getLiquidationEngineConfig**(`engine`): `Promise`\<[`LiquidationEngineConfig`](LiquidationEngineConfig.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2963 The LiquidationEngine's configured bounds — penalty, spread range, per-block volume cap, registered backstop bidders. Not its history, which is indexed as `LiquidationEvent`. `bidderCount === 0n` is an operational signal: with no registered bidders the takeover stage has nobody to take a position over, so the waterfall reaches ADL sooner than the configuration implies. #### Parameters ##### engine `` `0x${string}` `` #### Returns `Promise`\<[`LiquidationEngineConfig`](LiquidationEngineConfig.md)\> *** ### tryGetPerpAccountEquity() > **tryGetPerpAccountEquity**(`marginBank`, `account`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2972 An account's equity, or `null` when it could not be computed. [getAccountHealth](#getaccounthealth) propagates an oracle failure, which is exactly when a health sweep most needs an answer. Null means "not computable right now" — an unpriceable market in the account's set — never "zero equity". #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint` \| `null`\> *** ### getPerpCollateralBasis() > **getPerpCollateralBasis**(`marginBank`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2981 Collateral BACKING an account: `max(0, unlocked + locked)`, raw units. Deliberately unlike equity — one storage pair, no market walk, no oracle, and it cannot revert. A solvency floor that survives a dead price feed; use equity when you need mark-to-market truth. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### listPerpPoolStatuses() > **listPerpPoolStatuses**(`p`): `Promise`\<[`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3007 Every perp market the factory has deployed, in deployment order, with the two independent gates that decide whether it is tradeable: `restricted` (close-only) and `registered` (activated on the MarginBank). **Do not build a market list from the factory's raw pool list** — that is the deployment history and includes markets wound down to close-only, so listing it unfiltered presents dead markets as tradeable. Chain-sourced, which makes it complete and available when the indexer is not: the indexer builds its perp set dynamically from `PerpPoolDeployed`, so a pool deployed above its current head is invisible there and present here. You do not pass a MarginBank. It is a per-network singleton in practice, but each pool names its own and that is the bank its settlement path uses — so it is read per pool and returned on every row, ready for the [getMarginAccount](#getmarginaccount) / [getPerpPosition](#getperpposition) reads that follow. Feature-detects the factory's one-call status view and falls back to per-pool reads on a factory that predates it, returning the same shape either way. Per-pool reads go through Multicall3 in batches of up to 100 pools per request when the chain declares it, and through at most 8 concurrent point reads when it does not. Every read is pinned to one block. #### Parameters ##### p ###### factory `` `0x${string}` `` #### Returns `Promise`\<[`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md)[]\> *** ### listTradeablePerpPools() > **listTradeablePerpPools**(`p`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3010 Just the tradeable perp pools, filtered from [listPerpPoolStatuses](#listperppoolstatuses). #### Parameters ##### p ###### factory `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``[]\> *** ### readPerpMarketFromChain() > **readPerpMarketFromChain**(`p`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3026 One factory-deployed perp market as a native [PerpMarket](../type-aliases/PerpMarket.md) row, read entirely from the chain — for a market the indexer does not carry. Chain tier. Reads the pool's book grid and margin factor, the base token's symbol and decimals, and the pool's stop registry from the factory. History-derived fields come back as documented placeholders, because no chain read can supply them — see [UnifiedMarket.indexed](UnifiedMarket.md#indexed) for which ones and what they mean. **Gotchas** - Throws [RpcError](../classes/RpcError.md) when a read cannot be completed, and [ContractRevertError](../classes/ContractRevertError.md) when the pool or token rejects one. The grid, the margin factor and the decimals have no safe fallback, so an unreadable pool fails rather than producing a mis-scaled market. Two reads degrade instead: a token exposing no `symbol()` yields `baseSymbol: null`, and a factory predating `IPerpPoolFactoryStopRegistry` yields `stopRegistry: null`. #### Parameters ##### p ###### status [`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md) ###### collateralToken `` `0x${string}` `` ###### collateralDecimals `number` ###### collateralSymbol `string` \| `null` ###### factory `` `0x${string}` `` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)\> *** ### isPerpPoolRegistered() > **isPerpPoolRegistered**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3043 Whether the MarginBank has one perp pool registered — the activation gate on its own. Coming from the factory only proves a pool is authentic; registration is what makes it usable. Not interchangeable with `getPoolTier`, which is itself gated on registration and so returns 0 for an uncovered-but-registered market and an unregistered one alike. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### pool `` `0x${string}` `` #### Returns `Promise`\<`boolean`\> *** ### previewPerpOrderMargin() > **previewPerpOrderMargin**(`p`): `Promise`\<[`PerpOrderMarginPreview`](../type-aliases/PerpOrderMarginPreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3092 What a perp order will lock and whether the pool will accept it, computed BEFORE sending — the read behind an order form's "margin required" row and submit gate. Ports `PerpPool._computeLockAmount` plus the MarginBank gate it feeds, so the number shown is the number actually reserved. **Why not a contract pre-check.** `quoteMeetsIMForOrder` looks right and is not: it runs with the order's base margin treated as already reserved, because on the real path the lock has run first. Called cold it counts the order's margin nowhere and returns true for almost any size. `meetsIMForFill` does charge base margin but models neither the lock nor its adverse mark-to-entry reserve — the term that rejects a naively-sized "max" order. Reports **two gates** separately, because they fail for different reasons and imply different fixes: `hasCollateralForLock` (the lock can be taken at all) vs `meetsInitialMargin` (what remains still covers the requirement) — "deposit more" vs "close something". Every read is pinned to one block; a preview is a statement about that block, so re-quote near send time for anything close to the edge. **Pass `autoPull` when the transaction sender will be the order owner** — the pool's whole gate for topping the account up from its wallet (T70). With it on, both gates describe the post-pull balance. Off, they describe the in-bank balance alone, which is what an operator- or registry-routed placement actually faces. `topUpRequired` is the total the pull REQUESTS, not one wallet's debit: a linked child is funded by its own wallet first and its main for the residual, so show `ownWalletPull` and `mainWalletPull` beside the margin figure and read `fundingPayer` for whose wallet the second one is. Only `mainWalletPull > 0n` proves another wallet actually moves. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### quantity `bigint` ###### price `bigint` ###### autoPull? `boolean` ###### builderFeeBpsTimes1k? `bigint` #### Returns `Promise`\<[`PerpOrderMarginPreview`](../type-aliases/PerpOrderMarginPreview.md)\> *** ### meetsPerpImForFill() > **meetsPerpImForFill**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3111 The MarginBank's initial-margin probe for an order not yet locked — the closest single contract call to a pre-trade gate. Charges the increasing leg's base margin against free equity, but does not model the lock's adverse mark-to-entry reserve; [previewPerpOrderMargin](#previewperpordermargin) is the accurate gate. `additionalSize` is the INCREASING quantity, not necessarily the whole order. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### additionalSize `bigint` ###### price `bigint` #### Returns `Promise`\<`boolean`\> *** ### quoteMeetsPerpImForOrder() > **quoteMeetsPerpImForOrder**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3128 The MarginBank's placement-time initial-margin check, verbatim. **Not a pre-trade gate, despite the name** — it treats the order's base margin as already reserved, so called cold it answers true for almost any size. Correct only for a caller that has already taken the lock, i.e. for mirroring the placement check itself. For "will my order be accepted", use [previewPerpOrderMargin](#previewperpordermargin). #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### additionalSize `bigint` ###### price `bigint` #### Returns `Promise`\<`boolean`\> *** ### quotePerpOrderTopUp() > **quotePerpOrderTopUp**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3150 The MarginBank's auto-pull sizing, verbatim — how much placing an order would take from the owner's wallet. **For an order form use `previewPerpOrderMargin` with `autoPull` instead.** It derives `lockAmount`, `feeHeadroom` and `increasingQuantity` from the order, which is the awkward part: they come from the POOL, not the bank, so calling this directly means reproducing the same three numbers the pool would pass. This is the cross-check on that port. Returns `0n` both when no pull is needed and in the three cases where a pull would be wrong rather than unnecessary — a purely reducing order, an account already in debt, and a voucher-blocked increase — so read it beside the unlocked balance. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### account `` `0x${string}` `` ###### lockAmount `bigint` ###### feeHeadroom `bigint` ###### increasingQuantity `bigint` ###### price `bigint` #### Returns `Promise`\<`bigint`\> *** ### getPerpLeverageImSurcharge() > **getPerpLeverageImSurcharge**(`marginBank`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3175 The EXTRA initial margin an account's own leverage settings demand, summed over every market where it BOTH holds a position AND has set a stricter-than-market cap. This explains an `InsufficientMarginForOrder` that [quotePerpOrderTopUp](#quoteperpordertopup) cannot. The two measure different things: the quote funds one order against the UNLOCKED balance, while the admission gate measures whole-account EQUITY — so an order can be fully funded on its own market and still be refused because of an override on a different one. Deposit this deliberately rather than expecting a pull to cover it. Reverts if a market that is both positioned and overridden is unpriceable; use [tryGetPerpLeverageImSurcharge](#trygetperpleverageimsurcharge) in a sweep. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### tryGetPerpLeverageImSurcharge() > **tryGetPerpLeverageImSurcharge**(`marginBank`, `account`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3189 [getPerpLeverageImSurcharge](#getperpleverageimsurcharge) without the revert — `null` when it could not be computed. `null` means "not computable right now", never "no surcharge". Substituting `0n` would under-state the requirement, which is the wrong direction to be wrong in. Only a revert from the view itself becomes `null`. A read that never reached the chain throws, and so does an address that does not declare the view. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint` \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete, or `marginBank` does not declare the view. *** ### getPerpMaxLeverage() > **getPerpMaxLeverage**(`ref`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3210 One account's own leverage cap for one perp pool, as the MarginBank stores it — the cheap path to the number [getPerpLeverage](#getperpleverage) reports as `accountMaxLeverageX`. Chain tier, exactly one storage read. Unlike [getPerpLeverage](#getperpleverage) it does NOT walk the account, so a stale mark on some other market cannot take it down — the cap is a setting, not a measurement, and never needed a price. Use it for a per-position badge or a leverage dialog; use [getPerpLeverage](#getperpleverage) when the question is realized account-wide leverage. `0` means "no account cap set", never zero leverage — the market ceiling binds then. Returned unchanged for the caller to compose. **Details** - `ref`: the (bank, account, pool) triple - `opts.blockNumber`: read at this block instead of head. Combining the cap with an enumeration's or analytics row's figures? Pass that row's `asOfBlock` so both describe one moment. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) ##### opts? [`GetPerpMaxLeverageOptions`](GetPerpMaxLeverageOptions.md) #### Returns `Promise`\<`number`\> *** ### getPerpLinkedWalletRegistry() > **getPerpLinkedWalletRegistry**(`marginBank`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3220 The registry the bank resolves wallet links through, or `null` while the linked-wallet funding rail is DORMANT. Read it from the bank rather than a deployment manifest: the bank decides which registry is authoritative, and a registry nobody has armed is inert. `null` means no child can draw on any main on this deployment. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> *** ### quotePerpFundingPayer() > **quotePerpFundingPayer**(`marginBank`, `account`): `Promise`\<[`PerpFundingPayer`](../type-aliases/PerpFundingPayer.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3230 Whether this account's next position-increasing order would spend a main's wallet, and whose. A discriminated union, because the contract's single zero collapses three cases a UI must not render alike: the rail is dormant, the wallet is unlinked, or the wallet IS a main. Only `unlinked` is the user's to fix. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpFundingPayer`](../type-aliases/PerpFundingPayer.md)\> *** ### getPerpMainFunding() > **getPerpMainFunding**(`marginBank`, `account`): `Promise`\<[`PerpMainFunding`](PerpMainFunding.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3240 Principal a main has funded into this account and not recovered, plus the payer recorded at funding time. What a main funds can be borrowed, never withdrawn — `withdraw` frees at most `balance - principal`. The payer is SNAPSHOTTED, so it is who gets repaid even if the link has since changed. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpMainFunding`](PerpMainFunding.md)\> *** ### getPerpWalletPullCapacity() > **getPerpWalletPullCapacity**(`marginBank`, `wallet`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3249 What a wallet could contribute to a pull right now — `min(balance, allowance)`. On a MAIN this is the ceiling on what its children can collectively draw, and the number to reduce to revoke the rail without unlinking (consent is the allowance). On a CHILD it is how much of its own money it burns before reaching its main's. #### Parameters ##### marginBank `` `0x${string}` `` ##### wallet `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getPerpWalletLinkage() > **getPerpWalletLinkage**(`registry`, `wallet`): `Promise`\<[`PerpWalletLinkage`](PerpWalletLinkage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3259 A wallet's link group and its ADL-netting maturity. Takes the REGISTRY address — resolve it with [getPerpLinkedWalletRegistry](#getperplinkedwalletregistry) so a dormant deployment reads as dormant rather than as an empty group. `maturesAt` gates ADL netting only: the funding rail reads the raw graph, so a link can be fundable and not yet mature. #### Parameters ##### registry `` `0x${string}` `` ##### wallet `` `0x${string}` `` #### Returns `Promise`\<[`PerpWalletLinkage`](PerpWalletLinkage.md)\> *** ### listPerpLinkedChildren() > **listPerpLinkedChildren**(`registry`, `main`): `Promise`\ Defined in: packages/sdk/src/somniaMarketsClient.ts:3265 Every child of a main, excluding the main — the isolated buckets one treasury currently serves. #### Parameters ##### registry `` `0x${string}` `` ##### main `` `0x${string}` `` #### Returns `Promise`\ *** ### getPerpMaxLinkedChildren() > **getPerpMaxLinkedChildren**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3271 How many children one main may hold. Owner-tunable, so read it before offering to link another wallet rather than hardcoding the cap. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### listPerpWalletLinkEvents() > **listPerpWalletLinkEvents**(`opts?`): `Promise`\<[`PerpWalletLinkEvent`](../type-aliases/PerpWalletLinkEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3282 The linked-wallet consent graph over time, newest first. **The only way to see a PENDING proposal** — the registry exposes no getter for one, so a `Proposed` row with no later row for the same pair is an offer still standing. Consent is not authority: a `Linked` row grants no power over funds by itself. Ask [quotePerpFundingPayer](#quoteperpfundingpayer) whether an order would actually spend a main's wallet. #### Parameters ##### opts? ###### main? `string` ###### child? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpWalletLinkEvent`](../type-aliases/PerpWalletLinkEvent.md)[]\> *** ### listPerpMarginPulls() > **listPerpMarginPulls**(`opts?`): `Promise`\<[`PerpMarginPull`](../type-aliases/PerpMarginPull.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3301 Margin pulled to fund placements, newest first — the POOL side of the rail, and the side that names an ORDER. One placement can produce TWO rows: `source: "OwnWallet"` for what the owner's own wallet covered, then `source: "Main"` for the residual drawn from their linked main. `amount` is what that leg pulled, not the order's total requirement. **Never sum these with [listPerpMainFundingEvents](#listperpmainfundingevents)** — one pull emits a row on each side for the same wei. #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### orderId? `string` ###### source? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpMarginPull`](../type-aliases/PerpMarginPull.md)[]\> *** ### listPerpMainFundingEvents() > **listPerpMainFundingEvents**(`opts?`): `Promise`\<[`PerpMainFundingEvent`](../type-aliases/PerpMainFundingEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3320 A main's claim against a child over time, newest first — the BANK side of the rail, carrying the running principal. The live claim is [getPerpMainFunding](#getperpmainfunding). `amount` is **null on `Settled`** and that is not missing data: the child's own losses discharged part of the claim, so no cash moved while `outstandingPrincipal` still fell. **Never sum these with [listPerpMarginPulls](#listperpmarginpulls)** — same wei, two sides. #### Parameters ##### opts? ###### account? `string` ###### payer? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpMainFundingEvent`](../type-aliases/PerpMainFundingEvent.md)[]\> *** ### getPerpVoucherCampaign() > **getPerpVoucherCampaign**(`marginBank`): `Promise`\<[`PerpVoucherCampaign`](PerpVoucherCampaign.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3351 The live credit-voucher campaign behind a MarginBank, or `null` when the bank has no credit granter. A credit voucher is a one-time grant of house money into a new account's MarginBank balance. The grant is non-withdrawable; profit above it is. Use this read to show the offer: the grant, the claim window, how many claims the budget still covers, and the leverage a voucher account may use. Chain tier, current to the RPC head. The bank names the distributor, so this read never needs a deployment address. **Gotchas** `null` means the programme is off on this deployment. It is not a read failure. An open window does not mean a claim succeeds: an empty budget (`claimsRemaining === 0n`) rejects every claim. Ask [getPerpVoucherEligibility](#getperpvouchereligibility) for one account's answer. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucherCampaign`](PerpVoucherCampaign.md) \| `null`\> *** ### getPerpVoucherEligibility() > **getPerpVoucherEligibility**(`marginBank`, `account`): `Promise`\<[`PerpVoucherEligibility`](../type-aliases/PerpVoucherEligibility.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3377 Whether an account can claim a credit voucher now, and if not, why. Use it before [Trader.claimPerpVoucher](Trader.md#claimperpvoucher). A claim that fails still mines and costs gas, because not every executor simulates before it sends. The reasons follow the distributor's own check order, so `reason` names the revert a claim would produce. Chain tier. Every read is pinned to one block, and the claim window is checked against that block's timestamp. **Gotchas** `alreadyClaimed` is permanent for that address on this distributor. The limit is once per address for the distributor's life, not once per campaign. `notFlat` includes resting orders, not only positions. The account must cancel every perp order before it can claim. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read, or the block read that pins them, did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. - Throws [InvariantError](../classes/InvariantError.md) - the node returned a latest block with no number. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucherEligibility`](../type-aliases/PerpVoucherEligibility.md)\> *** ### getPerpVoucher() > **getPerpVoucher**(`marginBank`, `account`): `Promise`\<[`PerpVoucher`](PerpVoucher.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3399 One account's credit-voucher state, or `null` when the bank has no credit granter. Use it to show how much of the account's balance is house money, and when that money can be swept back. `floor` is the part `withdraw` cannot take out. Chain tier, current to the RPC head. **Gotchas** After `expiresAt`, anyone can sweep the floor back to the distributor, but only while the account holds no positions or resting orders. A sweep never forces a close. A claimed account with `floor === 0n` either lost the grant in trading or was swept. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucher`](PerpVoucher.md) \| `null`\> *** ### getPerpRiskParams() > **getPerpRiskParams**(`pool`): `Promise`\<[`PerpRiskParams`](PerpRiskParams.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3401 #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpRiskParams`](PerpRiskParams.md)\> *** ### getPerpHealthSnapshot() > **getPerpHealthSnapshot**(`pool`): `Promise`\<[`PerpHealthSnapshot`](../type-aliases/PerpHealthSnapshot.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3414 A perp market's live health inputs in one call — mark price, projected cumulative funding, the effective (OI-scaled) IMF, and the maintenance / close-out thresholds. The contract exposes this precisely so a cross-margin health walk reads a market once instead of making five getter calls. Returns a discriminated union: an unpriceable market (stale or zero mark) arrives as `{ priceable: false }` rather than an all-zero struct, so a `maintenanceMarginBps` of 0 cannot be mistaken for "no maintenance requirement". Narrow on `priceable` before reading any field. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpHealthSnapshot`](../type-aliases/PerpHealthSnapshot.md)\> *** ### getEffectiveImfBps() > **getEffectiveImfBps**(`pool`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3426 The initial-margin factor a perp market is charging right now, in bps — OI-scaled when dynamic IMF is enabled, otherwise the static base. Sizing an order off `initialMarginBps` instead under-margins it whenever open interest has pushed the curve above its floor, and the pool rejects an order the client believed fit. Reverts if dynamic IMF is on and the index is stale. [getPerpHealthSnapshot](#getperphealthsnapshot) returns this alongside the rest for one round-trip. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getVaultBalance() > **getVaultBalance**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3443 Claimable balance an owner can withdraw from a pool's internal ERC20Vault for `token`, raw units — the value behind the append-only [getVaultPayoutFallbacks](#getvaultpayoutfallbacks) history. Reads at chain head. Pass `blockNumber` to pin it, which is what an answer combining this with other reads at one height needs: the balance is contract state behind an append-only payout history, so no indexed entity reconstructs it at a past height. A pinned read far behind head needs archive state. ```ts const owed = await client.getVaultBalance({ vault: pool, owner, token: quote }); const owedAt = await client.getVaultBalance({ vault: pool, owner, token: quote, blockNumber: 1_234n }); ``` #### Parameters ##### p [`GetVaultBalanceParams`](GetVaultBalanceParams.md) #### Returns `Promise`\<`bigint`\> *** ### getManualVaultMode() > **getManualVaultMode**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3450 Whether `user` has opted out of wallet auto-pull on this SpotPool, at chain head — see `trader.setManualVaultMode`. True means their orders draw only on pre-deposited vault balance and their payouts stay as vault credit. #### Parameters ##### p [`GetManualVaultModeParams`](GetManualVaultModeParams.md) #### Returns `Promise`\<`boolean`\> *** ### getAutoPullRequirement() > **getAutoPullRequirement**(`p`): `Promise`\<[`AutoPullRequirement`](AutoPullRequirement.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3458 What an order of this shape would consume from `owner`, and how far short their vault balance falls (`delta`) — the pool's own worst-case funding envelope. In auto-pull mode `delta` is what the wallet gets pulled for; under manual vault mode it is what must be deposited first. #### Parameters ##### p [`GetAutoPullRequirementParams`](GetAutoPullRequirementParams.md) #### Returns `Promise`\<[`AutoPullRequirement`](AutoPullRequirement.md)\> *** ### isOperatorAuthorized() > **isOperatorAuthorized**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3465 Whether `owner` authorized `operator` for `selector` on this SpotPool, at chain head — resolved through the pool's OperatorPermissionsRegistry, so no indexer lag. #### Parameters ##### p [`IsOperatorAuthorizedParams`](IsOperatorAuthorizedParams.md) #### Returns `Promise`\<`boolean`\> *** ### isGloballyApproved() > **isGloballyApproved**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3475 Whether a GLOBAL operator grant is on record for this owner/operator/selector, at chain head — the raw slot `trader.setOperatorApprovalGlobal` writes. Independent of pool registration and of denials, so `true` here does not mean the operator can act on a given pool. For that, use [isOperatorAuthorized](#isoperatorauthorized). #### Parameters ##### p [`IsGloballyApprovedParams`](IsGloballyApprovedParams.md) #### Returns `Promise`\<`boolean`\> *** ### isApprovedForPool() > **isApprovedForPool**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3484 Whether a PER-POOL operator grant is on record, at chain head — the read-back for `trader.setOperatorApprovalForPool`. Ignores any global grant and any denial. For the pool's resolved decision, use [isOperatorAuthorized](#isoperatorauthorized). #### Parameters ##### p [`IsApprovedForPoolParams`](IsApprovedForPoolParams.md) #### Returns `Promise`\<`boolean`\> *** ### getOperatorPermissionsRegistry() > **getOperatorPermissionsRegistry**(`pool`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3508 The OperatorPermissionsRegistry this SpotPool gates operator calls through, at chain head — or `null` when the pool is unwired and denies every operator call. Discovery for a caller with no `addresses.operatorPermissionsRegistry` configured: the grant writes and the two grant reads need that address and otherwise throw [NotConfiguredError](../classes/NotConfiguredError.md), and no deployment manifest carries the key yet. A configured address still wins where it is used — this read adds a path, it does not redirect one. The pool is the authority: its own gate consults this registry and no other, so a grant written elsewhere admits nobody here. Failures. This read needs no address of its own, but it does need chain access, and every chain client is resolved lazily on first use — so it throws [NotConfiguredError](../classes/NotConfiguredError.md) when neither `wsRpcUrl` nor the chain definition's own WebSocket endpoint exists. It throws [ContractRevertError](../classes/ContractRevertError.md) when the pool rejects the call, and [RpcError](../classes/RpcError.md) when the read gets no answer — which is also what an EOA or any non-pool address produces, because an empty return is classified as a failed read rather than as a revert. `null` is an answer, never a failure. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> *** ### getOwnLockedBalance() > **getOwnLockedBalance**(`p`): `Promise`\<[`LockedBalance`](LockedBalance.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3514 Base/quote `owner` has locked in this pool's resting orders. Pair with [getVaultBalance](#getvaultbalance) to account for everything the pool holds for them. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### owner `` `0x${string}` `` #### Returns `Promise`\<[`LockedBalance`](LockedBalance.md)\> *** ### getLockedTokenBreakdown() > **getLockedTokenBreakdown**(`pool`): `Promise`\<[`LockedTokenBreakdown`](LockedTokenBreakdown.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3520 How the pool's reserves of each token split between resting orders and leftover — venue-health introspection, not a portfolio read. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`LockedTokenBreakdown`](LockedTokenBreakdown.md)\> *** ### convertToQuoteAtPriceCeil() > **convertToQuoteAtPriceCeil**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3526 Base→quote at a price using the pool's OWN ceil rounding — for interpreting [getLockedTokenBreakdown](#getlockedtokenbreakdown) without reimplementing it. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### baseQuantity `bigint` ###### price `bigint` #### Returns `Promise`\<`bigint`\> *** ### getMarketOnchain() > **getMarketOnchain**(`marketId`): `Promise`\<[`MarketOnchain`](MarketOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3539 A binary market's full wiring + state (tokens, pool + nonce, status, expiry, resolution, finalized, decimals) straight from chain — authoritative for write eligibility, and works before the indexer has seen the market. BREAKING (0.13.0): takes the bytes32 `marketId` (resolved through the BinaryMarketsModule), NOT the BinaryMarket contract address — pools are recycled across successive markets in v2, so market identity is the module id. Post-finalize, `backing` falls back to the settlement record's net backing. Requires `addresses.binaryModule` in the config. #### Parameters ##### marketId `` `0x${string}` `` #### Returns `Promise`\<[`MarketOnchain`](MarketOnchain.md)\> *** ### getPoolMarketBinding() > **getPoolMarketBinding**(`pool`, `opts?`): `Promise`\<[`PoolMarketBinding`](PoolMarketBinding.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3564 Which market a binary pool currently hosts, read from chain alone — the cold-start source of the `(pool, marketId)` binding when the indexer is unreachable. Feed the result's `marketId` to `watchMarket(pool, { seed: "chain", marketId })` to start a live book during an indexer outage. The ordinary source of that binding is the indexer, so without this read the chain seed only serves callers who already hold a hand-maintained market list. Both chain reads are made at ONE block, and the result carries it. Resolves to `null` only when the pool's market does not belong to this module; a failed read throws. Throws `InvalidInputError` when the module's record disagrees with the pool on either the pool address or the nonce. Requires `addresses.binaryModule` in the config. ```ts const binding = await exchange.client.getPoolMarketBinding(pool); if (binding) await exchange.client.watchMarket(pool, { seed: "chain", marketId: binding.marketId }); ``` #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetPoolMarketBindingOptions`](GetPoolMarketBindingOptions.md) #### Returns `Promise`\<[`PoolMarketBinding`](PoolMarketBinding.md) \| `null`\> *** ### getMarketIdOnchain() > **getMarketIdOnchain**(`marketAddress`, `opts?`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3578 A BinaryMarket contract address's module id, read from chain alone. Use this when you hold a market ADDRESS and need its `marketId`, which is what every market-keyed read takes. A market page whose route carries the contract address is the usual case. `getBinaryMarketByAddress` answers the same question from the indexer, so this read is the one that survives an indexer outage. Resolves to `null` when this module did not create the market. A failed read throws. Requires `addresses.binaryModule` in the config. #### Parameters ##### marketAddress `` `0x${string}` `` ##### opts? ###### blockNumber? `bigint` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> *** ### getPoolCreator() > **getPoolCreator**(`pool`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3586 A pool's creator — its first-deploy market creator, the only party that can reuse it — straight from chain (`BinaryMarketsModule.poolCreator`). Zero address for a pool the module never deployed. No signer needed; requires `addresses.binaryModule`. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### getFreePools() > **getFreePools**(`creator`, `collateral`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3594 A creator's free (finalized + released, reusable) pools for `collateral`, LIFO order (the LAST entry is popped first on the creator's next createMarket), straight from chain (`BinaryMarketsModule.getFreePools`). No signer needed; requires `addresses.binaryModule`. #### Parameters ##### creator `` `0x${string}` `` ##### collateral `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``[]\> *** ### listPoolBindings() > **listPoolBindings**(`pool`, `opts?`): `Promise`\<[`PoolBindingRecord`](PoolBindingRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3632 One page of a pool's pool→market binding history from the indexer, newest (highest nonce) first. A recycled pool gains one binding per market and its history has no protocol cap, so this read is paged: `opts.limit` defaults to 50 and `opts.offset` to 0, and both execute at the indexer. A row with `toBlock === null` is the pool's CURRENT binding; `closedBy` says whether a past binding ended by `PoolReleased` ("Released") or by the next `MarketCreated` recycling the pool onward ("Rotated"). Offset pages are not a snapshot. When the pool opens new bindings between two requests, older rows move down by that many positions and the next page repeats that many rows. Deduplicate on `id` when you page to the end. Replaces `getPoolBindings(pool)`, which returned the whole history in one response. #### Parameters ##### pool `string` ##### opts? [`ListPoolBindingsOptions`](ListPoolBindingsOptions.md) #### Returns `Promise`\<[`PoolBindingRecord`](PoolBindingRecord.md)[]\> #### Example ```ts // The whole history of a recycled pool. A short page is the end. const byId = new Map(); for (let offset = 0; ; offset += 1000) { const page = await exchange.client.listPoolBindings(pool, { limit: 1000, offset }); for (const row of page) byId.set(row.id, row); if (page.length < 1000) break; } ``` #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, or `opts.offset` is not an integer from 0 to 2147483647 (GraphQL `Int`). Checked before the request, so the indexer is not blamed for the caller's own input. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. The union is [SomniaMarketsClientListPoolBindingsError](../type-aliases/SomniaMarketsClientListPoolBindingsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. *** ### getPool() > **getPool**(`address`): `Promise`\<[`IndexedPool`](IndexedPool.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3639 The indexer's per-pool aggregate (creator, collateral, current binding, generation count) for a long-lived, recycled BinaryPool — null if the indexer has never seen a `MarketCreated` on that address. #### Parameters ##### address `string` #### Returns `Promise`\<[`IndexedPool`](IndexedPool.md) \| `null`\> *** ### getErc20Balance() > **getErc20Balance**(`token`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3645 ERC-20 `balanceOf(account)`, raw units. For outcome positions use [getOutcomeBalance](#getoutcomebalance) (ERC-6909), not this. #### Parameters ##### token `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getErc20Metadata() > **getErc20Metadata**(`token`): `Promise`\<[`Erc20Metadata`](Erc20Metadata.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3651 ERC-20 `symbol`/`name`/`decimals` in one fan-out — label a token the indexer hasn't denormalized. #### Parameters ##### token `` `0x${string}` `` #### Returns `Promise`\<[`Erc20Metadata`](Erc20Metadata.md)\> *** ### getErc20Allowance() > **getErc20Allowance**(`token`, `owner`, `spender`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3657 ERC-20 `allowance(owner, spender)`, raw units — gate a write that pulls ERC-20 collateral (outcome tokens use per-operator approval instead). #### Parameters ##### token `` `0x${string}` `` ##### owner `` `0x${string}` `` ##### spender `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getOutcomeBalance() > **getOutcomeBalance**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3664 ERC-6909 `balanceOf(account, id)` on the outcome-token singleton, raw units. `p.outcomeToken` is the singleton (from [getMarketOnchain](#getmarketonchain)); `p.id` is the market's `yesId`/`noId`. #### Parameters ##### p [`GetOutcomeBalanceParams`](GetOutcomeBalanceParams.md) #### Returns `Promise`\<`bigint`\> *** ### getBalances() > **getBalances**(`tokens`, `account`): `Promise`\<`bigint`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3674 Batch-read many balances for one `account` in a single fan-out. Each entry is read as a plain ERC-20 `balanceOf(account)` when `id` is omitted, or as an ERC-6909 outcome position `balanceOf(account, id)` on the singleton `token` when `id` is set. Results are returned positionally, aligned to `tokens`. The explorer uses this to read a portfolio's collateral + outcome positions in one round-trip instead of N calls. #### Parameters ##### tokens readonly [`BalanceQuery`](BalanceQuery.md)[] ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`[]\> *** ### getStopOrderSomiPayment() > **getStopOrderSomiPayment**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3680 SOMI a SpotStopOrderRegistry charges per pending stop order (funds the trigger gas; refunded on cancel). Raw wei. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getMaxBuilderFeeBpsTimes1k() > **getMaxBuilderFeeBpsTimes1k**(`pool`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3686 A pool's protocol-wide per-order builder-fee ceiling (pool bps×1000). Read-only — no signer — for the order form's routing-fee ceiling hint. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getBuilderApproval() > **getBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3689 A user's raw per-builder approval cap on a pool (pool bps×1000; 0 = none). #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> *** ### getEffectiveBuilderApproval() > **getEffectiveBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3696 The ENFORCED per-builder approval on a pool: the user's raw cap clamped by the pool's protocol-wide ceiling — the limit a `builderFeeBpsTimes1k` must not exceed. Drives the order form's "approve builder first" gate. #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> *** ### getContractMeta() > **getContractMeta**(`address`, `opts?`): `Promise`\<[`ContractMeta`](ContractMeta.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3702 owner / EIP-1967 implementation / native balance for a deployed contract — the /system dashboard diagnostics. `proxy: true` reads the impl slot. #### Parameters ##### address `` `0x${string}` `` ##### opts? ###### proxy? `boolean` #### Returns `Promise`\<[`ContractMeta`](ContractMeta.md)\> *** ### getNativeBalance() > **getNativeBalance**(`address`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3709 Native (SOMI/STT) balance, raw wei. - Throws [RpcError](../classes/RpcError.md) - the balance read did not complete (`operation: "getBalance"`). #### Parameters ##### address `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### getTransactionSummary() > **getTransactionSummary**(`hash`): `Promise`\<[`TransactionSummary`](TransactionSummary.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3721 Chain-direct summary of one transaction — sender, gas spent, fee paid, status — for enriching an order/fill view with what its tx cost. Null for a malformed hash and for one the node reports as not found. A read that did not complete throws, so "it never landed" stays distinct from "the node could not be reached". #### Parameters ##### hash `string` #### Returns `Promise`\<[`TransactionSummary`](TransactionSummary.md) \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete. *** ### createNetworkTape() > **createNetworkTape**(`opts?`): [`NetworkTape`](../classes/NetworkTape.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:3730 The network-wide order-flow firehose: one topics-only chain-log subscription that sees OrderPlaced/OrderFilled from EVERY pool (including pools created later), no indexer on the hot path. Nothing connects until the tape's first `subscribe`; the last unsubscribe closes the socket. Each call returns an independent tape. #### Parameters ##### opts? [`NetworkTapeOptions`](NetworkTapeOptions.md) #### Returns [`NetworkTape`](../classes/NetworkTape.md) *** ### getHeadBlock() > **getHeadBlock**(): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3733 Latest block number as the RPC sees it. #### Returns `Promise`\<`number`\> *** ### getSystemInfo() > **getSystemInfo**(): `Promise`\<[`SystemInfo`](SystemInfo.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3745 Deployed protocol state (impl pointers, oracle, collateral) for ops dashboards. Needs `config.addresses`. A `null` field means the contract is not configured or not wired. A failed read throws, so the snapshot never reports a zero the chain did not answer. #### Returns `Promise`\<[`SystemInfo`](SystemInfo.md)\> #### Throws [RpcError](../classes/RpcError.md) A chain read did not complete. #### Throws [ContractRevertError](../classes/ContractRevertError.md) A configured contract rejected its read (usually an ABI mismatch). *** ### listOperators() > **listOperators**(`opts?`): `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3756 List operators, newest-first by id, paginated. Pass `owner` to scope to one owner's operators (the indexed "my operators", no log scan), `enabled` to filter by the kill switch, `limit`/`offset` to page. Indexer read. #### Parameters ##### opts? [`OperatorFilter`](../type-aliases/OperatorFilter.md) & `object` #### Returns `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md)[]\> *** ### countOperators() > **countOperators**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3766 Server-side COUNT of operators matching a filter (for directory pagination). Needs the privileged `_aggregate` role (server-only), like [countBinaryMarkets](#countbinarymarkets). Without that header the total is bounded at 10,000 by the row-scan fallback, and past it would be a lower bound reported as exact. `Operator` is orders of magnitude below the cap, so no bounded variant exists. #### Parameters ##### opts? [`OperatorFilter`](../type-aliases/OperatorFilter.md) #### Returns `Promise`\<`number`\> *** ### getOperator() > **getOperator**(`operatorId`): `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3768 One operator by id, or null if never registered. Indexer read. #### Parameters ##### operatorId `number` #### Returns `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md) \| `null`\> *** ### listVenues() > **listVenues**(`opts?`): `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3773 List venues, creation-order, optionally scoped to one operator and/or market type and/or the venue-level creation flag. Paginated. Indexer read. #### Parameters ##### opts? ###### operatorId? `number` ###### marketType? `string` ###### creationEnabled? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md)[]\> *** ### countVenues() > **countVenues**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3788 Server-side COUNT of venues matching a filter (for per-operator venue pagination). Needs the privileged `_aggregate` role (server-only). Without that header the total is bounded at 10,000 by the row-scan fallback, like [countOperators](#countoperators); `Venue` is far below the cap, so no bounded variant exists. #### Parameters ##### opts? ###### operatorId? `number` ###### marketType? `string` #### Returns `Promise`\<`number`\> *** ### getVenue() > **getVenue**(`venueId`): `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3790 One venue by its opaque bytes32 id, or null. Indexer read. #### Parameters ##### venueId `string` #### Returns `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md) \| `null`\> *** ### encodeBinaryVenueFeeParams() > **encodeBinaryVenueFeeParams**(`vp`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3797 Build a BINARY_V1 venue's `feeParams` bytes from plain-bps rates via the deployed BinaryMarketsModule's `encodeVenueFeeParams` — the on-chain ground truth for the version tag + struct shape (used by the create/edit venue forms). Needs `config.addresses.binaryModule`. #### Parameters ##### vp [`BinaryVenueParams`](BinaryVenueParams.md) #### Returns `Promise`\<`` `0x${string}` ``\> *** ### getMaxVenueFeeBps() > **getMaxVenueFeeBps**(): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3802 The module's protocol-level ceiling on any single venue fee rate, in plain bps (e.g. 1_000 = 10%). Needs `config.addresses.binaryModule`. #### Returns `Promise`\<`number`\> *** ### listMarketCreators() > **listMarketCreators**(`opts?`): `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3816 List MarketCreators, newest-first, paginated. Pass `owner` for "my machinery", `operatorId`/`venueId` to scope. Each row carries its nested `series`. Indexer read. #### Parameters ##### opts? [`MarketCreatorFilter`](../type-aliases/MarketCreatorFilter.md) & `object` #### Returns `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md)[]\> *** ### getMarketCreator() > **getMarketCreator**(`creator`): `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3818 One MarketCreator by address (with its series), or null. Indexer read. #### Parameters ##### creator `string` #### Returns `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md) \| `null`\> *** ### listOracleAdapters() > **listOracleAdapters**(`opts?`): `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3825 List oracle adapters, newest-first, paginated. Pass `owner` to scope, `approved` to filter by the module-approval gate. Oracle v2: the one approved adapter is the OracleHub — this directory tracks `AdapterApproved` history. Indexer read. #### Parameters ##### opts? ###### owner? `string` ###### approved? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md)[]\> *** ### getOracleAdapter() > **getOracleAdapter**(`adapter`): `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3832 One oracle adapter by address, or null. Indexer read. #### Parameters ##### adapter `string` #### Returns `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md) \| `null`\> *** ### listSeries() > **listSeries**(`opts?`): `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3834 List series, creation-order, optionally scoped to one creator. Indexer read. #### Parameters ##### opts? ###### creator? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md)[]\> *** ### listSeriesLatestMarkets() > **listSeriesLatestMarkets**(`opts?`): `Promise`\<[`SeriesLatestMarket`](../type-aliases/SeriesLatestMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3888 The most recent market of every series that has rolled at least once - one row per series, joined server-side. The read behind a "has this series stopped rolling" monitor. Paginated over series. Indexer read. A series with no market yet has NO row; see [SeriesLatestMarket](../type-aliases/SeriesLatestMarket.md). #### Parameters ##### opts? [`ListSeriesLatestMarketsOptions`](../type-aliases/ListSeriesLatestMarketsOptions.md) #### Returns `Promise`\<[`SeriesLatestMarket`](../type-aliases/SeriesLatestMarket.md)[]\> #### Example ```ts // Which of an owner's series have gone quiet. Page to exhaustion: the read // is bounded per call, so a short page is the end and a full one is not. const latest = new Map(); for (let offset = 0; ; offset += 100) { const page = await exchange.client.listSeriesLatestMarkets({ limit: 100, offset }); for (const row of page) latest.set(row.series, BigInt(row.createdAtTimestamp)); if (page.length < 100) break; } // A series with NO row has never rolled - that is "unanchored", NOT // "stalled". Nothing indexed says when a first roll is due, so judging a // missing row as late pages every newly registered series. // // RE-REGISTRATION needs the same treatment, and the indexer will not do it // for you: Market->Series links are preserved, so `latest` still holds the // PREVIOUS schedule's market after a restart. Ageing that row against the new // schedule reports a deliberate restart as quiet. A series is re-registered // when `updatedAtTimestamp` is later than `createdAtTimestamp`, and the row // in hand belongs to the old generation when it predates that restart - so // treat it as unanchored too, exactly as the probe's own sweep does. const seconds = (v: string | null) => (v == null ? Number.NaN : Number(v)); for (const s of await exchange.client.listSeries()) { const rolledAt = latest.get(s.id); if (rolledAt === undefined) continue; const restartedAt = seconds(s.updatedAtTimestamp); const registeredAt = seconds(s.createdAtTimestamp); const restarted = Number.isFinite(restartedAt) && (!Number.isFinite(registeredAt) || restartedAt > registeredAt); if (restarted && Number(rolledAt) <= restartedAt) continue; const lateBy = BigInt(Math.floor(Date.now() / 1000)) - rolledAt; if (lateBy > BigInt(s.intervalSec) * 2n) console.log("quiet:", s.id, lateBy); } ``` #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, or `opts.offset` is not a non-negative safe integer. Checked before the request: `NaN` and `Infinity` are ordinary `number` values that would serialize to `null` and lift the page bound entirely. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. The union is [SomniaMarketsClientListSeriesLatestMarketsError](../type-aliases/SomniaMarketsClientListSeriesLatestMarketsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. *** ### getSeries() > **getSeries**(`creator`, `seriesId`): `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3895 One series by its composite key `(creator, seriesId)` — seriesId is per-creator. The row is the CURRENT spec (`registerSeries` overwrites in place). Null when never registered. #### Parameters ##### creator `string` ##### seriesId `number` #### Returns `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md) \| `null`\> *** ### getSchedulingCost() > **getSchedulingCost**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3911 The hub's MARGINAL scheduling cost for `def` — 0 when an identical template definition is already scheduled (the call would dedup), the full oracle submission cost otherwise. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> *** ### earmarkedOf() > **earmarkedOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3916 Native LOCKED for an operator's outstanding markets (wei; never withdrawable). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### creditOf() > **creditOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3921 An operator's accrued WITHDRAWABLE surplus credit on the hub (wei). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### outstandingOf() > **outstandingOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3926 Count of an operator's bound-but-unresolved markets. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### withdrawableOf() > **withdrawableOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3931 Wei an operator's owner may withdraw right now (== `creditOf`). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> *** ### payerCreditOf() > **payerCreditOf**(`payer`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3938 A1: the withdrawable surplus credited to a reserve-PAYER (an open-venue creator, or the autonomous MarketCreator on its rolls) rather than the operator; drawn by that account via `createOracleHubAdmin().withdrawMyCredit`. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### payer `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### payerOf() > **payerOf**(`marketId`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3943 A1: the reserve-payer recorded for a market at onBind (surplus recipient); zero-address once settled + swept. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### marketId `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### resolveReserve() > **resolveReserve**(): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3948 The hub's `resolveReserve()` — the per-market reserve attached+locked at onBind (wei). Chain read; needs `config.addresses.oracleHub`. #### Returns `Promise`\<`bigint`\> *** ### quoteCreateMarketValue() > **quoteCreateMarketValue**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3955 THE §8e create-market value quote: `getSchedulingCost(def) + resolveReserve()` (the reserve is attached to the create). Attach exactly this to `scheduleAndCreateMarket` (excess refunds). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> *** ### getOracleQuestion() > **getOracleQuestion**(`oracleQuestionId`): `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3960 One hub-scheduled oracle question (dedup key, scheduler, bind count) by its oracleQuestionId, or null. Indexer read. #### Parameters ##### oracleQuestionId `string` #### Returns `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md) \| `null`\> *** ### listOracleQuestions() > **listOracleQuestions**(`opts?`): `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3965 Hub-scheduled questions, newest first — filter by `scheduler` / `questionKey`, paginate. Indexer read. #### Parameters ##### opts? ###### scheduler? `string` ###### questionKey? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md)[]\> *** ### getOperatorHubAccount() > **getOperatorHubAccount**(`operatorId`): `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3975 One operator's hub account (earmarked / credit / outstanding) by operatorId, or null. Indexer read. #### Parameters ##### operatorId `string` \| `number` #### Returns `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md) \| `null`\> *** ### listOperatorHubAccounts() > **listOperatorHubAccounts**(`opts?`): `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3980 Operator hub-account records, most-recently-updated first, paginated. Indexer read. #### Parameters ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md)[]\> *** ### listOracleBinds() > **listOracleBinds**(`opts?`): `Promise`\<[`OracleBindRecord`](../type-aliases/OracleBindRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3986 Bind records (operator attribution → exact metered resolve charge + subsidy per market, §8e), newest first — filter by `operatorId` / `oracleQuestionId` / `resolved`, paginate. Indexer read. #### Parameters ##### opts? ###### operatorId? `number` ###### oracleQuestionId? `string` ###### resolved? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleBindRecord`](../type-aliases/OracleBindRecord.md)[]\> *** ### listOracleCallbacks() > **listOracleCallbacks**(`opts?`): `Promise`\<[`OracleCallbackRecord`](../type-aliases/OracleCallbackRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3998 Resolution-callback conservation records (`CallbackAccounted`), newest first, paginated (a callback drains across many questions, so no per-question filter). Indexer read. #### Parameters ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleCallbackRecord`](../type-aliases/OracleCallbackRecord.md)[]\> *** ### createTrader() > **createTrader**(`traderConfig`): [`Trader`](Trader.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4024 Build a [Trader](Trader.md) bound to a signer and this client's chain, store, and socket. With a `privateKey`/local `account` the trader signs locally (fixed fees, locally-tracked nonce — zero pre-send RPCs) and confirms in one round-trip via `eth_sendRawTransactionSync`; with a browser `walletClient` it sends through the wallet and confirms off the newHeads subscription. Every write resolves only once mined, with its receipt. With an `executor` the trader sends through it instead — see [SomniaMarketsClient.createExecutor](#createexecutor). - Throws [SignerRequiredError](../classes/SignerRequiredError.md) - none of `executor`, `privateKey`, `account` or `walletClient` (with an account) is set. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `privateKey` is not a valid secp256k1 key, or `executor` sends on a chain other than this client's. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - this client has no chain transport (no `wsRpcUrl` and a chain without a WebSocket endpoint) and no `publicClient` was passed to send through. The complete union is [SomniaMarketsClientCreateTraderError](../type-aliases/SomniaMarketsClientCreateTraderError.md). #### Parameters ##### traderConfig [`TraderConfig`](TraderConfig.md) #### Returns [`Trader`](Trader.md) *** ### createExecutor() > **createExecutor**(`spec`): [`Executor`](Executor.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4083 Build one of the built-in executors, bound to this engine's chain, socket, fee envelope and nonce lane. The spec names only who acts — a private key or local account, a wallet client, a Somnia session seed, or a smart account from `@somnia-chain/accounts-sdk` with the executor that sends its outer transaction. Hand the result to `createTrader({ executor })`, or compose it (a smart account's `inner`), or place it in a [SomniaMarketsAccount](SomniaMarketsAccount.md) for the exchange to trade through. **Gotchas** - A smart account's `inner` must be authorized on the account when nothing signs (no `signer`, no `through`): its actor must be a direct owner of a threshold-1 account. A `signer` or a `through` chain of parent accounts switches to a real signature, which the accounts SDK nests to any depth. See [ExecutorSpec](../type-aliases/ExecutorSpec.md). - An account that is not a factory account from `@somnia-chain/accounts-sdk` needs a custom [Executor](Executor.md). Its `execute` returns an inner failure as `failure` on the result; Trader writes throw it. - Before it sends or signs, a smart-account executor checks that the account has code on this chain. Missing code raises [InvalidInputError](../classes/InvalidInputError.md): create the account on this chain first. A failed read raises [RpcError](../classes/RpcError.md), and a client with no chain transport raises [NotConfiguredError](../classes/NotConfiguredError.md). Successful checks are cached. - With a `signer` or `through`, a smart-account executor runs one write at a time per account on this engine, because each write signs the account's current nonce. Two processes that write through one account (for example a backend and a browser) can still sign the same nonce. - Throws [InvalidInputError](../classes/InvalidInputError.md) - a spec that names no actor or more than one (a spec with a removed `safe` key names none), a `privateKey` or `sessionSeed` that is not a valid 32-byte key, a wallet spec with no account to act as, a smart-account spec whose `inner` sends on another chain, a smart-account spec on a chain the accounts SDK has no deployment for, or a `through` spec with no `signer` and an `inner` that cannot sign typed data. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - a key, account, wallet or session spec on a client with no chain transport (no `wsRpcUrl` and a chain without a WebSocket endpoint); a smart-account spec needs none of its own. - An account's `inner` signs locally. A smart-account spec whose `inner` came from `{ sessionSeed }` throws [InvalidInputError](../classes/InvalidInputError.md): that executor sends the seed to the node on every write, and the seed would then control the account's funds. Use `{ privateKey }`; for a Somnia session seed the key is `sessionPrivateKey(seed)`. Do not also send node-side from that seed: both modes share one nonce space. The complete union is [SomniaMarketsClientCreateExecutorError](../type-aliases/SomniaMarketsClientCreateExecutorError.md). **Example** (A factory smart account driven by a local session key) ```ts const session = client.createExecutor({ privateKey: sessionKey }); const account = client.createExecutor({ smartAccount: ACCOUNT, inner: session }); const trader = client.createTrader({ executor: account }); await trader.placeOrder(params); // approval + order in ONE account transaction, nothing signs ``` #### Parameters ##### spec [`ExecutorSpec`](../type-aliases/ExecutorSpec.md) #### Returns [`Executor`](Executor.md) *** ### createOperatorAdmin() > **createOperatorAdmin**(`config`): [`OperatorAdmin`](OperatorAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4090 Build an [OperatorAdmin](OperatorAdmin.md) bound to a signer — registers/updates operators and creates/updates venues on MarketsCore. Same signer doctrine as [createTrader](#createtrader) (privateKey/local account, or a browser walletClient). #### Parameters ##### config [`OperatorAdminConfig`](OperatorAdminConfig.md) #### Returns [`OperatorAdmin`](OperatorAdmin.md) *** ### createOracleHubAdmin() > **createOracleHubAdmin**(`config`): [`OracleHubAdmin`](OracleHubAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4101 Build an [OracleHubAdmin](OracleHubAdmin.md) bound to a signer — the OracleHub surface (Oracle v2 §8e): quote reads (`quoteCreateMarketValue` = the §8e create value = scheduling cost + resolveReserve), the credit-only `withdraw` (owner-gated — draws accrued surplus credit only), and the protocol-admin writes (fundHub, gas + drain params, enableReactivity/migrateSubscription — precompile, testnet/mainnet only). Same signer doctrine as [createOperatorAdmin](#createoperatoradmin). Needs `config.addresses.oracleHub`. #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`OracleHubAdmin`](OracleHubAdmin.md) *** ### createGovernanceAdmin() > **createGovernanceAdmin**(`config`): [`GovernanceAdmin`](GovernanceAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4109 Build a [GovernanceAdmin](GovernanceAdmin.md) bound to a signer — the protocol-admin-only surface that approves oracle adapters on the module (`setAdapterApproved`; in Oracle v2 the ONE approved adapter is the OracleHub — deploy wiring + emergency revoke). Gate its UI on [GovernanceAdmin.isModuleOwner](GovernanceAdmin.md#ismoduleowner). #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`GovernanceAdmin`](GovernanceAdmin.md) *** ### createMarketCreatorAdmin() > **createMarketCreatorAdmin**(`config`): [`MarketCreatorAdmin`](MarketCreatorAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4116 Build a [MarketCreatorAdmin](MarketCreatorAdmin.md) bound to a signer — stamps MarketCreators (+ policies) from the factory, registers rolling series under them, funds them, and triggers rolls. Same signer doctrine as [createOperatorAdmin](#createoperatoradmin). #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`MarketCreatorAdmin`](MarketCreatorAdmin.md) --- # /docs/typescript/api/index/interfaces/SomniaMarketsClientWithObservations [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientWithObservations # Interface: SomniaMarketsClientWithObservations Defined in: packages/sdk/src/somniaMarketsClient.ts:4120 Concrete configured client with opt-in data observations. Existing client implementations need not provide these additions. ## Extends - [`SomniaMarketsClient`](SomniaMarketsClient.md) ## Properties ### config > `readonly` **config**: [`ClientConfig`](ClientConfig.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:518 The config this client was built with. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`config`](SomniaMarketsClient.md#config) *** ### lend > `readonly` **lend**: [`SomniaLendClient`](SomniaLendClient.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:569 The SomniaLend namespace — reads (`lend.listReserves()`, `lend.getAccount()`) and the `lend.createLender()` write factory for the third-party Aave v3 money market on Somnia (mainnet + testnet). Lazily bound to `config.addresses.lend` (set `SOMNIA_MAINNET_LEND` / `SOMNIA_TESTNET_LEND` from the root entry); its methods throw a clear error when those addresses are unset. The root entry also publishes its types, deployment constants, ray-math helpers and ABIs; this namespace is the only way to call it, so a lend read always rides the client's own chain transport. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`lend`](SomniaMarketsClient.md#lend) *** ### accounts > `readonly` **accounts**: [`SmartAccountsClient`](SmartAccountsClient.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:579 The smart-accounts capability — the factory account model of `@somnia-chain/accounts-sdk` on this client's chain: derive and discover accounts, walk ownership, build creation / owner-management / transfer calls for an executor to send, and read holdings and health. Built lazily; reads ride this client's own chain transport. See [SmartAccountsClient](SmartAccountsClient.md), and `createExecutor({ smartAccount, inner })` for sending AS an account. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`accounts`](SomniaMarketsClient.md#accounts) ## Methods ### getViemClient() > **getViemClient**(): `object` Defined in: packages/sdk/src/somniaMarketsClient.ts:556 This client's underlying viem client, undecorated — viem's own behaviour, over the socket this client already has. **When to use** Use to reach a contract or RPC method the SDK does not model: your own contracts, or plain calls like `getBalance` / `getCode` / `waitForTransactionReceipt`. Reads through it keep VIEM's error contract, so `e instanceof ContractFunctionRevertedError` and the rest of your existing viem error handling still work. Building your own client instead would open a second WebSocket; this one shares the SDK's. **Details** - Returns: The undecorated viem `PublicClient` for this client's chain. **Gotchas** Reads through this client do NOT get the SDK's decoded protocol errors — a revert arrives as viem's error, not a [ContractRevertError](../classes/ContractRevertError.md) with an `errorName`. That is the point of the accessor, but it means you should prefer the SDK's own methods for protocol contracts, where the decoding is the value. The two clients are deliberately different: everything reachable from this interface uses the decoded one. Calling this opens the WebSocket if it is not already open, and throws [NotConfiguredError](../classes/NotConfiguredError.md) on a client built without `wsRpcUrl`. The returned client belongs to this client's current connection. After `stopLive()` or the owner's `close()`, its requests reject with viem's `SocketClosedError`, and it never opens a socket again. Call `getViemClient()` again after `stopLive()` to get a working client. #### Returns `object` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getViemClient`](SomniaMarketsClient.md#getviemclient) *** ### watchMarket() > **watchMarket**(`pool`, `opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:657 Watch one market: hydrate a consistent snapshot of it (market row, recent fills, its full resting order book) and stream its events — order-book activity plus, for a binary market, its lifecycle/status events. While the watch is active, every `getLive*` read for this pool is current to the last block at zero round-trip cost. Watches are **ref-counted**: watching the same pool twice shares one subscription and one snapshot; each handle's `stop()` releases one reference, and the scope is torn down (subscription dropped, heavy rows purged) shortly after the last release — a brief linger absorbs quick re-watches (navigation, React remounts) without re-snapshotting. Resolves once the seam is sealed (snapshot + backfill + buffered replay) — i.e. once reads are live. Rejects (and releases the reference) if hydration fails; the socket dropping later is healed automatically by reconnect + chain backfill. The React data hooks call this automatically while mounted. **Details** `opts` opts INTO a chain seed. Omit it and the watch seeds from the indexer snapshot exactly as before, and `getLiveStatus().snapshotBlock` keeps its existing meaning. Pass `{ seed: "chain", marketId }` and the book is drained from the pool contract at one pinned block instead, so the watch starts with the indexer unreachable. Supply the `marketId` the pool currently serves: pools are recycled across markets and book reads filter on it. A chain seed also reads the market's row from the BinaryMarketsModule, so `config.addresses.binaryModule` must be set — the row is what every later order and fill event attributes through. It carries what the module answers (collateral, decimals, nonce, lifecycle state); indexer-only fields such as the question text, `strike`/`mode` and the creation history stay empty or null and STAY that way — a seeded pool is never re-hydrated, and the row outlives `stop()` until cold-market eviction drops it (see [getLiveMarkets](SomniaMarketsClient.md#getlivemarkets)). Read the indexer directly ([getBinaryMarket](SomniaMarketsClient.md#getbinarymarket)) when those fields are needed. A chain seed covers exactly ONE pool. N pools means N calls, which is the supported way to seed several: they share one tail and one subscription set, and each pool keeps its own seed status. Read that with [getSeedStatus](SomniaMarketsClient.md#getseedstatus), NOT [getLiveStatus](SomniaMarketsClient.md#getlivestatus), whose seed fields report the most recent seed only and are overwritten by the next pool's. The worst-case read cost is `2 × maxPages` contract reads per pool, 80 at the defaults, plus one module read for the market row. A chain seed has no per-scope order cap, unlike the indexer snapshot, whose budget is shared across the scope's pools and drops the OLDEST resting orders first. `getSeedStatus(pool).seedTruncated` is `true` only if that pool's drain hit its own page budget. **Gotchas** A chain seed loads NO fill history — the chain cannot answer fills from before the seam. The tape loads on a detached lane, so `getLiveFills` may be empty while the book is complete. Branch on `getSeedStatus(pool).fillsLoaded`, not on the tape being empty: `false` means never loaded, `true` with `[]` means genuinely no fills. The global `getLiveStatus().fillsLoaded` turns true when ANY pool's lane lands, so it cannot answer for one pool. A failed tape read sets `failure.operation` to `"fill-history"` and does not reject this promise. Seeded orders carry an empty `createdAt`/`txHash`: placement history is indexer-only and the seed does not invent it. `userOrders` sorts on `createdAt`, so they sort last until a snapshot dates them. #### Parameters ##### pool `string` ##### opts? [`SeedOptions`](SeedOptions.md) #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Throws [IndexerError](../classes/IndexerError.md) If the indexer snapshot fails (default seed only). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If a chain seed is requested with no `addresses.binaryModule`, or the indexer does not index the client's chain. #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.maxCount`/`opts.maxPages` is not a positive safe integer, or `opts.marketId` is not a bytes32 id. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If a chain-seed page read reverts. #### Throws [RpcError](../classes/RpcError.md) If a chain read or the subscription fails at the transport. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchMarket`](SomniaMarketsClient.md#watchmarket) *** ### watchMarkets() > **watchMarkets**(`opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:685 Watch every market whose book or lifecycle can still change — the whole-protocol tail for list views and multi-market bots. Prefer [watchMarket](SomniaMarketsClient.md#watchmarket) scoped to what you actually trade or render: this variant's cost grows with the protocol (snapshot size, subscription filter width, event volume). **Details** The watch selects markets by lifecycle, not by age. It hydrates every SPOT and PERP market and every BINARY market that is not finalized, which includes Locked, Settling, Resolved and Voided markets that still wait for settlement events. A finalized BINARY market is left out: its status is terminal, its book holds no live order, and its pool can serve a later market. Its redemption ledger (`netBacking`) keeps moving on the settlement contract, so read it with [getBinaryMarket](SomniaMarketsClient.md#getbinarymarket). [watchMarket](SomniaMarketsClient.md#watchmarket) applies no lifecycle filter, but it selects the market its pool serves now: it hydrates a finalized market only until the pool is recycled. One snapshot hydrates at most 500 eligible markets, newest first, so that the whole set shares one seam. When more eligible markets exist, `getLiveStatus().allMarketsTruncated` is `true` while this watch is active, and the oldest eligible markets are not watched. Watch those with [watchMarket](SomniaMarketsClient.md#watchmarket). - `opts.discover`: Also watch the MarketCreator factory so markets created AFTER this call join the watch live, in their creation block (requires `config.addresses.marketCreator`). Off by default. #### Parameters ##### opts? ###### discover? `boolean` #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchMarkets`](SomniaMarketsClient.md#watchmarkets) *** ### watchUser() > **watchUser**(`user`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:696 Hydrate one account's order/fill **history** (one indexer fetch) so [getLiveUserFills](SomniaMarketsClient.md#getliveuserfills) / [getLiveUserOrders](SomniaMarketsClient.md#getliveuserorders) have depth predating your watches. This does not subscribe to anything by itself: live events are attributed to every account automatically, but only within markets covered by an active [watchMarket](SomniaMarketsClient.md#watchmarket) / [watchMarkets](SomniaMarketsClient.md#watchmarkets) — an account's activity in unwatched markets stays at snapshot state. Ref-counted like market watches; supports multiple accounts at once. #### Parameters ##### user `string` #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchUser`](SomniaMarketsClient.md#watchuser) *** ### watchPerpMarkets() > **watchPerpMarkets**(`opts?`): `Promise`\<[`WatchHandle`](WatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:732 Watch the perp **plane**: hydrate the recent liquidation waterfall legs and per-account funding settlements, then stream both live — the same snapshot-then-live guarantee [watchMarket](SomniaMarketsClient.md#watchmarket) gives a book. ONE scope covers every perp market, and that is forced rather than chosen. MarginBank and LiquidationEngine are singletons, so the log subscription is one stream whatever the caller asks for — and the account-level waterfall legs (`AccountLiquidated`, `ResidualBadDebt`, ...) carry no pool at all, so a per-pool scope would either drop them or attach them to every pool. Filter at read time with [listLiveLiquidations](SomniaMarketsClient.md#listliveliquidations) / [listLiveFundingPayments](SomniaMarketsClient.md#listlivefundingpayments) instead. Independent of [watchMarket](SomniaMarketsClient.md#watchmarket): watching a perp pool gives you its book, funding RATE and open interest; this gives you liquidations and funding SETTLEMENT. Neither implies the other, and a UI showing both wants both watches. Ref-counted and lingered like the other watches. Resolves once the seam is sealed; a later socket drop is healed by reconnect and chain backfill, with no second indexer touch. **Details** - `opts.marginBank`: The MarginBank to read the plane's wiring from. Normally UNNECESSARY — the address is taken from an indexed perp market row, and `MarginBank.getSystemConfig()` reports the LiquidationEngine from there. Pass it for the one case that cannot cover: an indexer with no perp rows at all, where there is nothing to ask. It is a FALLBACK, never an override: it is used when the indexer names no bank, including on a scope a read hook acquired moments earlier with no hint to give, and it is ignored when the indexer named one — the hydrated rows are that bank's plane, so streaming another one would splice two venues into one feed. #### Parameters ##### opts? [`WatchPerpMarketsOptions`](WatchPerpMarketsOptions.md) #### Returns `Promise`\<[`WatchHandle`](WatchHandle.md)\> #### Throws InvalidInputError when `opts.marginBank` is not an address. #### Throws IndexerError when the plane snapshot fails. #### Throws RpcError when the MarginBank wiring read or the seam's head read fails — the liquidation half cannot be watched without the wiring, and watching the bank alone would stream funding settlements and no liquidations, which reads as a venue with none. #### Throws ContractRevertError when the resolved MarginBank — indexed, or supplied via `opts.marginBank` — reverts on `getSystemConfig()`, i.e. it is not a MarginBank the SDK can read. #### Throws NotConfiguredError on a client built without `wsRpcUrl` or `indexerUrl`, or whose indexer does not index its chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchPerpMarkets`](SomniaMarketsClient.md#watchperpmarkets) *** ### getWatchStatus() > **getWatchStatus**(`pool`): [`WatchStatus`](../type-aliases/WatchStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:740 Per-market watch state: `"unwatched"` (no active watch — `getLive*` reads return empty for this pool, which is how you distinguish "empty book" from "not watching"), `"hydrating"` (watch registered; snapshot, seam backfill, or reconnect in progress), or `"live"`. #### Parameters ##### pool `string` #### Returns [`WatchStatus`](../type-aliases/WatchStatus.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getWatchStatus`](SomniaMarketsClient.md#getwatchstatus) *** ### getPerpPlaneStatus() > **getPerpPlaneStatus**(): [`WatchStatus`](../type-aliases/WatchStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:746 Perp-plane watch state, in the same three values [getWatchStatus](SomniaMarketsClient.md#getwatchstatus) uses — so `"unwatched"` distinguishes "no liquidations happened" from "not watching". #### Returns [`WatchStatus`](../type-aliases/WatchStatus.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpPlaneStatus`](SomniaMarketsClient.md#getperpplanestatus) *** ### stopLive() > **stopLive**(): `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:763 Tear down every watch, subscription, timer, and socket this client opened (tests, shutdown), including the chain WebSocket — so a Node process that has touched the chain exits on its own afterwards. The store keeps its last state; `getLive*` and `listLive*` reads keep answering (stale), and a later chain read reopens a connection that the next `stopLive()` releases in turn. An indexer read already on the wire stays active, but one still QUEUED for an in-flight slot, or sleeping out a retry backoff, is rejected with [IndexerUnavailableError](../classes/IndexerUnavailableError.md) (`reason: "live-reset"`), so nothing sends after the stop. The client stays usable. Existing observed-read capabilities are invalidated; create a new one before observing again. Each client owns its own chain socket, even when several use the same `wsRpcUrl`, so stopping one never closes another's. #### Returns `void` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`stopLive`](SomniaMarketsClient.md#stoplive) *** ### subscribeLive() > **subscribeLive**(`listener`): () => `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:775 Fire `listener` after every batch of store changes — the "something changed, re-read" signal (the React hooks subscribe to exactly this). Re-read with any `getLive*` method; their results are memoized per store version, so re-reading without a change returns the same reference. **Details** - Returns: An unsubscribe function. #### Parameters ##### listener () => `void` #### Returns () => `void` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`subscribeLive`](SomniaMarketsClient.md#subscribelive) *** ### getLiveStatus() > **getLiveStatus**(): [`TailStatus`](TailStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:783 The tail's global health: mode (`"init"` until the first watch hydrates, then `"tailing"`), the last seam block, the last locally-materialized block, the chain head, socket state, and the active watch count. For one market's state, use [getWatchStatus](SomniaMarketsClient.md#getwatchstatus). #### Returns [`TailStatus`](TailStatus.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveStatus`](SomniaMarketsClient.md#getlivestatus) *** ### getSeedStatus() > **getSeedStatus**(`pool`): [`PoolSeedStatus`](PoolSeedStatus.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:811 One watched pool's OWN seed status, or `null` when the pool is not hydrated. **When to use** Use it whenever more than one pool is watched. [getLiveStatus](SomniaMarketsClient.md#getlivestatus) reports `seedSource`, `seedBlock`, `seedTruncated` and `fillsLoaded` for the MOST RECENT seed only, so with several pools those values cannot be attributed to a pool: a later seed writes `seedTruncated: false` over an earlier `true`, and `fillsLoaded` turns true when any pool's lane lands. **Gotchas** `null` means this pool has no hydrated watch — never that its seed was complete. Check [getWatchStatus](SomniaMarketsClient.md#getwatchstatus) to tell an unwatched pool from one still hydrating. A released watch drops its entry, so a rewatched pool cannot read the previous watch's truncation or fill-lane result. ```ts const seed = client.getSeedStatus(pool); if (seed && !seed.fillsLoaded) console.log("tape not loaded for", pool); ``` #### Parameters ##### pool `string` #### Returns [`PoolSeedStatus`](PoolSeedStatus.md) \| `null` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSeedStatus`](SomniaMarketsClient.md#getseedstatus) *** ### isTailing() > **isTailing**(): `boolean` Defined in: packages/sdk/src/somniaMarketsClient.ts:814 True once at least one watch is live (`mode === "tailing"`). #### Returns `boolean` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`isTailing`](SomniaMarketsClient.md#istailing) *** ### getLiveMarkets() > **getLiveMarkets**(): [`Market`](../type-aliases/Market.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:829 Every market the store retains (spot + binary, as the discriminated [Market](../type-aliases/Market.md) union), from any watch, past or present. Synchronous, memoized. The store always keeps a market that a pool is bound to or that a retained fill or order names. It keeps other markets (released or replaced) as metadata up to a fixed allowance of 500 rows and evicts the earliest-discovered ones after that. So the list does not grow with session age. An evicted market is also absent from [getLiveMarketByAddress](SomniaMarketsClient.md#getlivemarketbyaddress), and its late settlement events do not change the live store. Read it with [getMarket](SomniaMarketsClient.md#getmarket) or [getBinaryMarket](SomniaMarketsClient.md#getbinarymarket). #### Returns [`Market`](../type-aliases/Market.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveMarkets`](SomniaMarketsClient.md#getlivemarkets) *** ### getLiveMarketByPool() > **getLiveMarketByPool**(`pool`): [`Market`](../type-aliases/Market.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:832 One market by its pool address (either kind), or null if unknown. #### Parameters ##### pool `string` #### Returns [`Market`](../type-aliases/Market.md) \| `null` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveMarketByPool`](SomniaMarketsClient.md#getlivemarketbypool) *** ### getLiveMarketByAddress() > **getLiveMarketByAddress**(`marketAddress`): [`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:838 One binary market by its BinaryMarket contract address, or null. (Spot markets have no market contract — they are identified by pool.) #### Parameters ##### marketAddress `string` #### Returns [`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveMarketByAddress`](SomniaMarketsClient.md#getlivemarketbyaddress) *** ### getLiveFills() > **getLiveFills**(`pool`, `opts?`): [`LiveFill`](LiveFill.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:848 The most recent fills on one pool, newest first — the live trade tape. Maker/taker owner + side are back-joined from the order map where known. **Details** - `opts.limit`: Max rows (default 40; the store retains ~400 per pool). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns [`LiveFill`](LiveFill.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveFills`](SomniaMarketsClient.md#getlivefills) *** ### getLiveFundingUpdates() > **getLiveFundingUpdates**(`pool`, `opts?`): [`LiveFundingUpdate`](LiveFundingUpdate.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:866 Funding settlements the live tail has seen for a perp pool, OLDEST FIRST. The tail's counterpart to [listFundingRateHistory](SomniaMarketsClient.md#listfundingratehistory): splice these onto a one-shot query to extend a funding chart past the snapshot block, instead of only seeing the latest value on the market row. Deduped on (block, logIndex), so a reorg replay overwrites rather than appending a phantom point. Carries less than an indexed row, deliberately: `intervalsAccrued` needs `n` from the parameter-epoch series and the covered span needs the settlement anchor, neither of which the tail has. Both arrive with the indexed row a moment later. **Details** - `opts.limit`: Max rows (default 500). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns [`LiveFundingUpdate`](LiveFundingUpdate.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveFundingUpdates`](SomniaMarketsClient.md#getlivefundingupdates) *** ### listLiveLiquidations() > **listLiveLiquidations**(`opts?`): [`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:891 Liquidation waterfall legs the tail has seen, newest first — the live counterpart to [getLiquidations](SomniaMarketsClient.md#getliquidations), and the SAME [LiquidationEvent](../type-aliases/LiquidationEvent.md) rows, so the two merge without translation. The live window is hydrated from the newest indexed rows, so it OVERLAPS the newest indexed page: merge by `id`, never by concatenation, or legs and their amounts are counted twice. Requires an active [watchPerpMarkets](SomniaMarketsClient.md#watchperpmarkets). Without one this returns empty, except after [stopLive](SomniaMarketsClient.md#stoplive), which keeps the store: the last rows stay readable but stale. Check [getPerpPlaneStatus](SomniaMarketsClient.md#getperpplanestatus) rather than treating a non-empty result as current. One liquidation is SEVERAL rows sharing a `txHash` — stages of one waterfall, not repetitions of one event. Read `kind` first, and read the field TSDoc on [LiquidationEvent](../type-aliases/LiquidationEvent.md) before aggregating anything: only `insuranceCovered` and `coverageDeclined` are flows, while `badDebt` and `deficit` are levels that double-count when summed. **Details** - `opts.pool`: Restrict to one pool. This DROPS the account-level legs, which carry no pool — the same partial view the indexed read's nullable `pool` column gives. Filter by `account` for the whole story. - `opts.account`: Restrict to the LIQUIDATED account. An account assigned into an ADL as the profitable counterparty has no row of its own; it appears in `counterparty` instead. - `opts.limit`: Max rows (default 50; the store retains ~1000 plane rows). #### Parameters ##### opts? [`ListLiveLiquidationsOptions`](ListLiveLiquidationsOptions.md) #### Returns [`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listLiveLiquidations`](SomniaMarketsClient.md#listliveliquidations) *** ### listLiveFundingPayments() > **listLiveFundingPayments**(`opts?`): [`FundingPayment`](../type-aliases/FundingPayment.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:909 Per-account funding settlements the tail has seen, newest first — the live counterpart to [getFundingPayments](SomniaMarketsClient.md#getfundingpayments), and the same [FundingPayment](../type-aliases/FundingPayment.md) rows. Requires an active [watchPerpMarkets](SomniaMarketsClient.md#watchperpmarkets). After [stopLive](SomniaMarketsClient.md#stoplive) the last rows stay readable but stale; check [getPerpPlaneStatus](SomniaMarketsClient.md#getperpplanestatus). Distinct from [getLiveFundingUpdates](SomniaMarketsClient.md#getlivefundingupdates), which is the per-pool RATE series: this is what each account actually paid or received. `amount` is signed, and **positive is what the account pays**. **Details** - `opts.pool`: Restrict to one pool. - `opts.account`: Restrict to one account. - `opts.limit`: Max rows (default 50; the store retains ~1000 plane rows). #### Parameters ##### opts? [`ListLiveFundingPaymentsOptions`](ListLiveFundingPaymentsOptions.md) #### Returns [`FundingPayment`](../type-aliases/FundingPayment.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listLiveFundingPayments`](SomniaMarketsClient.md#listlivefundingpayments) *** ### getLiveUserFills() > **getLiveUserFills**(`pool`, `user`, `opts?`): [`LiveFill`](LiveFill.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:919 Fills `user` participated in (as maker or taker), newest first. **Details** - `pool`: Restrict to one pool, or null for all pools. - `opts.limit`: Max rows (default 50). #### Parameters ##### pool `string` \| `null` ##### user `string` ##### opts? ###### limit? `number` #### Returns [`LiveFill`](LiveFill.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveUserFills`](SomniaMarketsClient.md#getliveuserfills) *** ### getLiveUserOrders() > **getLiveUserOrders**(`pool`, `user`, `opts?`): [`LiveOrder`](LiveOrder.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:943 `user`'s orders on one pool, newest first — every lifecycle state (open, filled, cancelled, expired), so filter by `status === "Open"` for a working-orders view. Keeps every unexpired open order, recent terminal transitions, and terminal orders needed to attribute retained fills. An `Open` order past its expiry at the latest chain head is history, not liquidity: from that head it counts toward the terminal cap. Its status stays `Open`, because on chain it holds its escrow until a cancel or a sweep, and removal from the live store does not mean a refund. An active [watchUser](SomniaMarketsClient.md#watchuser) keeps all of its user's expired open orders until the watch is released. Older terminal history is available from [getOrders](SomniaMarketsClient.md#getorders); terminal history remains bounded even after a long watch. Accepted indexed `Closed` rows count toward the cap at hydration. A live `Closed` row waits for a later block from its pool so a delayed same-block `OrderRested` can promote it. An active [watchUser](SomniaMarketsClient.md#watchuser) also retains its seeded orders until that watch is released. Rows retained after a market watch ends remain account history, not book liquidity. **Details** - `opts.limit`: Max rows (default 100). #### Parameters ##### pool `string` ##### user `string` ##### opts? ###### limit? `number` #### Returns [`LiveOrder`](LiveOrder.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveUserOrders`](SomniaMarketsClient.md#getliveuserorders) *** ### getLiveBinaryOrderBook() > **getLiveBinaryOrderBook**(`pool`, `opts?`): [`BinaryOrderBook`](BinaryOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:957 The locally-materialized resting book of a **binary** pool, 4-sided (`yesBids`/`yesAsks` plus the NO sides derived as `1 − yesPrice`) — the event-derived book with a per-scope applied-event watermark. Heads alone do not advance `blockNumber`. Expiry uses the local wall clock. Use the pinned chain read for an exact as-of snapshot. Synchronous; safe to call every render (memoized per store version). **Details** - `opts.depth`: Price levels per side (default 10). #### Parameters ##### pool `string` ##### opts? ###### depth? `number` #### Returns [`BinaryOrderBook`](BinaryOrderBook.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveBinaryOrderBook`](SomniaMarketsClient.md#getlivebinaryorderbook) *** ### getLiveBinaryOrderBookByMarket() > **getLiveBinaryOrderBookByMarket**(`marketId`, `opts?`): [`BinaryOrderBook`](BinaryOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:974 The locally-materialized resting book of a **binary** market, resolved by its `marketId` rather than its pool address. Because a BinaryPool is RECYCLED across markets (one pool serves successive markets, never concurrently), a page keyed on a `marketId` must never render the pool's NEXT market's orders once its own market has ended. This read resolves the market's current pool and, if `marketId` is no longer the pool's current binding (stale/ended), returns an EMPTY book — so a stale page renders nothing rather than the successor market's liquidity. Prefer this over [getLiveBinaryOrderBook](SomniaMarketsClient.md#getlivebinaryorderbook) when you hold a `marketId` (not a live pool). **Details** - `opts.depth`: Price levels per side (default 10). #### Parameters ##### marketId `string` ##### opts? ###### depth? `number` #### Returns [`BinaryOrderBook`](BinaryOrderBook.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveBinaryOrderBookByMarket`](SomniaMarketsClient.md#getlivebinaryorderbookbymarket) *** ### getLiveSpotOrderBook() > **getLiveSpotOrderBook**(`pool`, `opts?`): [`SpotOrderBook`](SpotOrderBook.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:984 The locally-materialized resting book of a **spot** pool (`bids`/`asks`, best price first) — the zero-round-trip mirror of [getSpotOrderBook](SomniaMarketsClient.md#getspotorderbook). **Details** - `opts.depth`: Price levels per side (default 12). #### Parameters ##### pool `string` ##### opts? ###### depth? `number` #### Returns [`SpotOrderBook`](SpotOrderBook.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiveSpotOrderBook`](SomniaMarketsClient.md#getlivespotorderbook) *** ### quoteBinaryOrder() > **quoteBinaryOrder**(`params`): [`BinaryOrderQuote`](BinaryOrderQuote.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:1006 Preview a MARKET order against the live binary book — "you'll pay ~$X, average Y, slippage Z". Pure over the live store (synchronous); key it by `pool` (a live pool) or `marketId` (recycle-safe — a stale market quotes against an empty book). Crossing side: BUY_YES/BUY_NO consume the asks, SELL_YES/SELL_NO the bids; NO prices are the YES book inverted (`oneCollateral − yesPrice`). `cost` is raw collateral paid (buy) / received (sell); `avgPrice` the volume-weighted fill price; `wouldRest` the unfilled remainder that would rest as a maker order. **Details** - `params.quantity`: Order size in raw outcome-token units. - `params.depth`: Book levels to walk per side (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinarySide`](../type-aliases/BinarySide.md) ###### quantity `bigint` ###### depth? `number` #### Returns [`BinaryOrderQuote`](BinaryOrderQuote.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quoteBinaryOrder`](SomniaMarketsClient.md#quotebinaryorder) *** ### getBinaryBookParams() > **getBinaryBookParams**(`pool`): `Promise`\<[`BinaryBookParams`](BinaryBookParams.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1021 A BinaryPool's on-chain order-book grid (`tickSize`/`lotSize`/`minQuantity`) — the increments the pool validates every order against. One `eth_call`, cached per pool for the client's lifetime (the grid is admin-retunable but never changes per-order). [quoteBinaryStake](SomniaMarketsClient.md#quotebinarystake) and [quoteBinarySell](SomniaMarketsClient.md#quotebinarysell) read it through this cache. #### Parameters ##### pool `string` #### Returns `Promise`\<[`BinaryBookParams`](BinaryBookParams.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBinaryBookParams`](SomniaMarketsClient.md#getbinarybookparams) *** ### getClosingPrice() > **getClosingPrice**(`pool`): `Promise`\<[`ClosingPriceState`](ClosingPriceState.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1040 A BinaryPool's captured closing price and close state — the snapshot a `CLOB_SNAPSHOT` venue's void pays out against (`[p, D−p]` at the closing YES price instead of the uniform half-refund). One `eth_call`. Resolves `null` when the pool predates the capture surface: the selector doubles as the capability probe, mirroring how the module resolves a market's void policy at creation. `state` is `"OPEN"` until [Trader.captureClose](Trader.md#captureclose) (or a normal resolution) has run. `null` is that capability answer and nothing else. A failed read throws: `RpcError` on a transport failure, `ContractRevertError` on a revert that names an error or a reason. #### Parameters ##### pool `string` #### Returns `Promise`\<[`ClosingPriceState`](ClosingPriceState.md) \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The pool declares `closingPrice()` and rejected the call. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getClosingPrice`](SomniaMarketsClient.md#getclosingprice) *** ### quoteBinaryStake() > **quoteBinaryStake**(`params`): `Promise`\<[`BinaryStakeQuote`](BinaryStakeQuote.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1066 Size a stake-denominated market BUY against the live binary book — "bet $50 on Up" → the shares, protective limit, and escrow the order will actually use. The inverse of [quoteBinaryOrder](SomniaMarketsClient.md#quotebinaryorder): that prices a quantity; this sizes a quantity from a collateral budget, walking the asks cheapest-first while the escrow at the worst level touched stays within the stake. The protective limit is padded with a slippage cushion (so the IOC still crosses a moving book), tick-aligned, and the quantity re-fit and lot-aligned so the escrow never exceeds the stake. Live store + one cached chain read ([getBinaryBookParams](SomniaMarketsClient.md#getbinarybookparams)); needs an active watch for the book. The result feeds straight into `trader.placeOrder({ pool, side, price: yesPrice, quantity, orderType: ORDER_TYPE.MARKET })`. Resolves `null` when nothing is fillable (empty book, or a stake too small to buy a single lot). **Details** - `params.side`: "BUY_YES" (Up) or "BUY_NO" (Down). - `params.stake`: Collateral budget in raw units — the max loss. - `params.depth`: Book levels to sweep (default 10). - `params.slippageBps`: Protective-limit cushion in bps (default 300 = 3%). - `params.slippageMinTicks`: Minimum cushion in ticks (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinaryBuySide`](../type-aliases/BinaryBuySide.md) ###### stake `bigint` ###### depth? `number` ###### slippageBps? `bigint` ###### slippageMinTicks? `bigint` #### Returns `Promise`\<[`BinaryStakeQuote`](BinaryStakeQuote.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quoteBinaryStake`](SomniaMarketsClient.md#quotebinarystake) *** ### quoteBinarySell() > **quoteBinarySell**(`params`): `Promise`\<[`BinarySellQuote`](BinarySellQuote.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1093 Build a market SELL that unwinds an outcome position by crossing the resting bids, with a tick-aligned slippage cushion below the best bid — the sell-side sibling of [quoteBinaryStake](SomniaMarketsClient.md#quotebinarystake) (see it for the family's mental model and tiering). Resolves `null` when there's no bid to cross or nothing to sell — disable the Sell control rather than sending a doomed order. The quote's `fillableQuantity`/`estProceeds` report what the crossable bids can actually absorb — warn on a partial unwind before submitting. **Details** - `params.side`: "SELL_YES" (Up position) or "SELL_NO" (Down position). - `params.quantity`: Outcome tokens to sell, raw units (lot-aligned down). - `params.depth`: Book levels to resolve (default 10). - `params.slippageBps`: Protective-floor cushion in bps (default 300 = 3%). - `params.slippageMinTicks`: Minimum cushion in ticks (default 10). #### Parameters ##### params ###### pool? `string` ###### marketId? `string` ###### side [`BinarySellSide`](../type-aliases/BinarySellSide.md) ###### quantity `bigint` ###### depth? `number` ###### slippageBps? `bigint` ###### slippageMinTicks? `bigint` #### Returns `Promise`\<[`BinarySellQuote`](BinarySellQuote.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quoteBinarySell`](SomniaMarketsClient.md#quotebinarysell) *** ### getMarketStats24h() > **getMarketStats24h**(`target`): `Promise`\<[`MarketStats24h`](MarketStats24h.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1109 A market's trailing-24h stats (volume, trades, price change, high/low/open), summed from 1h OHLCV candle buckets — cheaper than scanning fills. Key it by `pool` or `marketId`. Prices are raw quote units; volume is raw collateral. One indexer round-trip. #### Parameters ##### target ###### pool? `string` ###### marketId? `string` #### Returns `Promise`\<[`MarketStats24h`](MarketStats24h.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketStats24h`](SomniaMarketsClient.md#getmarketstats24h) *** ### getBinaryPositionPnL() > **getBinaryPositionPnL**(`account`, `marketId`): `Promise`\<[`BinaryPositionPnL`](BinaryPositionPnL.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1147 An account's position + cost basis + PnL in one binary market, RAW units. Reconstructs cost basis (weighted-average) from the account's order-book fills on the market folded with complete-set mints/merges, marks the CURRENT balances to the book-clamped last price (see `markYesPrice`; the settlement payout once resolved), and realizes sells against the running average. Best-effort over indexed fills; see [BinaryPositionPnL](BinaryPositionPnL.md) for the accounting assumptions. One fan-out of indexer reads plus one top-of-book `eth_call` (skipped, falling back to `lastPrice` alone, when no chain client is configured). Every money field is BLENDED across both outcomes; `outcomes.yes` / `outcomes.no` carry each book on its own. Both are needed for a wallet holding YES and NO, where the blend can read `0` while the legs are large and opposite. RAW units throughout — format with `market.quoteDecimals`. A market that has never traded has NO price to mark against, so every mark-derived field is `null`: `markValue` and `unrealizedPnl`, and `markPrice` / `markValue` / `unrealizedPnl` on each leg. Show those as unknown; do NOT treat them as zero. `balance`, `costBasis`, `avgCost` and `realizedPnl` never depend on a mark and stay exact. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the account is unusable. - Throws [InvalidInputError](../classes/InvalidInputError.md) - no binary market with that id, or a voided market carrying a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [IndexerError](../classes/IndexerError.md) - a fills, actions or balances read did not complete, OR an indexed fill or router action is malformed: an `id` that is not `` `${blockNumber}_${logIndex}` ``, or a `quantity`, `fillPrice` or mint/merge `amount` that is not an unsigned decimal number. This method fetches those rows itself, so a row it cannot read is corrupt indexed data, never a bad argument; the specific parse failure is on `cause`. - Throws [RpcError](../classes/RpcError.md) - the top-of-book `eth_call` did not complete (only with a chain client configured; a failed read is never marked on `lastPrice` as if it had succeeded). - Throws [ContractRevertError](../classes/ContractRevertError.md) - the pool rejected the top-of-book read. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` ##### marketId `string` #### Returns `Promise`\<[`BinaryPositionPnL`](BinaryPositionPnL.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBinaryPositionPnL`](SomniaMarketsClient.md#getbinarypositionpnl) *** ### getOpenPositionsWithPnL() > **getOpenPositionsWithPnL**(`account`): `Promise`\<[`OpenPositionPnL`](../type-aliases/OpenPositionPnL.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1185 PnL for ALL of an account's open binary positions in one call — the batched, positions-list companion to [getBinaryPositionPnL](SomniaMarketsClient.md#getbinarypositionpnl). Each entry is a [OpenPositionPnL](../type-aliases/OpenPositionPnL.md): the position's market joined with its reliable avg-cost PnL (`costBasis` / `avgCost` / `markValue` / `unrealizedPnl` / `realizedPnl`, marked to the book-clamped price), computed identically to `getBinaryPositionPnL` per market. Prefer this over deriving PnL from book stats. Fetched in a bounded number of indexer round-trips (fills + router actions + top-of-book batched across every open market), not a per-position loop. Empty array when the account holds nothing. Still ONE entry per market, with both books on it. To render a row per outcome, read `row.outcomes.yes` / `row.outcomes.no` and keep the legs whose `balance > 0n` — the top-level money fields are blended across the two and belong to neither. A market that has never traded has NO price to mark against, so its `markValue` and `unrealizedPnl` are `null`, as are the same fields on each leg. Show those as unknown; do NOT treat them as zero. A positions list routinely mixes priced and unpriced markets, so handle `null` per row. **Errors** - Throws [IndexerError](../classes/IndexerError.md) when the positions, fills, router actions, or top-of-book request does not complete. - Throws [InvalidInputError](../classes/InvalidInputError.md) when a voided position carries a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [IndexerError](../classes/IndexerError.md) when an indexed fill or router action is malformed — an `id` that is not `` `${blockNumber}_${logIndex}` ``, or a `quantity`, `fillPrice` or mint/merge `amount` that is not an unsigned decimal number. This method fetches those rows itself, so a row it cannot read is corrupt indexed data, never a bad argument; the specific parse failure is on `cause`. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) when the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` #### Returns `Promise`\<[`OpenPositionPnL`](../type-aliases/OpenPositionPnL.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOpenPositionsWithPnL`](SomniaMarketsClient.md#getopenpositionswithpnl) *** ### getClaimable() > **getClaimable**(`account`): `Promise`\<[`ClaimablePosition`](ClaimablePosition.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1208 An account's redeemable positions across all SETTLED (resolved/voided) binary markets, each shaped to feed straight into `trader.redeemMany({ entries })`. Winners get `amount × (1 − settlementFee)`; a voided market pays each side against the payout vector it stored — a half per side under the `UNIFORM` void policy, `[p, D−p]` on a `CLOB_SNAPSHOT` void that captured a two-sided close, and never a settlement fee. Loser-side and still-trading positions are omitted. One portfolio read, then one settlement-fee read per unique winning market, with at most eight fee reads in flight at a time. **Errors** - Throws [IndexerError](../classes/IndexerError.md) when the portfolio or settlement-fee request does not complete. After a fee read fails, no new fee read starts. - Throws [InvalidInputError](../classes/InvalidInputError.md) when a voided position carries a present but invalid payout vector. A legacy row with both vector fields absent keeps the documented half-payout fallback. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) when the client has no indexer, or its indexer does not index the client's chain. #### Parameters ##### account `string` #### Returns `Promise`\<[`ClaimablePosition`](ClaimablePosition.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getClaimable`](SomniaMarketsClient.md#getclaimable) *** ### watchPrice() > **watchPrice**(`asset`): `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1235 Watch one asset's price (e.g. `"BTC"`, `"ETH"`): hydrate a snapshot (feed metadata + current price + recent ticks) to get roughly up to speed, then stream live over a Hasura WebSocket subscription. While active, every `getLivePrice`/`getLivePriceTicks` read for this asset is current to the last pushed tick at zero round-trip cost. Ref-counted like [watchMarket](SomniaMarketsClient.md#watchmarket): watching the same asset twice shares one subscription and one snapshot; each handle's `stop()` releases one reference, and a brief linger absorbs quick re-watches. Different assets share transport in this client: one price-feed socket per endpoint, and one batched snapshot request (up to 10 assets) for watches started in the same tick. Each asset keeps its own ticks, cursor and status. Requires `config.priceFeed`, INCLUDING its `quote`: a live watch rejects with a `NotConfiguredError` naming `config.priceFeed.quote` when the feed is unpinned, because the tick tape's cursor is only unique within one quote (see [PriceFeedConfig.quote](PriceFeedConfig.md#quote)). The one-shot `fetchPrice*` reads still work unpinned. Rejects (and releases the ref) in either case. #### Parameters ##### asset `string` #### Returns `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchPrice`](SomniaMarketsClient.md#watchprice) *** ### watchPrices() > **watchPrices**(`assets`): `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1247 Watch a batch of assets at once (e.g. `["BTC", "ETH"]`). Returns a single handle whose `stop()` releases all of them; each asset is independently ref-counted, so this composes with per-asset [watchPrice](SomniaMarketsClient.md#watchprice) calls. The assets hydrate in batched snapshot requests and stream on one shared socket. If a snapshot request fails, this rejects and releases every asset. Requires a quote-pinned `config.priceFeed` for the same reason [watchPrice](SomniaMarketsClient.md#watchprice) does. #### Parameters ##### assets `string`[] #### Returns `Promise`\<[`PriceWatchHandle`](PriceWatchHandle.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`watchPrices`](SomniaMarketsClient.md#watchprices) *** ### getPriceStatus() > **getPriceStatus**(`asset`): [`PriceFeedStatus`](../type-aliases/PriceFeedStatus.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:1255 Per-asset price-watch state: `"unwatched"`, `"hydrating"`, `"live"`, or `"error"`. Check it before rendering a live price — on `"error"` the reads still answer, but with values that have stopped updating. See [PriceFeedStatus](../type-aliases/PriceFeedStatus.md). #### Parameters ##### asset `string` #### Returns [`PriceFeedStatus`](../type-aliases/PriceFeedStatus.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPriceStatus`](SomniaMarketsClient.md#getpricestatus) *** ### subscribePrices() > **subscribePrices**(`listener`): () => `void` Defined in: packages/sdk/src/somniaMarketsClient.ts:1268 Fire `listener` after every batch of price-store changes (React hooks subscribe to exactly this). Re-read with `getLivePrice`/`getLivePriceTicks`. Each read keeps its reference until that asset's own data changes, so a change to another asset does not give a new value. Independent of [subscribeLive](SomniaMarketsClient.md#subscribelive) (prices are a separate store/service). **Details** - Returns: An unsubscribe function. #### Parameters ##### listener () => `void` #### Returns () => `void` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`subscribePrices`](SomniaMarketsClient.md#subscribeprices) *** ### getLivePrice() > **getLivePrice**(`asset`): [`LivePrice`](LivePrice.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:1274 The current price of a watched asset (from the live store), or null if unwatched / not yet hydrated. Synchronous, memoized. #### Parameters ##### asset `string` #### Returns [`LivePrice`](LivePrice.md) \| `null` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLivePrice`](SomniaMarketsClient.md#getliveprice) *** ### getLivePrices() > **getLivePrices**(`assets`): ([`LivePrice`](LivePrice.md) \| `null`)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:1280 Current prices for a batch of watched assets, aligned to `assets` (each entry null if that asset is unwatched / not yet hydrated). Synchronous. #### Parameters ##### assets `string`[] #### Returns ([`LivePrice`](LivePrice.md) \| `null`)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLivePrices`](SomniaMarketsClient.md#getliveprices) *** ### getLivePriceTicks() > **getLivePriceTicks**(`asset`, `opts?`): [`PricePoint`](PricePoint.md)[] Defined in: packages/sdk/src/somniaMarketsClient.ts:1292 The recent tick tape of a watched asset, newest first. Synchronous. The returned array keeps its reference until this asset receives new ticks. An asset with no ticks returns one shared empty array. Readers share the array, so it is frozen: copy it before you sort or reverse it. **Details** - `opts.limit`: Max ticks (default 100; the store retains ~1000). #### Parameters ##### asset `string` ##### opts? ###### limit? `number` #### Returns [`PricePoint`](PricePoint.md)[] #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLivePriceTicks`](SomniaMarketsClient.md#getlivepriceticks) *** ### getLivePriceFeedInfo() > **getLivePriceFeedInfo**(`asset`): [`PriceFeedInfo`](PriceFeedInfo.md) \| `null` Defined in: packages/sdk/src/somniaMarketsClient.ts:1298 Feed metadata + current price for a watched asset (from the live store), or null if unwatched. For a one-shot read without a watch use [fetchPriceFeedInfo](SomniaMarketsClient.md#fetchpricefeedinfo). #### Parameters ##### asset `string` #### Returns [`PriceFeedInfo`](PriceFeedInfo.md) \| `null` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLivePriceFeedInfo`](SomniaMarketsClient.md#getlivepricefeedinfo) *** ### fetchPriceFeedInfo() > **fetchPriceFeedInfo**(`asset`): `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1301 One-shot feed metadata + current price (one HTTP round-trip; no watch needed). #### Parameters ##### asset `string` #### Returns `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`fetchPriceFeedInfo`](SomniaMarketsClient.md#fetchpricefeedinfo) *** ### fetchPrice() > **fetchPrice**(`asset`): `Promise`\<[`LivePrice`](LivePrice.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1307 One-shot current price (one HTTP round-trip), or null if the feed has no observations yet. #### Parameters ##### asset `string` #### Returns `Promise`\<[`LivePrice`](LivePrice.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`fetchPrice`](SomniaMarketsClient.md#fetchprice) *** ### fetchPrices() > **fetchPrices**(`assets?`): `Promise`\<[`LivePrice`](LivePrice.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1314 One-shot current prices for a batch of assets, or ALL tracked assets when `assets` is omitted — the multi-asset "price wall" in one request. Assets with no observations yet are omitted from the result. #### Parameters ##### assets? `string`[] #### Returns `Promise`\<[`LivePrice`](LivePrice.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`fetchPrices`](SomniaMarketsClient.md#fetchprices) *** ### listPriceFeeds() > **listPriceFeeds**(): `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1320 One-shot feed catalog — metadata + current price for every tracked asset (discovery). One HTTP round-trip; no watch needed. #### Returns `Promise`\<[`PriceFeedInfo`](PriceFeedInfo.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPriceFeeds`](SomniaMarketsClient.md#listpricefeeds) *** ### fetchPriceHistory() > **fetchPriceHistory**(`asset`, `opts?`): `Promise`\<[`PricePoint`](PricePoint.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1326 Historic ticks for one asset, newest first — window with `from`/`to` (unix seconds, chain time), page with `limit` (default 500). #### Parameters ##### asset `string` ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`PricePoint`](PricePoint.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`fetchPriceHistory`](SomniaMarketsClient.md#fetchpricehistory) *** ### fetchPriceCandles() > **fetchPriceCandles**(`asset`, `resolution`, `opts?`): `Promise`\<[`PriceCandle`](PriceCandle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1332 OHLC candles for one asset + resolution (`"M1"`/`"H1"`/`"D1"`), oldest first (chart-ready). Window with `from`/`to` (unix seconds); page with `limit`. #### Parameters ##### asset `string` ##### resolution [`PriceCandleResolution`](../type-aliases/PriceCandleResolution.md) ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`PriceCandle`](PriceCandle.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`fetchPriceCandles`](SomniaMarketsClient.md#fetchpricecandles) *** ### listMarkets() > **listMarkets**(`opts?`): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1352 List markets, newest first, as the discriminated `Market = SpotMarket | BinaryMarket` union. **Details** - `opts.marketType`: Filter to `"SPOT"` or `"BINARY"`; omit for both. - `opts.limit`: Max rows (default 50). - `opts.offset`: Row offset for pagination (default 0). #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listMarkets`](SomniaMarketsClient.md#listmarkets) *** ### listRegistryMarkets() > **listRegistryMarkets**(): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1360 Registry sweep for the unified tier: every non-binary market plus the binary series that are still live (not finalized), paged until exhausted. Finalized series accumulate without bound; resolve those by pool via the raw-tier lookups instead. #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listRegistryMarkets`](SomniaMarketsClient.md#listregistrymarkets) *** ### listRegistryMarketsChecked() > **listRegistryMarketsChecked**(): `Promise`\<[`RegistrySweep`](RegistrySweep.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1375 [listRegistryMarkets](SomniaMarketsClient.md#listregistrymarkets) with the rows the SDK could not parse COUNTED, as `{ markets, dropped }`. A malformed row is dropped silently rather than failing the page, so a caller that treats the sweep as exhaustive — a monitor publishing coverage over it, say — cannot tell a short answer from a complete one. `dropped > 0` says the registry holds markets this read did not return. #### Returns `Promise`\<[`RegistrySweep`](RegistrySweep.md)\> #### Throws [IndexerError](../classes/IndexerError.md) The indexed read did not complete. The complete union is [SomniaMarketsClientListRegistryMarketsCheckedError](../type-aliases/SomniaMarketsClientListRegistryMarketsCheckedError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listRegistryMarketsChecked`](SomniaMarketsClient.md#listregistrymarketschecked) *** ### countMarkets() > **countMarkets**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1383 Server-side COUNT of markets (optionally one type) for pagination totals. Needs the privileged `_aggregate` role (server-only), like [countBinaryMarkets](SomniaMarketsClient.md#countbinarymarkets). Without it the count is a row scan capped at 10,000 and a larger total reads as exactly `10000` — [countMarketsBounded](SomniaMarketsClient.md#countmarketsbounded) reports whether it did. #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countMarkets`](SomniaMarketsClient.md#countmarkets) *** ### countMarketsBounded() > **countMarketsBounded**(`opts?`): `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1389 [countMarkets](SomniaMarketsClient.md#countmarkets) with the truncation reported: `truncated: true` means the public-role scan hit its cap and `count` is a lower bound. #### Parameters ##### opts? ###### marketType? [`MarketType`](../type-aliases/MarketType.md) #### Returns `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countMarketsBounded`](SomniaMarketsClient.md#countmarketsbounded) *** ### getMarket() > **getMarket**(`id`): `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1395 One market by primary key (bytes32 marketId for binary, pool address for spot), or null if the indexer doesn't have it. #### Parameters ##### id `string` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarket`](SomniaMarketsClient.md#getmarket) *** ### listBinaryMarkets() > **listBinaryMarkets**(`opts?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1398 [listMarkets](SomniaMarketsClient.md#listmarkets) pre-narrowed to binary markets. #### Parameters ##### opts? [`BinaryMarketFilter`](../type-aliases/BinaryMarketFilter.md) & `object` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listBinaryMarkets`](SomniaMarketsClient.md#listbinarymarkets) *** ### listLiveBinaryMarkets() > **listLiveBinaryMarkets**(`filter?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1406 Currently-live binary markets (`expiry > now`), soonest-to-expire first. Call with no argument for all live markets, or pass a [LiveBinaryMarketsFilter](../type-aliases/LiveBinaryMarketsFilter.md) to narrow by `operatorId` / `venueId` / `asset` / `intervalSec` / `status` (e.g. `{ venueId: "0x4d41494e" }`). #### Parameters ##### filter? [`LiveBinaryMarketsFilter`](../type-aliases/LiveBinaryMarketsFilter.md) #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listLiveBinaryMarkets`](SomniaMarketsClient.md#listlivebinarymarkets) *** ### listBinaryVenueIds() > **listBinaryVenueIds**(): `Promise`\<`object`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1413 Distinct (operatorId, venueId) pairs across binary markets — the cheap server-side source for operator/venue filter options (so a UI never fetches every market just to enumerate origins). Excludes null attribution. #### Returns `Promise`\<`object`[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listBinaryVenueIds`](SomniaMarketsClient.md#listbinaryvenueids) *** ### listBinaryAssets() > **listBinaryAssets**(): `Promise`\<`string`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1426 Distinct asset symbols across binary markets — the cheap server-side source for an asset filter's options. #### Returns `Promise`\<`string`[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listBinaryAssets`](SomniaMarketsClient.md#listbinaryassets) *** ### countBinaryMarkets() > **countBinaryMarkets**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1435 Server-side COUNT of binary markets matching a filter, optionally split by lifecycle phase (`"live"` / `"past"`; omit `phase` to count both) — a total without fetching rows (Hasura `_aggregate`). On the public role this is a row scan capped at 10,000, which `Market` passes in production during 2026 — [countBinaryMarketsBounded](SomniaMarketsClient.md#countbinarymarketsbounded) says which. #### Parameters ##### opts? [`BinaryMarketCountOptions`](../type-aliases/BinaryMarketCountOptions.md) #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countBinaryMarkets`](SomniaMarketsClient.md#countbinarymarkets) *** ### countBinaryMarketsBounded() > **countBinaryMarketsBounded**(`opts?`): `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1442 [countBinaryMarkets](SomniaMarketsClient.md#countbinarymarkets) with the truncation reported: `truncated: true` means the public-role scan hit its cap and `count` is a lower bound, so a `rows.length < count` pagination gate would stop early. #### Parameters ##### opts? [`BinaryMarketCountOptions`](../type-aliases/BinaryMarketCountOptions.md) #### Returns `Promise`\<[`CountResult`](../type-aliases/CountResult.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countBinaryMarketsBounded`](SomniaMarketsClient.md#countbinarymarketsbounded) *** ### listPastBinaryMarkets() > **listPastBinaryMarkets**(`opts?`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1448 Past binary markets (`expiry ≤ now`), most-recently-expired first, paginated with `limit` + `offset`. #### Parameters ##### opts? [`PastBinaryMarketsOptions`](../type-aliases/PastBinaryMarketsOptions.md) #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPastBinaryMarkets`](SomniaMarketsClient.md#listpastbinarymarkets) *** ### getBinaryMarket() > **getBinaryMarket**(`id`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1454 One binary market by bytes32 marketId, or null (also null if the id resolves to a spot market). #### Parameters ##### id `string` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBinaryMarket`](SomniaMarketsClient.md#getbinarymarket) *** ### getBinaryMarketByAddress() > **getBinaryMarketByAddress**(`marketAddress`): `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1460 One binary market by its on-chain BinaryMarket ADDRESS (the Market PK is the bytes32 marketId, so an address-keyed caller must resolve through this). Newest first for recycled/rebound addresses; null if not yet indexed. #### Parameters ##### marketAddress `string` #### Returns `Promise`\<[`BinaryMarket`](../type-aliases/BinaryMarket.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBinaryMarketByAddress`](SomniaMarketsClient.md#getbinarymarketbyaddress) *** ### getMarketFees() > **getMarketFees**(`id`): `Promise`\<[`MarketFees`](../type-aliases/MarketFees.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1465 Fee config frozen into the market's pool at creation (origin venue attribution + rates in bpsTimes1k), or null without attribution. #### Parameters ##### id `string` #### Returns `Promise`\<[`MarketFees`](../type-aliases/MarketFees.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketFees`](SomniaMarketsClient.md#getmarketfees) *** ### listSpotMarkets() > **listSpotMarkets**(`opts?`): `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1471 [listMarkets](SomniaMarketsClient.md#listmarkets) pre-narrowed to spot markets. Pass a [SpotMarketFilter](../type-aliases/SpotMarketFilter.md) (+ `limit`) to narrow by base/quote symbol. #### Parameters ##### opts? [`SpotMarketFilter`](../type-aliases/SpotMarketFilter.md) & `object` #### Returns `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listSpotMarkets`](SomniaMarketsClient.md#listspotmarkets) *** ### getSpotMarket() > **getSpotMarket**(`id`): `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1474 One spot market by pool address, or null (also null if not spot). #### Parameters ##### id `string` #### Returns `Promise`\<[`SpotMarket`](../type-aliases/SpotMarket.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSpotMarket`](SomniaMarketsClient.md#getspotmarket) *** ### getMarketStatusHistory() > **getMarketStatusHistory**(`marketId`): `Promise`\<[`MarketStatusUpdate`](../type-aliases/MarketStatusUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1480 A market's status-transition history (Trading→Locked→Settling→Resolved…), oldest-first — the resolution/lock timeline for a market page. #### Parameters ##### marketId `string` #### Returns `Promise`\<[`MarketStatusUpdate`](../type-aliases/MarketStatusUpdate.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketStatusHistory`](SomniaMarketsClient.md#getmarketstatushistory) *** ### listPerpMarkets() > **listPerpMarkets**(`opts?`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1486 [listMarkets](SomniaMarketsClient.md#listmarkets) pre-narrowed to perp markets. Pass a [PerpMarketFilter](../type-aliases/PerpMarketFilter.md) (+ `limit`) to narrow by base/quote symbol. #### Parameters ##### opts? [`PerpMarketFilter`](../type-aliases/PerpMarketFilter.md) & `object` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpMarkets`](SomniaMarketsClient.md#listperpmarkets) *** ### getPerpMarket() > **getPerpMarket**(`id`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1492 One perp market by pool address, or null (also null if the id resolves to another market kind). #### Parameters ##### id `string` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpMarket`](SomniaMarketsClient.md#getperpmarket) *** ### getCandles() > **getCandles**(`poolAddress`, `intervalSeconds`, `opts?`): `Promise`\<[`Candle`](../type-aliases/Candle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1504 OHLCV candles for one pool + interval, oldest first (chart-ready). **Details** - `intervalSeconds`: Bucket size — one of the indexer's rollup intervals. - `opts.limit`: Max buckets (default 500). - `opts.from`: Only buckets at/after this unix-seconds timestamp. - `opts.to`: Only buckets at/before this unix-seconds timestamp. #### Parameters ##### poolAddress `string` ##### intervalSeconds `number` ##### opts? ###### limit? `number` ###### from? `number` ###### to? `number` #### Returns `Promise`\<[`Candle`](../type-aliases/Candle.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getCandles`](SomniaMarketsClient.md#getcandles) *** ### getMarketActivity() > **getMarketActivity**(`market`, `opts?`): `Promise`\<[`MarketActivity`](../type-aliases/MarketActivity.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1537 One market's activity, newest first — trades interleaved with complete-set mints and merges, redemptions, oracle resolution and lifecycle transitions. This is the market's transaction history. Every row names the transaction it landed in, so a caller can follow any row to the chain. Narrow a row on its `kind` ([MarketActivity](../type-aliases/MarketActivity.md)). Use this for a market page's activity panel. It is the one-shot INDEXER read, so it carries the history the panel needs on first paint, and it does not update itself. For trades arriving with no round-trip, read [getLiveFills](SomniaMarketsClient.md#getlivefills) as well and merge on the trade rows' `id`, which is `TRADE:` followed by the fill id — FIELD BY FIELD, preferring whichever source has a value. Neither is a superset of the other: the tail leaves `taker`/`takerSide` undefined on the fills it hydrates, and the indexer's `takerIsBid` is null until its taker bridge lands. Preferring one source wholesale drops what the other knew. A spot or perp market returns `TRADE` rows only — the other kinds come from binary-only entities, so asking for them there is not an error, just empty. One round-trip. Page backwards with `until`, not an offset (see [MarketActivityOptions](../type-aliases/MarketActivityOptions.md)). #### Parameters ##### market `string` The market's bytes32 marketId (case-insensitive). On spot and perp this is the pool address. ##### opts? [`MarketActivityOptions`](../type-aliases/MarketActivityOptions.md) #### Returns `Promise`\<[`MarketActivity`](../type-aliases/MarketActivity.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketActivity`](SomniaMarketsClient.md#getmarketactivity) *** ### getTransactionActivity() > **getTransactionActivity**(`txHash`, `opts?`): `Promise`\<[`TransactionActivity`](../type-aliases/TransactionActivity.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1562 Everything the protocol did in ONE transaction — trades, complete-set mints and merges, redemptions, oracle resolution, lifecycle transitions, the orders it placed and the fees it paid ([TransactionActivity](../type-aliases/TransactionActivity.md)). The read behind a transaction detail view, and the counterpart to [getTradeContext](SomniaMarketsClient.md#gettradecontext): that starts from a trade and shows its transaction as context, this starts from a transaction and shows every trade in it. `events` is the same union [getMarketActivity](SomniaMarketsClient.md#getmarketactivity) returns, with the same row ids, so one component renders both — but in LOG order, earliest first, because a transaction reads forwards. A hash the indexer has nothing for returns empty collections and a null `blockNumber` rather than throwing: an unknown hash and a transaction that touched no protocol contract are both absence. Indexer first. The client asks the chain for the transaction's block only when the indexer has no event for the hash and `opts.anchor` is unset. That lookup is best-effort: if the chain cannot place the hash, the read probes the indexer's order table instead. #### Parameters ##### txHash `string` Transaction hash (case-insensitive). ##### opts? [`TransactionActivityOptions`](../type-aliases/TransactionActivityOptions.md) #### Returns `Promise`\<[`TransactionActivity`](../type-aliases/TransactionActivity.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getTransactionActivity`](SomniaMarketsClient.md#gettransactionactivity) *** ### getBlockActivity() > **getBlockActivity**(`blockNumber`, `opts?`): `Promise`\<[`BlockActivity`](../type-aliases/BlockActivity.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1585 What the protocol traded in one block, grouped by market — the level above [getTransactionActivity](SomniaMarketsClient.md#gettransactionactivity). The block's own timestamp anchors every read, because no block column in the indexer schema is indexed. Resolving it is a chain read, and this client owns the transport, so it happens here: a caller never needs a second client. Reach for [getViemClient](SomniaMarketsClient.md#getviemclient) only for chain work the SDK does not model. A block with no markets activity — the common case, since only ~42% of blocks carry any — returns an empty `markets` array rather than throwing. Order rows carry no `status`: `Order` is mutable, so its status is as-of-now and would show a state from the block's future. Use `touch`. `truncated` reports a stream that came back full; page with `opts.offset`. #### Parameters ##### blockNumber `bigint` Block to read. ##### opts? [`BlockActivityOptions`](../type-aliases/BlockActivityOptions.md) Rows per stream and the offset to page from. #### Returns `Promise`\<[`BlockActivity`](../type-aliases/BlockActivity.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBlockActivity`](SomniaMarketsClient.md#getblockactivity) *** ### getLatestActiveBlock() > **getLatestActiveBlock**(): `Promise`\<\{ `blockNumber`: `bigint`; `timestamp`: `bigint`; \} \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1595 The newest block the indexer has markets activity for, or null when it has none at all. The entry point for a block view: the chain head runs ahead of the indexer, and most blocks carry no markets activity, so the head is usually a blank page. Pair with [getBlockActivity](SomniaMarketsClient.md#getblockactivity). #### Returns `Promise`\<\{ `blockNumber`: `bigint`; `timestamp`: `bigint`; \} \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLatestActiveBlock`](SomniaMarketsClient.md#getlatestactiveblock) *** ### getAdjacentActiveBlocks() > **getAdjacentActiveBlocks**(`blockNumber`, `opts?`): `Promise`\<\{ `prev`: `bigint` \| `null`; `next`: `bigint` \| `null`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1610 The closest blocks with markets activity below and above one block. The read behind a block view's prev/next: most blocks carry no markets activity, so stepping by n±1 lands on a blank page more often than not. Either side is null when no active block was found within the bounded scan. Anchored the same way as [getBlockActivity](SomniaMarketsClient.md#getblockactivity), and for the same reason resolves that anchor itself. #### Parameters ##### blockNumber `bigint` The block being viewed; excluded from both answers. ##### opts? [`BlockActivityOptions`](../type-aliases/BlockActivityOptions.md) Rows per stream per direction. #### Returns `Promise`\<\{ `prev`: `bigint` \| `null`; `next`: `bigint` \| `null`; \}\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getAdjacentActiveBlocks`](SomniaMarketsClient.md#getadjacentactiveblocks) *** ### getFills() > **getFills**(`pool`, `opts?`): `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1624 Recent fills on one pool, newest first. Bound the tape with `since`/`until` in seconds, or with `sinceBlock` to resume from a processed block ([FillsOptions](../type-aliases/FillsOptions.md)). #### Parameters ##### pool `string` ##### opts? [`FillsOptions`](../type-aliases/FillsOptions.md) #### Returns `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> #### Throws The pool or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFills`](SomniaMarketsClient.md#getfills) *** ### getTradeContext() > **getTradeContext**(`id`): `Promise`\<[`TradeContext`](../type-aliases/TradeContext.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1644 ONE fill IN CONTEXT, by id — the trade, its market, both sides' orders resolved, the fees it paid, and the other fills its transaction produced ([TradeContext](../type-aliases/TradeContext.md)). [getFill](SomniaMarketsClient.md#getfill) is the cheaper sibling: one query, the fill and its market, no surrounding context. Prefer it when a caller only renders the trade. The read behind a trade detail view. `getFills` and [getMarketActivity](SomniaMarketsClient.md#getmarketactivity) are the list reads that produce the id; this is the drill-down from one of their rows. Returns `null` when no fill has this id — a stale or mistyped link, not a failure. Two round-trips: the transaction's siblings and fees are anchored on the fill's own timestamp, so the fill has to resolve first. #### Parameters ##### id `string` Fill id, `${blockNumber}_${logIndex}`. #### Returns `Promise`\<[`TradeContext`](../type-aliases/TradeContext.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getTradeContext`](SomniaMarketsClient.md#gettradecontext) *** ### getUserFills() > **getUserFills**(`account`, `opts?`): `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1662 Fills a user participated in (maker OR taker), newest first — the one-shot indexer counterpart to [getLiveUserFills](SomniaMarketsClient.md#getliveuserfills). Optionally scope to one market and/or pool, a `since`/`until` window, and a `sinceBlock` bound ([FillsScope](../type-aliases/FillsScope.md)). Use `sinceBlock` to resume from a processed block: blocks can share a timestamp, so a seconds bound repeats or skips them. On binary, scope by `market` rather than `pool` for one market's tape: a pool is recycled by successive markets, so `pool` also returns the fills of that pool's earlier lives. Both predicates run at the indexer, so `limit` applies to the rows you asked for. #### Parameters ##### account `string` ##### opts? [`FillsScope`](../type-aliases/FillsScope.md) #### Returns `Promise`\<[`FillRow`](../type-aliases/FillRow.md)[]\> #### Throws The account, a scope value or a block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getUserFills`](SomniaMarketsClient.md#getuserfills) *** ### getUserFillsPage() > **getUserFillsPage**(`account`, `options?`): `Promise`\<[`UserFillsPage`](../type-aliases/UserFillsPage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1714 Read one historical fill page through this owner's indexer. Prefer this to offset paging when new fills can arrive between reads. Numeric timestamp, block number and log index define a total descending order. Self-trades appear once. Existing fill fields and account-side interpretation are unchanged. The default limit is 50; valid limits are integers from 1 to 1000. A sentinel row establishes continuation without returning it. Null continuation means no further row was observed, not that indexing or historical coverage is complete. Cursors bind account, chain, configured endpoint, normalized filters, sort, and the serving Fill dataset generation. A replacement behind the same URL rejects continuation with [FillHistoryRestartRequiredError](../classes/FillHistoryRestartRequiredError.md). A legacy cursor without a generation also requires a restart. Discard all accumulated pages and restart without a cursor. The generation comes from the serving indexer database, so it survives Hasura replica restarts. A fresh replay with changed hashed producer inputs rotates it; an identical replay does not. A code-only resume preserves the old identity and therefore cannot roll out a handler change that affects stored fills. An endpoint without this producer contract fails closed. Newer inserts belong to a fresh first-page read; a page is not a complete-history coverage guarantee. Cancellation through the configured owner's signal preserves the caller's abort reason rather than converting it to an IndexerError. #### Parameters ##### account `string` Wallet participating as maker or taker. ##### options? [`GetUserFillsPageOptions`](../type-aliases/GetUserFillsPageOptions.md) Market/pool, market kind (`marketType`), inclusive time and source-block filters, bounded limit and cursor. Omit `marketType` to read every kind. The cursor is scoped to the normalized filters, including `sinceBlock` and `marketType`. #### Returns `Promise`\<[`UserFillsPage`](../type-aliases/UserFillsPage.md)\> The dataset generation, existing fill rows and the next cursor, or null when this read has no next row. #### Throws [InvalidInputError](../classes/InvalidInputError.md) For invalid input or malformed/foreign cursors. #### Throws [IndexerError](../classes/IndexerError.md) When the read fails or returned position scalars are invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Throws [IndexerUnavailableError](../classes/IndexerUnavailableError.md) When local backpressure or the circuit breaker refuses the read. #### Throws [FillHistoryUnavailableError](../classes/FillHistoryUnavailableError.md) When the serving indexer has not initialized its dataset generation. #### Throws [FillHistoryRestartRequiredError](../classes/FillHistoryRestartRequiredError.md) When the cursor's generation differs from the serving dataset, or a legacy cursor lacks a generation. #### Example ```ts const first = await exchange.client.getUserFillsPage(account, { limit: 100 }); try { if (first.nextCursor !== null) { const next = await exchange.client.getUserFillsPage(account, { limit: 100, cursor: first.nextCursor }); console.log(next.fills); } } catch (error) { if (error instanceof FillHistoryRestartRequiredError) { const restarted = await exchange.client.getUserFillsPage(account, { limit: 100 }); console.log(restarted.fills); } else throw error; } ``` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getUserFillsPage`](SomniaMarketsClient.md#getuserfillspage) *** ### getFillsPage() > **getFillsPage**(`options`): `Promise`\<[`FillsPage`](../type-aliases/FillsPage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1760 Every fill of one MARKET KIND in an inclusive block range, across every pool of that kind, oldest first — the read behind a published trade feed. Takes no pool, unlike [getFills](SomniaMarketsClient.md#getfills): a feed indexes the whole venue and must not enumerate its pools. The block range is what bounds the read. Use blocks, not `since`/`until` seconds, whenever successive reads must tile the chain exactly. Several Somnia blocks can share a timestamp, so a seconds window drops or repeats the fills in them at every seam. Both bounds here are inclusive and `(blockNumber, logIndex)` is a total order, so `[a, b]` then `[b + 1, c]` covers every fill once. Pages default to 500 rows. The cursor names the last row returned and binds the chain, endpoint, kind and both bounds, so a cursor from one range is rejected by another. A full page always returns a cursor, so a range that ends on a page boundary costs one empty final page. Drain a range until `nextCursor` is null; a null cursor means this read saw no further row IN THE RANGE, not that indexing is complete — [getLatestFillBlock](SomniaMarketsClient.md#getlatestfillblock) is what reports how far the fill data reaches. Amounts stay raw strings, as everywhere on [FillRow](../type-aliases/FillRow.md). Do not route a published feed through the human-unit market reads. #### Parameters ##### options [`FillsPageOptions`](../type-aliases/FillsPageOptions.md) Kind, inclusive block range, page size and continuation. #### Returns `Promise`\<[`FillsPage`](../type-aliases/FillsPage.md)\> #### Throws A bound, the kind, the limit or the cursor is unusable. #### Throws The read did not complete, or returned unusable block positions. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Example ```ts let cursor: string | undefined; do { const page = await exchange.client.getFillsPage({ marketType: "SPOT", sinceBlock: 441_000_000n, toBlock: 441_010_000n, cursor, }); console.log(page.fills.length); cursor = page.nextCursor ?? undefined; } while (cursor !== undefined); ``` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFillsPage`](SomniaMarketsClient.md#getfillspage) *** ### getLatestFillBlock() > **getLatestFillBlock**(`marketType`): `Promise`\<[`LatestFillBlock`](../type-aliases/LatestFillBlock.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1779 The newest block carrying an indexed fill of one market kind, with that block's timestamp — the head marker to poll before asking for a range. Taken from the fill data rather than from the indexer's processed-block watermark, so the marker can never name a block [getFillsPage](SomniaMarketsClient.md#getfillspage) cannot yet serve. Returns `null` when no fill of that kind is indexed — a fresh deployment or one still replaying, not a failure. [getLatestActiveBlock](SomniaMarketsClient.md#getlatestactiveblock) is the wider question: the newest block with ANY markets activity, fills included. #### Parameters ##### marketType [`MarketType`](../type-aliases/MarketType.md) Market kind to report on. #### Returns `Promise`\<[`LatestFillBlock`](../type-aliases/LatestFillBlock.md) \| `null`\> #### Throws The market kind is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLatestFillBlock`](SomniaMarketsClient.md#getlatestfillblock) *** ### getFill() > **getFill**(`id`): `Promise`\<[`FillDetail`](../type-aliases/FillDetail.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1786 One fill by its id (`${blockNumber}_${logIndex}`) with both parties' order linkage and the market it executed on — the single lookup behind a fill detail view. Null when not indexed (a just-executed fill can lag a beat). #### Parameters ##### id `string` #### Returns `Promise`\<[`FillDetail`](../type-aliases/FillDetail.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFill`](SomniaMarketsClient.md#getfill) *** ### getOrderFills() > **getOrderFills**(`pool`, `orderId`, `opts?`): `Promise`\<[`OrderFillRow`](../type-aliases/OrderFillRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1798 Every fill one order participated in — either side, newest first. `(pool, orderId)` names exactly one order forever (ids never reuse). This bounded whole-history lookup accepts only `limit`; use `getFills` or `getUserFills` with `sinceBlock` to resume a pool or account tape. #### Parameters ##### pool `string` ##### orderId `string` \| `bigint` ##### opts? ###### limit? `number` #### Returns `Promise`\<[`OrderFillRow`](../type-aliases/OrderFillRow.md)[]\> #### Throws The pool identifier or order id is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOrderFills`](SomniaMarketsClient.md#getorderfills) *** ### getOrder() > **getOrder**(`pool`, `orderId`): `Promise`\<[`OrderDetail`](../type-aliases/OrderDetail.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1805 One order by `(pool, orderId)` — the indexer's view, including owner and full lifecycle attribution (status, cancelReason, amend chain). Null when not indexed; for chain-head truth use [getOrderOnchain](SomniaMarketsClient.md#getorderonchain). #### Parameters ##### pool `string` ##### orderId `string` \| `bigint` #### Returns `Promise`\<[`OrderDetail`](../type-aliases/OrderDetail.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOrder`](SomniaMarketsClient.md#getorder) *** ### listMarketsByPool() > **listMarketsByPool**(`pool`, `opts?`): `Promise`\<[`Market`](../type-aliases/Market.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1812 Every market a pool has hosted, newest first — one row for SPOT/PERP, the full recycle history for a BINARY pool. First row = the current market. The one-row shortcut is [getMarketByPool](SomniaMarketsClient.md#getmarketbypool). #### Parameters ##### pool `string` ##### opts? ###### limit? `number` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listMarketsByPool`](SomniaMarketsClient.md#listmarketsbypool) *** ### getOpenOrders() > **getOpenOrders**(`owner`, `opts?`): `Promise`\<[`OpenOrder`](../type-aliases/OpenOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1827 `owner`'s currently-OPEN orders, newest first. Pass [OrdersOptions](../type-aliases/OrdersOptions.md) (minus `status` — always "Open" here) to scope by `pool`/`pools`/`market`/ `markets`/`side`/`userData`/`sinceBlock` and page. Each row carries the placement's own `userData` tag, so a caller can match a row to the order it sent. NOTE: this lags the chain — for a trading loop prefer [getLiveUserOrders](SomniaMarketsClient.md#getliveuserorders) (or track the `orderId`s your own `placeOrder` calls return). For non-open history use [getOrders](SomniaMarketsClient.md#getorders). #### Parameters ##### owner `string` ##### opts? `Omit`\<[`OrdersOptions`](../type-aliases/OrdersOptions.md), `"status"`\> #### Returns `Promise`\<[`OpenOrder`](../type-aliases/OpenOrder.md)[]\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOpenOrders`](SomniaMarketsClient.md#getopenorders) *** ### getOrders() > **getOrders**(`owner`, `opts?`): `Promise`\<[`OrderRow`](../type-aliases/OrderRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1842 `owner`'s orders across ALL statuses (Open/Filled/Cancelled/Expired/Closed), newest first — the order-history counterpart to [getOpenOrders](SomniaMarketsClient.md#getopenorders). Each row carries its lifecycle `status`, fill progress and the placement's own `userData` tag. Filter by `status`/`side`/`pool`/`pools`/`market`/ `markets`/`userData`/`sinceBlock` and page via [OrdersOptions](../type-aliases/OrdersOptions.md). `sinceBlock` bounds the PLACEMENT block, so it does not report later changes to older orders. #### Parameters ##### owner `string` ##### opts? [`OrdersOptions`](../type-aliases/OrdersOptions.md) #### Returns `Promise`\<[`OrderRow`](../type-aliases/OrderRow.md)[]\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The read did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOrders`](SomniaMarketsClient.md#getorders) *** ### listSweepableOrders() > **listSweepableOrders**(`opts?`): `Promise`\<[`SweepableOrder`](../type-aliases/SweepableOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1863 Orders past expiry that are STILL RESTING, across the whole book — the work-list for a permissionless expired-order sweep. Not scoped to an account. Works on every market kind; scope with `pool` and/or `marketType`. Each row carries exactly what the sweep verbs need: `orderId` for `trader.cancelExpiredOrders`, and `isBid` + `price` for `trader.sweepExpiredAtLevel`. **This is not `status: "Expired"`.** That status is written when the chain emits `OrderExpired` — i.e. once an order has ALREADY been removed. The sweepable set is the opposite: `status = "Open"` and `expireTimestampNs < now`, orders the book still holds because nobody has cleaned them up. They are NOT matched against — the matcher skips an expired maker — but each costs a warm SLOAD per traversal and holds a priority-index slot. Longest-overdue first. GTC excludes itself because this SDK writes it as now + 50 years, not via any contract sentinel. #### Parameters ##### opts? ###### pool? `string` ###### marketType? [`MarketType`](../type-aliases/MarketType.md) ###### owner? `string` ###### asOfSec? `number` \| `bigint` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`SweepableOrder`](../type-aliases/SweepableOrder.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listSweepableOrders`](SomniaMarketsClient.md#listsweepableorders) *** ### getOutcomeBalances() > **getOutcomeBalances**(`account`, `marketAddress`): `Promise`\<[`OutcomeBalances`](../type-aliases/OutcomeBalances.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1877 Indexed YES/NO outcome-token balances of `account` in one binary market ("0" when unseen). Display-grade: to gate a write, read the tokens' on-chain balances via [getErc20Balance](SomniaMarketsClient.md#geterc20balance) instead. #### Parameters ##### account `string` ##### marketAddress `string` #### Returns `Promise`\<[`OutcomeBalances`](../type-aliases/OutcomeBalances.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOutcomeBalances`](SomniaMarketsClient.md#getoutcomebalances) *** ### getPortfolio() > **getPortfolio**(`account`, `opts?`): `Promise`\<[`Portfolio`](../type-aliases/Portfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1885 A wallet's whole binary portfolio in one round-trip once the registry is warm (a cold call resolves the market-type scope first): non-zero outcome positions, open orders, and recent trades (each with market context). Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page orders/trades or window trades. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`Portfolio`](../type-aliases/Portfolio.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPortfolio`](SomniaMarketsClient.md#getportfolio) *** ### getSpotPortfolio() > **getSpotPortfolio**(`account`, `opts?`): `Promise`\<[`SpotPortfolio`](../type-aliases/SpotPortfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1892 A wallet's spot activity: open orders, pending stop orders, and recent trades. Token holdings are NOT here — spot balances are plain ERC-20 / native balances; read them on-chain. Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`SpotPortfolio`](../type-aliases/SpotPortfolio.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSpotPortfolio`](SomniaMarketsClient.md#getspotportfolio) *** ### getSpotStopOrders() > **getSpotStopOrders**(`account`, `opts?`): `Promise`\<[`SpotStopOrder`](../type-aliases/SpotStopOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1901 A wallet's spot stop orders — PENDING by default (list + cancel via `trader.cancelStopOrder`). Pass `status` to see triggered/failed/cancelled history, `pool` to scope to one market, `limit` to page. Rows don't include a LIMIT stop's limit price. See [SpotStopOrder](../type-aliases/SpotStopOrder.md). #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### status? [`StopOrderStatus`](../type-aliases/StopOrderStatus.md) ###### limit? `number` #### Returns `Promise`\<[`SpotStopOrder`](../type-aliases/SpotStopOrder.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSpotStopOrders`](SomniaMarketsClient.md#getspotstoporders) *** ### getPerpPortfolio() > **getPerpPortfolio**(`account`, `opts?`): `Promise`\<[`PerpPortfolio`](../type-aliases/PerpPortfolio.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1912 A wallet's perp activity as indexed: open perp orders + recent perp trades. Positions/collateral live in the MarginBank — read them on-chain with [getPerpPosition](SomniaMarketsClient.md#getperpposition) / [getMarginAccount](SomniaMarketsClient.md#getmarginaccount). Pass [PortfolioOptions](../type-aliases/PortfolioOptions.md) to page. Trades default to the last seven days — the bound comes back as `tradesSince`; pass `since` to widen it. #### Parameters ##### account `string` ##### opts? [`PortfolioOptions`](../type-aliases/PortfolioOptions.md) #### Returns `Promise`\<[`PerpPortfolio`](../type-aliases/PerpPortfolio.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpPortfolio`](SomniaMarketsClient.md#getperpportfolio) *** ### listPerpStopOrders() > **listPerpStopOrders**(`opts?`): `Promise`\<[`PerpStopOrder`](../type-aliases/PerpStopOrder.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1935 Perp take-profit / stop-loss orders, newest first — the read that makes TP/SL usable at all. The PerpStopOrderRegistry keeps pending orders in private storage behind no enumeration getter, so there is no chain read that answers "what stops do I have". Creation and triggering both work; without this a trader cannot see, price or cancel what they created, which is why the feature shipped gated. Every scope comes from the same call: `{ account }` for a trader's working stops (default status `PENDING`), `{ pool }` with no account for a market's whole pending book, and `status` for history. `account` is optional deliberately — a market-wide view of what will fire is a legitimate monitoring read. Read `dropReason` before calling a `TRIGGER_FAILED` order a failure: a reduce-only drop means the stop was overtaken by events, which is ordinary; only `PlacementFailed` is a rejection. Rows don't include `limitPrice`. Fetch it for live stops with [getPerpStopOrders](SomniaMarketsClient.md#getperpstoporders). #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### status? [`StopOrderStatus`](../type-aliases/StopOrderStatus.md)[] ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpStopOrder`](../type-aliases/PerpStopOrder.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpStopOrders`](SomniaMarketsClient.md#listperpstoporders) *** ### getPerpStopOrder() > **getPerpStopOrder**(`ref`): `Promise`\<[`PerpStopOrderOnChain`](../type-aliases/PerpStopOrderOnChain.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:1960 One pending stop read straight from its registry — the chain tier [listPerpStopOrders](SomniaMarketsClient.md#listperpstoporders) does not have. The only way to read a LIMIT stop's `limitPrice`, its linked `siblingOrderId` and its `intent`: no event carries them, so [PerpStopOrder](../type-aliases/PerpStopOrder.md) cannot. Cannot enumerate — list ids there, then enrich each here. `null` when the id is not live. **Do not infer liveness from the terms**: a dead id keeps plausible values until its slot is recycled, so `live` is the only truth. #### Parameters ##### ref [`PerpStopOrderRef`](../type-aliases/PerpStopOrderRef.md) #### Returns `Promise`\<[`PerpStopOrderOnChain`](../type-aliases/PerpStopOrderOnChain.md) \| `null`\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) The order id is not a valid uint128 integer. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The owner has no chain WebSocket endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) The registry read failed before it returned a contract result. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The registry rejected the read. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpStopOrder`](SomniaMarketsClient.md#getperpstoporder) *** ### getPerpStopOrders() > **getPerpStopOrders**(`refs`): `Promise`\ Defined in: packages/sdk/src/somniaMarketsClient.ts:1994 Enrich known perp stop ids with one ordered chain batch. Use [listPerpStopOrders](SomniaMarketsClient.md#listperpstoporders) to discover ids. Each result belongs to the input ref at the same index. `absent` means the registry confirmed that the stop is not live. `failed` means only that member was unreadable. The configured chain uses Multicall3 when available. Other chains use a bounded point-read fallback. Both paths pin every result to one chain head. A contract revert or RPC failure for a member is returned as `failed`. #### Parameters ##### refs readonly [`PerpStopOrderRef`](../type-aliases/PerpStopOrderRef.md)[] #### Returns `Promise`\ #### Throws [InvalidInputError](../classes/InvalidInputError.md) An order id is not a canonical unsigned uint128 decimal. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The owner has no chain WebSocket endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) The head could not be pinned or the batch result was malformed. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The Multicall3 aggregate rejected the batch. #### Example ```ts const indexed = await client.listPerpStopOrders({ account: owner }); const refs = indexed.map((stop) => { if (!isAddress(stop.registry)) throw new Error(`Invalid registry ${stop.registry}`); return { registry: stop.registry, orderId: stop.orderIdRaw }; }); const reads = await client.getPerpStopOrders(refs); for (const [index, read] of reads.entries()) { const stop = indexed[index]; if (stop === undefined) throw new Error(`Missing indexed stop ${index}`); if (read.status === "present") console.log(stop.id, read.order); if (read.status === "absent") console.log(stop.id, "no longer live"); if (read.status === "failed") console.error(stop.id, read.error); } ``` #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpStopOrders`](SomniaMarketsClient.md#getperpstoporders) *** ### getPerpStopOrderSomiPayment() > **getPerpStopOrderSomiPayment**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2000 SOMI a perp stop registry charges per pending order, in wei. Send exactly this with a create or it reverts; refunded on cancel, consumed on a fire. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpStopOrderSomiPayment`](SomniaMarketsClient.md#getperpstopordersomipayment) *** ### getUnclaimedPerpStopSomi() > **getUnclaimedPerpStopSomi**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2008 SOMI a perp stop registry owes `account`, in wei, claimable with `trader.claimPerpStopSomi`. Credited when a cancel's direct refund fails (a contract owner with no payable receiver) OR when the registry is wound down, which credits every owner — **including EOAs**. #### Parameters ##### ref ###### registry `` `0x${string}` `` ###### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getUnclaimedPerpStopSomi`](SomniaMarketsClient.md#getunclaimedperpstopsomi) *** ### listPerpOrderHistory() > **listPerpOrderHistory**(`account`, `opts?`): `Promise`\<[`PerpOrderHistoryRow`](../type-aliases/PerpOrderHistoryRow.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2026 An account's FINISHED perp orders, most-recently-ended first — the history tab behind [getPerpPortfolio](SomniaMarketsClient.md#getperpportfolio)'s open-orders list. `getPerpPortfolio` hard-filters `status = "Open"`, so before this there was no way to see a filled, cancelled or expired perp order at all. Excludes working orders by default (`status != "Open"`); pass `status` to narrow to particular outcomes. Ordered by when each order ENDED, not when it was placed — a long-resting order that just filled belongs at the top of a history view, not buried at its placement date. Note `Closed` is terminal, not transitional: an IOC that partially filled without resting stays `Closed` forever, so treating it as "still working" would show a finished order as live. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### status? [`TerminalOrderStatus`](../type-aliases/TerminalOrderStatus.md)[] ###### orderBy? `"placed"` \| `"ended"` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpOrderHistoryRow`](../type-aliases/PerpOrderHistoryRow.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpOrderHistory`](SomniaMarketsClient.md#listperporderhistory) *** ### getSyncStatus() > **getSyncStatus**(`chainId`): `Promise`\<[`IndexerSyncStatus`](../type-aliases/IndexerSyncStatus.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2046 Read the indexer's own metadata without chain RPC. A missing row for another chain returns null. For the client's own chain, a missing row fails the first read's binding check with NotConfiguredError; a row that goes missing after the check passed still returns null. Use the concrete owner's getIndexerFreshness for an independent comparison. #### Parameters ##### chainId `number` #### Returns `Promise`\<[`IndexerSyncStatus`](../type-aliases/IndexerSyncStatus.md) \| `null`\> #### Throws A query variable is invalid. #### Throws The metadata request failed. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSyncStatus`](SomniaMarketsClient.md#getsyncstatus) *** ### waitForIndexedBlock() > **waitForIndexedBlock**(`chainId`, `block`, `opts?`): `Promise`\<[`IndexedBlockWait`](../type-aliases/IndexedBlockWait.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2083 Wait until the indexer has processed `block` on `chainId`, then resolve with what the wait observed. The step between a confirmed write and an indexer read of that write: every indexer-backed read answers from the processed height, so a read issued before the block is indexed correctly reports the row as absent. Resolving means a read issued afterwards sees what that block wrote. Polls `chain_metadata` every `pollMs` (default 500) until `timeoutMs` (default 30,000). Pass `signal` to abort; the caller's abort reason is rethrown unchanged. For the client's own chain, the wait reads the RPC head once when it would resolve. An indexer more than 10,000 blocks past that head follows an earlier genesis of the same chain id, so the wait rejects instead of resolving. A client with no chain endpoint skips this read. **Example** (Read your own write) ```ts const receipt = await exchange.client.getViemClient().waitForTransactionReceipt({ hash }); await exchange.client.waitForIndexedBlock(exchange.client.config.chain.id, receipt.blockNumber); const orders = await exchange.client.getOpenOrders(owner, { userData: 7n }); ``` #### Parameters ##### chainId `number` ##### block `number` \| `bigint` ##### opts? [`WaitForIndexedBlockOptions`](../type-aliases/WaitForIndexedBlockOptions.md) #### Returns `Promise`\<[`IndexedBlockWait`](../type-aliases/IndexedBlockWait.md)\> #### Throws The block height, `timeoutMs` or `pollMs` is not a usable whole number. #### Throws The deadline passed with the indexer still behind the block. #### Throws A metadata read failed, or the indexer serves no row for this chain. #### Throws The client has no indexer, its indexer does not serve its own chain, or its indexer is more than 10,000 blocks past the RPC head. #### Throws The RPC head read failed. The complete union is [SomniaMarketsClientWaitForIndexedBlockError](../type-aliases/SomniaMarketsClientWaitForIndexedBlockError.md). #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`waitForIndexedBlock`](SomniaMarketsClient.md#waitforindexedblock) *** ### getMarketByPool() > **getMarketByPool**(`pool`): `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2093 Resolve a market by its pool address (one query; no live watch), or null. Binary markets are keyed by bytes32 marketId, so this is the by-pool lookup. #### Parameters ##### pool `string` #### Returns `Promise`\<[`Market`](../type-aliases/Market.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketByPool`](SomniaMarketsClient.md#getmarketbypool) *** ### countOrders() > **countOrders**(`owner`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2109 Server-side COUNT of `owner`'s orders matching an [OrdersOptions](../type-aliases/OrdersOptions.md) filter — the total for an order-history page. Privileged `_aggregate` role (server-only), with a bounded row-count fallback on the public role. WITHOUT THAT HEADER THE RESULT IS A LOWER BOUND, returned as if exact: the fallback scan stops at 10,000 rows and reports 10,000, and `Order` is far past that in production. There is no bounded variant of this method yet — [countMarketsBounded](SomniaMarketsClient.md#countmarketsbounded) is the shape to copy. #### Parameters ##### owner `string` ##### opts? [`OrdersOptions`](../type-aliases/OrdersOptions.md) #### Returns `Promise`\<`number`\> #### Throws The owner, a scope, tag or block bound is unusable. #### Throws The count did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countOrders`](SomniaMarketsClient.md#countorders) *** ### countUserFills() > **countUserFills**(`account`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2127 Server-side COUNT of the fills `account` participated in (maker OR taker), optionally scoped by market and/or pool + a `since`/`until` window or inclusive `sinceBlock` source-block bound ([FillsScope](../type-aliases/FillsScope.md)) — a history-page total. WITHOUT THE PRIVILEGED `_aggregate` HEADER THE RESULT IS A LOWER BOUND, returned as if exact: the fallback scan stops at 10,000 rows and reports 10,000, and `Fill` is the deepest counted table in production. There is no bounded variant of this method yet — [countMarketsBounded](SomniaMarketsClient.md#countmarketsbounded) is the shape to copy. #### Parameters ##### account `string` ##### opts? [`FillsScope`](../type-aliases/FillsScope.md) #### Returns `Promise`\<`number`\> #### Throws The account, a scope value or a block bound is unusable. #### Throws The count did not complete. #### Throws The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countUserFills`](SomniaMarketsClient.md#countuserfills) *** ### getRouterActions() > **getRouterActions**(`account`, `opts?`): `Promise`\<[`RouterActionRecord`](../type-aliases/RouterActionRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2138 An account's RouterMinter action history (redeem / mint / merge), newest first — optionally scoped to one `market` (or several via `markets`) and/or `kind`, paginated ([RouterActionsOptions](../type-aliases/RouterActionsOptions.md)). Mint and merge move a position's cost basis, so scope this the same way you scope the fills you fold it against: an account-wide capped read drops the OLDEST rows, which are the ones that set the basis. #### Parameters ##### account `string` ##### opts? [`RouterActionsOptions`](../type-aliases/RouterActionsOptions.md) #### Returns `Promise`\<[`RouterActionRecord`](../type-aliases/RouterActionRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getRouterActions`](SomniaMarketsClient.md#getrouteractions) *** ### getMarketResolution() > **getMarketResolution**(`marketId`): `Promise`\<\{ `events`: [`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]; `reference`: [`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md) \| `null`; `closingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `openingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `oracleAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2148 Everything the indexer knows about how a market resolves: lifecycle events, the oracle reference link, and the posted oracle answers. `closingAnswer` is the market's own resolution answer (the CLOSING price for a reference-mode up/down market); `openingAnswer` is the reference-question answer (the OPENING price it resolves against, null for fixed-strike markets). Any piece may be absent. `oracleAnswer` is a deprecated alias of `closingAnswer`. #### Parameters ##### marketId `string` #### Returns `Promise`\<\{ `events`: [`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]; `reference`: [`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md) \| `null`; `closingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `openingAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; `oracleAnswer`: [`OracleAnswer`](../type-aliases/OracleAnswer.md) \| `null`; \}\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketResolution`](SomniaMarketsClient.md#getmarketresolution) *** ### listMarketResolutionEvents() > **listMarketResolutionEvents**(`opts?`): `Promise`\<[`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2188 Market-resolution lifecycle events across markets, newest first — filter by `market`, `kinds` and/or `sinceTimestamp`, paginate ([ListMarketResolutionEventsOptions](ListMarketResolutionEventsOptions.md)). The cross-market counterpart to [getMarketResolution](SomniaMarketsClient.md#getmarketresolution), which reports one market in full. One row per delivery ATTEMPT and append-only, so a monitor watching for `"Skipped"` / `"Failed"` wants `sinceTimestamp` — without a lower bound this returns every failure the deployment has ever recorded, and a count over it only ever grows. #### Parameters ##### opts? [`ListMarketResolutionEventsOptions`](ListMarketResolutionEventsOptions.md) #### Returns `Promise`\<[`MarketResolutionEvent`](../type-aliases/MarketResolutionEvent.md)[]\> #### Throws The indexer request failed or returned an error. An empty page is `[]`. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listMarketResolutionEvents`](SomniaMarketsClient.md#listmarketresolutionevents) *** ### listMarketReferenceLinks() > **listMarketReferenceLinks**(`opts?`): `Promise`\<[`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2206 Reference-question links, oldest first — filter by `pending` and/or `market`, paginate ([ListMarketReferenceLinksOptions](ListMarketReferenceLinksOptions.md)). `pending: true` is the set worth sweeping: markets holding their own oracle answer while the question they resolve AGAINST is not final. They stay unresolved with no on-chain retry until `pokeOracle` lands the reference or `voidExpired` backstops them. Only reference-resolved markets have a link, so this never lists fixed-strike markets. Oldest first, because the rows are live state rather than a trail: the first row is the market that has been stuck longest. #### Parameters ##### opts? [`ListMarketReferenceLinksOptions`](ListMarketReferenceLinksOptions.md) #### Returns `Promise`\<[`MarketReferenceLink`](../type-aliases/MarketReferenceLink.md)[]\> #### Throws The indexer request failed or returned an error. An empty page is `[]`. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listMarketReferenceLinks`](SomniaMarketsClient.md#listmarketreferencelinks) *** ### getOpeningPrices() > **getOpeningPrices**(`marketIds`): `Promise`\<`Record`\<`string`, `string` \| `null`\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2214 Batch opening (reference-question) prices for many markets in one pair of round-trips — for list views. Map of lowercased marketId → raw oracle `numericValue` (null when no reference answer yet). Format with the market's oracle price scale. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, `string` \| `null`\>\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOpeningPrices`](SomniaMarketsClient.md#getopeningprices) *** ### getResolutionPrices() > **getResolutionPrices**(`marketIds`): `Promise`\<`Record`\<`string`, `string` \| `null`\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2222 Batch RESOLUTION (settlement) prices for many markets in one pair of round-trips — the settlement counterpart to [getOpeningPrices](SomniaMarketsClient.md#getopeningprices). Map of lowercased marketId → raw oracle `numericValue`, null where unresolved. Joins each market's OWN question, so fixed-strike markets are covered too. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, `string` \| `null`\>\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getResolutionPrices`](SomniaMarketsClient.md#getresolutionprices) *** ### getOnchainResolutionPrice() > **getOnchainResolutionPrice**(`marketId`): `Promise`\<[`OnchainResolutionPrice`](OnchainResolutionPrice.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2232 A market's RESOLUTION price read straight from CHAIN — the fallback for a settled market whose answer the indexer never saw, because its oracle adapter is not the one whose events the indexer ingests. Resolves the market's bound adapter through the module, so it works for any adapter. Null while the question is not final. Carries its own `decimals` (adapters differ — do NOT assume a scale). #### Parameters ##### marketId `string` #### Returns `Promise`\<[`OnchainResolutionPrice`](OnchainResolutionPrice.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOnchainResolutionPrice`](SomniaMarketsClient.md#getonchainresolutionprice) *** ### getBookTops() > **getBookTops**(`marketIds`): `Promise`\<`Record`\<`string`, [`BookTop`](../type-aliases/BookTop.md)\>\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2242 Batch top of book (best resting bid/ask + mid) for many markets in one round-trip — for list views that want a book-derived price without an N+1 per-pool fan-out. EVERY market kind: spot and perp pool addresses and binary market ids are all valid, and may be mixed in one call. Map of lowercased marketId → [BookTop](../type-aliases/BookTop.md), whose prices are raw and in each market's own terms; empty-book markets are absent. #### Parameters ##### marketIds `string`[] #### Returns `Promise`\<`Record`\<`string`, [`BookTop`](../type-aliases/BookTop.md)\>\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBookTops`](SomniaMarketsClient.md#getbooktops) *** ### listProtocolFees() > **listProtocolFees**(`opts?`): `Promise`\<[`ProtocolFeeRecord`](../type-aliases/ProtocolFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2249 Realized protocol-fee records, newest first — filter by `recipient` / `market` / `pool` / `payer`, paginate. The per-fill stream behind [getMarketFees](SomniaMarketsClient.md#getmarketfees)'s running total. #### Parameters ##### opts? ###### recipient? `string` ###### market? `string` ###### pool? `string` ###### payer? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`ProtocolFeeRecord`](../type-aliases/ProtocolFeeRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listProtocolFees`](SomniaMarketsClient.md#listprotocolfees) *** ### listBuilderFees() > **listBuilderFees**(`opts?`): `Promise`\<[`BuilderFeeRecord`](../type-aliases/BuilderFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2262 Realized builder/routing-fee records, newest first — filter by `builder` / `market` / `payer`, paginate. #### Parameters ##### opts? ###### builder? `string` ###### market? `string` ###### payer? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`BuilderFeeRecord`](../type-aliases/BuilderFeeRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listBuilderFees`](SomniaMarketsClient.md#listbuilderfees) *** ### listSettlementFees() > **listSettlementFees**(`opts?`): `Promise`\<[`SettlementFeeRecord`](../type-aliases/SettlementFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2274 Realized settlement-fee records, newest first — filter by `market` / `recipient`, paginate. #### Parameters ##### opts? ###### market? `string` ###### recipient? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`SettlementFeeRecord`](../type-aliases/SettlementFeeRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listSettlementFees`](SomniaMarketsClient.md#listsettlementfees) *** ### listBuilderApprovals() > **listBuilderApprovals**(`opts?`): `Promise`\<[`BuilderApproval`](../type-aliases/BuilderApproval.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2286 Builder-approval directory, newest-updated first — filter by `user` and/or `builder`, paginate. The directory complement to the on-chain point read [getBuilderApproval](SomniaMarketsClient.md#getbuilderapproval). #### Parameters ##### opts? ###### user? `string` ###### builder? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`BuilderApproval`](../type-aliases/BuilderApproval.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listBuilderApprovals`](SomniaMarketsClient.md#listbuilderapprovals) *** ### getVaultPayoutFallbacks() > **getVaultPayoutFallbacks**(`owner`, `opts?`): `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2298 An owner's vault-credit fallback history (append-only), newest first — optionally scoped to one `token`, paginated. The live claimable balance is the chain read [getVaultBalance](SomniaMarketsClient.md#getvaultbalance). #### Parameters ##### owner `string` ##### opts? ###### token? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getVaultPayoutFallbacks`](SomniaMarketsClient.md#getvaultpayoutfallbacks) *** ### listVaultPayoutFallbacks() > **listVaultPayoutFallbacks**(`opts?`): `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2335 Vault-credit fallbacks across EVERY owner, newest first by default — filter by `owner`, `token` and/or `pool`, window with `from`/`to`, paginate. [getVaultPayoutFallbacks](SomniaMarketsClient.md#getvaultpayoutfallbacks) is the per-owner view of the same log; this is the operator's: every payout that could not reach a wallet and was credited to a pool vault instead, without knowing the owners in advance. Each row names the `pool` whose vault holds the credit; the live claimable amount is the chain read [getVaultBalance](SomniaMarketsClient.md#getvaultbalance) with that pool as the `vault`. The sort is a TOTAL order — `timestamp`, then the `id` primary key — so the sequence is stable between requests. The table is live and append-only, so offset paging is approximate; to follow the log forward pass `order: "asc"` with `from` at the last row's timestamp and skip the ids already seen there. Returns one [VaultPayoutFallback](../type-aliases/VaultPayoutFallback.md) per indexed credit, an empty array when none matches. An INDEXED read: as current as the indexer's processed block, never ahead of it (see the read tiers reference). Usage is shown in the binary markets guide under "Vault credits". #### Parameters ##### opts? [`ListVaultPayoutFallbacksOptions`](ListVaultPayoutFallbacksOptions.md) #### Returns `Promise`\<[`VaultPayoutFallback`](../type-aliases/VaultPayoutFallback.md)[]\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, `opts.offset` is not a non-negative safe integer, or `opts.from` / `opts.to` are not whole, non-negative unix seconds. Checked before the request: `NaN` and `Infinity` are ordinary `number` values that would serialize to `null` and lift the page bound, or reach the indexer as an invalid numeric and come back as its failure. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. #### Throws [IndexerUnavailableError](../classes/IndexerUnavailableError.md) Local backpressure or the circuit breaker refused the read before it was sent. The union is [SomniaMarketsClientListVaultPayoutFallbacksError](../type-aliases/SomniaMarketsClientListVaultPayoutFallbacksError.md). #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listVaultPayoutFallbacks`](SomniaMarketsClient.md#listvaultpayoutfallbacks) *** ### getFundingPayments() > **getFundingPayments**(`account`, `opts?`): `Promise`\<[`FundingPayment`](../type-aliases/FundingPayment.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2341 An account's funding-payment history, newest first — optionally scoped to one `pool`, paginated. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`FundingPayment`](../type-aliases/FundingPayment.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFundingPayments`](SomniaMarketsClient.md#getfundingpayments) *** ### getMarginEvents() > **getMarginEvents**(`account`, `opts?`): `Promise`\<[`MarginEvent`](../type-aliases/MarginEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2350 An account's margin-account movement history (deposits/withdraws/locks), newest first — paginated. #### Parameters ##### account `string` ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`MarginEvent`](../type-aliases/MarginEvent.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarginEvents`](SomniaMarketsClient.md#getmarginevents) *** ### listLiquidations() > **listLiquidations**(`opts?`): `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2369 Liquidation events, newest first — filter by `account`, `pool` and/or `kind`, paginate. `kind` matters more than it looks: the rows are stages of one mechanism, so one cascade produces many rows and an unfiltered `limit` is spent mostly on stages the caller did not ask about. See [LiquidationEvent.kind](../type-aliases/LiquidationEvent.md#kind). The sort is a TOTAL order — `timestamp`, then `blockNumber`, then the `id` primary key — so the sequence is stable between requests. That fixes tie ordering only: these are live rows, and an event indexed ahead of your offset still repeats a row while a reorg that removes one still skips a row. Offset paging here is approximate, not snapshot-consistent. #### Parameters ##### opts? [`ListLiquidationsOptions`](ListLiquidationsOptions.md) #### Returns `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> #### Throws [IndexerError](../classes/IndexerError.md) The indexed read did not complete. The complete union is [SomniaMarketsClientListLiquidationsError](../type-aliases/SomniaMarketsClientListLiquidationsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listLiquidations`](SomniaMarketsClient.md#listliquidations) *** ### ~~getLiquidations()~~ > **getLiquidations**(`opts?`): `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2381 Liquidation events, newest first. #### Parameters ##### opts? [`ListLiquidationsOptions`](ListLiquidationsOptions.md) #### Returns `Promise`\<[`LiquidationEvent`](../type-aliases/LiquidationEvent.md)[]\> #### Deprecated Renamed to [listLiquidations](SomniaMarketsClient.md#listliquidations), per SDK-TYPE-006. Forwards verbatim. #### Throws [IndexerError](../classes/IndexerError.md) As [SomniaMarketsClient.listLiquidations](SomniaMarketsClient.md#listliquidations). The union is [SomniaMarketsClientGetLiquidationsError](../type-aliases/SomniaMarketsClientGetLiquidationsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiquidations`](SomniaMarketsClient.md#getliquidations) *** ### listFundingRateHistory() > **listFundingRateHistory**(`pool`, `opts?`): `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2395 A perp pool's funding-rate history, newest first by default. `from`/`to` are unix SECONDS and are what a chart should use — settlement is hourly (24 rows per pool per day, and 288 across the retired 300s cadence still in indexed history), so paging by offset to reach a date is both slow and fragile. Normalize each row with its OWN `fundingWindowSec`. Pass `order: "asc"` to make `from` a forward CURSOR. Under the default `"desc"` a page always comes off the newest end, so `from = last.timestamp + 1` re-reads the tail instead of advancing. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` ###### order? `"asc"` \| `"desc"` #### Returns `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listFundingRateHistory`](SomniaMarketsClient.md#listfundingratehistory) *** ### listFundingRateCandles() > **listFundingRateCandles**(`pool`, `intervalSeconds`, `opts?`): `Promise`\<[`FundingRateCandle`](../type-aliases/FundingRateCandle.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2417 A perp pool's funding-rate ROLLUPS at one resolution (3600 | 14400 | 86400), newest first — for ranges the raw series is too dense for. Buckets can be ABSENT where no settlement's span reached them: zero-fill those grid slots as `{ avgFundingRate8h: 0, coverage: 0 }` and never carry the previous rate forward. Past buckets also get REVISED when a catch-up settlement reaches backwards. Pages NEWEST-first against a default `limit` of 500, so a month of hourly buckets (720) silently returns its newest 500 — treat `rows.length === limit` as truncated. #### Parameters ##### pool `string` ##### intervalSeconds `number` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` #### Returns `Promise`\<[`FundingRateCandle`](../type-aliases/FundingRateCandle.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listFundingRateCandles`](SomniaMarketsClient.md#listfundingratecandles) *** ### listPerpFees() > **listPerpFees**(`opts?`): `Promise`\<[`PerpFeeRecord`](../type-aliases/PerpFeeRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2431 Realized perp fees / rebates / builder credits, newest first — the perps fee rail off MarginBank, distinct from the binary/spot `listBuilderFees`. `insurancePortion` is a component OF `amount`, not an addition to it: a fee total is `SUM(amount)`, an insurance inflow is `SUM(insurancePortion)`, and adding the two double-counts. `amount` is unsigned — `isRebate` carries the direction. #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### builder? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpFeeRecord`](../type-aliases/PerpFeeRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpFees`](SomniaMarketsClient.md#listperpfees) *** ### listPerpOrderRejections() > **listPerpOrderRejections**(`opts?`): `Promise`\<[`PerpOrderRejection`](../type-aliases/PerpOrderRejection.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2452 Orders refused inside a BATCH placement, newest first. `placeOrders` / `placeOrdersFor` only — the singular entry points revert, and a revert discards its logs, so a singular placement leaves no row here. Nothing here has an `Order` row either: a rejected request never rested and never filled. Map a row back to what was sent with `requestIndex`. `reason` is the decoded name and is null for a member this SDK version does not know; `reasonRaw` always carries the index. The `reason` FILTER takes the index, so a caller can select a reason this SDK cannot yet name. #### Parameters ##### opts? ###### owner? `string` ###### pool? `string` ###### reason? `number` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpOrderRejection`](../type-aliases/PerpOrderRejection.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpOrderRejections`](SomniaMarketsClient.md#listperporderrejections) *** ### ~~getFundingRateHistory()~~ > **getFundingRateHistory**(`pool`, `opts?`): `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2465 Lists funding-rate history through the compatibility alias. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` ###### from? `number` \| `bigint` ###### to? `number` \| `bigint` #### Returns `Promise`\<[`FundingRateUpdate`](../type-aliases/FundingRateUpdate.md)[]\> #### Deprecated Use [listFundingRateHistory](SomniaMarketsClient.md#listfundingratehistory) instead. This alias forwards verbatim. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFundingRateHistory`](SomniaMarketsClient.md#getfundingratehistory) *** ### getOpenInterestHistory() > **getOpenInterestHistory**(`pool`, `opts?`): `Promise`\<[`OpenInterestSnapshot`](../type-aliases/OpenInterestSnapshot.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2471 A perp pool's open-interest history, newest first — paginated. #### Parameters ##### pool `string` ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OpenInterestSnapshot`](../type-aliases/OpenInterestSnapshot.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOpenInterestHistory`](SomniaMarketsClient.md#getopeninteresthistory) *** ### listPerpPositions() > **listPerpPositions**(`account`, `opts?`): `Promise`\<[`IndexedPerpPosition`](../type-aliases/IndexedPerpPosition.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2486 An account's perp positions across every pool, newest-updated first — ONE round-trip, replacing a chain read per market. A snapshot as of each row's `updatedAtBlock`, NOT marked to market: unrealized PnL, liquidation price and margin health all still need a chain read. `entryFundingIndex` is not selected — the deployed Hasura schema does not carry it yet — so anything funding-sensitive belongs on [getPerpPosition](SomniaMarketsClient.md#getperpposition). Size-0 (fully closed) rows are excluded unless `includeFlat` — upserted rows are never deleted, so closed positions linger forever. An empty array means the indexer has no rows, not that the account is flat. #### Parameters ##### account `string` ##### opts? ###### pool? `string` ###### includeFlat? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedPerpPosition`](../type-aliases/IndexedPerpPosition.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpPositions`](SomniaMarketsClient.md#listperppositions) *** ### getBinaryOrderBook() > **getBinaryOrderBook**(`pool`, `opts?`): `Promise`\<[`BinaryOrderBook`](BinaryOrderBook.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2533 Read a binary pool's resting book from the contract (`getBookLevels`, both sides in one pipelined round-trip), 4-sided like the live variant. Use when the tail isn't running or as a checksum. A live watch can serve render and quote paths without another chain read. A binary pool can be recycled onto another market. This pool-keyed read has no `marketId` guard, so an address saved for an older market can return the next market's book. If you hold a `marketId` and have an active watch, use [getLiveBinaryOrderBookByMarket](SomniaMarketsClient.md#getlivebinaryorderbookbymarket) to avoid showing that book. For a chain-only snapshot, read the selected market with `getMarketOnchain`, compare its pool's binding with the selected id, and pass that binding's `blockNumber` plus the market's collateral `decimals` to this read. Return no book when the binding is absent or differs: ```ts const market = await client.getMarketOnchain(marketId); const binding = await client.getPoolMarketBinding(market.pool); const book = binding?.marketId.toLowerCase() === marketId.toLowerCase() ? await client.getBinaryOrderBook(market.pool, { blockNumber: binding.blockNumber, decimals: market.decimals, }) : null; ``` **Details** - `opts.depth`: Price levels per side (default 10). - `opts.decimals`: Price scale decimals for the NO-side inversion (default 6). - `opts.blockNumber`: Pin both sides to this block. Omitted: select one head. Successful empty books retain the pin. This is an exact chain snapshot. #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetBinaryOrderBookOptions`](GetBinaryOrderBookOptions.md) #### Returns `Promise`\<[`BinaryOrderBook`](BinaryOrderBook.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If depth or the block pin is invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If selecting the head or reading either side fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects either read. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBinaryOrderBook`](SomniaMarketsClient.md#getbinaryorderbook) *** ### getSpotOrderBook() > **getSpotOrderBook**(`pool`, `opts?`): `Promise`\<[`SpotOrderBook`](SpotOrderBook.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2550 Read a spot OR perp pool's resting book from the contract (both ride the shared OrderBook base). Live variant: [getLiveSpotOrderBook](SomniaMarketsClient.md#getlivespotorderbook). **Details** - `opts.depth`: Levels per side (default 12). - `opts.blockNumber`: Pin both sides to this block. Omitted: select one head. Successful empty books retain the pin. #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetSpotOrderBookOptions`](GetSpotOrderBookOptions.md) #### Returns `Promise`\<[`SpotOrderBook`](SpotOrderBook.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If depth or the block pin is invalid. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If selecting the head or reading either side fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects either read. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSpotOrderBook`](SomniaMarketsClient.md#getspotorderbook) *** ### getOrderOnchain() > **getOrderOnchain**(`pool`, `orderId`, `opts?`): `Promise`\<[`OnchainOrder`](OnchainOrder.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2595 One order's state at chain head, by `(pool, orderId)` — ids are unique per pool. Reads your own writes: answers from the block a placement landed in, while the indexed [getOrders](SomniaMarketsClient.md#getorders) may still lag. `null` when the pool has no ACTIVE order for that id (never assigned, filled, cancelled, expired-and-swept, or replaced by an amend, which re-places under a NEW id; a `reduceOrder` keeps its id and stays active) - the indexer is the surface that keeps history. `opts.blockNumber` reads at the end of that block instead - historical order state, for a consumer decoding `OrderFilled` from chain logs. That event carries the fill's own `fillPrice` (which IS the maker's resting price), `quantityFilled` and `makerRemainingQuantity`, so take those from the event; what it does not carry is the maker's SIDE, and the fill removes the maker order in the same transaction, so the last height holding it is `fill.blockNumber - 1n`. That read is exact for the maker's identity - `isBid`, `owner`, `userData`, `expireTimestampNs`, none of which any fill log carries - and BLOCK-LEVEL for BOTH quantities: an earlier transaction in the fill's own block may have filled this maker, or reduced it (`reduceOrder` decrements `fullQuantity` and `quantityRemaining` together, under the same id), and no block read sees between transactions. Two edges answer plausibly rather than failing: a PARTIAL fill leaves the order in place with a smaller `quantityRemaining`, so reading at the fill's own block succeeds with different numbers; and an order placed and filled inside ONE block is absent at `blockNumber - 1n`, so that read is `null` and the placement has to come from the same block's `OrderPlaced`. A pinned read far behind head needs archive state. ```ts // A fill's side, for a maker this process never saw rest. const maker = await client.getOrderOnchain(pool, makerOrderId, { blockNumber: fillBlock - 1n }); // `null` is an UNRESOLVED side, not a sell: an order placed and filled inside one // block has no state one block earlier, and its side is in that block's OrderPlaced. const takerBought = maker === null ? null : !maker.isBid; ``` #### Parameters ##### pool `` `0x${string}` `` ##### orderId `bigint` ##### opts? [`GetOrderOnchainOptions`](GetOrderOnchainOptions.md) #### Returns `Promise`\<[`OnchainOrder`](OnchainOrder.md) \| `null`\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If the read fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If the contract rejects the read for any reason other than the id having no active order. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOrderOnchain`](SomniaMarketsClient.md#getorderonchain) *** ### getBookTopsOnchain() > **getBookTopsOnchain**(`markets`, `opts?`): `Promise`\<[`BookTopsOnchain`](BookTopsOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2617 Top of book for many markets, read from POOL STATE at ONE pinned block — the chain-sourced sibling of [getBookTops](SomniaMarketsClient.md#getbooktops). Prefer this wherever a quote must not lag: a board, a selector, a mark for open positions. [getBookTops](SomniaMarketsClient.md#getbooktops) stays the cheaper read (one indexed round-trip, no chain dependency) for an unbounded list that tolerates indexer lag. Pass the market rows a view already holds — each supplies its own `poolAddress`, so nothing is resolved twice. `tops` is keyed by lowercased market id and omits empty-book markets, exactly as [getBookTops](SomniaMarketsClient.md#getbooktops) does, so the two are comparable key for key. Cost is two reads per market where the chain declares no Multicall3; keep the set to what a view shows. #### Parameters ##### markets `object`[] ##### opts? [`GetBookTopsOnchainOptions`](GetBookTopsOnchainOptions.md) #### Returns `Promise`\<[`BookTopsOnchain`](BookTopsOnchain.md)\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) If the owner has no chain endpoint, or its RPC serves a retired genesis of the chain. #### Throws [RpcError](../classes/RpcError.md) If the read fails. #### Throws [ContractRevertError](../classes/ContractRevertError.md) If a pool rejects the read. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBookTopsOnchain`](SomniaMarketsClient.md#getbooktopsonchain) *** ### getOwnOpenOrdersOnchain() > **getOwnOpenOrdersOnchain**(`pool`, `owner`, `opts?`): `Promise`\<`bigint`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2629 An owner's open order ids at chain head, or at a pinned block. Any address may be asked about — the pool's view reads `msg.sender` and this impersonates via the `eth_call` sender, so no signer is involved. Indexed counterpart, with human units and history: [getOpenOrders](SomniaMarketsClient.md#getopenorders). For the full rows rather than the ids, use [getOpenOrdersOnchain](SomniaMarketsClient.md#getopenordersonchain). #### Parameters ##### pool `` `0x${string}` `` ##### owner `` `0x${string}` `` ##### opts? [`GetOwnOpenOrdersOnchainOptions`](GetOwnOpenOrdersOnchainOptions.md) #### Returns `Promise`\<`bigint`[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOwnOpenOrdersOnchain`](SomniaMarketsClient.md#getownopenordersonchain) *** ### getOpenOrdersOnchain() > **getOpenOrdersOnchain**(`pools`, `owner`, `opts?`): `Promise`\<[`OpenOrdersOnchain`](OpenOrdersOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2647 One owner's full open-order rows across several pools, read from chain at ONE pinned block. This is the outage-resilient companion to [getOpenOrders](SomniaMarketsClient.md#getopenorders), which is an indexer read: it throws `IndexerError` while the indexer is unreachable and lists stale rows while it lags. Point a bot that must know what it has resting at this read instead of wrapping the indexed one in a catch. The caller supplies the pool list; there is no discovery, because resolving pools by symbol is itself an indexer read. Rows carry `isBid` and no YES/NO side, no market or symbol, and no history — see the function's own TSDoc for why the binary side is not derivable. A pool with no resting orders contributes no rows. A failed read throws. #### Parameters ##### pools `` `0x${string}` ``[] ##### owner `` `0x${string}` `` ##### opts? [`GetOpenOrdersOnchainOptions`](GetOpenOrdersOnchainOptions.md) #### Returns `Promise`\<[`OpenOrdersOnchain`](OpenOrdersOnchain.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOpenOrdersOnchain`](SomniaMarketsClient.md#getopenordersonchain) *** ### getAllOpenOrdersOnchain() > **getAllOpenOrdersOnchain**(`pool`, `opts`): `Promise`\<\{ `orders`: [`OnchainOrder`](OnchainOrder.md)[]; `hasMore`: `boolean`; `nextCursor`: `bigint`; \}\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2670 One page of every open order on one side, at chain head — the per-order detail the aggregated book reads ([getBinaryOrderBook](SomniaMarketsClient.md#getbinaryorderbook), [getSpotOrderBook](SomniaMarketsClient.md#getspotorderbook)) collapse into levels. The pool accepts this view only from the zero address, so a configured signer is never forwarded. Loop while `hasMore`, feeding `nextCursor` back as `cursor`; pin a block if pages must be mutually consistent. **Details** - `opts.maxCount`: Orders per page (default 100). - `opts.blockNumber`: Read at that exact block instead of the current head, so every page of a multi-page snapshot sees one book. Sample a head with `getBlockNumber` and pass it to every page. #### Parameters ##### pool `` `0x${string}` `` ##### opts ###### isBid `boolean` ###### maxCount? `number` ###### cursor? `bigint` ###### blockNumber? `bigint` #### Returns `Promise`\<\{ `orders`: [`OnchainOrder`](OnchainOrder.md)[]; `hasMore`: `boolean`; `nextCursor`: `bigint`; \}\> #### Throws [InvalidInputError](../classes/InvalidInputError.md) If `opts.blockNumber` is negative. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getAllOpenOrdersOnchain`](SomniaMarketsClient.md#getallopenordersonchain) *** ### getPerpState() > **getPerpState**(`pool`): `Promise`\<[`PerpStateOnchain`](PerpStateOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2680 A perp pool's live mark/index price, funding rate + cumulative index, and open interest in one pipelined fan-out — fresher than the indexed row (which only updates on funding settlements). #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpStateOnchain`](PerpStateOnchain.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpState`](SomniaMarketsClient.md#getperpstate) *** ### getPerpFeedStatus() > **getPerpFeedStatus**(`pool`): `Promise`\<[`PerpFeedStatus`](PerpFeedStatus.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2705 Is a perp pool's mark feed live, and how much open interest is riding on it — the pair a mark-feed monitor needs, with the index timestamp as best-effort corroboration. Prefer this to [getPerpState](SomniaMarketsClient.md#getperpstate) for MONITORING a feed. That read is all-or-nothing and one of its legs is a bare `IOracle.getPrice()`, so a dead oracle rejects the whole call and the mark verdict is lost in exactly the case it is wanted. Here the verdict cannot be taken down by the oracle: `tryGetMarkPrice` reports staleness rather than reverting, open interest consults no oracle, and only the index timestamp — which arrives `undefined` instead — is allowed to fail. Read [getPerpState](SomniaMarketsClient.md#getperpstate) instead when you want the full pricing and funding picture and a dead oracle is a legitimate reason to fail the call. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpFeedStatus`](PerpFeedStatus.md)\> #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) No WebSocket endpoint is configured — `wsRpcUrl`, or a chain whose `rpcUrls` carry one. Raised when this read resolves its client, before any request goes out. #### Throws [RpcError](../classes/RpcError.md) A chain read did not complete — the block pin included. #### Throws [ContractRevertError](../classes/ContractRevertError.md) The pool rejected the mark or open-interest read. A reverting INDEX read is NOT among these: it is swallowed by design and surfaces as an absent `indexUpdatedAt`. The complete union is [SomniaMarketsClientGetPerpFeedStatusError](../type-aliases/SomniaMarketsClientGetPerpFeedStatusError.md). #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpFeedStatus`](SomniaMarketsClient.md#getperpfeedstatus) *** ### getPerpFundingPremium() > **getPerpFundingPremium**(`pool`): `Promise`\<[`PerpFundingPremium`](PerpFundingPremium.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2720 A perp pool's funding-premium state: what the next settlement will charge, the standing instantaneous sample, and the raw accumulator behind them. Separate from [getPerpState](SomniaMarketsClient.md#getperpstate) on purpose — these getters arrived with Wave 28 and do not exist on an older pool implementation, and `getPerpState` batches with `allowFailure: false`, so folding them in would let one un-upgraded pool take a core read down. Read `timeWeightedPremium` for a predicted funding rate, never `lastObservedPremium` — the contract getter behind the latter kept its signature and changed its meaning. Check `armed` before calling the figure an average. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpFundingPremium`](PerpFundingPremium.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpFundingPremium`](SomniaMarketsClient.md#getperpfundingpremium) *** ### getPerpPosition() > **getPerpPosition**(`ref`): `Promise`\<[`PerpPosition`](PerpPosition.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2726 An account's position in one perp pool, from the MarginBank (signed size: positive = long). `ref.marginBank` comes off the [PerpMarket](../type-aliases/PerpMarket.md) row. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpPosition`](PerpPosition.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpPosition`](SomniaMarketsClient.md#getperpposition) *** ### getMarginAccount() > **getMarginAccount**(`marginBank`, `account`): `Promise`\<[`MarginAccount`](MarginAccount.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2735 An account's cross-margin state (free/locked collateral, equity, withdrawable, active pools) from the MarginBank — now including the account health (`imReq`/`mmReq`/`cmReq`) and `marginStatus`. The client samples the chain head once and pins every component read to that block, so all fields describe one chain state. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`MarginAccount`](MarginAccount.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarginAccount`](SomniaMarketsClient.md#getmarginaccount) *** ### getAccountHealth() > **getAccountHealth**(`marginBank`, `account`): `Promise`\<[`AccountHealth`](AccountHealth.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2742 An account's cross-margin health alone (equity vs IM/MM/CM + the derived status) — a lighter read than [getMarginAccount](SomniaMarketsClient.md#getmarginaccount) when only health matters. The health tuple and status are pinned to one sampled chain block. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`AccountHealth`](AccountHealth.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getAccountHealth`](SomniaMarketsClient.md#getaccounthealth) *** ### getLiquidationPrice() > **getLiquidationPrice**(`ref`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2754 Estimated liquidation price for an account's position in one perp pool (raw quote units per whole base), or null when flat. Solves `equity == mmReq` with BOTH sides moving against the mark — see `perpLiquidationPrice` — over the cross-margin equity/mmReq, so it is the price at which this pool's move alone trips maintenance. Throws on a stale mark anywhere in the account. This is where liquidation *triggers*. For the contract's own figure of where a position's equity is *exhausted*, see [getBankruptcyPrice](SomniaMarketsClient.md#getbankruptcyprice). #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<`bigint` \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiquidationPrice`](SomniaMarketsClient.md#getliquidationprice) *** ### getPerpLeverage() > **getPerpLeverage**(`ref`): `Promise`\<[`PerpLeverage`](PerpLeverage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2769 An account's realized leverage at one position and across the whole cross-margin account, plus every ceiling that bounds it — the market's IMF-implied max, the account's own cap, the protocol limit, and the credit-voucher confinement. Ratios are bps of 1x. Derived, not read: the MarginBank exposes only leverage *caps*, never a measurement of a position. The ceilings are returned as stored and do not compose by taking a minimum — see [PerpLeverage.voucherLeverageCapX](PerpLeverage.md#voucherleveragecapx). For whether a specific order passes, use `previewPerpOrderMargin`. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpLeverage`](PerpLeverage.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpLeverage`](SomniaMarketsClient.md#getperpleverage) *** ### getPerpPositionAnalytics() > **getPerpPositionAnalytics**(`ref`): `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2785 One position, marked — unrealized PnL, accrued funding, notional, the three margin requirements it contributes, and its return on margin. Two reads, pinned to one block. The split `getAccountHealth` cannot give you: that returns one equity figure for the whole account, with every market's PnL and funding already summed and netted, so a two-position trader cannot see which one carries the loss and cannot see funding at all. `accruedFunding` is **owed** — positive means the account pays. Returns `{ priceable: false }` on a stale mark rather than throwing, because in a positions table one dead feed must degrade one row, not the page. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) #### Returns `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpPositionAnalytics`](SomniaMarketsClient.md#getperppositionanalytics) *** ### listPerpPositionAnalytics() > **listPerpPositionAnalytics**(`p`): `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2798 Every position the account holds, each marked — the positions-table read. `1 + 2n` reads for `n` active markets, all pinned to ONE block, which is the point of having it rather than looping the single read: unpinned, the rows come from different heights and their `equityContribution`s do not re-sum to any equity the account ever had. Scoped to the bank's own `activePerpPools`, so a closed position does not linger the way it does on the indexed rows. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpPositionAnalytics`](../type-aliases/PerpPositionAnalytics.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpPositionAnalytics`](SomniaMarketsClient.md#listperppositionanalytics) *** ### getMaxPerpOrderSize() > **getMaxPerpOrderSize**(`p`): `Promise`\<[`PerpMaxOrderSize`](../type-aliases/PerpMaxOrderSize.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2819 The largest order this account can place at `price` — what a **Max** button should call. The inverse of `previewPerpOrderMargin`, and the protocol has no such view. Does not re-derive the sizing rule: it binary-searches the forward one, so the two cannot disagree. A hand-rolled `equity / (price × imf)` drops the adverse mark-to-entry term, which is the usual reason a "max" order is rejected. `maxQuantity` is aligned down to the pool's lot grid. **Check `placeable`** — a size below the pool's `minQuantity` is a revert, not a small order. `limitedBy` says which gate bound it. Market-wide `maxOpenInterest` and book depth are deliberately not modelled. **Pass `autoPull` when the transaction sender will be the order owner.** That is the pool's whole gate for topping the account up from its wallet (T70), and with it on, an account with an empty bank and a funded, approved wallet goes from a max of `0n` to whatever the wallet funds. Leave it off for `placeOrderFor`, an operator grant or the stop registry, where no pull happens. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### price `bigint` ###### autoPull? `boolean` ###### builderFeeBpsTimes1k? `bigint` #### Returns `Promise`\<[`PerpMaxOrderSize`](../type-aliases/PerpMaxOrderSize.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMaxPerpOrderSize`](SomniaMarketsClient.md#getmaxperpordersize) *** ### previewPerpClosePnl() > **previewPerpClosePnl**(`p`): `Promise`\<[`PerpClosePreview`](../type-aliases/PerpClosePreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2842 What closing a position — all of it or part — would actually realise. Backs a close modal. Two things it gets right that a hand-derived figure usually does not, both silent: the close is **aligned down to the lot grid** first, so a "close all" on a position that is not a lot multiple leaves a remainder open; and funding settles on the **whole** position rather than the closed share, because `settleTrade` settles before it touches the position. `netProceeds` is the number to show — `realizedPnl − fundingSettled − fee`. `fundingSettled` is positive when the account pays. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### quantity? `bigint` ###### price? `bigint` ###### asMaker? `boolean` #### Returns `Promise`\<[`PerpClosePreview`](../type-aliases/PerpClosePreview.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`previewPerpClosePnl`](SomniaMarketsClient.md#previewperpclosepnl) *** ### previewPerpLiquidationPrice() > **previewPerpLiquidationPrice**(`p`): `Promise`\<[`PerpLiquidationPreview`](../type-aliases/PerpLiquidationPreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2861 Where a proposed order would leave the liquidation price if it filled in full at its limit price, alongside where it sits now — the projection an order form needs, which [getLiquidationPrice](SomniaMarketsClient.md#getliquidationprice) cannot give for an order not yet placed. Ports all four of `MarginBank.settleTrade`'s cases (open / increase / reduce / flip) and charges the fill's fee, so a reduce and an add move the answer in opposite directions. Whether the order is ACCEPTED is [previewPerpOrderMargin](SomniaMarketsClient.md#previewperpordermargin)'s question, not this one. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### quantity `bigint` ###### price `bigint` ###### asMaker? `boolean` #### Returns `Promise`\<[`PerpLiquidationPreview`](../type-aliases/PerpLiquidationPreview.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`previewPerpLiquidationPrice`](SomniaMarketsClient.md#previewperpliquidationprice) *** ### getPerpSideHolders() > **getPerpSideHolders**(`ref`, `opts?`): `Promise`\<[`PerpSideHolders`](PerpSideHolders.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2893 Every account holding an open position on one side of one perp market, from the MarginBank's own per-(pool, side) holder array — the read that lets a liquidation keeper find its watch set from head state alone, no off-chain indexer. Chain tier. Pages through the bank's bounded slice view (many holders per round-trip, never one call per holder), with every page pinned to ONE block — `opts.blockNumber`, or the head sampled once — so a holder entering or leaving mid-walk can neither be missed nor double-counted. The result carries `asOfBlock`; feed it into [getBankruptcyPrice](SomniaMarketsClient.md#getbankruptcyprice)'s `opts.blockNumber` (and the other side's call) to keep a sweep on one consistent snapshot — the other position/health reads answer at head only. The indexed counterpart, [listPerpPositions](SomniaMarketsClient.md#listperppositions), answers the inverse question (one account's positions across pools) and lags head. **Details** - `opts.blockNumber`: pin to this block instead of the current head - `opts.pageSize`: holders per contract call (default 1000) #### Parameters ##### ref [`PerpSideHoldersRef`](PerpSideHoldersRef.md) ##### opts? [`GetPerpSideHoldersOptions`](GetPerpSideHoldersOptions.md) #### Returns `Promise`\<[`PerpSideHolders`](PerpSideHolders.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpSideHolders`](SomniaMarketsClient.md#getperpsideholders) *** ### getBankruptcyPrice() > **getBankruptcyPrice**(`ref`, `opts?`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2914 The MarginBank's OWN bankruptcy price for an account's position in one perp pool (raw quote units per whole base) — the contract-computed price at which the position's allocated equity is exhausted. What a liquidation keeper prices a bankrupt position against. A different quantity from [getLiquidationPrice](SomniaMarketsClient.md#getliquidationprice), not a better version of it: that is the SDK's client-side estimate of where liquidation *triggers* (use it for UI/monitoring); this is the contract's figure for where there is nothing left (use it for anything that settles or bids). Reverts rather than returning a sentinel — a [ContractRevertError](../classes/ContractRevertError.md) with `errorName: "NoOpenPosition"` when the account is flat in that pool (branch on `errorName`, never message text). **Details** - `opts.blockNumber`: read at this block instead of head. Pricing an enumerated holder? Pass the enumeration's `asOfBlock` — at head, a holder that closed after the snapshot reverts `NoOpenPosition`. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) ##### opts? [`GetBankruptcyPriceOptions`](GetBankruptcyPriceOptions.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBankruptcyPrice`](SomniaMarketsClient.md#getbankruptcyprice) *** ### getPerpSystemConfig() > **getPerpSystemConfig**(`marginBank`): `Promise`\<[`PerpSystemConfig`](PerpSystemConfig.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2929 How the perps stack is wired — the address book for every other contract in the plane (collateral token, pool factory, liquidation engine, insurance fund, fee recipient), plus the protocol-wide leverage ceiling and a `fullyWired` flag. Read this first: the addresses here are what the other protocol-state reads should be pointed at, so nothing is hardcoded per chain, and they are the bank's own view — the addresses it will actually call. `liquidationEngine` is the PROXY. An implementation address answers reads with unset defaults (zero bidders, zero penalty), which looks like a configured-but-idle engine rather than the wrong address. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<[`PerpSystemConfig`](PerpSystemConfig.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpSystemConfig`](SomniaMarketsClient.md#getperpsystemconfig) *** ### getInsuranceFundState() > **getInsuranceFundState**(`fund`): `Promise`\<[`InsuranceFundState`](InsuranceFundState.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2935 The InsuranceFund's per-tier balances and the total bad debt it can absorb. Point it at `insuranceFund` from [getPerpSystemConfig](SomniaMarketsClient.md#getperpsystemconfig). #### Parameters ##### fund `` `0x${string}` `` #### Returns `Promise`\<[`InsuranceFundState`](InsuranceFundState.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getInsuranceFundState`](SomniaMarketsClient.md#getinsurancefundstate) *** ### listPerpInsuranceFundEvents() > **listPerpInsuranceFundEvents**(`opts?`): `Promise`\<[`PerpInsuranceFundEvent`](../type-aliases/PerpInsuranceFundEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2946 The InsuranceFund's tier ledger, newest first — how each tier reached the balance [getInsuranceFundState](SomniaMarketsClient.md#getinsurancefundstate) reports. Indexer tier; the chain keeps no history. **Do not sum `amount` bare.** It is populated on inflows, outflows and the internal `TierAllocated` move alike, so a plain total is turnover rather than a balance — fold it by `kind`. `covered` on a `BadDebtAuthorised` row restates the `TierDebited` rows beside it, and `TierCredited` restates the fee plane's `insurancePortion`. #### Parameters ##### opts? ###### kind? `string` ###### tier? `number` \| `bigint` ###### account? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpInsuranceFundEvent`](../type-aliases/PerpInsuranceFundEvent.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpInsuranceFundEvents`](SomniaMarketsClient.md#listperpinsurancefundevents) *** ### getLiquidationEngineConfig() > **getLiquidationEngineConfig**(`engine`): `Promise`\<[`LiquidationEngineConfig`](LiquidationEngineConfig.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2963 The LiquidationEngine's configured bounds — penalty, spread range, per-block volume cap, registered backstop bidders. Not its history, which is indexed as `LiquidationEvent`. `bidderCount === 0n` is an operational signal: with no registered bidders the takeover stage has nobody to take a position over, so the waterfall reaches ADL sooner than the configuration implies. #### Parameters ##### engine `` `0x${string}` `` #### Returns `Promise`\<[`LiquidationEngineConfig`](LiquidationEngineConfig.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLiquidationEngineConfig`](SomniaMarketsClient.md#getliquidationengineconfig) *** ### tryGetPerpAccountEquity() > **tryGetPerpAccountEquity**(`marginBank`, `account`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2972 An account's equity, or `null` when it could not be computed. [getAccountHealth](SomniaMarketsClient.md#getaccounthealth) propagates an oracle failure, which is exactly when a health sweep most needs an answer. Null means "not computable right now" — an unpriceable market in the account's set — never "zero equity". #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint` \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`tryGetPerpAccountEquity`](SomniaMarketsClient.md#trygetperpaccountequity) *** ### getPerpCollateralBasis() > **getPerpCollateralBasis**(`marginBank`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:2981 Collateral BACKING an account: `max(0, unlocked + locked)`, raw units. Deliberately unlike equity — one storage pair, no market walk, no oracle, and it cannot revert. A solvency floor that survives a dead price feed; use equity when you need mark-to-market truth. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpCollateralBasis`](SomniaMarketsClient.md#getperpcollateralbasis) *** ### listPerpPoolStatuses() > **listPerpPoolStatuses**(`p`): `Promise`\<[`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3007 Every perp market the factory has deployed, in deployment order, with the two independent gates that decide whether it is tradeable: `restricted` (close-only) and `registered` (activated on the MarginBank). **Do not build a market list from the factory's raw pool list** — that is the deployment history and includes markets wound down to close-only, so listing it unfiltered presents dead markets as tradeable. Chain-sourced, which makes it complete and available when the indexer is not: the indexer builds its perp set dynamically from `PerpPoolDeployed`, so a pool deployed above its current head is invisible there and present here. You do not pass a MarginBank. It is a per-network singleton in practice, but each pool names its own and that is the bank its settlement path uses — so it is read per pool and returned on every row, ready for the [getMarginAccount](SomniaMarketsClient.md#getmarginaccount) / [getPerpPosition](SomniaMarketsClient.md#getperpposition) reads that follow. Feature-detects the factory's one-call status view and falls back to per-pool reads on a factory that predates it, returning the same shape either way. Per-pool reads go through Multicall3 in batches of up to 100 pools per request when the chain declares it, and through at most 8 concurrent point reads when it does not. Every read is pinned to one block. #### Parameters ##### p ###### factory `` `0x${string}` `` #### Returns `Promise`\<[`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpPoolStatuses`](SomniaMarketsClient.md#listperppoolstatuses) *** ### listTradeablePerpPools() > **listTradeablePerpPools**(`p`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3010 Just the tradeable perp pools, filtered from [listPerpPoolStatuses](SomniaMarketsClient.md#listperppoolstatuses). #### Parameters ##### p ###### factory `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listTradeablePerpPools`](SomniaMarketsClient.md#listtradeableperppools) *** ### readPerpMarketFromChain() > **readPerpMarketFromChain**(`p`): `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3026 One factory-deployed perp market as a native [PerpMarket](../type-aliases/PerpMarket.md) row, read entirely from the chain — for a market the indexer does not carry. Chain tier. Reads the pool's book grid and margin factor, the base token's symbol and decimals, and the pool's stop registry from the factory. History-derived fields come back as documented placeholders, because no chain read can supply them — see [UnifiedMarket.indexed](UnifiedMarket.md#indexed) for which ones and what they mean. **Gotchas** - Throws [RpcError](../classes/RpcError.md) when a read cannot be completed, and [ContractRevertError](../classes/ContractRevertError.md) when the pool or token rejects one. The grid, the margin factor and the decimals have no safe fallback, so an unreadable pool fails rather than producing a mis-scaled market. Two reads degrade instead: a token exposing no `symbol()` yields `baseSymbol: null`, and a factory predating `IPerpPoolFactoryStopRegistry` yields `stopRegistry: null`. #### Parameters ##### p ###### status [`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md) ###### collateralToken `` `0x${string}` `` ###### collateralDecimals `number` ###### collateralSymbol `string` \| `null` ###### factory `` `0x${string}` `` #### Returns `Promise`\<[`PerpMarket`](../type-aliases/PerpMarket.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`readPerpMarketFromChain`](SomniaMarketsClient.md#readperpmarketfromchain) *** ### isPerpPoolRegistered() > **isPerpPoolRegistered**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3043 Whether the MarginBank has one perp pool registered — the activation gate on its own. Coming from the factory only proves a pool is authentic; registration is what makes it usable. Not interchangeable with `getPoolTier`, which is itself gated on registration and so returns 0 for an uncovered-but-registered market and an unregistered one alike. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### pool `` `0x${string}` `` #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`isPerpPoolRegistered`](SomniaMarketsClient.md#isperppoolregistered) *** ### previewPerpOrderMargin() > **previewPerpOrderMargin**(`p`): `Promise`\<[`PerpOrderMarginPreview`](../type-aliases/PerpOrderMarginPreview.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3092 What a perp order will lock and whether the pool will accept it, computed BEFORE sending — the read behind an order form's "margin required" row and submit gate. Ports `PerpPool._computeLockAmount` plus the MarginBank gate it feeds, so the number shown is the number actually reserved. **Why not a contract pre-check.** `quoteMeetsIMForOrder` looks right and is not: it runs with the order's base margin treated as already reserved, because on the real path the lock has run first. Called cold it counts the order's margin nowhere and returns true for almost any size. `meetsIMForFill` does charge base margin but models neither the lock nor its adverse mark-to-entry reserve — the term that rejects a naively-sized "max" order. Reports **two gates** separately, because they fail for different reasons and imply different fixes: `hasCollateralForLock` (the lock can be taken at all) vs `meetsInitialMargin` (what remains still covers the requirement) — "deposit more" vs "close something". Every read is pinned to one block; a preview is a statement about that block, so re-quote near send time for anything close to the edge. **Pass `autoPull` when the transaction sender will be the order owner** — the pool's whole gate for topping the account up from its wallet (T70). With it on, both gates describe the post-pull balance. Off, they describe the in-bank balance alone, which is what an operator- or registry-routed placement actually faces. `topUpRequired` is the total the pull REQUESTS, not one wallet's debit: a linked child is funded by its own wallet first and its main for the residual, so show `ownWalletPull` and `mainWalletPull` beside the margin figure and read `fundingPayer` for whose wallet the second one is. Only `mainWalletPull > 0n` proves another wallet actually moves. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### isBid `boolean` ###### quantity `bigint` ###### price `bigint` ###### autoPull? `boolean` ###### builderFeeBpsTimes1k? `bigint` #### Returns `Promise`\<[`PerpOrderMarginPreview`](../type-aliases/PerpOrderMarginPreview.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`previewPerpOrderMargin`](SomniaMarketsClient.md#previewperpordermargin) *** ### meetsPerpImForFill() > **meetsPerpImForFill**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3111 The MarginBank's initial-margin probe for an order not yet locked — the closest single contract call to a pre-trade gate. Charges the increasing leg's base margin against free equity, but does not model the lock's adverse mark-to-entry reserve; [previewPerpOrderMargin](SomniaMarketsClient.md#previewperpordermargin) is the accurate gate. `additionalSize` is the INCREASING quantity, not necessarily the whole order. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### additionalSize `bigint` ###### price `bigint` #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`meetsPerpImForFill`](SomniaMarketsClient.md#meetsperpimforfill) *** ### quoteMeetsPerpImForOrder() > **quoteMeetsPerpImForOrder**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3128 The MarginBank's placement-time initial-margin check, verbatim. **Not a pre-trade gate, despite the name** — it treats the order's base margin as already reserved, so called cold it answers true for almost any size. Correct only for a caller that has already taken the lock, i.e. for mirroring the placement check itself. For "will my order be accepted", use [previewPerpOrderMargin](SomniaMarketsClient.md#previewperpordermargin). #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### account `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### additionalSize `bigint` ###### price `bigint` #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quoteMeetsPerpImForOrder`](SomniaMarketsClient.md#quotemeetsperpimfororder) *** ### quotePerpOrderTopUp() > **quotePerpOrderTopUp**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3150 The MarginBank's auto-pull sizing, verbatim — how much placing an order would take from the owner's wallet. **For an order form use `previewPerpOrderMargin` with `autoPull` instead.** It derives `lockAmount`, `feeHeadroom` and `increasingQuantity` from the order, which is the awkward part: they come from the POOL, not the bank, so calling this directly means reproducing the same three numbers the pool would pass. This is the cross-check on that port. Returns `0n` both when no pull is needed and in the three cases where a pull would be wrong rather than unnecessary — a purely reducing order, an account already in debt, and a voucher-blocked increase — so read it beside the unlocked balance. #### Parameters ##### p ###### marginBank `` `0x${string}` `` ###### pool `` `0x${string}` `` ###### account `` `0x${string}` `` ###### lockAmount `bigint` ###### feeHeadroom `bigint` ###### increasingQuantity `bigint` ###### price `bigint` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quotePerpOrderTopUp`](SomniaMarketsClient.md#quoteperpordertopup) *** ### getPerpLeverageImSurcharge() > **getPerpLeverageImSurcharge**(`marginBank`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3175 The EXTRA initial margin an account's own leverage settings demand, summed over every market where it BOTH holds a position AND has set a stricter-than-market cap. This explains an `InsufficientMarginForOrder` that [quotePerpOrderTopUp](SomniaMarketsClient.md#quoteperpordertopup) cannot. The two measure different things: the quote funds one order against the UNLOCKED balance, while the admission gate measures whole-account EQUITY — so an order can be fully funded on its own market and still be refused because of an override on a different one. Deposit this deliberately rather than expecting a pull to cover it. Reverts if a market that is both positioned and overridden is unpriceable; use [tryGetPerpLeverageImSurcharge](SomniaMarketsClient.md#trygetperpleverageimsurcharge) in a sweep. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpLeverageImSurcharge`](SomniaMarketsClient.md#getperpleverageimsurcharge) *** ### tryGetPerpLeverageImSurcharge() > **tryGetPerpLeverageImSurcharge**(`marginBank`, `account`): `Promise`\<`bigint` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3189 [getPerpLeverageImSurcharge](SomniaMarketsClient.md#getperpleverageimsurcharge) without the revert — `null` when it could not be computed. `null` means "not computable right now", never "no surcharge". Substituting `0n` would under-state the requirement, which is the wrong direction to be wrong in. Only a revert from the view itself becomes `null`. A read that never reached the chain throws, and so does an address that does not declare the view. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint` \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete, or `marginBank` does not declare the view. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`tryGetPerpLeverageImSurcharge`](SomniaMarketsClient.md#trygetperpleverageimsurcharge) *** ### getPerpMaxLeverage() > **getPerpMaxLeverage**(`ref`, `opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3210 One account's own leverage cap for one perp pool, as the MarginBank stores it — the cheap path to the number [getPerpLeverage](SomniaMarketsClient.md#getperpleverage) reports as `accountMaxLeverageX`. Chain tier, exactly one storage read. Unlike [getPerpLeverage](SomniaMarketsClient.md#getperpleverage) it does NOT walk the account, so a stale mark on some other market cannot take it down — the cap is a setting, not a measurement, and never needed a price. Use it for a per-position badge or a leverage dialog; use [getPerpLeverage](SomniaMarketsClient.md#getperpleverage) when the question is realized account-wide leverage. `0` means "no account cap set", never zero leverage — the market ceiling binds then. Returned unchanged for the caller to compose. **Details** - `ref`: the (bank, account, pool) triple - `opts.blockNumber`: read at this block instead of head. Combining the cap with an enumeration's or analytics row's figures? Pass that row's `asOfBlock` so both describe one moment. #### Parameters ##### ref [`PerpPositionRef`](PerpPositionRef.md) ##### opts? [`GetPerpMaxLeverageOptions`](GetPerpMaxLeverageOptions.md) #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpMaxLeverage`](SomniaMarketsClient.md#getperpmaxleverage) *** ### getPerpLinkedWalletRegistry() > **getPerpLinkedWalletRegistry**(`marginBank`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3220 The registry the bank resolves wallet links through, or `null` while the linked-wallet funding rail is DORMANT. Read it from the bank rather than a deployment manifest: the bank decides which registry is authoritative, and a registry nobody has armed is inert. `null` means no child can draw on any main on this deployment. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpLinkedWalletRegistry`](SomniaMarketsClient.md#getperplinkedwalletregistry) *** ### quotePerpFundingPayer() > **quotePerpFundingPayer**(`marginBank`, `account`): `Promise`\<[`PerpFundingPayer`](../type-aliases/PerpFundingPayer.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3230 Whether this account's next position-increasing order would spend a main's wallet, and whose. A discriminated union, because the contract's single zero collapses three cases a UI must not render alike: the rail is dormant, the wallet is unlinked, or the wallet IS a main. Only `unlinked` is the user's to fix. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpFundingPayer`](../type-aliases/PerpFundingPayer.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quotePerpFundingPayer`](SomniaMarketsClient.md#quoteperpfundingpayer) *** ### getPerpMainFunding() > **getPerpMainFunding**(`marginBank`, `account`): `Promise`\<[`PerpMainFunding`](PerpMainFunding.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3240 Principal a main has funded into this account and not recovered, plus the payer recorded at funding time. What a main funds can be borrowed, never withdrawn — `withdraw` frees at most `balance - principal`. The payer is SNAPSHOTTED, so it is who gets repaid even if the link has since changed. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpMainFunding`](PerpMainFunding.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpMainFunding`](SomniaMarketsClient.md#getperpmainfunding) *** ### getPerpWalletPullCapacity() > **getPerpWalletPullCapacity**(`marginBank`, `wallet`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3249 What a wallet could contribute to a pull right now — `min(balance, allowance)`. On a MAIN this is the ceiling on what its children can collectively draw, and the number to reduce to revoke the rail without unlinking (consent is the allowance). On a CHILD it is how much of its own money it burns before reaching its main's. #### Parameters ##### marginBank `` `0x${string}` `` ##### wallet `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpWalletPullCapacity`](SomniaMarketsClient.md#getperpwalletpullcapacity) *** ### getPerpWalletLinkage() > **getPerpWalletLinkage**(`registry`, `wallet`): `Promise`\<[`PerpWalletLinkage`](PerpWalletLinkage.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3259 A wallet's link group and its ADL-netting maturity. Takes the REGISTRY address — resolve it with [getPerpLinkedWalletRegistry](SomniaMarketsClient.md#getperplinkedwalletregistry) so a dormant deployment reads as dormant rather than as an empty group. `maturesAt` gates ADL netting only: the funding rail reads the raw graph, so a link can be fundable and not yet mature. #### Parameters ##### registry `` `0x${string}` `` ##### wallet `` `0x${string}` `` #### Returns `Promise`\<[`PerpWalletLinkage`](PerpWalletLinkage.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpWalletLinkage`](SomniaMarketsClient.md#getperpwalletlinkage) *** ### listPerpLinkedChildren() > **listPerpLinkedChildren**(`registry`, `main`): `Promise`\ Defined in: packages/sdk/src/somniaMarketsClient.ts:3265 Every child of a main, excluding the main — the isolated buckets one treasury currently serves. #### Parameters ##### registry `` `0x${string}` `` ##### main `` `0x${string}` `` #### Returns `Promise`\ #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpLinkedChildren`](SomniaMarketsClient.md#listperplinkedchildren) *** ### getPerpMaxLinkedChildren() > **getPerpMaxLinkedChildren**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3271 How many children one main may hold. Owner-tunable, so read it before offering to link another wallet rather than hardcoding the cap. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpMaxLinkedChildren`](SomniaMarketsClient.md#getperpmaxlinkedchildren) *** ### listPerpWalletLinkEvents() > **listPerpWalletLinkEvents**(`opts?`): `Promise`\<[`PerpWalletLinkEvent`](../type-aliases/PerpWalletLinkEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3282 The linked-wallet consent graph over time, newest first. **The only way to see a PENDING proposal** — the registry exposes no getter for one, so a `Proposed` row with no later row for the same pair is an offer still standing. Consent is not authority: a `Linked` row grants no power over funds by itself. Ask [quotePerpFundingPayer](SomniaMarketsClient.md#quoteperpfundingpayer) whether an order would actually spend a main's wallet. #### Parameters ##### opts? ###### main? `string` ###### child? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpWalletLinkEvent`](../type-aliases/PerpWalletLinkEvent.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpWalletLinkEvents`](SomniaMarketsClient.md#listperpwalletlinkevents) *** ### listPerpMarginPulls() > **listPerpMarginPulls**(`opts?`): `Promise`\<[`PerpMarginPull`](../type-aliases/PerpMarginPull.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3301 Margin pulled to fund placements, newest first — the POOL side of the rail, and the side that names an ORDER. One placement can produce TWO rows: `source: "OwnWallet"` for what the owner's own wallet covered, then `source: "Main"` for the residual drawn from their linked main. `amount` is what that leg pulled, not the order's total requirement. **Never sum these with [listPerpMainFundingEvents](SomniaMarketsClient.md#listperpmainfundingevents)** — one pull emits a row on each side for the same wei. #### Parameters ##### opts? ###### account? `string` ###### pool? `string` ###### orderId? `string` ###### source? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpMarginPull`](../type-aliases/PerpMarginPull.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpMarginPulls`](SomniaMarketsClient.md#listperpmarginpulls) *** ### listPerpMainFundingEvents() > **listPerpMainFundingEvents**(`opts?`): `Promise`\<[`PerpMainFundingEvent`](../type-aliases/PerpMainFundingEvent.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3320 A main's claim against a child over time, newest first — the BANK side of the rail, carrying the running principal. The live claim is [getPerpMainFunding](SomniaMarketsClient.md#getperpmainfunding). `amount` is **null on `Settled`** and that is not missing data: the child's own losses discharged part of the claim, so no cash moved while `outstandingPrincipal` still fell. **Never sum these with [listPerpMarginPulls](SomniaMarketsClient.md#listperpmarginpulls)** — same wei, two sides. #### Parameters ##### opts? ###### account? `string` ###### payer? `string` ###### kind? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`PerpMainFundingEvent`](../type-aliases/PerpMainFundingEvent.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPerpMainFundingEvents`](SomniaMarketsClient.md#listperpmainfundingevents) *** ### getPerpVoucherCampaign() > **getPerpVoucherCampaign**(`marginBank`): `Promise`\<[`PerpVoucherCampaign`](PerpVoucherCampaign.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3351 The live credit-voucher campaign behind a MarginBank, or `null` when the bank has no credit granter. A credit voucher is a one-time grant of house money into a new account's MarginBank balance. The grant is non-withdrawable; profit above it is. Use this read to show the offer: the grant, the claim window, how many claims the budget still covers, and the leverage a voucher account may use. Chain tier, current to the RPC head. The bank names the distributor, so this read never needs a deployment address. **Gotchas** `null` means the programme is off on this deployment. It is not a read failure. An open window does not mean a claim succeeds: an empty budget (`claimsRemaining === 0n`) rejects every claim. Ask [getPerpVoucherEligibility](SomniaMarketsClient.md#getperpvouchereligibility) for one account's answer. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. #### Parameters ##### marginBank `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucherCampaign`](PerpVoucherCampaign.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpVoucherCampaign`](SomniaMarketsClient.md#getperpvouchercampaign) *** ### getPerpVoucherEligibility() > **getPerpVoucherEligibility**(`marginBank`, `account`): `Promise`\<[`PerpVoucherEligibility`](../type-aliases/PerpVoucherEligibility.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3377 Whether an account can claim a credit voucher now, and if not, why. Use it before [Trader.claimPerpVoucher](Trader.md#claimperpvoucher). A claim that fails still mines and costs gas, because not every executor simulates before it sends. The reasons follow the distributor's own check order, so `reason` names the revert a claim would produce. Chain tier. Every read is pinned to one block, and the claim window is checked against that block's timestamp. **Gotchas** `alreadyClaimed` is permanent for that address on this distributor. The limit is once per address for the distributor's life, not once per campaign. `notFlat` includes resting orders, not only positions. The account must cancel every perp order before it can claim. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read, or the block read that pins them, did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. - Throws [InvariantError](../classes/InvariantError.md) - the node returned a latest block with no number. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucherEligibility`](../type-aliases/PerpVoucherEligibility.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpVoucherEligibility`](SomniaMarketsClient.md#getperpvouchereligibility) *** ### getPerpVoucher() > **getPerpVoucher**(`marginBank`, `account`): `Promise`\<[`PerpVoucher`](PerpVoucher.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3399 One account's credit-voucher state, or `null` when the bank has no credit granter. Use it to show how much of the account's balance is house money, and when that money can be swept back. `floor` is the part `withdraw` cannot take out. Chain tier, current to the RPC head. **Gotchas** After `expiresAt`, anyone can sweep the floor back to the distributor, but only while the account holds no positions or resting orders. A sweep never forces a close. A claimed account with `floor === 0n` either lost the grant in trading or was swept. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the client has no chain transport. - Throws [RpcError](../classes/RpcError.md) - a chain read did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a read reverted, for example because `marginBank` is not a MarginBank. #### Parameters ##### marginBank `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<[`PerpVoucher`](PerpVoucher.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpVoucher`](SomniaMarketsClient.md#getperpvoucher) *** ### getPerpRiskParams() > **getPerpRiskParams**(`pool`): `Promise`\<[`PerpRiskParams`](PerpRiskParams.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3401 #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpRiskParams`](PerpRiskParams.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpRiskParams`](SomniaMarketsClient.md#getperpriskparams) *** ### getPerpHealthSnapshot() > **getPerpHealthSnapshot**(`pool`): `Promise`\<[`PerpHealthSnapshot`](../type-aliases/PerpHealthSnapshot.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3414 A perp market's live health inputs in one call — mark price, projected cumulative funding, the effective (OI-scaled) IMF, and the maintenance / close-out thresholds. The contract exposes this precisely so a cross-margin health walk reads a market once instead of making five getter calls. Returns a discriminated union: an unpriceable market (stale or zero mark) arrives as `{ priceable: false }` rather than an all-zero struct, so a `maintenanceMarginBps` of 0 cannot be mistaken for "no maintenance requirement". Narrow on `priceable` before reading any field. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`PerpHealthSnapshot`](../type-aliases/PerpHealthSnapshot.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPerpHealthSnapshot`](SomniaMarketsClient.md#getperphealthsnapshot) *** ### getEffectiveImfBps() > **getEffectiveImfBps**(`pool`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3426 The initial-margin factor a perp market is charging right now, in bps — OI-scaled when dynamic IMF is enabled, otherwise the static base. Sizing an order off `initialMarginBps` instead under-margins it whenever open interest has pushed the curve above its floor, and the pool rejects an order the client believed fit. Reverts if dynamic IMF is on and the index is stale. [getPerpHealthSnapshot](SomniaMarketsClient.md#getperphealthsnapshot) returns this alongside the rest for one round-trip. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getEffectiveImfBps`](SomniaMarketsClient.md#geteffectiveimfbps) *** ### getVaultBalance() > **getVaultBalance**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3443 Claimable balance an owner can withdraw from a pool's internal ERC20Vault for `token`, raw units — the value behind the append-only [getVaultPayoutFallbacks](SomniaMarketsClient.md#getvaultpayoutfallbacks) history. Reads at chain head. Pass `blockNumber` to pin it, which is what an answer combining this with other reads at one height needs: the balance is contract state behind an append-only payout history, so no indexed entity reconstructs it at a past height. A pinned read far behind head needs archive state. ```ts const owed = await client.getVaultBalance({ vault: pool, owner, token: quote }); const owedAt = await client.getVaultBalance({ vault: pool, owner, token: quote, blockNumber: 1_234n }); ``` #### Parameters ##### p [`GetVaultBalanceParams`](GetVaultBalanceParams.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getVaultBalance`](SomniaMarketsClient.md#getvaultbalance) *** ### getManualVaultMode() > **getManualVaultMode**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3450 Whether `user` has opted out of wallet auto-pull on this SpotPool, at chain head — see `trader.setManualVaultMode`. True means their orders draw only on pre-deposited vault balance and their payouts stay as vault credit. #### Parameters ##### p [`GetManualVaultModeParams`](GetManualVaultModeParams.md) #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getManualVaultMode`](SomniaMarketsClient.md#getmanualvaultmode) *** ### getAutoPullRequirement() > **getAutoPullRequirement**(`p`): `Promise`\<[`AutoPullRequirement`](AutoPullRequirement.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3458 What an order of this shape would consume from `owner`, and how far short their vault balance falls (`delta`) — the pool's own worst-case funding envelope. In auto-pull mode `delta` is what the wallet gets pulled for; under manual vault mode it is what must be deposited first. #### Parameters ##### p [`GetAutoPullRequirementParams`](GetAutoPullRequirementParams.md) #### Returns `Promise`\<[`AutoPullRequirement`](AutoPullRequirement.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getAutoPullRequirement`](SomniaMarketsClient.md#getautopullrequirement) *** ### isOperatorAuthorized() > **isOperatorAuthorized**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3465 Whether `owner` authorized `operator` for `selector` on this SpotPool, at chain head — resolved through the pool's OperatorPermissionsRegistry, so no indexer lag. #### Parameters ##### p [`IsOperatorAuthorizedParams`](IsOperatorAuthorizedParams.md) #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`isOperatorAuthorized`](SomniaMarketsClient.md#isoperatorauthorized) *** ### isGloballyApproved() > **isGloballyApproved**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3475 Whether a GLOBAL operator grant is on record for this owner/operator/selector, at chain head — the raw slot `trader.setOperatorApprovalGlobal` writes. Independent of pool registration and of denials, so `true` here does not mean the operator can act on a given pool. For that, use [isOperatorAuthorized](SomniaMarketsClient.md#isoperatorauthorized). #### Parameters ##### p [`IsGloballyApprovedParams`](IsGloballyApprovedParams.md) #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`isGloballyApproved`](SomniaMarketsClient.md#isgloballyapproved) *** ### isApprovedForPool() > **isApprovedForPool**(`p`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3484 Whether a PER-POOL operator grant is on record, at chain head — the read-back for `trader.setOperatorApprovalForPool`. Ignores any global grant and any denial. For the pool's resolved decision, use [isOperatorAuthorized](SomniaMarketsClient.md#isoperatorauthorized). #### Parameters ##### p [`IsApprovedForPoolParams`](IsApprovedForPoolParams.md) #### Returns `Promise`\<`boolean`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`isApprovedForPool`](SomniaMarketsClient.md#isapprovedforpool) *** ### getOperatorPermissionsRegistry() > **getOperatorPermissionsRegistry**(`pool`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3508 The OperatorPermissionsRegistry this SpotPool gates operator calls through, at chain head — or `null` when the pool is unwired and denies every operator call. Discovery for a caller with no `addresses.operatorPermissionsRegistry` configured: the grant writes and the two grant reads need that address and otherwise throw [NotConfiguredError](../classes/NotConfiguredError.md), and no deployment manifest carries the key yet. A configured address still wins where it is used — this read adds a path, it does not redirect one. The pool is the authority: its own gate consults this registry and no other, so a grant written elsewhere admits nobody here. Failures. This read needs no address of its own, but it does need chain access, and every chain client is resolved lazily on first use — so it throws [NotConfiguredError](../classes/NotConfiguredError.md) when neither `wsRpcUrl` nor the chain definition's own WebSocket endpoint exists. It throws [ContractRevertError](../classes/ContractRevertError.md) when the pool rejects the call, and [RpcError](../classes/RpcError.md) when the read gets no answer — which is also what an EOA or any non-pool address produces, because an empty return is classified as a failed read rather than as a revert. `null` is an answer, never a failure. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOperatorPermissionsRegistry`](SomniaMarketsClient.md#getoperatorpermissionsregistry) *** ### getOwnLockedBalance() > **getOwnLockedBalance**(`p`): `Promise`\<[`LockedBalance`](LockedBalance.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3514 Base/quote `owner` has locked in this pool's resting orders. Pair with [getVaultBalance](SomniaMarketsClient.md#getvaultbalance) to account for everything the pool holds for them. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### owner `` `0x${string}` `` #### Returns `Promise`\<[`LockedBalance`](LockedBalance.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOwnLockedBalance`](SomniaMarketsClient.md#getownlockedbalance) *** ### getLockedTokenBreakdown() > **getLockedTokenBreakdown**(`pool`): `Promise`\<[`LockedTokenBreakdown`](LockedTokenBreakdown.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3520 How the pool's reserves of each token split between resting orders and leftover — venue-health introspection, not a portfolio read. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<[`LockedTokenBreakdown`](LockedTokenBreakdown.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getLockedTokenBreakdown`](SomniaMarketsClient.md#getlockedtokenbreakdown) *** ### convertToQuoteAtPriceCeil() > **convertToQuoteAtPriceCeil**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3526 Base→quote at a price using the pool's OWN ceil rounding — for interpreting [getLockedTokenBreakdown](SomniaMarketsClient.md#getlockedtokenbreakdown) without reimplementing it. #### Parameters ##### p ###### pool `` `0x${string}` `` ###### baseQuantity `bigint` ###### price `bigint` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`convertToQuoteAtPriceCeil`](SomniaMarketsClient.md#converttoquoteatpriceceil) *** ### getMarketOnchain() > **getMarketOnchain**(`marketId`): `Promise`\<[`MarketOnchain`](MarketOnchain.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3539 A binary market's full wiring + state (tokens, pool + nonce, status, expiry, resolution, finalized, decimals) straight from chain — authoritative for write eligibility, and works before the indexer has seen the market. BREAKING (0.13.0): takes the bytes32 `marketId` (resolved through the BinaryMarketsModule), NOT the BinaryMarket contract address — pools are recycled across successive markets in v2, so market identity is the module id. Post-finalize, `backing` falls back to the settlement record's net backing. Requires `addresses.binaryModule` in the config. #### Parameters ##### marketId `` `0x${string}` `` #### Returns `Promise`\<[`MarketOnchain`](MarketOnchain.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketOnchain`](SomniaMarketsClient.md#getmarketonchain) *** ### getPoolMarketBinding() > **getPoolMarketBinding**(`pool`, `opts?`): `Promise`\<[`PoolMarketBinding`](PoolMarketBinding.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3564 Which market a binary pool currently hosts, read from chain alone — the cold-start source of the `(pool, marketId)` binding when the indexer is unreachable. Feed the result's `marketId` to `watchMarket(pool, { seed: "chain", marketId })` to start a live book during an indexer outage. The ordinary source of that binding is the indexer, so without this read the chain seed only serves callers who already hold a hand-maintained market list. Both chain reads are made at ONE block, and the result carries it. Resolves to `null` only when the pool's market does not belong to this module; a failed read throws. Throws `InvalidInputError` when the module's record disagrees with the pool on either the pool address or the nonce. Requires `addresses.binaryModule` in the config. ```ts const binding = await exchange.client.getPoolMarketBinding(pool); if (binding) await exchange.client.watchMarket(pool, { seed: "chain", marketId: binding.marketId }); ``` #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`GetPoolMarketBindingOptions`](GetPoolMarketBindingOptions.md) #### Returns `Promise`\<[`PoolMarketBinding`](PoolMarketBinding.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPoolMarketBinding`](SomniaMarketsClient.md#getpoolmarketbinding) *** ### getMarketIdOnchain() > **getMarketIdOnchain**(`marketAddress`, `opts?`): `Promise`\<`` `0x${string}` `` \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3578 A BinaryMarket contract address's module id, read from chain alone. Use this when you hold a market ADDRESS and need its `marketId`, which is what every market-keyed read takes. A market page whose route carries the contract address is the usual case. `getBinaryMarketByAddress` answers the same question from the indexer, so this read is the one that survives an indexer outage. Resolves to `null` when this module did not create the market. A failed read throws. Requires `addresses.binaryModule` in the config. #### Parameters ##### marketAddress `` `0x${string}` `` ##### opts? ###### blockNumber? `bigint` #### Returns `Promise`\<`` `0x${string}` `` \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketIdOnchain`](SomniaMarketsClient.md#getmarketidonchain) *** ### getPoolCreator() > **getPoolCreator**(`pool`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3586 A pool's creator — its first-deploy market creator, the only party that can reuse it — straight from chain (`BinaryMarketsModule.poolCreator`). Zero address for a pool the module never deployed. No signer needed; requires `addresses.binaryModule`. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPoolCreator`](SomniaMarketsClient.md#getpoolcreator) *** ### getFreePools() > **getFreePools**(`creator`, `collateral`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3594 A creator's free (finalized + released, reusable) pools for `collateral`, LIFO order (the LAST entry is popped first on the creator's next createMarket), straight from chain (`BinaryMarketsModule.getFreePools`). No signer needed; requires `addresses.binaryModule`. #### Parameters ##### creator `` `0x${string}` `` ##### collateral `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getFreePools`](SomniaMarketsClient.md#getfreepools) *** ### listPoolBindings() > **listPoolBindings**(`pool`, `opts?`): `Promise`\<[`PoolBindingRecord`](PoolBindingRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3632 One page of a pool's pool→market binding history from the indexer, newest (highest nonce) first. A recycled pool gains one binding per market and its history has no protocol cap, so this read is paged: `opts.limit` defaults to 50 and `opts.offset` to 0, and both execute at the indexer. A row with `toBlock === null` is the pool's CURRENT binding; `closedBy` says whether a past binding ended by `PoolReleased` ("Released") or by the next `MarketCreated` recycling the pool onward ("Rotated"). Offset pages are not a snapshot. When the pool opens new bindings between two requests, older rows move down by that many positions and the next page repeats that many rows. Deduplicate on `id` when you page to the end. Replaces `getPoolBindings(pool)`, which returned the whole history in one response. #### Parameters ##### pool `string` ##### opts? [`ListPoolBindingsOptions`](ListPoolBindingsOptions.md) #### Returns `Promise`\<[`PoolBindingRecord`](PoolBindingRecord.md)[]\> #### Example ```ts // The whole history of a recycled pool. A short page is the end. const byId = new Map(); for (let offset = 0; ; offset += 1000) { const page = await exchange.client.listPoolBindings(pool, { limit: 1000, offset }); for (const row of page) byId.set(row.id, row); if (page.length < 1000) break; } ``` #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, or `opts.offset` is not an integer from 0 to 2147483647 (GraphQL `Int`). Checked before the request, so the indexer is not blamed for the caller's own input. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. The union is [SomniaMarketsClientListPoolBindingsError](../type-aliases/SomniaMarketsClientListPoolBindingsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listPoolBindings`](SomniaMarketsClient.md#listpoolbindings) *** ### getPool() > **getPool**(`address`): `Promise`\<[`IndexedPool`](IndexedPool.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3639 The indexer's per-pool aggregate (creator, collateral, current binding, generation count) for a long-lived, recycled BinaryPool — null if the indexer has never seen a `MarketCreated` on that address. #### Parameters ##### address `string` #### Returns `Promise`\<[`IndexedPool`](IndexedPool.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getPool`](SomniaMarketsClient.md#getpool) *** ### getErc20Balance() > **getErc20Balance**(`token`, `account`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3645 ERC-20 `balanceOf(account)`, raw units. For outcome positions use [getOutcomeBalance](SomniaMarketsClient.md#getoutcomebalance) (ERC-6909), not this. #### Parameters ##### token `` `0x${string}` `` ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getErc20Balance`](SomniaMarketsClient.md#geterc20balance) *** ### getErc20Metadata() > **getErc20Metadata**(`token`): `Promise`\<[`Erc20Metadata`](Erc20Metadata.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3651 ERC-20 `symbol`/`name`/`decimals` in one fan-out — label a token the indexer hasn't denormalized. #### Parameters ##### token `` `0x${string}` `` #### Returns `Promise`\<[`Erc20Metadata`](Erc20Metadata.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getErc20Metadata`](SomniaMarketsClient.md#geterc20metadata) *** ### getErc20Allowance() > **getErc20Allowance**(`token`, `owner`, `spender`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3657 ERC-20 `allowance(owner, spender)`, raw units — gate a write that pulls ERC-20 collateral (outcome tokens use per-operator approval instead). #### Parameters ##### token `` `0x${string}` `` ##### owner `` `0x${string}` `` ##### spender `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getErc20Allowance`](SomniaMarketsClient.md#geterc20allowance) *** ### getOutcomeBalance() > **getOutcomeBalance**(`p`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3664 ERC-6909 `balanceOf(account, id)` on the outcome-token singleton, raw units. `p.outcomeToken` is the singleton (from [getMarketOnchain](SomniaMarketsClient.md#getmarketonchain)); `p.id` is the market's `yesId`/`noId`. #### Parameters ##### p [`GetOutcomeBalanceParams`](GetOutcomeBalanceParams.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOutcomeBalance`](SomniaMarketsClient.md#getoutcomebalance) *** ### getBalances() > **getBalances**(`tokens`, `account`): `Promise`\<`bigint`[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3674 Batch-read many balances for one `account` in a single fan-out. Each entry is read as a plain ERC-20 `balanceOf(account)` when `id` is omitted, or as an ERC-6909 outcome position `balanceOf(account, id)` on the singleton `token` when `id` is set. Results are returned positionally, aligned to `tokens`. The explorer uses this to read a portfolio's collateral + outcome positions in one round-trip instead of N calls. #### Parameters ##### tokens readonly [`BalanceQuery`](BalanceQuery.md)[] ##### account `` `0x${string}` `` #### Returns `Promise`\<`bigint`[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBalances`](SomniaMarketsClient.md#getbalances) *** ### getStopOrderSomiPayment() > **getStopOrderSomiPayment**(`registry`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3680 SOMI a SpotStopOrderRegistry charges per pending stop order (funds the trigger gas; refunded on cancel). Raw wei. #### Parameters ##### registry `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getStopOrderSomiPayment`](SomniaMarketsClient.md#getstopordersomipayment) *** ### getMaxBuilderFeeBpsTimes1k() > **getMaxBuilderFeeBpsTimes1k**(`pool`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3686 A pool's protocol-wide per-order builder-fee ceiling (pool bps×1000). Read-only — no signer — for the order form's routing-fee ceiling hint. #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMaxBuilderFeeBpsTimes1k`](SomniaMarketsClient.md#getmaxbuilderfeebpstimes1k) *** ### getBuilderApproval() > **getBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3689 A user's raw per-builder approval cap on a pool (pool bps×1000; 0 = none). #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getBuilderApproval`](SomniaMarketsClient.md#getbuilderapproval) *** ### getEffectiveBuilderApproval() > **getEffectiveBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3696 The ENFORCED per-builder approval on a pool: the user's raw cap clamped by the pool's protocol-wide ceiling — the limit a `builderFeeBpsTimes1k` must not exceed. Drives the order form's "approve builder first" gate. #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getEffectiveBuilderApproval`](SomniaMarketsClient.md#geteffectivebuilderapproval) *** ### getContractMeta() > **getContractMeta**(`address`, `opts?`): `Promise`\<[`ContractMeta`](ContractMeta.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3702 owner / EIP-1967 implementation / native balance for a deployed contract — the /system dashboard diagnostics. `proxy: true` reads the impl slot. #### Parameters ##### address `` `0x${string}` `` ##### opts? ###### proxy? `boolean` #### Returns `Promise`\<[`ContractMeta`](ContractMeta.md)\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getContractMeta`](SomniaMarketsClient.md#getcontractmeta) *** ### getNativeBalance() > **getNativeBalance**(`address`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3709 Native (SOMI/STT) balance, raw wei. - Throws [RpcError](../classes/RpcError.md) - the balance read did not complete (`operation: "getBalance"`). #### Parameters ##### address `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getNativeBalance`](SomniaMarketsClient.md#getnativebalance) *** ### getTransactionSummary() > **getTransactionSummary**(`hash`): `Promise`\<[`TransactionSummary`](TransactionSummary.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3721 Chain-direct summary of one transaction — sender, gas spent, fee paid, status — for enriching an order/fill view with what its tx cost. Null for a malformed hash and for one the node reports as not found. A read that did not complete throws, so "it never landed" stays distinct from "the node could not be reached". #### Parameters ##### hash `string` #### Returns `Promise`\<[`TransactionSummary`](TransactionSummary.md) \| `null`\> #### Throws [RpcError](../classes/RpcError.md) The chain read did not complete. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getTransactionSummary`](SomniaMarketsClient.md#gettransactionsummary) *** ### createNetworkTape() > **createNetworkTape**(`opts?`): [`NetworkTape`](../classes/NetworkTape.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:3730 The network-wide order-flow firehose: one topics-only chain-log subscription that sees OrderPlaced/OrderFilled from EVERY pool (including pools created later), no indexer on the hot path. Nothing connects until the tape's first `subscribe`; the last unsubscribe closes the socket. Each call returns an independent tape. #### Parameters ##### opts? [`NetworkTapeOptions`](NetworkTapeOptions.md) #### Returns [`NetworkTape`](../classes/NetworkTape.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createNetworkTape`](SomniaMarketsClient.md#createnetworktape) *** ### getHeadBlock() > **getHeadBlock**(): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3733 Latest block number as the RPC sees it. #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getHeadBlock`](SomniaMarketsClient.md#getheadblock) *** ### getSystemInfo() > **getSystemInfo**(): `Promise`\<[`SystemInfo`](SystemInfo.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3745 Deployed protocol state (impl pointers, oracle, collateral) for ops dashboards. Needs `config.addresses`. A `null` field means the contract is not configured or not wired. A failed read throws, so the snapshot never reports a zero the chain did not answer. #### Returns `Promise`\<[`SystemInfo`](SystemInfo.md)\> #### Throws [RpcError](../classes/RpcError.md) A chain read did not complete. #### Throws [ContractRevertError](../classes/ContractRevertError.md) A configured contract rejected its read (usually an ABI mismatch). #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSystemInfo`](SomniaMarketsClient.md#getsysteminfo) *** ### listOperators() > **listOperators**(`opts?`): `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3756 List operators, newest-first by id, paginated. Pass `owner` to scope to one owner's operators (the indexed "my operators", no log scan), `enabled` to filter by the kill switch, `limit`/`offset` to page. Indexer read. #### Parameters ##### opts? [`OperatorFilter`](../type-aliases/OperatorFilter.md) & `object` #### Returns `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOperators`](SomniaMarketsClient.md#listoperators) *** ### countOperators() > **countOperators**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3766 Server-side COUNT of operators matching a filter (for directory pagination). Needs the privileged `_aggregate` role (server-only), like [countBinaryMarkets](SomniaMarketsClient.md#countbinarymarkets). Without that header the total is bounded at 10,000 by the row-scan fallback, and past it would be a lower bound reported as exact. `Operator` is orders of magnitude below the cap, so no bounded variant exists. #### Parameters ##### opts? [`OperatorFilter`](../type-aliases/OperatorFilter.md) #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countOperators`](SomniaMarketsClient.md#countoperators) *** ### getOperator() > **getOperator**(`operatorId`): `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3768 One operator by id, or null if never registered. Indexer read. #### Parameters ##### operatorId `number` #### Returns `Promise`\<[`IndexedOperator`](../type-aliases/IndexedOperator.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOperator`](SomniaMarketsClient.md#getoperator) *** ### listVenues() > **listVenues**(`opts?`): `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3773 List venues, creation-order, optionally scoped to one operator and/or market type and/or the venue-level creation flag. Paginated. Indexer read. #### Parameters ##### opts? ###### operatorId? `number` ###### marketType? `string` ###### creationEnabled? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listVenues`](SomniaMarketsClient.md#listvenues) *** ### countVenues() > **countVenues**(`opts?`): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3788 Server-side COUNT of venues matching a filter (for per-operator venue pagination). Needs the privileged `_aggregate` role (server-only). Without that header the total is bounded at 10,000 by the row-scan fallback, like [countOperators](SomniaMarketsClient.md#countoperators); `Venue` is far below the cap, so no bounded variant exists. #### Parameters ##### opts? ###### operatorId? `number` ###### marketType? `string` #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`countVenues`](SomniaMarketsClient.md#countvenues) *** ### getVenue() > **getVenue**(`venueId`): `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3790 One venue by its opaque bytes32 id, or null. Indexer read. #### Parameters ##### venueId `string` #### Returns `Promise`\<[`IndexedVenue`](../type-aliases/IndexedVenue.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getVenue`](SomniaMarketsClient.md#getvenue) *** ### encodeBinaryVenueFeeParams() > **encodeBinaryVenueFeeParams**(`vp`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3797 Build a BINARY_V1 venue's `feeParams` bytes from plain-bps rates via the deployed BinaryMarketsModule's `encodeVenueFeeParams` — the on-chain ground truth for the version tag + struct shape (used by the create/edit venue forms). Needs `config.addresses.binaryModule`. #### Parameters ##### vp [`BinaryVenueParams`](BinaryVenueParams.md) #### Returns `Promise`\<`` `0x${string}` ``\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`encodeBinaryVenueFeeParams`](SomniaMarketsClient.md#encodebinaryvenuefeeparams) *** ### getMaxVenueFeeBps() > **getMaxVenueFeeBps**(): `Promise`\<`number`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3802 The module's protocol-level ceiling on any single venue fee rate, in plain bps (e.g. 1_000 = 10%). Needs `config.addresses.binaryModule`. #### Returns `Promise`\<`number`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMaxVenueFeeBps`](SomniaMarketsClient.md#getmaxvenuefeebps) *** ### listMarketCreators() > **listMarketCreators**(`opts?`): `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3816 List MarketCreators, newest-first, paginated. Pass `owner` for "my machinery", `operatorId`/`venueId` to scope. Each row carries its nested `series`. Indexer read. #### Parameters ##### opts? [`MarketCreatorFilter`](../type-aliases/MarketCreatorFilter.md) & `object` #### Returns `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listMarketCreators`](SomniaMarketsClient.md#listmarketcreators) *** ### getMarketCreator() > **getMarketCreator**(`creator`): `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3818 One MarketCreator by address (with its series), or null. Indexer read. #### Parameters ##### creator `string` #### Returns `Promise`\<[`IndexedMarketCreator`](../type-aliases/IndexedMarketCreator.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getMarketCreator`](SomniaMarketsClient.md#getmarketcreator) *** ### listOracleAdapters() > **listOracleAdapters**(`opts?`): `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3825 List oracle adapters, newest-first, paginated. Pass `owner` to scope, `approved` to filter by the module-approval gate. Oracle v2: the one approved adapter is the OracleHub — this directory tracks `AdapterApproved` history. Indexer read. #### Parameters ##### opts? ###### owner? `string` ###### approved? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOracleAdapters`](SomniaMarketsClient.md#listoracleadapters) *** ### getOracleAdapter() > **getOracleAdapter**(`adapter`): `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3832 One oracle adapter by address, or null. Indexer read. #### Parameters ##### adapter `string` #### Returns `Promise`\<[`IndexedOracleAdapter`](../type-aliases/IndexedOracleAdapter.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOracleAdapter`](SomniaMarketsClient.md#getoracleadapter) *** ### listSeries() > **listSeries**(`opts?`): `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3834 List series, creation-order, optionally scoped to one creator. Indexer read. #### Parameters ##### opts? ###### creator? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listSeries`](SomniaMarketsClient.md#listseries) *** ### listSeriesLatestMarkets() > **listSeriesLatestMarkets**(`opts?`): `Promise`\<[`SeriesLatestMarket`](../type-aliases/SeriesLatestMarket.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3888 The most recent market of every series that has rolled at least once - one row per series, joined server-side. The read behind a "has this series stopped rolling" monitor. Paginated over series. Indexer read. A series with no market yet has NO row; see [SeriesLatestMarket](../type-aliases/SeriesLatestMarket.md). #### Parameters ##### opts? [`ListSeriesLatestMarketsOptions`](../type-aliases/ListSeriesLatestMarketsOptions.md) #### Returns `Promise`\<[`SeriesLatestMarket`](../type-aliases/SeriesLatestMarket.md)[]\> #### Example ```ts // Which of an owner's series have gone quiet. Page to exhaustion: the read // is bounded per call, so a short page is the end and a full one is not. const latest = new Map(); for (let offset = 0; ; offset += 100) { const page = await exchange.client.listSeriesLatestMarkets({ limit: 100, offset }); for (const row of page) latest.set(row.series, BigInt(row.createdAtTimestamp)); if (page.length < 100) break; } // A series with NO row has never rolled - that is "unanchored", NOT // "stalled". Nothing indexed says when a first roll is due, so judging a // missing row as late pages every newly registered series. // // RE-REGISTRATION needs the same treatment, and the indexer will not do it // for you: Market->Series links are preserved, so `latest` still holds the // PREVIOUS schedule's market after a restart. Ageing that row against the new // schedule reports a deliberate restart as quiet. A series is re-registered // when `updatedAtTimestamp` is later than `createdAtTimestamp`, and the row // in hand belongs to the old generation when it predates that restart - so // treat it as unanchored too, exactly as the probe's own sweep does. const seconds = (v: string | null) => (v == null ? Number.NaN : Number(v)); for (const s of await exchange.client.listSeries()) { const rolledAt = latest.get(s.id); if (rolledAt === undefined) continue; const restartedAt = seconds(s.updatedAtTimestamp); const registeredAt = seconds(s.createdAtTimestamp); const restarted = Number.isFinite(restartedAt) && (!Number.isFinite(registeredAt) || restartedAt > registeredAt); if (restarted && Number(rolledAt) <= restartedAt) continue; const lateBy = BigInt(Math.floor(Date.now() / 1000)) - rolledAt; if (lateBy > BigInt(s.intervalSec) * 2n) console.log("quiet:", s.id, lateBy); } ``` #### Throws [InvalidInputError](../classes/InvalidInputError.md) `opts.limit` is not an integer from 1 to 1000, or `opts.offset` is not a non-negative safe integer. Checked before the request: `NaN` and `Infinity` are ordinary `number` values that would serialize to `null` and lift the page bound entirely. #### Throws [IndexerError](../classes/IndexerError.md) The indexer request failed or returned an unusable response. The union is [SomniaMarketsClientListSeriesLatestMarketsError](../type-aliases/SomniaMarketsClientListSeriesLatestMarketsError.md). #### Throws [NotConfiguredError](../classes/NotConfiguredError.md) The client has no indexer, or its indexer does not index the client's chain. #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listSeriesLatestMarkets`](SomniaMarketsClient.md#listserieslatestmarkets) *** ### getSeries() > **getSeries**(`creator`, `seriesId`): `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3895 One series by its composite key `(creator, seriesId)` — seriesId is per-creator. The row is the CURRENT spec (`registerSeries` overwrites in place). Null when never registered. #### Parameters ##### creator `string` ##### seriesId `number` #### Returns `Promise`\<[`IndexedSeries`](../type-aliases/IndexedSeries.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSeries`](SomniaMarketsClient.md#getseries) *** ### getSchedulingCost() > **getSchedulingCost**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3911 The hub's MARGINAL scheduling cost for `def` — 0 when an identical template definition is already scheduled (the call would dedup), the full oracle submission cost otherwise. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getSchedulingCost`](SomniaMarketsClient.md#getschedulingcost) *** ### earmarkedOf() > **earmarkedOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3916 Native LOCKED for an operator's outstanding markets (wei; never withdrawable). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`earmarkedOf`](SomniaMarketsClient.md#earmarkedof) *** ### creditOf() > **creditOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3921 An operator's accrued WITHDRAWABLE surplus credit on the hub (wei). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`creditOf`](SomniaMarketsClient.md#creditof) *** ### outstandingOf() > **outstandingOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3926 Count of an operator's bound-but-unresolved markets. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`outstandingOf`](SomniaMarketsClient.md#outstandingof) *** ### withdrawableOf() > **withdrawableOf**(`operatorId`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3931 Wei an operator's owner may withdraw right now (== `creditOf`). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### operatorId `number` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`withdrawableOf`](SomniaMarketsClient.md#withdrawableof) *** ### payerCreditOf() > **payerCreditOf**(`payer`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3938 A1: the withdrawable surplus credited to a reserve-PAYER (an open-venue creator, or the autonomous MarketCreator on its rolls) rather than the operator; drawn by that account via `createOracleHubAdmin().withdrawMyCredit`. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### payer `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`payerCreditOf`](SomniaMarketsClient.md#payercreditof) *** ### payerOf() > **payerOf**(`marketId`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3943 A1: the reserve-payer recorded for a market at onBind (surplus recipient); zero-address once settled + swept. Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### marketId `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`payerOf`](SomniaMarketsClient.md#payerof) *** ### resolveReserve() > **resolveReserve**(): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3948 The hub's `resolveReserve()` — the per-market reserve attached+locked at onBind (wei). Chain read; needs `config.addresses.oracleHub`. #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`resolveReserve`](SomniaMarketsClient.md#resolvereserve) *** ### quoteCreateMarketValue() > **quoteCreateMarketValue**(`def`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3955 THE §8e create-market value quote: `getSchedulingCost(def) + resolveReserve()` (the reserve is attached to the create). Attach exactly this to `scheduleAndCreateMarket` (excess refunds). Chain read; needs `config.addresses.oracleHub`. #### Parameters ##### def [`QuestionDefinitionInput`](QuestionDefinitionInput.md) #### Returns `Promise`\<`bigint`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`quoteCreateMarketValue`](SomniaMarketsClient.md#quotecreatemarketvalue) *** ### getOracleQuestion() > **getOracleQuestion**(`oracleQuestionId`): `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3960 One hub-scheduled oracle question (dedup key, scheduler, bind count) by its oracleQuestionId, or null. Indexer read. #### Parameters ##### oracleQuestionId `string` #### Returns `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOracleQuestion`](SomniaMarketsClient.md#getoraclequestion) *** ### listOracleQuestions() > **listOracleQuestions**(`opts?`): `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3965 Hub-scheduled questions, newest first — filter by `scheduler` / `questionKey`, paginate. Indexer read. #### Parameters ##### opts? ###### scheduler? `string` ###### questionKey? `string` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleQuestionRecord`](../type-aliases/OracleQuestionRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOracleQuestions`](SomniaMarketsClient.md#listoraclequestions) *** ### getOperatorHubAccount() > **getOperatorHubAccount**(`operatorId`): `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3975 One operator's hub account (earmarked / credit / outstanding) by operatorId, or null. Indexer read. #### Parameters ##### operatorId `string` \| `number` #### Returns `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md) \| `null`\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`getOperatorHubAccount`](SomniaMarketsClient.md#getoperatorhubaccount) *** ### listOperatorHubAccounts() > **listOperatorHubAccounts**(`opts?`): `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3980 Operator hub-account records, most-recently-updated first, paginated. Indexer read. #### Parameters ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OperatorHubAccountRecord`](../type-aliases/OperatorHubAccountRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOperatorHubAccounts`](SomniaMarketsClient.md#listoperatorhubaccounts) *** ### listOracleBinds() > **listOracleBinds**(`opts?`): `Promise`\<[`OracleBindRecord`](../type-aliases/OracleBindRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3986 Bind records (operator attribution → exact metered resolve charge + subsidy per market, §8e), newest first — filter by `operatorId` / `oracleQuestionId` / `resolved`, paginate. Indexer read. #### Parameters ##### opts? ###### operatorId? `number` ###### oracleQuestionId? `string` ###### resolved? `boolean` ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleBindRecord`](../type-aliases/OracleBindRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOracleBinds`](SomniaMarketsClient.md#listoraclebinds) *** ### listOracleCallbacks() > **listOracleCallbacks**(`opts?`): `Promise`\<[`OracleCallbackRecord`](../type-aliases/OracleCallbackRecord.md)[]\> Defined in: packages/sdk/src/somniaMarketsClient.ts:3998 Resolution-callback conservation records (`CallbackAccounted`), newest first, paginated (a callback drains across many questions, so no per-question filter). Indexer read. #### Parameters ##### opts? ###### limit? `number` ###### offset? `number` #### Returns `Promise`\<[`OracleCallbackRecord`](../type-aliases/OracleCallbackRecord.md)[]\> #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`listOracleCallbacks`](SomniaMarketsClient.md#listoraclecallbacks) *** ### createTrader() > **createTrader**(`traderConfig`): [`Trader`](Trader.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4024 Build a [Trader](Trader.md) bound to a signer and this client's chain, store, and socket. With a `privateKey`/local `account` the trader signs locally (fixed fees, locally-tracked nonce — zero pre-send RPCs) and confirms in one round-trip via `eth_sendRawTransactionSync`; with a browser `walletClient` it sends through the wallet and confirms off the newHeads subscription. Every write resolves only once mined, with its receipt. With an `executor` the trader sends through it instead — see [SomniaMarketsClient.createExecutor](SomniaMarketsClient.md#createexecutor). - Throws [SignerRequiredError](../classes/SignerRequiredError.md) - none of `executor`, `privateKey`, `account` or `walletClient` (with an account) is set. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `privateKey` is not a valid secp256k1 key, or `executor` sends on a chain other than this client's. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - this client has no chain transport (no `wsRpcUrl` and a chain without a WebSocket endpoint) and no `publicClient` was passed to send through. The complete union is [SomniaMarketsClientCreateTraderError](../type-aliases/SomniaMarketsClientCreateTraderError.md). #### Parameters ##### traderConfig [`TraderConfig`](TraderConfig.md) #### Returns [`Trader`](Trader.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createTrader`](SomniaMarketsClient.md#createtrader) *** ### createExecutor() > **createExecutor**(`spec`): [`Executor`](Executor.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4083 Build one of the built-in executors, bound to this engine's chain, socket, fee envelope and nonce lane. The spec names only who acts — a private key or local account, a wallet client, a Somnia session seed, or a smart account from `@somnia-chain/accounts-sdk` with the executor that sends its outer transaction. Hand the result to `createTrader({ executor })`, or compose it (a smart account's `inner`), or place it in a [SomniaMarketsAccount](SomniaMarketsAccount.md) for the exchange to trade through. **Gotchas** - A smart account's `inner` must be authorized on the account when nothing signs (no `signer`, no `through`): its actor must be a direct owner of a threshold-1 account. A `signer` or a `through` chain of parent accounts switches to a real signature, which the accounts SDK nests to any depth. See [ExecutorSpec](../type-aliases/ExecutorSpec.md). - An account that is not a factory account from `@somnia-chain/accounts-sdk` needs a custom [Executor](Executor.md). Its `execute` returns an inner failure as `failure` on the result; Trader writes throw it. - Before it sends or signs, a smart-account executor checks that the account has code on this chain. Missing code raises [InvalidInputError](../classes/InvalidInputError.md): create the account on this chain first. A failed read raises [RpcError](../classes/RpcError.md), and a client with no chain transport raises [NotConfiguredError](../classes/NotConfiguredError.md). Successful checks are cached. - With a `signer` or `through`, a smart-account executor runs one write at a time per account on this engine, because each write signs the account's current nonce. Two processes that write through one account (for example a backend and a browser) can still sign the same nonce. - Throws [InvalidInputError](../classes/InvalidInputError.md) - a spec that names no actor or more than one (a spec with a removed `safe` key names none), a `privateKey` or `sessionSeed` that is not a valid 32-byte key, a wallet spec with no account to act as, a smart-account spec whose `inner` sends on another chain, a smart-account spec on a chain the accounts SDK has no deployment for, or a `through` spec with no `signer` and an `inner` that cannot sign typed data. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - a key, account, wallet or session spec on a client with no chain transport (no `wsRpcUrl` and a chain without a WebSocket endpoint); a smart-account spec needs none of its own. - An account's `inner` signs locally. A smart-account spec whose `inner` came from `{ sessionSeed }` throws [InvalidInputError](../classes/InvalidInputError.md): that executor sends the seed to the node on every write, and the seed would then control the account's funds. Use `{ privateKey }`; for a Somnia session seed the key is `sessionPrivateKey(seed)`. Do not also send node-side from that seed: both modes share one nonce space. The complete union is [SomniaMarketsClientCreateExecutorError](../type-aliases/SomniaMarketsClientCreateExecutorError.md). **Example** (A factory smart account driven by a local session key) ```ts const session = client.createExecutor({ privateKey: sessionKey }); const account = client.createExecutor({ smartAccount: ACCOUNT, inner: session }); const trader = client.createTrader({ executor: account }); await trader.placeOrder(params); // approval + order in ONE account transaction, nothing signs ``` #### Parameters ##### spec [`ExecutorSpec`](../type-aliases/ExecutorSpec.md) #### Returns [`Executor`](Executor.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createExecutor`](SomniaMarketsClient.md#createexecutor) *** ### createOperatorAdmin() > **createOperatorAdmin**(`config`): [`OperatorAdmin`](OperatorAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4090 Build an [OperatorAdmin](OperatorAdmin.md) bound to a signer — registers/updates operators and creates/updates venues on MarketsCore. Same signer doctrine as [createTrader](SomniaMarketsClient.md#createtrader) (privateKey/local account, or a browser walletClient). #### Parameters ##### config [`OperatorAdminConfig`](OperatorAdminConfig.md) #### Returns [`OperatorAdmin`](OperatorAdmin.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createOperatorAdmin`](SomniaMarketsClient.md#createoperatoradmin) *** ### createOracleHubAdmin() > **createOracleHubAdmin**(`config`): [`OracleHubAdmin`](OracleHubAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4101 Build an [OracleHubAdmin](OracleHubAdmin.md) bound to a signer — the OracleHub surface (Oracle v2 §8e): quote reads (`quoteCreateMarketValue` = the §8e create value = scheduling cost + resolveReserve), the credit-only `withdraw` (owner-gated — draws accrued surplus credit only), and the protocol-admin writes (fundHub, gas + drain params, enableReactivity/migrateSubscription — precompile, testnet/mainnet only). Same signer doctrine as [createOperatorAdmin](SomniaMarketsClient.md#createoperatoradmin). Needs `config.addresses.oracleHub`. #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`OracleHubAdmin`](OracleHubAdmin.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createOracleHubAdmin`](SomniaMarketsClient.md#createoraclehubadmin) *** ### createGovernanceAdmin() > **createGovernanceAdmin**(`config`): [`GovernanceAdmin`](GovernanceAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4109 Build a [GovernanceAdmin](GovernanceAdmin.md) bound to a signer — the protocol-admin-only surface that approves oracle adapters on the module (`setAdapterApproved`; in Oracle v2 the ONE approved adapter is the OracleHub — deploy wiring + emergency revoke). Gate its UI on [GovernanceAdmin.isModuleOwner](GovernanceAdmin.md#ismoduleowner). #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`GovernanceAdmin`](GovernanceAdmin.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createGovernanceAdmin`](SomniaMarketsClient.md#creategovernanceadmin) *** ### createMarketCreatorAdmin() > **createMarketCreatorAdmin**(`config`): [`MarketCreatorAdmin`](MarketCreatorAdmin.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4116 Build a [MarketCreatorAdmin](MarketCreatorAdmin.md) bound to a signer — stamps MarketCreators (+ policies) from the factory, registers rolling series under them, funds them, and triggers rolls. Same signer doctrine as [createOperatorAdmin](SomniaMarketsClient.md#createoperatoradmin). #### Parameters ##### config [`OracleHubAdminConfig`](OracleHubAdminConfig.md) #### Returns [`MarketCreatorAdmin`](MarketCreatorAdmin.md) #### Inherited from [`SomniaMarketsClient`](SomniaMarketsClient.md).[`createMarketCreatorAdmin`](SomniaMarketsClient.md#createmarketcreatoradmin) *** ### getIndexerFreshness() > **getIndexerFreshness**(`chainId`): `Promise`\<[`IndexerFreshness`](../type-aliases/IndexerFreshness.md) \| `null`\> Defined in: packages/sdk/src/somniaMarketsClient.ts:4136 Compare main-indexer progress with this owner's independently read chain head. The binding check throws NotConfiguredError when the indexer has no row for the owner's chain, so `null` is normally not reached; it remains for a row that goes missing after the check passed. Lag is raw blocks and chain-time seconds, without a stale threshold. A lead of up to 10,000 blocks past the head reads as lag 0. A larger lead means the indexer follows an earlier genesis of the same chain id, so the read throws instead of reporting lag. Use getSyncStatus for metadata-only availability checks. #### Parameters ##### chainId `number` #### Returns `Promise`\<[`IndexerFreshness`](../type-aliases/IndexerFreshness.md) \| `null`\> #### Throws chainId does not match the owner or a variable is invalid. #### Throws Metadata request failed. #### Throws The owner's chain transport is unavailable, the owner has no indexer, its indexer does not index the owner's chain, or its indexer is more than 10,000 blocks past the RPC head. #### Throws A latest or processed block read failed. *** ### createObservedReads() > **createObservedReads**(): `Promise`\<[`ObservedReads`](ObservedReads.md)\> Defined in: packages/sdk/src/somniaMarketsClient.ts:4157 Observe one independent head and derive response-associated main-indexer reads. Reuse the returned capability for a batch; create another to refresh the comparison head. The capability shares this owner's cancellation and transports. No polling is started. **Example** ```ts const observed = await exchange.client.createObservedReads(); const [markets, count] = await observed.batch([ { operation: "listMarkets", args: [{ limit: 20 }] }, { operation: "countMarkets", args: [] }, ]); console.log(markets.data, markets.observation.latestProcessedBlock); console.log(count.data, count.observation.independentHead.blockNumber); const freshness = await exchange.client.getIndexerFreshness(exchange.client.config.chain.id); console.log(freshness?.lagBlocks, freshness?.lagSeconds); ``` #### Returns `Promise`\<[`ObservedReads`](ObservedReads.md)\> #### Throws The owner has no chain transport. #### Throws The head read failed. *** ### getPriceHealth() > **getPriceHealth**(`asset`): [`PriceFeedHealth`](../type-aliases/PriceFeedHealth.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4160 Read precise delivery health without I/O. Unwatched assets return "unwatched". Shares the existing price watch and subscribePrices notifications. #### Parameters ##### asset `string` #### Returns [`PriceFeedHealth`](../type-aliases/PriceFeedHealth.md) *** ### listPriceHealth() > **listPriceHealth**(): `object`[] Defined in: packages/sdk/src/somniaMarketsClient.ts:4162 Read precise health for each retained asset without I/O or new watches. #### Returns `object`[] --- # /docs/typescript/api/index/interfaces/SomniaMarketsFetchPortfolioAnalyticsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchPortfolioAnalyticsOptions # Interface: SomniaMarketsFetchPortfolioAnalyticsOptions Defined in: packages/sdk/src/unified/exchange.ts:286 Options for complete indexed portfolio analytics. ## Properties ### sessionSince? > `optional` **sessionSince?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:288 Session start in milliseconds for `volume.sessionUsd`. *** ### cexRateBps? > `optional` **cexRateBps?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:290 Comparison taker rate in basis points; defaults to [PortfolioAnalytics.DEFAULT\_CEX\_RATE\_BPS](../variables/DEFAULT_CEX_RATE_BPS.md). *** ### maxFillPages? > `optional` **maxFillPages?**: `number` Defined in: packages/sdk/src/unified/exchange.ts:292 Maximum non-empty logical fill pages (up to two requests each); omitted reads all role-visible history. Exceeding it rejects without analytics. *** ### funding? > `optional` **funding?**: readonly [`PortfolioFundingEvent`](PortfolioFundingEvent.md)[] Defined in: packages/sdk/src/unified/exchange.ts:300 External capital movements (deposits/withdrawals) for the wallet, USD valued at event time. When any of them bears on the window they define the MWRR capital base (`mwrr.capitalBasis: "funding"`) in place of the trades-only proxy. They never affect PnL or volume. Venue fills are not funding — see `PortfolioFundingEvent` for the sourcing rules. --- # /docs/typescript/api/index/interfaces/SomniaMarketsSignerConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsSignerConfig # Interface: SomniaMarketsSignerConfig Defined in: packages/sdk/src/unified/exchange.ts:140 The signer half of [SomniaMarketsConfig](../type-aliases/SomniaMarketsConfig.md): a private key, a local account, or a browser wallet client. Optional — authenticated methods throw [SignerRequiredError](../classes/SignerRequiredError.md) without one. ## Properties ### walletClient? > `optional` **walletClient?**: `object` Defined in: packages/sdk/src/unified/exchange.ts:142 A pre-built signer (e.g. a browser/wagmi wallet over an injected provider). *** ### account? > `optional` **account?**: `` `0x${string}` `` \| `Account` \| [`SomniaMarketsAccount`](SomniaMarketsAccount.md) Defined in: packages/sdk/src/unified/exchange.ts:148 A local signing account, a bare address (reads only), or a [SomniaMarketsAccount](SomniaMarketsAccount.md): one address on every chain plus the executor that acts as it on each — the shape a cross-chain safe takes. *** ### privateKey? > `optional` **privateKey?**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/exchange.ts:150 Private key — the SDK derives the account. --- # /docs/typescript/api/index/interfaces/Span [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Span # Interface: Span Defined in: packages/sdk/src/debug.ts:115 Handle for an open span, passed to the `span`/`traced` callback so a call site can parent a nested span explicitly or annotate it mid-flight. ## Properties ### id > `readonly` **id**: `number` Defined in: packages/sdk/src/debug.ts:120 The span's event id — `0` when debugging is disabled (an inert handle: no event was emitted for it, and annotating it is a no-op). *** ### name > `readonly` **name**: `string` Defined in: packages/sdk/src/debug.ts:122 The name the span was started with (empty on the inert disabled handle). --- # /docs/typescript/api/index/interfaces/SpotOrderBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotOrderBook # Interface: SpotOrderBook Defined in: packages/sdk/src/orders.ts:1380 A plain two-sided spot order book (no YES/NO inversion). Prices are raw quote units per whole base; quantities are raw base units. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/orders.ts:1382 Pinned chain block or scope applied-event watermark; absent without provenance. *** ### bids > **bids**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:1384 Resting buys, best (highest price) first. *** ### asks > **asks**: [`BookLevel`](BookLevel.md)[] Defined in: packages/sdk/src/orders.ts:1386 Resting sells, best (lowest price) first. --- # /docs/typescript/api/index/interfaces/SpotOrderRequest [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotOrderRequest # Interface: SpotOrderRequest Defined in: packages/sdk/src/trade.ts:547 One order inside a [Trader.placeSpotOrders](Trader.md#placespotorders) batch — the per-order fields of [PlaceSpotOrderParams](PlaceSpotOrderParams.md), minus everything the batch supplies once (`pool`, token context, gas). ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:549 True = buy the base asset (pay quote); false = sell base (pay base/native). *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:554 Limit price — raw quote units per whole base token. For a MARKET order pass a crossing price (best opposite level ± slippage); it bounds the escrow. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/trade.ts:556 Base quantity, raw base units. *** ### orderType? > `optional` **orderType?**: `number` Defined in: packages/sdk/src/trade.ts:558 0 limit (default) or 2 market (IOC). See [ORDER\_TYPE](../variables/ORDER_TYPE.md). *** ### selfMatchingOption? > `optional` **selfMatchingOption?**: `number` Defined in: packages/sdk/src/trade.ts:565 Self-match behaviour when this order crosses your OWN resting order, default 0 (`CANCEL_TAKER`). Set per rung: a ladder that crosses its own quotes can keep the incoming order and drop the resting one instead. See [SELF\_MATCHING\_OPTION](../variables/SELF_MATCHING_OPTION.md). *** ### expireTimestampNs? > `optional` **expireTimestampNs?**: `bigint` Defined in: packages/sdk/src/trade.ts:567 Order expiry in ns. Defaults to ~50y (GTC). *** ### userData? > `optional` **userData?**: `bigint` Defined in: packages/sdk/src/trade.ts:569 Opaque 64-bit tag carried on the order — for market-maker bookkeeping. *** ### builder? > `optional` **builder?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:575 Routing/builder frontend address to attribute this rung to. Requires the trader to have opted this builder in via [Trader.approveBuilder](Trader.md#approvebuilder) on the batch's pool. Omit (or zero) for no routing fee. *** ### builderFeeBpsTimes1k? > `optional` **builderFeeBpsTimes1k?**: `bigint` Defined in: packages/sdk/src/trade.ts:580 Per-order builder/routing fee in the pool's native bps×1000 unit (≤ the pool's `maxBuilderFee` ceiling AND ≤ the trader's approval). 0 = none. --- # /docs/typescript/api/index/interfaces/SwapCreatorParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SwapCreatorParams # Interface: SwapCreatorParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:258 Params for [MarketCreatorAdmin.swapCreator](MarketCreatorAdmin.md#swapcreator). ## Properties ### policy > **policy**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:260 The venue's MarketCreatorPolicy. Caller must be its owner. *** ### from > **from**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:262 Outgoing creator to revoke. *** ### to > **to**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:264 Incoming creator to authorize. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:266 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/SweepExpiredAtLevelParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SweepExpiredAtLevelParams # Interface: SweepExpiredAtLevelParams Defined in: packages/sdk/src/trade.ts:389 Permissionless keeper drain: walk ONE price level from the best order on a side, cleaning up to `maxCount` expired orders. The complement of [CancelExpiredOrdersParams](CancelExpiredOrdersParams.md) when you have a price level rather than a list of ids (e.g. draining a locked market's book so its pool can be released). Each cleaned order's escrow returns to its owner. ## Properties ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:391 BinaryPool (or SpotPool) address to sweep. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/trade.ts:393 True to sweep the bid side, false the ask side. *** ### price > **price**: `bigint` Defined in: packages/sdk/src/trade.ts:395 The exact price level to sweep (raw pool price units). *** ### maxCount > **maxCount**: `bigint` Defined in: packages/sdk/src/trade.ts:397 Max number of expired orders to clean in this call. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:403 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/SyncSettlementParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SyncSettlementParams # Interface: SyncSettlementParams Defined in: packages/sdk/src/trade.ts:1934 Permissionless earmark reconcile: release the oracle earmark of a market that was voided via the `BinaryMarket.voidExpired()` escape hatch (which bypasses the module, so the hub's earmark release never fired). ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1936 bytes32 marketId to reconcile; the market must be resolved or voided. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1938 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1944 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/SystemInfo [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SystemInfo # Interface: SystemInfo Defined in: packages/sdk/src/system.ts:45 Live snapshot of the deployed CLOB-family contract state, as read by [SomniaMarketsClient.getSystemInfo](SomniaMarketsClient.md#getsysteminfo). `null` means the contract is not configured or not wired. A live read that FAILS throws — this snapshot never reports a value the chain did not answer, because a dashboard cannot tell a fabricated zero from a real one. ## Properties ### clobFactory > **clobFactory**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/system.ts:47 BinaryMarketsModule.clobFactory() (authoritative) or the configured fallback. *** ### binaryMarketImpl > **binaryMarketImpl**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/system.ts:53 ClobFactory.binaryMarketImpl(), or null when no ClobFactory resolved (there is no configured market-impl fallback; `binaryPoolImpl` is a different contract). *** ### factoryMismatch > **factoryMismatch**: `boolean` Defined in: packages/sdk/src/system.ts:55 True when the live ClobFactory differs from the configured one. *** ### settlement > **settlement**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/system.ts:62 The BinarySettlement singleton the module is wired to (live `BinaryMarketsModule.settlement()`, falling back to the configured `addresses.binarySettlement`). Null pre-wire, on a pre-v2 module that does not declare the view, and when neither is configured. A failed read throws. *** ### settlementMismatch > **settlementMismatch**: `boolean` Defined in: packages/sdk/src/system.ts:64 True when the module's live settlement differs from the configured one. *** ### marketCreator > **marketCreator**: [`MarketCreatorInfo`](MarketCreatorInfo.md) \| `null` Defined in: packages/sdk/src/system.ts:66 The configured MarketCreator's state; null when `addresses.marketCreator` is unset. *** ### oracle > **oracle**: \{ `owner`: `` `0x${string}` ``; `binaryModule`: `` `0x${string}` ``; \} \| `null` Defined in: packages/sdk/src/system.ts:68 FakeOracle wiring; null when `addresses.fakeOracle` is unset. #### Union Members ##### Type Literal \{ `owner`: `` `0x${string}` ``; `binaryModule`: `` `0x${string}` ``; \} ##### owner > **owner**: `` `0x${string}` `` FakeOracle owner (the resolve/void signer). ##### binaryModule > **binaryModule**: `` `0x${string}` `` The module the oracle delivers to (its `RECEIVER`). *** `null` *** ### usdc > **usdc**: \{ `symbol`: `string`; `decimals`: `number`; \} \| `null` Defined in: packages/sdk/src/system.ts:78 Collateral ERC-20 metadata (from `addresses.collateral`, falling back to the legacy `testUsdc`); null when neither is configured. #### Union Members ##### Type Literal \{ `symbol`: `string`; `decimals`: `number`; \} ##### symbol > **symbol**: `string` Token symbol. ##### decimals > **decimals**: `number` Token decimals. *** `null` --- # /docs/typescript/api/index/interfaces/TailDivergence [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TailDivergence # Interface: TailDivergence Defined in: packages/sdk/src/store.ts:229 Raw native levels differing at a fixed chain checkpoint. ## Properties ### pool > **pool**: `string` Defined in: packages/sdk/src/store.ts:231 Pool compared. *** ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/store.ts:233 Both chain sides and the local capture describe this target. *** ### depth > **depth**: `number` Defined in: packages/sdk/src/store.ts:235 Maximum compared levels per side. *** ### local > **local**: `object` Defined in: packages/sdk/src/store.ts:237 Event-derived levels filtered using the target chain timestamp. #### bids > **bids**: [`BookLevel`](BookLevel.md)[] #### asks > **asks**: [`BookLevel`](BookLevel.md)[] *** ### chain > **chain**: `object` Defined in: packages/sdk/src/store.ts:239 Contract levels read at the same target. #### bids > **bids**: [`BookLevel`](BookLevel.md)[] #### asks > **asks**: [`BookLevel`](BookLevel.md)[] --- # /docs/typescript/api/index/interfaces/TailFailure [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TailFailure # Interface: TailFailure Defined in: packages/sdk/src/store.ts:217 An observable background operation failure. ## Properties ### operation > **operation**: `"recovery"` \| `"reconciliation"` \| `"subscription"` \| `"fill-history"` Defined in: packages/sdk/src/store.ts:223 Failed operation; reconciliation is diagnostic and does not replace the book. `fill-history` is the indexer fills lane of a chain-seeded watch: it fails on its own, without blocking the book the chain already seeded. *** ### error > **error**: [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/store.ts:225 Semantic SDK failure with the original cause. --- # /docs/typescript/api/index/interfaces/TailReconciliationConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TailReconciliationConfig # Interface: TailReconciliationConfig Defined in: packages/sdk/src/config.ts:594 Opt-in live-book diagnostic bounds. ## Properties ### blockInterval > **blockInterval**: `bigint` Defined in: packages/sdk/src/config.ts:596 Positive block interval. Heads coalesce while a comparison is pending. *** ### depth > **depth**: `number` Defined in: packages/sdk/src/config.ts:598 Top levels per side, an integer from 1 to 100. --- # /docs/typescript/api/index/interfaces/TailStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TailStatus # Interface: TailStatus Defined in: packages/sdk/src/store.ts:131 Live-tail health snapshot — how current the store's `getLive*` reads are: block coverage (snapshot/last/head), socket state, and active watch count. ## Properties ### healedGaps > **healedGaps**: `number` Defined in: packages/sdk/src/store.ts:133 Nonempty intervening ranges successfully recovered. Empty probes do not count. *** ### lastDivergence > **lastDivergence**: [`TailDivergence`](TailDivergence.md) \| `null` Defined in: packages/sdk/src/store.ts:135 Last observed divergence, retained after later matching checks. *** ### failure > **failure**: [`TailFailure`](TailFailure.md) \| `null` Defined in: packages/sdk/src/store.ts:137 Background failure; cleared only after the failed work succeeds. *** ### mode > **mode**: [`TailMode`](../type-aliases/TailMode.md) Defined in: packages/sdk/src/store.ts:139 Current data-source mode ("init" until the first watch is hydrated). *** ### seedSource > **seedSource**: [`SeedSource`](../type-aliases/SeedSource.md) \| `null` Defined in: packages/sdk/src/store.ts:150 Where the most recent watch took its book seed: `"indexer"` for the indexer snapshot (the default), `"chain"` for a `seed: "chain"` watch. `null` in "init", before any watch has hydrated. LATEST SEED, not an aggregate. This field and the three below describe the most recent seed only, so with several watched pools they cannot be attributed to a pool. Read [PoolSeedStatus](PoolSeedStatus.md) through `getSeedStatus(pool)` for a per-pool answer. *** ### seedBlock > **seedBlock**: `number` Defined in: packages/sdk/src/store.ts:157 Block the seed was consistent to — the indexer snapshot block, or the pinned block every chain-seed page was read at. 0 before any watch has hydrated. Equal to [TailStatus.snapshotBlock](#snapshotblock); this field names the value, while `seedSource` names where it came from. *** ### seedTruncated > **seedTruncated**: `boolean` Defined in: packages/sdk/src/store.ts:163 Whether the chain seed hit its page budget and read a SHALLOW book. Always false for an indexer seed. A truncated seed is a successful bounded read, not a failure — the book is real but incomplete at its deep end. *** ### allMarketsTruncated > **allMarketsTruncated**: `boolean` Defined in: packages/sdk/src/store.ts:177 Whether the active all-markets watch left eligible markets out. One `watchMarkets` snapshot hydrates at most 500 eligible markets, newest first. This is `true` when more exist: the watched markets are complete, but the oldest eligible markets are not watched. Watch those with `watchMarket(pool)`. Owned by the all-markets scope alone, so a later pool or chain seed does not overwrite it. It stays set while that scope is watched or lingering, and returns to `false` when the scope is torn down. `false` when no all-markets watch exists. *** ### fillsLoaded > **fillsLoaded**: `boolean` Defined in: packages/sdk/src/store.ts:187 Whether fill history was loaded for the current scope. A chain seed cannot reconstruct fills from before its block: the seam backfills only snapshotBlock+1..head, and older fills live only in the indexer. So `false` plus an empty `getLiveFills` means "never loaded", while `true` plus an empty `getLiveFills` means "genuinely no fills in the loaded range". Without this flag the two are indistinguishable. *** ### snapshotBlock > **snapshotBlock**: `number` Defined in: packages/sdk/src/store.ts:197 Block the most recent watch seed was consistent to — a watch's seam covers snapshotBlock+1.. either way. For an indexer-seeded watch this is the indexer snapshot block, unchanged. For a chain-seeded watch it is the block every drained page was pinned to, the same value [TailStatus.seedBlock](#seedblock) reports. Read [TailStatus.seedSource](#seedsource) to tell the two apart. *** ### lastBlock > **lastBlock**: `number` Defined in: packages/sdk/src/store.ts:199 Highest applied event or sealed scope block; heads alone do not advance it. *** ### headBlock > **headBlock**: `number` Defined in: packages/sdk/src/store.ts:201 Latest chain head observed over the WS *** ### wsConnected > **wsConnected**: `boolean` Defined in: packages/sdk/src/store.ts:203 Whether the chain WS subscriptions are currently delivering *** ### watchCount > **watchCount**: `number` Defined in: packages/sdk/src/store.ts:213 Active watch SCOPES: pools currently subscribed (including an all-markets watch's set), plus the perp plane as one if it is watched. `0` → the tail is idle and no socket is held for it, and that invariant is the point of the field. The perp plane is counted precisely because it holds a socket while subscribing no pool at all, so a pool-only count would report an idle tail that is in fact streaming. --- # /docs/typescript/api/index/interfaces/TapeFill [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TapeFill # Interface: TapeFill Defined in: packages/sdk/src/networkTape.ts:75 An executed fill as the tape saw it. ## Properties ### key > **key**: `string` Defined in: packages/sdk/src/networkTape.ts:77 Stable row key: `${blockNumber}_${logIndex}_${pool}`. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/networkTape.ts:78 *** ### takerOrderId > **takerOrderId**: `bigint` Defined in: packages/sdk/src/networkTape.ts:79 *** ### makerOrderId > **makerOrderId**: `bigint` Defined in: packages/sdk/src/networkTape.ts:80 *** ### price > **price**: `bigint` Defined in: packages/sdk/src/networkTape.ts:82 Execution price, raw quote units per whole base. *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/networkTape.ts:84 Quantity filled, raw base/outcome units. *** ### taker > **taker**: `string` \| `null` Defined in: packages/sdk/src/networkTape.ts:91 Resolved from the session's OrderPlaced stream. The taker's placement follows its fills in the same tx, so this back-fills within one message batch; null until then (and forever, for a maker quoted before the tape started — resolve those via [SomniaMarketsClient.getFill](SomniaMarketsClient.md#getfill) if needed). *** ### maker > **maker**: `string` \| `null` Defined in: packages/sdk/src/networkTape.ts:92 *** ### blockNumber > **blockNumber**: `number` Defined in: packages/sdk/src/networkTape.ts:93 *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/networkTape.ts:94 *** ### at > **at**: `number` Defined in: packages/sdk/src/networkTape.ts:95 --- # /docs/typescript/api/index/interfaces/TapeOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TapeOrder # Interface: TapeOrder Defined in: packages/sdk/src/networkTape.ts:54 An order placement as the tape saw it (either side of the book). ## Properties ### key > **key**: `string` Defined in: packages/sdk/src/networkTape.ts:56 Stable row key: `${blockNumber}_${logIndex}_${pool}`. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/networkTape.ts:58 Lowercased pool address the order landed on. *** ### orderId > **orderId**: `bigint` Defined in: packages/sdk/src/networkTape.ts:60 uint128 order id — with `pool`, a permanent identity (ids never reuse). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/networkTape.ts:62 Order owner, lowercased. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/networkTape.ts:63 *** ### price > **price**: `bigint` Defined in: packages/sdk/src/networkTape.ts:65 Limit price, raw quote units per whole base (binary: YES-probability scale). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/networkTape.ts:67 Full order size, raw base/outcome units. *** ### blockNumber > **blockNumber**: `number` Defined in: packages/sdk/src/networkTape.ts:68 *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/networkTape.ts:69 *** ### at > **at**: `number` Defined in: packages/sdk/src/networkTape.ts:71 Arrival time (ms since epoch) — Somnia logs carry no timestamp. --- # /docs/typescript/api/index/interfaces/TokenLockBreakdown [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TokenLockBreakdown # Interface: TokenLockBreakdown Defined in: packages/sdk/src/spot/poolReads.ts:180 How one token's reserves in a pool divide up — see [SomniaMarketsClient.getLockedTokenBreakdown](SomniaMarketsClient.md#getlockedtokenbreakdown). ## Properties ### principalLocked > **principalLocked**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:182 Tradeable principal backing resting orders. *** ### lockedSurplus > **lockedSurplus**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:184 Locked above principal (rounding + fee headroom the orders reserved). *** ### leftover > **leftover**: `bigint` Defined in: packages/sdk/src/spot/poolReads.ts:186 Reserves backing NO resting order — accrued fees and stray balance. --- # /docs/typescript/api/index/interfaces/Tradable [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Tradable # Interface: Tradable Defined in: packages/sdk/src/unified/symbols.ts:29 A parsed + resolved tradable: the market it lives on, and (for outcome markets) which outcome book it addresses. ## Properties ### market > **market**: [`Market`](../type-aliases/Market.md) Defined in: packages/sdk/src/unified/symbols.ts:31 The native market row this tradable lives on (union — narrow by `marketType`). *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/symbols.ts:37 Numeric chain id the market lives on. A market is unique to one chain, so this is where every write for the tradable is sent and where every read for it is answered. *** ### marketSymbol > **marketSymbol**: `string` Defined in: packages/sdk/src/unified/symbols.ts:39 Canonical MARKET symbol (no outcome suffix). *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/symbols.ts:41 Canonical tradable symbol (with outcome suffix where applicable). *** ### outcome? > `optional` **outcome?**: `string` Defined in: packages/sdk/src/unified/symbols.ts:43 Outcome label (binary: "YES" | "NO"); undefined for spot. *** ### outcomeIndex? > `optional` **outcomeIndex?**: `number` Defined in: packages/sdk/src/unified/symbols.ts:45 Outcome index (binary: 0 = YES, 1 = NO); undefined for spot. *** ### pool > **pool**: `` `0x${string}` `` Defined in: packages/sdk/src/unified/symbols.ts:50 The pool the tradable's orders go to — always `market.poolAddress`, so it carries that field's type rather than widening it back to `string`. --- # /docs/typescript/api/index/interfaces/Trader [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Trader # Interface: Trader Defined in: packages/sdk/src/trade.ts:2313 The SDK's write tier — every pool/market transaction it can sign and send, bound to one signer. Built via `client.createTrader(config)` (see [TraderConfig](TraderConfig.md)); shares that client's chain, addresses, and WebSocket. Sending methods preserve [ExecutorExecuteError](../type-aliases/ExecutorExecuteError.md), including missing executor transport as [NotConfiguredError](../classes/NotConfiguredError.md) and a transaction whose receipt was not observed as [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md). Every write AWAITS its receipt before resolving — there is no bare-hash return to babysit. Order placements additionally resolve to the decoded order id + fills. ## Properties ### executor > `readonly` **executor**: [`Executor`](Executor.md) Defined in: packages/sdk/src/trade.ts:2319 The executor this trader sends through — who signs, and the address the pools see as the caller (`executor.actor`). Read-only; build another trader to change it. ## Methods ### placeOrder() > **placeOrder**(`params`): `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2348 Place a limit order (auto-approving the escrow token by default). Resolves once mined, with the resting order id and any fills. **Gotchas** - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `price` or `quantity` was not > 0. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the pool rejected the order; `errorName` carries the protocol's own error (e.g. `InsufficientBalance`). Also thrown when the transaction mines with a reverted status — the SDK replays the call to recover the reason, so you get a name rather than a failed receipt. - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Placing a binary bid) Bid 0.62 for 10 YES using an indexed binary market row `market`. ```ts const trader = client.createTrader({ privateKey }); const decimals = market.quoteDecimals; const res = await trader.placeOrder({ pool: market.poolAddress, side: "BUY_YES", price: probabilityToPrice(0.62, decimals), quantity: fromHuman(10, decimals), }); console.log(res.orderId, res.fills.length); // resting id (if it rested) + immediate fills ``` #### Parameters ##### params [`PlaceOrderParams`](PlaceOrderParams.md) #### Returns `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> *** ### cancelOrder() > **cancelOrder**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2359 Cancel a resting order on its pool (works for spot + binary). **Gotchas** - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the cancel did not land (already filled, already canceled, not the owner — `errorName` distinguishes them). - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. #### Parameters ##### params [`CancelOrderParams`](CancelOrderParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### reduceOrder() > **reduceOrder**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2367 Shrink a resting order's remaining quantity in place, keeping its price-time queue priority (works for spot + binary). Reverts on-chain for an expired order — use [Trader.cancelOrder](#cancelorder) there. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ReduceOrderParams`](ReduceOrderParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### cancelExpiredOrders() > **cancelExpiredOrders**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2375 Permissionless keeper drain: clean an explicit list of expired resting orders on a pool, returning each order's escrow to its owner (best-effort; skips non-expired / stale ids). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`CancelExpiredOrdersParams`](CancelExpiredOrdersParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### sweepExpiredAtLevel() > **sweepExpiredAtLevel**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2382 Permissionless keeper drain: clean up to `maxCount` expired orders at one price level on a side. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SweepExpiredAtLevelParams`](SweepExpiredAtLevelParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### captureClose() > **captureClose**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2391 Permissionless closing-price capture on a BinaryPool (post-expiry): stores the closing mid and lifts the closing-book lock. Required before sweeping a pre-terminal closing book — a `CloseNotCaptured` revert on a cancel/sweep means "capture first, then retry". - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`CaptureCloseParams`](CaptureCloseParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### approveBuilder() > **approveBuilder**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2409 Opt a routing/builder frontend in on a pool so orders the trader places with that builder code may charge up to `maxFeeBpsTimes1k` (0 revokes). Required before a non-zero `builder`/`builderFeeBpsTimes1k` on [Trader.placeOrder](#placeorder), [Trader.placeSpotOrder](#placespotorder) or [Trader.placePerpOrder](#placeperporder). Binary, spot and perp pools each implement this interface, but the approval is stored PER POOL: approving a builder on one pool grants nothing on another. Call it once per pool the trader will place attributed orders on, or the placement reverts. Each pool declares the whole builder-error set; which one fires depends on the check that trips first. With NO approval at all that is `BuilderNotApproved` on a SpotPool (it guards `approved > 0`), `BuilderFeeExceedsApproval` on a PerpPool, and `BuilderFeeExceedsCap` on a BinaryPool — whose ceiling, unlike the other two, is frozen at init. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ApproveBuilderParams`](ApproveBuilderParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### getBuilderApproval() > **getBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/trade.ts:2411 Read a trader's per-builder approval cap on a pool (pool bps×1000; 0 = none). #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> *** ### getEffectiveBuilderApproval() > **getEffectiveBuilderApproval**(`ref`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/trade.ts:2417 Effective builder approval on a pool: the trader's raw cap clamped by the pool's protocol-wide `getMaxBuilderFeeBpsTimes1k` ceiling — the actual enforced limit a `builderFeeBpsTimes1k` on any place-order verb must not exceed. #### Parameters ##### ref [`BuilderApprovalRef`](BuilderApprovalRef.md) #### Returns `Promise`\<`bigint`\> *** ### getMaxBuilderFeeBpsTimes1k() > **getMaxBuilderFeeBpsTimes1k**(`pool`): `Promise`\<`bigint`\> Defined in: packages/sdk/src/trade.ts:2419 Read a pool's protocol-wide builder-fee ceiling (bps×1000). #### Parameters ##### pool `` `0x${string}` `` #### Returns `Promise`\<`bigint`\> *** ### placeSpotOrder() > **placeSpotOrder**(`params`): `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2432 Place a spot limit/market order on a SpotPool (auto-approves the escrow token, or sends native msg.value on a native-base sell). An ERC-20 approval check uses `requiredAmount`, which is the pool's worst-case reserve including fee headroom. A native sell sends `delta`, which subtracts the owner's current vault balance from that reserve. The SDK reads the requirement once per uncached token/pool approval and on each native-base sell. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`PlaceSpotOrderParams`](PlaceSpotOrderParams.md) #### Returns `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> *** ### placeSpotOrders() > **placeSpotOrders**(`params`): `Promise`\<[`PlaceSpotOrdersResult`](PlaceSpotOrdersResult.md)\> Defined in: packages/sdk/src/trade.ts:2484 Place several orders on one SpotPool in a single transaction — a market maker's ladder in one tx instead of a loop of sends. **Gotchas** This write is NON-PAYABLE: unlike [Trader.placeSpotOrder](#placespotorder), it takes no `msg.value`. A native-base sell in a batch therefore funds from the pool's VAULT balance — pre-deposit native to the vault and auto-pull consumes it. ERC-20 auto-pull works normally per request, and the batch approves each escrow token once for the whole batch's total. SPOT ONLY. A binary pool reverts `UseBinaryPlacement` on generic placement — the YES/NO kind must be explicit, so use [Trader.placeOrder](#placeorder) there. A request that does not place is NOT an error: `outcomes[i].success` is false with no id for a PostOnly that would cross, an unfilled FillOrKill, an IOC that found no liquidity, an already-expired expiry, or a CancelTaker self-match. A hard validation error (bad lot size, insufficient funds) reverts the whole batch. Outcome attribution matches each `OrderPlaced` event to its request on every field the event echoes (side, price, quantity, userData, expiry), in order. Two byte-identical adjacent requests with different outcomes are therefore indistinguishable from logs — the earlier index gets the credit. Tag rungs with distinct `userData` when exact attribution matters. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `orders` was empty, or a request had a non-positive price or quantity. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the batch was rejected; `errorName` carries the protocol's error (`EmptyBatch`, `UseBinaryPlacement` on a binary pool, or a per-order validation failure). - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Placing a spot-order batch) ```ts // Place a three-rung sell ladder in one transaction. const trader = client.createTrader({ privateKey }); const res = await trader.placeSpotOrders({ pool, quoteToken, baseToken, orders: [1_010_000n, 1_020_000n, 1_030_000n].map((price) => ({ isBid: false, price, quantity: 1_000_000n, })), }); // Index-aligned with `orders`; a rung that did not place is success:false. const ids = res.outcomes.flatMap((o) => (o.success ? [o.orderId!] : [])); ``` #### Parameters ##### params [`PlaceSpotOrdersParams`](PlaceSpotOrdersParams.md) #### Returns `Promise`\<[`PlaceSpotOrdersResult`](PlaceSpotOrdersResult.md)\> *** ### cancelOrders() > **cancelOrders**(`params`): `Promise`\<[`CancelOrdersResult`](CancelOrdersResult.md)\> Defined in: packages/sdk/src/trade.ts:2513 Cancel several resting orders on one pool in a single transaction — pull a whole ladder without leaving the remaining rungs exposed. Works on spot AND binary pools (cancel is inherited from the OrderBook base, not placement-gated). **Gotchas** BEST-EFFORT by design: an id that can no longer be cancelled (already filled, already cancelled, expired-and-swept, not owned by the signer) is SKIPPED on-chain instead of reverting the batch — which is the point in a fast market. Each `outcomes[i].cancelled` is inferred from whether the id emitted a cancel event, so a `false` does NOT tell you WHY: a benign fill race and a wrong id look identical here. Reconcile against the book if you need to know. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `orderIds` was empty. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `errorName` `EmptyBatch` when the contract rejects the payload. - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Inspecting batch cancellations) ```ts const trader = client.createTrader({ privateKey }); const res = await trader.cancelOrders({ pool, orderIds: ladderIds }); const skipped = res.outcomes.filter((o) => !o.cancelled).map((o) => o.orderId); ``` #### Parameters ##### params [`CancelOrdersParams`](CancelOrdersParams.md) #### Returns `Promise`\<[`CancelOrdersResult`](CancelOrdersResult.md)\> *** ### cancelAllOrders() > **cancelAllOrders**(`pool`, `opts?`): `Promise`\<[`CancelAllOrdersResult`](../type-aliases/CancelAllOrdersResult.md)\> Defined in: packages/sdk/src/trade.ts:2571 Pull EVERY resting order the signer holds on one pool — the kill switch. Reads the ids and cancels them in one call. Works on spot AND binary pools. **When to use** Use it to stop quoting when the bot holds no local ids: after a restart, or after a send whose outcome is unknown. [Trader.cancelOrders](#cancelorders) stays the right call when you already know which ids to pull. **Details** The default `source: "chain"` costs one `eth_call` plus the cancel transaction. `source: "live"` takes the ids from the live store instead, so the cancel is the only round trip — it needs an active market watch covering the pool. Nothing resting is a SUCCESS, not an error: the result is then `{ sent: false, orderIds: [], outcomes: [] }` and no transaction goes out. Branch on `sent`. When `sent` is true the result carries everything [Trader.cancelOrders](#cancelorders) returns, per-id `outcomes` included. **Gotchas** An EXPIRED order that still rests is NOT cancelled on the default chain source. The pool's `getOwnOpenOrders` view filters expired orders out of the owner's own list, and expiry is lazy, so such an order keeps sitting on the book holding its funds while this read cannot see it. Clear that residue with [Trader.cancelExpiredOrders](#cancelexpiredorders) or [Trader.sweepExpiredAtLevel](#sweepexpiredatlevel). The two sources differ exactly here, and `source: "live"` is the stronger one. The live store marks an order expired only when it sees the pool's `OrderExpired` event, which lazy expiry does not emit until something touches the order — so a lapsed order still reads as resting and its id IS forwarded. On-chain the cancel then goes through: the pool gates a best-effort cancel on owner and id, not on expiry, so the order is removed from the book and its funds released. It emits `OrderExpired` rather than `OrderCancelled`, and both count as terminated, so the outcome reads `cancelled: true`. The live source therefore clears the residue that the chain source cannot even see. A `side` filter is not supported yet. Pass the ids to [Trader.cancelOrders](#cancelorders) when you must pull one side only. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or `source: "live"` without an active watch covering the pool. An unwatched store cannot tell an empty book from an unseen one, so it refuses rather than cancelling nothing. - Throws [RpcError](../classes/RpcError.md) - the id read did not complete. A failed read never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the cancel transaction reverted. - Throws [InvalidInputError](../classes/InvalidInputError.md) - the executor rejects the call. **Example** (Pulling every quote after a restart) ```ts const trader = client.createTrader({ privateKey }); const res = await trader.cancelAllOrders(pool); const pulled = res.sent ? res.outcomes.filter((o) => o.cancelled).length : 0; ``` #### Parameters ##### pool `` `0x${string}` `` ##### opts? [`CancelAllOrdersOptions`](CancelAllOrdersOptions.md) #### Returns `Promise`\<[`CancelAllOrdersResult`](../type-aliases/CancelAllOrdersResult.md)\> *** ### reduceOrders() > **reduceOrders**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2590 Shrink several resting orders in place in a single transaction, each keeping its price-time queue priority. Works on spot AND binary pools. **Gotchas** ATOMIC, unlike [Trader.cancelOrders](#cancelorders): the FIRST invalid reduction reverts the entire batch and no order changes. A reduction is invalid if the new quantity is not a `lotSize` multiple, is below `minQuantity`, is not strictly less than the current remaining, or the order has expired (cancel those instead). Size the batch accordingly — one stale id loses the whole tx. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `reductions` was empty. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a reduction was rejected; `errorName` carries the protocol's error. - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. #### Parameters ##### params [`ReduceOrdersParams`](ReduceOrdersParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### placePerpOrder() > **placePerpOrder**(`params`): `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2597 Place a perp limit/market order on a PerpPool. Margin is locked from the signer's MarginBank balance — [Trader.depositMargin](#depositmargin) first. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`PlacePerpOrderParams`](PlacePerpOrderParams.md) #### Returns `Promise`\<[`PlaceOrderResult`](PlaceOrderResult.md)\> *** ### amendOrder() > **amendOrder**(`params`): `Promise`\<[`AmendOrderResult`](AmendOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2644 Cancel ONE resting order and place its replacement atomically — the re-quote primitive, with no gap on the book. **When to use** Re-pricing a single quote. For a whole ladder use [Trader.amendOrders](#amendorders), which cancels every old order before placing any replacement. To shrink an order without losing its place in the queue use [Trader.reduceOrder](#reduceorder) — amend is not priority-preserving. **Details** Prefer this over [Trader.amendOrders](#amendorders) with a one-element array: this raises the replacement's own landing-time reason (`PostOnlyWouldCross`, `SelfMatchCancelTaker`, `ImmediateOrCancelNoFill`, `FillOrKillNotFillable`, `OrderAlreadyExpired`), where the batch wraps it as `AmendReplacementRejected(requestIndex, reason)` and leaves the caller unwrapping an index it already knew. **Gotchas** SpotPool and PerpPool only — a BinaryPool reverts `UseBinaryPlacement`, since binary placement is its own entry point. The replacement gets a NEW order id, so update local tracking. Non-payable: a native auto-pull amend reverts, because the cancel leg delivers the freed native to the wallet and the place leg cannot reach it — fund native replacements from a manual-vault balance. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `price` or `quantity` was not > 0. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the old order was gone and `alwaysPlace` was not set (`AmendOldOrderGone`), it belongs to someone else (`IncorrectSender`), or the replacement did not rest or fill; `errorName` carries the protocol's error. - Throws [RpcError](../classes/RpcError.md) - a request did not complete, or the node refused the transaction. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. **Example** (Amending an order) Re-quote one bid a tick lower, and keep the new id. ```ts const { newOrderId } = await trader.amendOrder({ pool, oldOrderId: resting, newOrder: { isBid: true, price: 1_990_000n, quantity: 5_000_000n }, }); ``` #### Parameters ##### params [`AmendOrderParams`](AmendOrderParams.md) #### Returns `Promise`\<[`AmendOrderResult`](AmendOrderResult.md)\> *** ### amendOrders() > **amendOrders**(`params`): `Promise`\<[`AmendOrdersResult`](AmendOrdersResult.md)\> Defined in: packages/sdk/src/trade.ts:2651 Cancel N orders and place their replacements atomically. All-or-nothing, and it places — so the same BinaryPool restriction applies. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`AmendOrdersParams`](AmendOrdersParams.md) #### Returns `Promise`\<[`AmendOrdersResult`](AmendOrdersResult.md)\> *** ### buildPlaceOrder() > **buildPlaceOrder**(`params`): `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> Defined in: packages/sdk/src/trade.ts:2692 Build a binary placement WITHOUT sending it — the same inputs as [Trader.placeOrder](#placeorder), handed back as unsigned calls. **When to use** Reach for this when the signing and the sending are not the same moment: to pre-sign an ERC-4337 UserOp while the user is still filling in the form, to batch the order into a multicall, to hand it to a relayer, or to simulate it. For ordinary "place this order now", use [Trader.placeOrder](#placeorder) — it is one call and it handles the approval for you. **Gotchas** The approval is RETURNED, not sent. `placeOrder` approves as a side effect; this cannot, because sending is exactly what it must not do. Send `approval` first when it is present, or the order reverts on-chain. Still `async`: a binary placement reads the pool's market expiry when the caller does not pass `expireTimestampNs`, and resolves the pool's escrow tokens to work out which approval is needed. Pass `expireTimestampNs`, `outcomeToken`, `yesId`, `noId`, and `collateral` to keep it off the network. No gas estimate and no nonce ride along — those belong to the signer, and pinning them here would stale the moment the call is cached. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `price` or `quantity` was not > 0. **Example** (Building an unsigned order) Pre-sign off the form, send on the click. ```ts const { order, approval } = await trader.buildPlaceOrder({ pool, side: "BUY_YES", price: 620_000n, quantity: 10_000_000n, }); if (approval) await walletClient.sendTransaction({ ...approval, account }); const signed = await account.signTransaction({ ...order, nonce, ...fees }); ``` #### Parameters ##### params [`PlaceOrderParams`](PlaceOrderParams.md) #### Returns `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> *** ### buildPlaceSpotOrder() > **buildPlaceSpotOrder**(`params`): `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> Defined in: packages/sdk/src/trade.ts:2716 Build a spot placement WITHOUT sending it — see [Trader.buildPlaceOrder](#buildplaceorder) for when to reach for this and how the returned approval works. A native-base sell pays via `msg.value`, so it comes back with no `approval` and a non-zero `order.value`: the pool's vault shortfall for this order, fee headroom included, as read when the call is built. A vault that gains funds before the send only shrinks the requirement (the pool refunds the overage); one that loses them makes the pool reject the call. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `price` or `quantity` is not positive. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the native-sell funding read reverted. - Throws [RpcError](../classes/RpcError.md) - the native-sell funding read did not complete. **Gotchas** A spot placement that DEFAULTS its expiry pins it to ~50 years from *now*, so two builds a second apart differ in that one argument. Harmless against a 50-year horizon, but it means such a build is not byte-reproducible: sign and send the `order` you were handed rather than rebuilding and expecting the same bytes. Pass [PlaceSpotOrderParams.expireTimestampNs](PlaceSpotOrderParams.md#expiretimestampns) explicitly and the build is reproducible, as binary and perp already are. #### Parameters ##### params [`PlaceSpotOrderParams`](PlaceSpotOrderParams.md) #### Returns `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> *** ### buildPlacePerpOrder() > **buildPlacePerpOrder**(`params`): `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> Defined in: packages/sdk/src/trade.ts:2724 Build a perp placement WITHOUT sending it — see [Trader.buildPlaceOrder](#buildplaceorder) for when to reach for this. Never carries an `approval`: margin is locked from the MarginBank balance rather than escrowed per order ([Trader.depositMargin](#depositmargin) first). #### Parameters ##### params [`PlacePerpOrderParams`](PlacePerpOrderParams.md) #### Returns `Promise`\<[`UnsignedOrder`](UnsignedOrder.md)\> *** ### depositMargin() > **depositMargin**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2731 Deposit collateral into the MarginBank (auto-approving the collateral token to the bank by default). One cross-margin balance covers every perp pool. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`DepositMarginParams`](DepositMarginParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### withdrawMargin() > **withdrawMargin**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2736 Withdraw free collateral from the MarginBank (margin-checked on-chain). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`WithdrawMarginParams`](WithdrawMarginParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### withdrawVault() > **withdrawVault**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2746 Claim a payout that fell back to a pool's internal ERC20Vault (a `PayoutFallbackToVault` credit) back to the wallet. Read the claimable amount first with `client.getVaultBalance({ vault, owner, token })`. Also how funds leave a manual-mode balance — see [setManualVaultMode](#setmanualvaultmode). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`WithdrawVaultParams`](WithdrawVaultParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### depositVault() > **depositVault**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2755 Pre-fund an ERC-20 balance in a pool's internal vault (approves the pool when needed). Ordinary placement needs no deposit — auto-pull covers it; deposit when funding must precede the order. Native goes in via [depositVaultNative](#depositvaultnative). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`DepositVaultParams`](DepositVaultParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### depositVaultNative() > **depositVaultNative**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2771 Pre-fund a native (SOMI) vault balance for the signer, or for another account when `owner` is set. The amount travels as `msg.value`. A binary pool's vault takes exactly one token, so the SDK reads the pool's `collateralToken()` first and refuses a native deposit into a pool whose collateral is not native rather than spending a failed transaction. A pool without that view (a SpotPool) goes straight to the chain. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `amount` is not positive, or the pool is a binary pool whose collateral is not native. - Throws [RpcError](../classes/RpcError.md) - the preflight read or the deposit did not complete. A failed preflight never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - the pool rejected the deposit (`InvalidDepositOrWithdrawal` when native is not one of its tokens). #### Parameters ##### params [`DepositVaultNativeParams`](DepositVaultNativeParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### depositVaultNativeFor() > **depositVaultNativeFor**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2778 Pre-fund ANOTHER account's native vault balance — [depositVaultNative](#depositvaultnative) with `owner` required (an operator funding a bot wallet). Same errors. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`DepositVaultNativeParams`](DepositVaultNativeParams.md) & `object` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setManualVaultMode() > **setManualVaultMode**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2786 Opt out of (or back into) wallet auto-pull on one SpotPool. While enabled, orders draw only on pre-deposited vault balance AND payouts stay as vault credit — claim them with [withdrawVault](#withdrawvault). Scoped per user per pool. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SetManualVaultModeParams`](SetManualVaultModeParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setOperatorApprovalForPool() > **setOperatorApprovalForPool**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2794 Grant or revoke an operator on ONE SpotPool — the tighter way to let a bot trade for you. The signer is the granting owner; `approved: false` revokes. Read it back with [SomniaMarketsClient.isApprovedForPool](SomniaMarketsClient.md#isapprovedforpool). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SetOperatorApprovalForPoolParams`](SetOperatorApprovalForPoolParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setOperatorApprovalGlobal() > **setOperatorApprovalGlobal**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2802 Grant or revoke an operator across EVERY registered pool. Required for `SpotRouter` (not on any pool's allowlist); prefer [setOperatorApprovalForPool](#setoperatorapprovalforpool) for a single-venue bot. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SetOperatorApprovalGlobalParams`](SetOperatorApprovalGlobalParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### setPerpLeverage() > **setPerpLeverage**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2807 Set the signer's max leverage for one perp pool (caps position size vs margin). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SetPerpLeverageParams`](SetPerpLeverageParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### proposePerpWalletLink() > **proposePerpWalletLink**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2828 Offer a child wallet a link to the signer as its main — the first half of the handshake that gives a perp sub-account access to the signer's wallet. Isolated margin on perps is one wallet per position, so a trader running N isolated positions runs N wallets. Linking them lets each child's position-increasing order draw its shortfall from this main's wallet, so one funded treasury serves all N. The signer is the MAIN and this moves no money. The child must send [acceptPerpWalletLink](#acceptperpwalletlink) next, and it is the only party that can: read the offer from `client.listPerpWalletLinkEvents({ child })`, which is the ONLY record of a pending proposal. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `registry` is the zero address, or none of `registry`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or the bank holds no registry, so the rail is dormant on this deployment. - Throws [RpcError](../classes/RpcError.md) - the registry or bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `CannotLinkSelf`, `CallerIsChild` (the signer is already someone's child), `AlreadyLinked` (`child` already has a main), `NoStateChange` (this offer already stands), or `ZeroAddress`. #### Parameters ##### params [`ProposePerpWalletLinkParams`](ProposePerpWalletLinkParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### acceptPerpWalletLink() > **acceptPerpWalletLink**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2843 Accept a main's standing offer, as the child — the second half of the handshake. From here the signer's position-increasing orders pull their shortfall from `main`'s wallet. Funding does not wait for link maturity; `maturesAt` gates ADL netting only. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `registry` is the zero address, or none of `registry`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or the bank holds no registry, so the rail is dormant on this deployment. - Throws [RpcError](../classes/RpcError.md) - the registry or bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `NoProposalPending`, `CallerIsChild` (`main` has itself become a child), `CallerIsMain` (the signer already has children), `AlreadyLinked`, or `MaxChildrenReached`. #### Parameters ##### params [`AcceptPerpWalletLinkParams`](AcceptPerpWalletLinkParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### cancelPerpWalletLinkProposal() > **cancelPerpWalletLinkProposal**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2854 Withdraw an offer the signer made and the child has not accepted. An ACCEPTED link comes down with [unlinkPerpWallet](#unlinkperpwallet) instead. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `registry` is the zero address, or none of `registry`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or the bank holds no registry, so the rail is dormant on this deployment. - Throws [RpcError](../classes/RpcError.md) - the registry or bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `NoProposalPending` (nothing pending for this pair, including an offer already accepted). #### Parameters ##### params [`CancelPerpWalletLinkProposalParams`](CancelPerpWalletLinkProposalParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### unlinkPerpWallet() > **unlinkPerpWallet**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2868 Dissolve an accepted link, from either end — pass the other party. Settles no money: a claim the main funded survives the unlink and still gates the child's withdrawals. `PerpsUnlinkGuard` vetoes it while the leaver holds open positions and is liquidatable. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `registry` is the zero address, or none of `registry`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or the bank holds no registry, so the rail is dormant on this deployment. - Throws [RpcError](../classes/RpcError.md) - the registry or bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `NotLinked` (the two are not a linked pair) or `UnlinkBlockedByGuard` (the leaver is liquidatable with open positions). #### Parameters ##### params [`UnlinkPerpWalletParams`](UnlinkPerpWalletParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### repayPerpMainFunding() > **repayPerpMainFunding**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2883 Return principal the signer's main funded, as the child. Over-asking is clamped to `min(amount, outstanding, balance)` rather than rejected, so the outstanding figure from `client.getPerpMainFunding` cannot be stale-high. Repaying is what unlocks the child's own money: `withdraw` frees at most `balance - outstanding`. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `amount` is not positive, `marginBank` is the zero address, or neither `marginBank` nor `pool` was passed. - Throws [RpcError](../classes/RpcError.md) - the bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `NoFundedPrincipal` (nothing outstanding), `NothingToReturn` (the clamp reached zero, so the balance is gone), or `InsufficientMarginAfterWithdrawal`. #### Parameters ##### params [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### recallPerpMainFunding() > **recallPerpMainFunding**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2897 Pull principal back out of a child, as the payer. The signer must be the payer the bank recorded at funding time. Recovers principal, never winnings, and performs no unlink — the child can be funded again without a fresh handshake. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `amount` is not positive, `marginBank` is the zero address, or neither `marginBank` nor `pool` was passed. - Throws [RpcError](../classes/RpcError.md) - the bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - `OnlyFundingPayer` (the signer is not the recorded payer), `NoFundedPrincipal`, `NothingToReturn`, or `InsufficientMarginAfterWithdrawal`. #### Parameters ##### params [`RecallPerpMainFundingParams`](RecallPerpMainFundingParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### claimPerpVoucher() > **claimPerpVoucher**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2936 Claim the signer's one-time credit voucher: a grant of house money into its MarginBank balance. The grant is non-withdrawable. The signer can trade with it, and can withdraw profit above it. Read `client.getPerpVoucherEligibility` first: a claim that fails still mines and costs gas, because not every executor simulates before it sends. **Gotchas** A claim is once per address for the distributor's life, not once per campaign. While the grant remains, the bank confines the account's position increases: only allowlisted markets, at no more than the voucher leverage cap, and the account cannot change its own leverage setting. Reducing a position is never blocked. Builder fees are not charged on voucher accounts. The account can still deposit its own collateral, and an order placed with an ERC-20 allowance to the bank can pull the wallet's collateral in. Both mix with the grant in one balance. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `distributor` or `marginBank` is the zero address, or none of `distributor`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport, or the bank holds no credit granter, so the voucher programme is off on this deployment. - Throws [RpcError](../classes/RpcError.md) - the distributor or bank resolution read did not complete. A failed resolution never broadcasts. - Throws [TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md) - the transaction may have reached the node and its receipt was not observed. Look up `hash` before sending again. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a pool or bank resolution read reverted (for example, `pool` is not a PerpPool or `marginBank` is not a MarginBank), and nothing was broadcast; or `claim()` reverted: `CampaignInactive` (outside the claim window), `AlreadyClaimed`, `BudgetExhausted`, `ClaimantNotFlat` (the signer holds a position or resting order), or `ClaimantIsMainFunded` (the signer carries principal from a linked main). The SDK's bundled error table does not name the last two yet, so they arrive with raw `data` and no `errorName`; `client.getPerpVoucherEligibility` reports them by name. Branch on `functionName` to tell a resolution revert (`marginBank`, `getCreditGranter`) from a claim revert (`claim`). #### Parameters ##### params [`ClaimPerpVoucherParams`](ClaimPerpVoucherParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> #### Example **Checking eligibility, then claiming** ```ts const eligibility = await markets.client.getPerpVoucherEligibility(marginBank, account); if (eligibility.eligible) { await markets.trader.claimPerpVoucher({ marginBank }); } else if (eligibility.reason === "notFlat") { // Close every position and cancel every resting perp order first. } ``` *** ### pokeFunding() > **pokeFunding**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2938 Permissionlessly poke a perp pool's funding settlement (updateFunding). #### Parameters ##### params ###### pool `` `0x${string}` `` ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### placeSpotStopOrder() > **placeSpotStopOrder**(`params`): `Promise`\<[`PlaceStopOrderResult`](PlaceStopOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2945 Place a spot stop-loss / take-profit pending order on a SpotStopOrderRegistry (funds the trigger via SOMI msg.value). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`PlaceSpotStopOrderParams`](PlaceSpotStopOrderParams.md) #### Returns `Promise`\<[`PlaceStopOrderResult`](PlaceStopOrderResult.md)\> *** ### cancelStopOrder() > **cancelStopOrder**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2950 Cancel a pending stop order on its registry. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`CancelStopOrderParams`](CancelStopOrderParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### placePerpStopOrder() > **placePerpStopOrder**(`params`): `Promise`\<[`PlacePerpStopOrderResult`](PlacePerpStopOrderResult.md)\> Defined in: packages/sdk/src/trade.ts:2963 Place a perp take-profit / stop-loss on a PerpStopOrderRegistry (funds the trigger via SOMI msg.value), granting the registry's one-time operator approval first if the signer has not already. The single perp-stop create entry: pass `pair` for a linked one-cancels-other set, or `intent: "opening"` for a stop-entry. Both default off, so an existing call is an ordinary reduce-only stop and produces the same transaction it always did. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`PlacePerpStopOrderParams`](PlacePerpStopOrderParams.md) #### Returns `Promise`\<[`PlacePerpStopOrderResult`](PlacePerpStopOrderResult.md)\> *** ### linkPerpStopOrders() > **linkPerpStopOrders**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2970 Link two existing perp stops into a one-cancels-other pair — the after-the-fact form of `placePerpStopOrder({ pair })`, and how a survivor is re-paired. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`LinkPerpStopOrdersParams`](LinkPerpStopOrdersParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### cancelPerpStopOrder() > **cancelPerpStopOrder**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2977 Cancel a pending perp stop. If it is one leg of a pair the other stays armed and is unlinked — use [cancelPerpStopOrders](#cancelperpstoporders) to tear down both. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`CancelStopOrderParams`](CancelStopOrderParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### cancelPerpStopOrders() > **cancelPerpStopOrders**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2982 Cancel several of the signer's pending perp stops in one tx, one refund transfer. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`CancelPerpStopOrdersParams`](CancelPerpStopOrdersParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### claimPerpStopSomi() > **claimPerpStopSomi**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:2989 Claim SOMI the perp stop registry owes the signer — the refund path for an owner that cannot receive native. Reverts `NothingToClaim` on a zero balance. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ClaimPerpStopSomiParams`](ClaimPerpStopSomiParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### buildPlacePerpStopOrder() > **buildPlacePerpStopOrder**(`params`): `Promise`\<[`UnsignedPerpStopOrder`](UnsignedPerpStopOrder.md)\> Defined in: packages/sdk/src/trade.ts:3009 Build [placePerpStopOrder](#placeperpstoporder) without sending it — the stop-registry call plus, unless skipped, the operator grant the trigger needs first. Recover the created ids from your own receipt with `decodePerpStopOrderIds`. #### Parameters ##### params [`PlacePerpStopOrderParams`](PlacePerpStopOrderParams.md) #### Returns `Promise`\<[`UnsignedPerpStopOrder`](UnsignedPerpStopOrder.md)\> *** ### buildCancelOrders() > **buildCancelOrders**(`params`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/trade.ts:3016 Build [cancelOrders](#cancelorders) without sending it — so a ladder pull can ride in the same transaction as the replacement quotes. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `orderIds` was empty. #### Parameters ##### params [`CancelOrdersParams`](CancelOrdersParams.md) #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildReduceOrders() > **buildReduceOrders**(`params`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/trade.ts:3022 Build [reduceOrders](#reduceorders) without sending it. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `reductions` was empty. #### Parameters ##### params [`ReduceOrdersParams`](ReduceOrdersParams.md) #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildCancelPerpStopOrder() > **buildCancelPerpStopOrder**(`params`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/trade.ts:3024 Build [cancelPerpStopOrder](#cancelperpstoporder) without sending it. #### Parameters ##### params [`CancelStopOrderParams`](CancelStopOrderParams.md) #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildCancelPerpStopOrders() > **buildCancelPerpStopOrders**(`params`): [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/trade.ts:3026 Build [cancelPerpStopOrders](#cancelperpstoporders) without sending it. #### Parameters ##### params [`CancelPerpStopOrdersParams`](CancelPerpStopOrdersParams.md) #### Returns [`UnsignedCall`](UnsignedCall.md) *** ### buildDepositMargin() > **buildDepositMargin**(`params`): `Promise`\<[`UnsignedMarginDeposit`](UnsignedMarginDeposit.md)\> Defined in: packages/sdk/src/trade.ts:3031 Build [depositMargin](#depositmargin) without sending it — the `deposit` call plus, unless `autoApprove: false`, the ERC-20 approval the bank needs first. #### Parameters ##### params [`DepositMarginParams`](DepositMarginParams.md) #### Returns `Promise`\<[`UnsignedMarginDeposit`](UnsignedMarginDeposit.md)\> *** ### buildWithdrawMargin() > **buildWithdrawMargin**(`params`): `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> Defined in: packages/sdk/src/trade.ts:3033 Build [withdrawMargin](#withdrawmargin) without sending it. Nothing to approve. #### Parameters ##### params [`WithdrawMarginParams`](WithdrawMarginParams.md) #### Returns `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> *** ### buildAcceptPerpWalletLink() > **buildAcceptPerpWalletLink**(`params`): `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> Defined in: packages/sdk/src/trade.ts:3043 Build [acceptPerpWalletLink](#acceptperpwalletlink) without sending it, so the accept and the child's first isolated placement go out as ONE transaction. The accept must execute first, or the placement finds no main. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `registry` is the zero address, or none of `registry`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the bank holds no registry, so the rail is dormant on this deployment. - Throws [RpcError](../classes/RpcError.md) - the registry or bank resolution read did not complete. A failed resolution never broadcasts. #### Parameters ##### params [`AcceptPerpWalletLinkParams`](AcceptPerpWalletLinkParams.md) #### Returns `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> *** ### buildRepayPerpMainFunding() > **buildRepayPerpMainFunding**(`params`): `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> Defined in: packages/sdk/src/trade.ts:3052 Build [repayPerpMainFunding](#repayperpmainfunding) without sending it, so the repayment and the withdrawal it unlocks go out as ONE transaction. The repayment must execute first — the withdrawal's gate reads the claim it clears. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `amount` is not positive, `marginBank` is the zero address, or neither `marginBank` nor `pool` was passed. - Throws [RpcError](../classes/RpcError.md) - the bank resolution read did not complete. #### Parameters ##### params [`RepayPerpMainFundingParams`](RepayPerpMainFundingParams.md) #### Returns `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> *** ### buildClaimPerpVoucher() > **buildClaimPerpVoucher**(`params`): `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> Defined in: packages/sdk/src/trade.ts:3064 Build [claimPerpVoucher](#claimperpvoucher) without sending it, so the claim and the first order go out as ONE transaction. The claim must execute first. Otherwise the order finds no grant, and with an ERC-20 allowance to the bank it pulls the wallet's own collateral instead. - Throws [InvalidInputError](../classes/InvalidInputError.md) - `distributor` or `marginBank` is the zero address, or none of `distributor`, `marginBank` and `pool` was passed. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the bank holds no credit granter, so the voucher programme is off on this deployment. - Throws [RpcError](../classes/RpcError.md) - the distributor or bank resolution read did not complete. - Throws [ContractRevertError](../classes/ContractRevertError.md) - a resolution read reverted, for example because `marginBank` is not a MarginBank. #### Parameters ##### params [`ClaimPerpVoucherParams`](ClaimPerpVoucherParams.md) #### Returns `Promise`\<[`UnsignedCall`](UnsignedCall.md)\> *** ### mintSet() > **mintSet**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3070 Mint a YES+NO set: deposit collateral, receive equal YES + NO. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`MintSetParams`](MintSetParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### burnSet() > **burnSet**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3075 Burn a YES+NO set: surrender both halves, receive collateral back. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`BurnSetParams`](BurnSetParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### redeem() > **redeem**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3084 Burn winning outcome tokens for collateral (resolved/voided markets). Settlement-extraction v2: module-routed — the module pulls the caller's winning tokens, finalizes-if-needed, and redeems through BinarySettlement. Takes `marketId` (not a pool address — a pool serves successive markets). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`RedeemParams`](RedeemParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### signRedeemAuth() > **signRedeemAuth**(`params`): `Promise`\<[`RedeemAuthorization`](RedeemAuthorization.md)\> Defined in: packages/sdk/src/trade.ts:3102 Produce an EIP-712 [RedeemAuthorization](RedeemAuthorization.md) the connected signer (the position owner) hands to a relayer, so the relayer can call [Trader.redeemFor](#redeemfor) and pay the gas while the OWNER receives the payout. Signs over the module's `REDEEM_AUTH_TYPEHASH` in the `SomniaMarkets` domain; no transaction is sent. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - no BinaryMarketsModule address is configured and none was passed. - Throws [SignerRequiredError](../classes/SignerRequiredError.md) - this trader's executor cannot sign typed data as the actor: a safe or a session key (`executor.signTypedData` is absent). A private key or a wallet can. - Throws [RpcError](../classes/RpcError.md) - the signer failed or refused (a wallet rejection, a custom signer's own error), preserved as `cause`. The complete union is [TraderSignRedeemAuthError](../type-aliases/TraderSignRedeemAuthError.md). #### Parameters ##### params [`SignRedeemAuthParams`](SignRedeemAuthParams.md) #### Returns `Promise`\<[`RedeemAuthorization`](RedeemAuthorization.md)\> *** ### redeemFor() > **redeemFor**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3110 Relayer path: submit a position owner's pre-signed [RedeemAuthorization](RedeemAuthorization.md) (from [Trader.signRedeemAuth](#signredeemauth)). The caller pays gas; the module pays the OWNER the collateral (payout is hard-pinned to `owner`, never the relayer). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`RedeemForParams`](RedeemForParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### redeemMany() > **redeemMany**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3115 Claim winnings from many settled markets in one transaction (batch redeem). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`RedeemManyParams`](RedeemManyParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### redeemDirect() > **redeemDirect**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3122 Low-level direct redemption against the BinarySettlement singleton (bypasses the module; no operator attribution). Takes the raw ERC-6909 `outcomeId`. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`RedeemDirectParams`](RedeemDirectParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### claimOwed() > **claimOwed**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3127 Claim an accrued push-fallback (`owed`) balance on the settlement singleton. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ClaimOwedParams`](ClaimOwedParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### pokeOracle() > **pokeOracle**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3151 Permissionless oracle retry — the FIRST move when a market is past expiry with no resolution: ask the module to re-pull the answer for its oracle question. **When to use** Use before [Trader.voidExpired](#voidexpired). A poke that succeeds resolves the market normally (winners paid in full); voiding pays everyone 1/N instead, so it is the fallback, not the first resort. **Gotchas** Keyed by ORACLE QUESTION, not market: the module fans out to every market bound to that question and resolves the ones whose adapter answers. Unanswered adapters are skipped, so this can resolve some markets and leave others — a success is not "all bound markets resolved". Reverts `OracleNotAnswered` only when none answered, `UnknownOracleQuestion` when no market is bound; both decode as [ContractRevertError](../classes/ContractRevertError.md), so a keeper loop can branch on `errorName`. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`PokeOracleParams`](PokeOracleParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### voidExpired() > **voidExpired**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3179 Permissionless dead-oracle escape hatch: void a market whose oracle never answered, so both sides can redeem at 1/N collateral. **When to use** Use only after [Trader.pokeOracle](#pokeoracle) has failed and `expiry + settlementWindow` has elapsed — this is the funds-unstranding backstop, and it pays 1/N rather than the real outcome. **Gotchas** This writes to the MARKET contract, bypassing the module — so the oracle hub's earmark release never fires. Follow with [Trader.syncSettlement](#syncsettlement), then [Trader.finalizeMarket](#finalizemarket) and [Trader.releasePool](#releasepool), to leave the market fully reconciled. Before sending, this reads the market's status, expiry, and settlement window and throws [InvalidInputError](../classes/InvalidInputError.md) naming the gate time if the window is still open — the on-chain `SettlementWindowOpen` revert carries no timestamp, and "when can I retry" is the operator's real question. The comparison uses the chain's `block.timestamp`, matching the contract, so a skewed local clock neither lets a doomed call through nor blocks a valid one. Pass `skipPreflight` to send blind and let the contract judge. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`VoidExpiredParams`](VoidExpiredParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### finalizeMarket() > **finalizeMarket**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3186 Permissionless keeper: finalize a settled market (sweep its pool's backing + resolution snapshot to the settlement singleton). No-op-guarded on repeat. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`FinalizeMarketParams`](FinalizeMarketParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### syncSettlement() > **syncSettlement**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3194 Permissionless earmark reconcile: release the oracle earmark of a market voided via `BinaryMarket.voidExpired()` (which bypasses the module, so the hub's earmark release never fired). Idempotent; reverts `MarketNotSettled` while still live. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`SyncSettlementParams`](SyncSettlementParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### releasePool() > **releasePool**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3201 Permissionless keeper: release a finalized, drained pool back to its creator's free list for recycle onto the next market. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ReleasePoolParams`](ReleasePoolParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### getSettlement() > **getSettlement**(`marketId`, `opts?`): `Promise`\<[`SettlementRecord`](SettlementRecord.md) \| `null`\> Defined in: packages/sdk/src/trade.ts:3207 Read a market's settlement record from the BinarySettlement singleton (by bytes32 marketId — resolves the marketKey via the module's yesId). Returns null when the market has never been finalized. #### Parameters ##### marketId `` `0x${string}` `` ##### opts? ###### module? `` `0x${string}` `` ###### settlement? `` `0x${string}` `` #### Returns `Promise`\<[`SettlementRecord`](SettlementRecord.md) \| `null`\> *** ### getFreePools() > **getFreePools**(`creator`, `collateral`, `opts?`): `Promise`\<`` `0x${string}` ``[]\> Defined in: packages/sdk/src/trade.ts:3209 Read a creator's free (finalized + released, reusable) pools for a collateral. #### Parameters ##### creator `` `0x${string}` `` ##### collateral `` `0x${string}` `` ##### opts? ###### module? `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``[]\> *** ### poolCreator() > **poolCreator**(`pool`, `opts?`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/trade.ts:3214 Read a pool's creator (its first-deploy creator — the only party that can reuse it). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### pool `` `0x${string}` `` ##### opts? ###### module? `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### mintSetNative() > **mintSetNative**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3221 Mint a complete YES+NO set paying with NATIVE token via the CollateralRouter (wraps `msg.value` → wNative). The market's collateral must be wNative. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`MintSetNativeParams`](MintSetNativeParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### mintSetPermit2() > **mintSetPermit2**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3228 Mint a complete YES+NO set pulling collateral via a Permit2 signature through the CollateralRouter (no prior ERC-20 `approve`). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`MintSetPermit2Params`](MintSetPermit2Params.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### redeemNative() > **redeemNative**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3235 Redeem winning outcome tokens for a NATIVE payout via the CollateralRouter (unwraps wNative → native). Approve the router for the winning outcome first. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`RedeemNativeParams`](RedeemNativeParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### faucet() > **faucet**(`params?`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3240 Mint TestUSDC from the faucet to the signer. - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params? [`FaucetParams`](FaucetParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### resolve() > **resolve**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3245 Resolve a market via the FakeOracle (demo resolver). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`ResolveParams`](ResolveParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### voidMarket() > **voidMarket**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3250 Void a market via the FakeOracle (demo resolver). - Throws [NotConfiguredError](../classes/NotConfiguredError.md) - the executor has no chain transport. #### Parameters ##### params [`VoidMarketParams`](VoidMarketParams.md) #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### poke() > **poke**(`params`): `Promise`\<[`TxResult`](TxResult.md)\> Defined in: packages/sdk/src/trade.ts:3252 Poke a market to advance its lifecycle. No-op since status is derived; kept for ABI stability. #### Parameters ##### params ###### market `` `0x${string}` `` ###### gas? `bigint` #### Returns `Promise`\<[`TxResult`](TxResult.md)\> *** ### clearApprovalCache() > **clearApprovalCache**(`token?`, `spender?`): `void` Defined in: packages/sdk/src/trade.ts:3258 Forget cached token approvals so the next escrowing write re-checks allowance. Pass a (token, spender) to clear one pair, or nothing to clear all. Rarely needed — maxUint256 approvals don't decrement. #### Parameters ##### token? `` `0x${string}` `` ##### spender? `` `0x${string}` `` #### Returns `void` --- # /docs/typescript/api/index/interfaces/TraderConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderConfig # Interface: TraderConfig Defined in: packages/sdk/src/trade.ts:72 Signer + defaults for `client.createTrader` — how a [Trader](Trader.md) signs and sends. Provide one source of authority: an `executor` (any [Executor](Executor.md), built-in or your own), or the signer sugar that builds the matching built-in — `privateKey`, a local `account`, or a `walletClient`. ## Properties ### executor? > `optional` **executor?**: [`Executor`](Executor.md) Defined in: packages/sdk/src/trade.ts:96 Who signs and sends: any [Executor](Executor.md) — the built-ins from `client.createExecutor(...)` (a private key, a wallet, a session key, a smart account) or your own. When set, `privateKey` / `account` / `walletClient` are ignored for sending; the writer reads allowances and operator grants for `executor.actor`. When unset, the three signer fields below build the matching built-in executor, so existing callers change nothing. **Gotchas** Must send on this client's chain — a mismatch throws [InvalidInputError](../classes/InvalidInputError.md) at `createTrader`. Verbs that SIGN rather than send (`signRedeemAuth`) need an executor with `signTypedData`; a safe or a session key has none, and those verbs throw [SignerRequiredError](../classes/SignerRequiredError.md). **Ownership.** An executor supplies signing and submission ONLY. The trader keeps its owner's chain, reads (allowances, operator grants and revert replays all go through the owner's client), deployments and lifecycle, and the built-ins from `client.createExecutor` are themselves owner-derived. A custom executor owning its own submission path is the point of the seam (a safe, a bundler, a relayer, custody); that deviation from SDK-OWN-001 / SDK-OWN-002 is recorded in the seam's proposal. *** ### walletClient? > `optional` **walletClient?**: `object` Defined in: packages/sdk/src/trade.ts:103 A pre-built signer (e.g. a browser/wagmi wallet over an injected provider). Only needed when the SDK can't sign locally — with `privateKey` / a local `account`, the SDK signs itself and sends over the client's WebSocket via eth_sendRawTransactionSync (send + confirm in one round-trip). *** ### account? > `optional` **account?**: `` `0x${string}` `` \| `Account` Defined in: packages/sdk/src/trade.ts:105 A local signing account (e.g. from viem's privateKeyToAccount). *** ### privateKey? > `optional` **privateKey?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:107 Private key — the SDK derives the account. *** ### publicClient? > `optional` **publicClient?**: `object` Defined in: packages/sdk/src/trade.ts:109 Read client for allowance/receipts. Defaults to the client's WebSocket client. *** ### decimals? > `optional` **decimals?**: `number` Defined in: packages/sdk/src/trade.ts:111 Scale for the testnet faucet's default amount (6 if unset). Order inputs use raw units; convert them with the selected market's `quoteDecimals`. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:116 Default gas ceiling per tx (10,000,000 when unset); each write can override per-call via its params' `gas`. --- # /docs/typescript/api/index/interfaces/TransactionSummary [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransactionSummary # Interface: TransactionSummary Defined in: packages/sdk/src/system.ts:218 Chain-direct summary of one transaction — sender, gas spent, fee paid, status — for enriching an order/fill view with what the tx cost. One `eth_getTransactionByHash` + one `eth_getTransactionReceipt`, in parallel. ## Properties ### from > **from**: `string` Defined in: packages/sdk/src/system.ts:220 Sender (the wallet that paid gas), lowercased. *** ### to > **to**: `string` \| `null` Defined in: packages/sdk/src/system.ts:222 Target contract, lowercased; null on a deployment. *** ### nonce > **nonce**: `number` Defined in: packages/sdk/src/system.ts:223 *** ### status > **status**: `"success"` \| `"reverted"` Defined in: packages/sdk/src/system.ts:224 *** ### gasUsed > **gasUsed**: `bigint` Defined in: packages/sdk/src/system.ts:225 *** ### gasLimit > **gasLimit**: `bigint` Defined in: packages/sdk/src/system.ts:227 The sender's gas limit for the tx. *** ### effectiveGasPrice > **effectiveGasPrice**: `bigint` Defined in: packages/sdk/src/system.ts:228 *** ### feeWei > **feeWei**: `bigint` Defined in: packages/sdk/src/system.ts:230 gasUsed × effectiveGasPrice — the fee paid, wei of the native token. *** ### value > **value**: `bigint` Defined in: packages/sdk/src/system.ts:232 Native value sent with the tx (wei). *** ### logCount > **logCount**: `number` Defined in: packages/sdk/src/system.ts:234 Log records in the receipt — how much the tx did (batch orders emit many). --- # /docs/typescript/api/index/interfaces/TransferOperatorOwnershipParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransferOperatorOwnershipParams # Interface: TransferOperatorOwnershipParams Defined in: packages/sdk/src/operatorAdmin.ts:157 Params for [OperatorAdmin.transferOperatorOwnership](OperatorAdmin.md#transferoperatorownership). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:159 The operator whose ownership is staged. Caller must be its owner. *** ### newOwner > **newOwner**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:164 The staged new owner — must later call [OperatorAdmin.acceptOperatorOwnership](OperatorAdmin.md#acceptoperatorownership) to complete the transfer. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:166 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/TriggerRollParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TriggerRollParams # Interface: TriggerRollParams Defined in: packages/sdk/src/marketCreatorAdmin.ts:146 Params for [MarketCreatorAdmin.triggerRoll](MarketCreatorAdmin.md#triggerroll). ## Properties ### creator > **creator**: `` `0x${string}` `` Defined in: packages/sdk/src/marketCreatorAdmin.ts:148 The MarketCreator owning the series. Caller must be its owner. *** ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:150 The series to roll. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/marketCreatorAdmin.ts:152 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/TxResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TxResult # Interface: TxResult Defined in: packages/sdk/src/trade.ts:124 Base result of a confirmed write — the SDK waits for the receipt before resolving. ## Extended by - [`PlaceOrderResult`](PlaceOrderResult.md) - [`PlaceStopOrderResult`](PlaceStopOrderResult.md) - [`PlacePerpStopOrderResult`](PlacePerpStopOrderResult.md) - [`PlaceSpotOrdersResult`](PlaceSpotOrdersResult.md) - [`CancelOrdersResult`](CancelOrdersResult.md) - [`AmendOrderResult`](AmendOrderResult.md) - [`AmendOrdersResult`](AmendOrdersResult.md) - [`RegisterOperatorResult`](RegisterOperatorResult.md) - [`CreateVenueResult`](CreateVenueResult.md) - [`ScheduleQuestionResult`](ScheduleQuestionResult.md) - [`CreateMarketCreatorResult`](CreateMarketCreatorResult.md) ## Properties ### hash > **hash**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:126 The transaction hash. *** ### receipt > **receipt**: `TransactionReceipt` Defined in: packages/sdk/src/trade.ts:128 The mined receipt (status, gas used, logs). *** ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Defined in: packages/sdk/src/trade.ts:139 Node-side end-to-end time of the write in microseconds: from the node receiving the send to its answer, which covers mempool, finality and execution inside Somnia. Set when the node reports it with the receipt (`eth_sendRawTransactionSync` and session sends on a current Somnia node, or an executor that passes it through). Absent on an older node, on the `eth_sendRawTransaction` fallback, and for a wallet-client send. For a write with prerequisites (an approval first), it times the last transaction only. --- # /docs/typescript/api/index/interfaces/UnifiedBalance [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedBalance # Interface: UnifiedBalance Defined in: packages/sdk/src/unified/structs.ts:320 One currency's balance, human units (ccxt shape). For spot/binary, funds escrowed in resting orders live in the pools — not the wallet — so `used` is 0 and `free === total`. NOTE: this "used is 0" property is a fact about wallet-held tokens, not a law of the venue — perp collateral IS locked (MarginBank margin against open positions), and a margin-aware `fetchBalance` arm must report it through `used` rather than pretending the invariant generalizes. ## Properties ### free > **free**: `number` Defined in: packages/sdk/src/unified/structs.ts:322 Spendable balance. *** ### used > **used**: `number` Defined in: packages/sdk/src/unified/structs.ts:324 Locked balance (0 for wallet-held spot/binary tokens; perp margin when reported). *** ### total > **total**: `number` Defined in: packages/sdk/src/unified/structs.ts:326 `free + used`, human units. *** ### byChain > **byChain**: `Record`\<`number`, [`UnifiedChainBalance`](UnifiedChainBalance.md)\> Defined in: packages/sdk/src/unified/structs.ts:334 The same figures per chain, keyed by numeric chain id. The top-level numbers are the sum across every configured chain; this is where they came from. A single-chain exchange reports one entry. The native coin is one asset across chains (post-bridge SOMI on Hideki is the same SOMI), so it aggregates under one code and breaks down here. --- # /docs/typescript/api/index/interfaces/UnifiedBalances [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedBalances # Interface: UnifiedBalances Defined in: packages/sdk/src/unified/structs.ts:356 Balances keyed by currency code, plus the raw reads under `info`. ## Indexable > \[`code`: `string`\]: [`UnifiedBalance`](UnifiedBalance.md) --- # /docs/typescript/api/index/interfaces/UnifiedChainBalance [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedChainBalance # Interface: UnifiedChainBalance Defined in: packages/sdk/src/unified/structs.ts:342 One chain's share of a [UnifiedBalance](UnifiedBalance.md). ## Properties ### free > **free**: `number` Defined in: packages/sdk/src/unified/structs.ts:344 Spendable balance on this chain. *** ### used > **used**: `number` Defined in: packages/sdk/src/unified/structs.ts:346 Locked balance on this chain. *** ### total > **total**: `number` Defined in: packages/sdk/src/unified/structs.ts:348 `free + used` on this chain, human units. --- # /docs/typescript/api/index/interfaces/UnifiedFundingRate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedFundingRate # Interface: UnifiedFundingRate Defined in: packages/sdk/src/unified/structs.ts:529 A perp funding-rate snapshot (live chain read; rates are fractions, not %). ## Properties ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:531 The perp's tradable symbol, e.g. "BTC/USDSO:USDSO". *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:533 Numeric chain id the market lives on. *** ### markPrice > **markPrice**: `number` \| `undefined` Defined in: packages/sdk/src/unified/structs.ts:541 Mark price, human quote units. Undefined when the mark feed is stale — a live read reports that explicitly, and a historical row carries the contract's 0 sentinel, neither of which should be flattened to a price of zero. *** ### indexPrice > **indexPrice**: `number` Defined in: packages/sdk/src/unified/structs.ts:543 Oracle index price, human quote units. *** ### fundingRate > **fundingRate**: `number` Defined in: packages/sdk/src/unified/structs.ts:559 Funding rate per 8 HOURS as a plain fraction (0.0001 = 0.01%). Normalized to a fixed 8h axis (the Hyperliquid/Binance convention) from the chain's per-calculation-window value, so it stays comparable across a parameter change. NOT the amount charged at each settlement: that is this divided by `n = fundingWindowSec / fundingIntervalSec`, which is 8 on every live pool and has been 96 at a 300s cadence. `info` carries both figures. On a HISTORICAL row that caught up over several intervals, `rate / n` is only ONE interval's worth: the amount that settlement actually charged is `rate * intervalsAccrued / n`. Rows at the deployed one-interval horizon have `intervalsAccrued` of 1, so the two agree there and disagree only on older catch-up rows. *** ### fundingTimestamp? > `optional` **fundingTimestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:567 When funding next settles, or when this row settled (ms). For a live read this is the last settlement anchor plus the settlement interval; because settlement is permissionless and LAZY it can be in the past, which means a settlement is due rather than that anything is wrong. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/structs.ts:569 When this snapshot was read (ms, local clock). *** ### datetime > **datetime**: `string` Defined in: packages/sdk/src/unified/structs.ts:571 ISO-8601 of `timestamp`. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:573 The native on-chain perp state (raw 1e18/quote-unit bigints). --- # /docs/typescript/api/index/interfaces/UnifiedMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedMarket # Interface: UnifiedMarket Defined in: packages/sdk/src/unified/structs.ts:31 A unified market object. `info` is the native `Market` union row. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/unified/structs.ts:33 Venue-internal id (the native market id: bytes32 for binary, pool for spot). *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:35 Numeric chain id the market lives on. *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:40 Canonical MARKET symbol (no outcome suffix), e.g. "SOMI/USDC" or "BTC-95000-31DEC26/USDC". Key into `exchange.markets`. *** ### type > **type**: [`UnifiedMarketType`](../type-aliases/UnifiedMarketType.md) Defined in: packages/sdk/src/unified/structs.ts:42 Market kind — see [UnifiedMarketType](../type-aliases/UnifiedMarketType.md). *** ### base > **base**: `string` Defined in: packages/sdk/src/unified/structs.ts:47 Base currency code — for outcome markets, the market's asset-strike-expiry stem (everything before the slash). *** ### quote > **quote**: `string` Defined in: packages/sdk/src/unified/structs.ts:49 Quote currency code (outcome markets: the collateral token's code). *** ### settle? > `optional` **settle?**: `string` Defined in: packages/sdk/src/unified/structs.ts:54 Settlement currency code. Set on swap (== quote for a linear perp) and outcome markets; absent on spot. *** ### active > **active**: `boolean` Defined in: packages/sdk/src/unified/structs.ts:56 Derived from live/indexed lifecycle — false once trading is impossible. *** ### contract > **contract**: `boolean` Defined in: packages/sdk/src/unified/structs.ts:58 ccxt's derivative flag: true only for swap (perp) markets. *** ### precision > **precision**: `object` Defined in: packages/sdk/src/unified/structs.ts:63 Decimal places implied by the market's tick (price) and lot (amount) grids — what [SomniaMarkets.priceToPrecision](../classes/SomniaMarkets.md#pricetoprecision) snaps to. #### price > **price**: `number` Price decimal places (from the tick grid). #### amount > **amount**: `number` Amount decimal places (from the lot grid). *** ### limits > **limits**: `object` Defined in: packages/sdk/src/unified/structs.ts:70 Order-size floors, human units; `min` is absent when the pool sets none. #### amount > **amount**: `object` Amount (order size) bounds. ##### amount.min? > `optional` **min?**: `number` Minimum order size, human base units. *** ### outcomes? > `optional` **outcomes?**: `object`[] Defined in: packages/sdk/src/unified/structs.ts:78 Outcome tradables (binary/categorical). Absent on spot/swap. #### symbol > **symbol**: `string` The outcome's tradable symbol, e.g. "BTC-95000-31DEC26/USDC#YES". #### label > **label**: `string` Outcome label ("YES" / "NO"). #### index > **index**: `number` Outcome index on the ERC-6909 singleton (0 = YES, 1 = NO). *** ### indexed > **indexed**: `boolean` Defined in: packages/sdk/src/unified/structs.ts:117 Whether the indexer has a row for this market. True for every spot and outcome market — those are discovered through the indexer, so a row is the only way they appear at all. It can be **false only on a perp**, which `loadMarkets()` also discovers from the PerpPoolFactory: a market deployed after the indexer's perp manifest was written is present on the chain and absent from the indexer. **Branch on this before reading anything history-derived.** On a market with `indexed: false`, `info.cumulativeBaseVolume`, `info.cumulativeQuoteVolume`, `info.tradeCount`, `info.createdAtTimestamp` and `info.createdAtBlock` are `"0"` placeholders meaning UNKNOWN — not "never traded" — and every funding, mark-price and open-interest field is null. `info.lastPrice` and `info.lastTradeAt` need care of their own. They are null here for the same reason, but on an INDEXED market null carries the narrower meaning "no fill yet". So null on a market with `indexed: false` says nothing about whether it has traded, and rendering it as "no trades" is wrong. The chain-backed reads work in full — positions, collateral, the order book — and the indexer-backed ones (candles, fills, order history, portfolio) return empty. TP/SL depends on `info.stopRegistry`, which comes from the factory and is null when it records none. **Placement is a separate question from `indexed`.** Discovery reports every factory pool, including restricted and unregistered ones, so a market being present here does not mean an order will be accepted: check [UnifiedMarket.active](#active) or [UnifiedMarket.perpStatus](#perpstatus). A restricted market takes closes and cancels but reverts anything position-increasing. *** ### perpStatus? > `optional` **perpStatus?**: `Pick`\<[`PerpPoolStatus`](../type-aliases/PerpPoolStatus.md), `"restricted"` \| `"registered"` \| `"tradeable"`\> Defined in: packages/sdk/src/unified/structs.ts:132 Live tradeability gates, perp markets only. Absent on spot and outcome markets; on every market when no PerpPoolFactory could be reached (see `SomniaMarkets.perpDiscoveryError`); and per-market on an indexed perp the reachable factory does not list — which happens after a factory rotation, and leaves that market's `active` falling back to `true`. Read from the chain on each `loadMarkets()`, because "deployed" is not "tradeable" and the two gates fail for unrelated reasons — see [PerpPoolStatus](../type-aliases/PerpPoolStatus.md). [UnifiedMarket.active](#active) folds them together; these are here for a consumer that must tell a wound-down market from one that was never activated. *** ### info > **info**: [`Market`](../type-aliases/Market.md) Defined in: packages/sdk/src/unified/structs.ts:134 The native `Market` union row (raw strings/bigint-scale fields). --- # /docs/typescript/api/index/interfaces/UnifiedOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrder # Interface: UnifiedOrder Defined in: packages/sdk/src/unified/structs.ts:209 An order, in the tradable's own terms (prices/amounts human units). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/unified/structs.ts:214 On-chain order id (decimal string) — pass to [SomniaMarkets.cancelOrder](../classes/SomniaMarkets.md#cancelorder). Falls back to the tx hash for a write that left nothing resting. *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:216 The tradable symbol the order is viewed on. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:218 Numeric chain id the market lives on. *** ### type? > `optional` **type?**: `"market"` \| `"limit"` Defined in: packages/sdk/src/unified/structs.ts:234 Requested execution style ("market" computed a crossing IOC limit). **Absent on orders read back from the indexer** — `fetchOrders`, `fetchOpenOrders` and `watchOrders` all leave it undefined. The pools do not emit the order type: `OrderPlaced` carries a `placedOrder` struct with no order-type member, and binary pools emit only the YES/NO side, so the indexer has nothing to store and the SDK has nothing to read. Populating it needs a contract change. Present only where the value is genuinely known: on the result of [SomniaMarkets.createOrder](../classes/SomniaMarkets.md#createorder), which echoes the caller's own argument. ([UnifiedStopOrder.type](UnifiedStopOrder.md#type) is always known — the stop registry does emit the order type.) *** ### side > **side**: `"buy"` \| `"sell"` Defined in: packages/sdk/src/unified/structs.ts:236 Direction on this tradable's book (a NO buy is a YES sell internally). *** ### price? > `optional` **price?**: `number` Defined in: packages/sdk/src/unified/structs.ts:238 Limit price, human units; absent when unknown. *** ### amount > **amount**: `number` Defined in: packages/sdk/src/unified/structs.ts:240 Full order size, human base units. *** ### filled > **filled**: `number` Defined in: packages/sdk/src/unified/structs.ts:242 Quantity filled so far, human base units. *** ### remaining > **remaining**: `number` Defined in: packages/sdk/src/unified/structs.ts:244 Quantity still open (`amount − filled`), human base units. *** ### status > **status**: [`UnifiedOrderStatus`](../type-aliases/UnifiedOrderStatus.md) Defined in: packages/sdk/src/unified/structs.ts:246 Lifecycle state — see [UnifiedOrderStatus](../type-aliases/UnifiedOrderStatus.md). *** ### txHash? > `optional` **txHash?**: `string` Defined in: packages/sdk/src/unified/structs.ts:248 Tx hash the order was placed in, when known. *** ### timestamp? > `optional` **timestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:250 Placement time (ms); write results stamp the local clock. *** ### datetime? > `optional` **datetime?**: `string` Defined in: packages/sdk/src/unified/structs.ts:252 ISO-8601 of `timestamp`. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:254 The native order row / [PlaceOrderResult](PlaceOrderResult.md). --- # /docs/typescript/api/index/interfaces/UnifiedOrderBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrderBook # Interface: UnifiedOrderBook Defined in: packages/sdk/src/unified/structs.ts:142 An L2 book: [price, amount] pairs, best first, human units. ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/unified/structs.ts:144 Pinned chain block or scope applied-event watermark; absent without provenance. *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:149 The tradable symbol this book view addresses (a NO book is the YES book inverted into NO terms). *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:151 Numeric chain id the market lives on. *** ### bids > **bids**: \[`number`, `number`\][] Defined in: packages/sdk/src/unified/structs.ts:153 Buy side, best (highest) bid first. *** ### asks > **asks**: \[`number`, `number`\][] Defined in: packages/sdk/src/unified/structs.ts:155 Sell side, best (lowest) ask first. *** ### timestamp? > `optional` **timestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:157 When this view was assembled (ms) — local clock, not a block timestamp. *** ### info? > `optional` **info?**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:159 The native book (raw bigint levels; YES terms for binary). --- # /docs/typescript/api/index/interfaces/UnifiedPosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedPosition # Interface: UnifiedPosition Defined in: packages/sdk/src/unified/structs.ts:581 An open perp position, human units. ## Properties ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:583 The perp's tradable symbol. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:585 Numeric chain id the market lives on. *** ### side > **side**: `"short"` \| `"long"` Defined in: packages/sdk/src/unified/structs.ts:587 Position direction (from the sign of the on-chain size). *** ### contracts > **contracts**: `number` Defined in: packages/sdk/src/unified/structs.ts:589 Absolute position size in base units. *** ### entryPrice > **entryPrice**: `number` Defined in: packages/sdk/src/unified/structs.ts:591 Average entry price, human quote units. *** ### markPrice? > `optional` **markPrice?**: `number` Defined in: packages/sdk/src/unified/structs.ts:593 Current EMA mark price, human quote units. Absent when `perpState` is `"degraded"`. *** ### unrealizedPnl? > `optional` **unrealizedPnl?**: `number` Defined in: packages/sdk/src/unified/structs.ts:598 (mark − entry) × signed size, human quote units. Excludes pending funding. Absent when `perpState` is `"degraded"`. *** ### liquidationPrice? > `optional` **liquidationPrice?**: `number` Defined in: packages/sdk/src/unified/structs.ts:609 Estimated liquidation price, human quote units — the price at which THIS market's move alone would trip the account's cross-margin maintenance requirement. `undefined` when it can't be derived (a stale mark anywhere in the account reverts the health read this needs). Solved with both sides of `equity == mmReq` moving against the mark; see `perpLiquidationPrice` for the identity and what is held constant. For the price a proposed order would move this to, use `client.previewPerpLiquidationPrice`. *** ### timestamp? > `optional` **timestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:611 When the position last changed on-chain (ms). *** ### datetime? > `optional` **datetime?**: `string` Defined in: packages/sdk/src/unified/structs.ts:613 ISO-8601 of `timestamp`. *** ### perpState > **perpState**: `"ok"` \| `"degraded"` Defined in: packages/sdk/src/unified/structs.ts:625 Whether the pool state behind `markPrice` and `unrealizedPnl` was read. The same flag as [UnifiedTicker.perpState](UnifiedTicker.md#perpstate), without `"not-applicable"`, because a position is always a perp. - `"ok"` — the pool state was read. `markPrice` and `unrealizedPnl` are present. - `"degraded"` — the pool state read failed, for example because the pool's oracle reverts. The position is real; only `markPrice` and `unrealizedPnl` are absent. The other positions in the same read are not affected. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:630 The native reads: `{ position, state, markFromIndex }` (raw bigints), or `{ position }` alone when `perpState` is `"degraded"`. --- # /docs/typescript/api/index/interfaces/UnifiedPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedPrice # Interface: UnifiedPrice Defined in: packages/sdk/src/unified/structs.ts:638 A realtime price snapshot for one asset (the on-chain EMA oracle feed). ## Properties ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:640 Asset symbol, e.g. "BTC", "ETH". *** ### price > **price**: `number` Defined in: packages/sdk/src/unified/structs.ts:642 Latest price, human units. *** ### ema > **ema**: `number` Defined in: packages/sdk/src/unified/structs.ts:644 Latest EMA (exponential moving average) price, human units. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/structs.ts:646 Block timestamp of the latest observation (ms). *** ### datetime > **datetime**: `string` Defined in: packages/sdk/src/unified/structs.ts:648 ISO-8601 of `timestamp`. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:650 The native [LivePrice](LivePrice.md) row (raw 1e18 strings + block metadata). --- # /docs/typescript/api/index/interfaces/UnifiedStopOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedStopOrder # Interface: UnifiedStopOrder Defined in: packages/sdk/src/unified/structs.ts:271 A stop / take-profit order resting OFF the book on the market's SpotStopOrderRegistry, human units. Fires as a market or limit order when the pool's mark price crosses `triggerPrice`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/unified/structs.ts:273 Registry order id (decimal string) — pass to [SomniaMarkets.cancelStopOrder](../classes/SomniaMarkets.md#cancelstoporder). *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:275 The spot tradable the stop targets. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:277 Numeric chain id the market lives on. *** ### type > **type**: `"market"` \| `"limit"` Defined in: packages/sdk/src/unified/structs.ts:279 Execution style at trigger time. *** ### side > **side**: `"buy"` \| `"sell"` Defined in: packages/sdk/src/unified/structs.ts:281 Direction of the triggered order. *** ### amount > **amount**: `number` Defined in: packages/sdk/src/unified/structs.ts:283 Order size, human base units. *** ### triggerPrice > **triggerPrice**: `number` Defined in: packages/sdk/src/unified/structs.ts:285 Mark price that arms the trigger, human quote units. *** ### triggerDirection > **triggerDirection**: `"above"` \| `"below"` Defined in: packages/sdk/src/unified/structs.ts:287 Which side of the mark the trigger arms on. *** ### price? > `optional` **price?**: `number` Defined in: packages/sdk/src/unified/structs.ts:294 Limit price of the triggered order (limit stops only), human quote units. Undefined when unknown, including limit stops returned by [SomniaMarkets.fetchOpenStopOrders](../classes/SomniaMarkets.md#fetchopenstoporders). Treat undefined as unknown, not zero. *** ### status > **status**: [`UnifiedStopOrderStatus`](../type-aliases/UnifiedStopOrderStatus.md) Defined in: packages/sdk/src/unified/structs.ts:296 Lifecycle state — see [UnifiedStopOrderStatus](../type-aliases/UnifiedStopOrderStatus.md). *** ### triggeredOrderId? > `optional` **triggeredOrderId?**: `string` Defined in: packages/sdk/src/unified/structs.ts:298 The spot order id the trigger produced, once it fired. *** ### timestamp? > `optional` **timestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:300 Creation time (ms). *** ### datetime? > `optional` **datetime?**: `string` Defined in: packages/sdk/src/unified/structs.ts:302 ISO-8601 of `timestamp`. *** ### txHash? > `optional` **txHash?**: `string` Defined in: packages/sdk/src/unified/structs.ts:304 Tx hash of the create, when known (write results only). *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:306 The native registry row / write result. --- # /docs/typescript/api/index/interfaces/UnifiedTicker [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedTicker # Interface: UnifiedTicker Defined in: packages/sdk/src/unified/structs.ts:373 A rolling 24h market snapshot (ccxt ticker shape), human units. Absent fields mean the window had no trades to derive them from. ## Properties ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:375 The tradable symbol the ticker describes. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:377 Numeric chain id the market lives on. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/structs.ts:379 When this snapshot was computed (ms, local clock). *** ### datetime > **datetime**: `string` Defined in: packages/sdk/src/unified/structs.ts:381 ISO-8601 of `timestamp`. *** ### high? > `optional` **high?**: `number` Defined in: packages/sdk/src/unified/structs.ts:383 Highest fill price in the window. *** ### low? > `optional` **low?**: `number` Defined in: packages/sdk/src/unified/structs.ts:385 Lowest fill price in the window. *** ### open? > `optional` **open?**: `number` Defined in: packages/sdk/src/unified/structs.ts:387 First fill price in the window. *** ### last? > `optional` **last?**: `number` Defined in: packages/sdk/src/unified/structs.ts:389 Most recent fill price (may predate the window on quiet markets). *** ### lastSource? > `optional` **lastSource?**: `object` Defined in: packages/sdk/src/unified/structs.ts:407 When the trade behind `last` happened (ms). Present on BOTH paths that produce a `last`. A candle stamps its bucket start. The cached fallback — the market row's lifetime last price, used when the candle window is empty — stamps that row's `lastTradeAt`, which can be much older than the window. Compare the timestamp; do not read presence alone as a freshness signal. ABSENCE IS MEANINGFUL, and narrower than it looks. No `lastSource` means either there is no `last` at all, or the cached fallback supplied `last` while the row carried no `lastTradeAt`. In both cases no provenance exists, so a consumer that needs a fresh print must treat `last` as stale. Read it against [statsAsOf](#statsasof), not against `timestamp`: `timestamp` is when this snapshot was assembled and says nothing about either half's age. #### timestamp > **timestamp**: `number` When the trade happened (ms). *** ### statsAsOf? > `optional` **statsAsOf?**: `number` Defined in: packages/sdk/src/unified/structs.ts:418 The end of the window the 24h statistics (`open`, `high`, `low`, `change`, `percentage`, `baseVolume`, `quoteVolume`) were folded over (ms). This is the statistics' own as-of, derived from the candle window — NOT the response time. Absent when the window held no candles to fold. *** ### change? > `optional` **change?**: `number` Defined in: packages/sdk/src/unified/structs.ts:420 `last − open`, when both are known. *** ### percentage? > `optional` **percentage?**: `number` Defined in: packages/sdk/src/unified/structs.ts:422 `change / open` as a plain fraction (0.05 = +5%), when derivable. *** ### baseVolume? > `optional` **baseVolume?**: `number` Defined in: packages/sdk/src/unified/structs.ts:430 Σ base-asset volume over the window. Absent when [statsState](#statsstate) is `"unavailable"` — there is no honest number to report then. A `0` means a successful read over a window with no fills, which is a true zero. Branch on `statsState`, not on absence. *** ### quoteVolume? > `optional` **quoteVolume?**: `number` Defined in: packages/sdk/src/unified/structs.ts:436 Σ quote-asset volume over the window. Absent when [statsState](#statsstate) is `"unavailable"`. See [baseVolume](#basevolume). *** ### statsState > **statsState**: `"ok"` \| `"unavailable"` Defined in: packages/sdk/src/unified/structs.ts:459 Whether the 24h statistics above were read, and WHY when they were not. Two states, always one of them: - `"ok"` — the candle window was read. `baseVolume` and `quoteVolume` are present. They are `0` when the window held no fills, which is a true zero and not a missing value. - `"unavailable"` — the statistics could not be read. Either the candle request failed with an `IndexerError`, or the market is `indexed: false` and no candle request was sent. `open`, `high`, `low`, `change`, `percentage`, `statsAsOf`, `baseVolume` and `quoteVolume` are ALL absent, and [info](#info) carries no fold. The call still resolves in the `"unavailable"` state, and the perp chain fields below are still read. That is the point of the field: a candle outage must not take down mark price, index price, funding and open interest, which come from chain and would have worked. `last` and `lastSource` are independent of this state. They still come from the cached market row when it carries them. *** ### markPrice? > `optional` **markPrice?**: `number` Defined in: packages/sdk/src/unified/structs.ts:468 PERP ONLY — mark price, human quote units. Undefined on spot/binary, and undefined on a perp whose mark is unusable — either the feed reported stale, or the price is zero. A zero mark is never published: flattened to a number it reads as a real price, and downstream an unguarded `markPrice - entryPrice` becomes a 100% loss on every open position. *** ### indexPrice? > `optional` **indexPrice?**: `number` Defined in: packages/sdk/src/unified/structs.ts:470 PERP ONLY — oracle index price, human quote units. Undefined on spot/binary. *** ### fundingRate? > `optional` **fundingRate?**: `number` Defined in: packages/sdk/src/unified/structs.ts:482 PERP ONLY — funding rate per **8 HOURS** as a plain fraction (0.0001 = 0.01%). The same axis [UnifiedFundingRate.fundingRate](UnifiedFundingRate.md#fundingrate) and `fetchFundingRateHistory` use, deliberately: a header reading one basis while the chart beside it reads another is a wrong number that looks right. NOT the amount charged per settlement — that is this divided by `fundingWindowSec / fundingIntervalSec` (8 on every live pool; it has been 96 at a 300s cadence), and `info.perp` carries both figures. On a historical catch-up row, multiply by that row's `intervalsAccrued` — one settlement can charge more than one interval's worth. *** ### fundingTimestamp? > `optional` **fundingTimestamp?**: `number` Defined in: packages/sdk/src/unified/structs.ts:487 PERP ONLY — when funding next settles (ms). Settlement is permissionless and lazy, so a past value means a settlement is DUE, not that anything is broken. *** ### openInterest? > `optional` **openInterest?**: `number` Defined in: packages/sdk/src/unified/structs.ts:494 PERP ONLY — total open interest in base units. ONE counter, not a long/short pair: in a matched CLOB the short side is provably equal, so there is nothing to sum. *** ### perpState > **perpState**: `"ok"` \| `"not-applicable"` \| `"degraded"` Defined in: packages/sdk/src/unified/structs.ts:510 Whether the perp chain fields above are present, and WHY when they are not. Three states, always one of them: - `"not-applicable"` — spot or binary. No perp fields exist to report. - `"ok"` — a perp, and its chain state was read. The perp fields are present. - `"degraded"` — a perp whose chain state read FAILED. The perp fields are absent and the 24h half below is still valid. Without this, a missing `markPrice` is ambiguous: it reads the same on a spot market as on a perp whose oracle reverted. The degrade is deliberate — losing candle statistics to an oracle outage would be worse — but it must be visible, so branch on this rather than on the absence of a field. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:521 The raw fold this snapshot came from (raw-unit bigints). On a perp it also carries `perp`, the full on-chain state — including `fundingWindowSec` / `fundingIntervalSec` for re-basing the funding rate. There is no fold to carry when [statsState](#statsstate) is `"unavailable"`. This is then `undefined` on a spot or binary market, and carries only `perp` on a perp. Check `statsState` before reading a fold field off it; the type is `unknown`, so the compiler cannot warn you. --- # /docs/typescript/api/index/interfaces/UnifiedTrade [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedTrade # Interface: UnifiedTrade Defined in: packages/sdk/src/unified/structs.ts:167 A fill, in the tradable's own terms (prices/amounts human units). ## Properties ### blockNumber? > `optional` **blockNumber?**: `bigint` Defined in: packages/sdk/src/unified/structs.ts:169 Source fill block, preserved in outcome views. Absent when the input has no block provenance. *** ### logIndex? > `optional` **logIndex?**: `number` Defined in: packages/sdk/src/unified/structs.ts:171 Source log position. Absent when the input has no log provenance. *** ### id > **id**: `string` Defined in: packages/sdk/src/unified/structs.ts:173 Native fill id — unique per fill, stable across reads. *** ### symbol > **symbol**: `string` Defined in: packages/sdk/src/unified/structs.ts:175 The tradable symbol the fill is viewed on. *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/structs.ts:177 Numeric chain id the market lives on. *** ### price > **price**: `number` Defined in: packages/sdk/src/unified/structs.ts:179 Fill price, human units (binary: this outcome's probability). *** ### amount > **amount**: `number` Defined in: packages/sdk/src/unified/structs.ts:181 Filled quantity, human base units. *** ### cost > **cost**: `number` Defined in: packages/sdk/src/unified/structs.ts:183 price × amount, in quote units. *** ### side? > `optional` **side?**: `"buy"` \| `"sell"` Defined in: packages/sdk/src/unified/structs.ts:185 Taker direction on this tradable's book; undefined when unresolved. *** ### txHash? > `optional` **txHash?**: `string` Defined in: packages/sdk/src/unified/structs.ts:187 Tx hash the fill landed in, when known. *** ### timestamp > **timestamp**: `number` Defined in: packages/sdk/src/unified/structs.ts:189 Fill block timestamp (ms). *** ### datetime > **datetime**: `string` Defined in: packages/sdk/src/unified/structs.ts:191 ISO-8601 of `timestamp`. *** ### info > **info**: `unknown` Defined in: packages/sdk/src/unified/structs.ts:193 The native fill row (raw units, maker/taker addresses). --- # /docs/typescript/api/index/interfaces/UnlinkPerpWalletParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnlinkPerpWalletParams # Interface: UnlinkPerpWalletParams Defined in: packages/sdk/src/trade.ts:1132 Inputs to [Trader.unlinkPerpWallet](Trader.md#unlinkperpwallet) — dissolve an accepted link. Works from either end: pass the OTHER party and the registry resolves which side is the main. ## Extends - [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md) ## Properties ### registry? > `optional` **registry?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1070 The LinkedWalletRegistry. Skips resolution entirely. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`registry`](PerpWalletLinkTarget.md#registry) *** ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1072 MarginBank address — its `getLinkedWalletRegistry()` is read (never cached). #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`marginBank`](PerpWalletLinkTarget.md#marginbank) *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1074 A PerpPool — its `marginBank()` is read (and cached), then the registry. #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`pool`](PerpWalletLinkTarget.md#pool) *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1080 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) #### Inherited from [`PerpWalletLinkTarget`](PerpWalletLinkTarget.md).[`gas`](PerpWalletLinkTarget.md#gas) *** ### counterparty > **counterparty**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1134 The other party to the link — the signer's main, or one of its children. --- # /docs/typescript/api/index/interfaces/UnsignedAccountCreation [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnsignedAccountCreation # Interface: UnsignedAccountCreation Defined in: packages/sdk/src/smartAccounts.ts:66 An account-creation call with the gas it needs. Safe's `setup` runs nested, so EIP-150 makes creation need a floor of gas REMAINING that no estimate of gas spent supplies — send it as `executor.execute([call], { gas })`. ## Properties ### call > `readonly` **call**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/smartAccounts.ts:68 The creation call, aimed at the factory. Any funded actor may send it. *** ### gas > `readonly` **gas**: `bigint` Defined in: packages/sdk/src/smartAccounts.ts:70 The gas the transaction must carry. Not an estimate — a floor the accounts SDK measured. --- # /docs/typescript/api/index/interfaces/UnsignedCall [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnsignedCall # Interface: UnsignedCall Defined in: packages/sdk/src/writer.ts:155 One unsigned call, ready for any signer: spread into viem's `sendTransaction`, wrap as an ERC-4337 UserOp call field, or hand to a relayer. Deliberately minimal, following `BridgeTransaction` in the `/chains` bridge module: no nonce, no fees, no gas — those are the signer's job, and pinning them here would stale the moment the call is cached. `description` is a human label for a confirmation UI. `chainId` names the chain the call must be executed on. An exchange that spans several chains hands back calls for markets on any of them, and an [Executor](Executor.md) bound to another chain refuses a call whose `chainId` is not its own. Note `value` is a `bigint`, so `JSON.stringify` throws on it — convert it yourself if the call crosses a serialization boundary. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/writer.ts:157 Numeric chain id the call must be sent on. *** ### to > **to**: `` `0x${string}` `` Defined in: packages/sdk/src/writer.ts:159 Contract to call. *** ### data > **data**: `` `0x${string}` `` Defined in: packages/sdk/src/writer.ts:161 ABI-encoded calldata. *** ### value > **value**: `bigint` Defined in: packages/sdk/src/writer.ts:163 Native value to attach, in wei. `0n` unless the call pays native. *** ### description > **description**: `string` Defined in: packages/sdk/src/writer.ts:165 What this call does, for a UI to label a confirmation with. *** ### functionName? > `optional` **functionName?**: `string` Defined in: packages/sdk/src/writer.ts:172 The contract function the calldata encodes (`"approve"`, `"placeOrder"`, …), for error messages: an executor names it in the revert it raises for THIS call. Set on every call the SDK builds; optional so a call assembled by hand still executes. --- # /docs/typescript/api/index/interfaces/UnsignedMarginDeposit [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnsignedMarginDeposit # Interface: UnsignedMarginDeposit Defined in: packages/sdk/src/perp/margin.ts:1433 A MarginBank deposit expanded into the unsigned calls it actually takes. Two or one: the bank pulls the collateral, so it needs an ERC-20 allowance first — unless `autoApprove: false` says the caller manages that themselves. ## Properties ### deposit > **deposit**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/perp/margin.ts:1435 The `deposit` call itself. *** ### approval? > `optional` **approval?**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/perp/margin.ts:1437 The ERC-20 approval the bank needs first; absent when `autoApprove: false`. --- # /docs/typescript/api/index/interfaces/UnsignedOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnsignedOrder # Interface: UnsignedOrder Defined in: packages/sdk/src/writer.ts:244 A placement expanded into the unsigned calls it actually takes. Two or one: a placement that escrows an ERC-20 (or outcome tokens) needs an approval before the order call, while a native-base sell and every perp placement need only the order. `approval` is simply absent when there is nothing to approve — branching on it narrows: **Example** (Sending an unsigned order) ```ts const { order, approval } = await trader.buildPlaceOrder(params); if (approval) await walletClient.sendTransaction({ ...approval, account }); await walletClient.sendTransaction({ ...order, account }); ``` The approval is RETURNED, never sent — unlike `placeOrder`, which sends it as a side effect. A caller who skips a needed approval gets an on-chain revert, so check `approval` rather than assuming it is handled. `approval` is present whenever the placement escrows something, without checking the current allowance (that check is an `eth_call`, which a build-only verb should not make) — so it may be redundant, never short: it approves `maxUint256`, as the send path does. (A token that demands its allowance be zeroed before being re-set would reject that, same as on the send path.) Pass `autoApprove: false` to drop it and skip the escrow lookup. ## Properties ### order > **order**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/writer.ts:246 The placement call itself. *** ### approval? > `optional` **approval?**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/writer.ts:248 The approval the placement needs first; absent when nothing needs approving. --- # /docs/typescript/api/index/interfaces/UnsignedPerpStopOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnsignedPerpStopOrder # Interface: UnsignedPerpStopOrder Defined in: packages/sdk/src/perp/stops.ts:957 A perp stop placement expanded into the unsigned calls it actually takes. Two or one, and the difference matters more here than for a token approval: the registry places on the owner's behalf, so without the operator grant the trigger reverts **and the prepaid SOMI is consumed having placed nothing**. Batch both. ## Properties ### stopOrder > **stopOrder**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/perp/stops.ts:959 The registry call that creates the stop — or, for a `pair`, both legs at once. *** ### operatorApproval? > `optional` **operatorApproval?**: [`UnsignedCall`](UnsignedCall.md) Defined in: packages/sdk/src/perp/stops.ts:964 The one-time operator grant the trigger needs first; absent only when `skipOperatorApproval: true` was passed. --- # /docs/typescript/api/index/interfaces/UpdateOperatorParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UpdateOperatorParams # Interface: UpdateOperatorParams Defined in: packages/sdk/src/operatorAdmin.ts:123 Params for [OperatorAdmin.updateOperator](OperatorAdmin.md#updateoperator). Every mutable field is replaced — pass the full desired state, not a delta. ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:125 The operator to update. Caller must be its owner. *** ### feeRecipient > **feeRecipient**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:127 New default recipient of the operator's venue fees. *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:129 New enabled flag (the operator-wide kill switch). *** ### policy > **policy**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:131 New IVenuePolicy address; zero clears the operator-wide gate. *** ### context? > `optional` **context?**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:133 Opaque metadata bytes; replaces the prior value (empty `0x` clears it). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:135 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/UpdateVenueParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UpdateVenueParams # Interface: UpdateVenueParams Defined in: packages/sdk/src/operatorAdmin.ts:212 Params for [OperatorAdmin.updateVenue](OperatorAdmin.md#updatevenue). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:214 The operator owning the venue. Caller must be its owner. *** ### venueId > **venueId**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:216 The venue to update (within the operator). *** ### config > **config**: [`VenueConfigInput`](VenueConfigInput.md) Defined in: packages/sdk/src/operatorAdmin.ts:221 Replacement config — the full desired state, not a delta. `marketType` stays whatever it was at creation. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:223 Gas ceiling for this tx; overrides the config default. --- # /docs/typescript/api/index/interfaces/ValidAnswersInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ValidAnswersInput # Interface: ValidAnswersInput Defined in: packages/sdk/src/oracleHub.ts:94 The set of valid answers a question may resolve to. ## Properties ### answerType > **answerType**: `number` Defined in: packages/sdk/src/oracleHub.ts:96 [ANSWER\_TYPE](../variables/ANSWER_TYPE.md) value (uint8 on the wire). *** ### discreteOutcomes > **discreteOutcomes**: `string`[] Defined in: packages/sdk/src/oracleHub.ts:98 Outcome labels for a Discrete question; empty for Numeric. *** ### numericIntervals > **numericIntervals**: [`QuestionIntervalInput`](QuestionIntervalInput.md)[] Defined in: packages/sdk/src/oracleHub.ts:100 Value buckets for a Numeric question (one outcome slot each); empty for Discrete. *** ### numericDecimals > **numericDecimals**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:102 Fixed-point decimals the numeric answer and interval bounds are scaled by. --- # /docs/typescript/api/index/interfaces/VenueConfigInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VenueConfigInput # Interface: VenueConfigInput Defined in: packages/sdk/src/operatorAdmin.ts:58 A venue's mutable config (mirror of MarketsCore's `VenueConfig` input tuple) — passed whole to [OperatorAdmin.createVenue](OperatorAdmin.md#createvenue) and [OperatorAdmin.updateVenue](OperatorAdmin.md#updatevenue). ## Properties ### feeParams > **feeParams**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:63 Type-specific fee parameters, abi-encoded (see `encodeBinaryVenueFeeParams` for BINARY_V1). Opaque to the registry. *** ### feeRecipientOverride > **feeRecipientOverride**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:65 Per-venue fee recipient; zero falls back to the operator's default. *** ### policy > **policy**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:71 IVenuePolicy address; zero means no per-venue gate (the operator-wide policy still applies). Creation needs SOME create-side policy set — point this at the deployed OpenPolicy to make the venue open. *** ### signer > **signer**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:73 EIP-712 signer; non-zero requires a venue-signed authorization to create. *** ### creationEnabled > **creationEnabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:78 Whether market creation on this venue is live. Trading/settlement on existing markets is unaffected. *** ### context? > `optional` **context?**: `` `0x${string}` `` Defined in: packages/sdk/src/operatorAdmin.ts:83 Opaque metadata bytes attached to the venue; the registry attaches no semantics (indexed as-is). Defaults to `0x` (empty). Capped at 4 KiB. --- # /docs/typescript/api/index/interfaces/VenuePreflightInput [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VenuePreflightInput # Interface: VenuePreflightInput Defined in: packages/sdk/src/preflight.ts:126 The venue fields the venue-step preflight inspects (subset of [IndexedVenue](../type-aliases/IndexedVenue.md)) plus whether the venue's market type is bound to a module in MarketsCore. ## Properties ### caller > **caller**: `` `0x${string}` `` Defined in: packages/sdk/src/preflight.ts:128 The connected signer — must own the venue's operator. *** ### operatorOwner > **operatorOwner**: `string` Defined in: packages/sdk/src/preflight.ts:130 The owner of the operator the venue belongs to. *** ### creationEnabled > **creationEnabled**: `boolean` Defined in: packages/sdk/src/preflight.ts:132 The venue's creation flag — off blocks new markets on the venue. *** ### moduleBound > **moduleBound**: `boolean` Defined in: packages/sdk/src/preflight.ts:137 Whether MarketsCore has a module bound for the venue's market type (`moduleOf(marketType) != 0`). --- # /docs/typescript/api/index/interfaces/VoidExpiredParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VoidExpiredParams # Interface: VoidExpiredParams Defined in: packages/sdk/src/trade.ts:1995 Permissionless dead-oracle escape hatch: void a market whose settlement window has lapsed without a resolution. ## Properties ### marketId > **marketId**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1997 bytes32 marketId to void; its market contract is resolved from the module. *** ### module? > `optional` **module?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1999 BinaryMarketsModule address; resolved from `config.addresses.binaryModule` when omitted. *** ### skipPreflight? > `optional` **skipPreflight?**: `boolean` Defined in: packages/sdk/src/trade.ts:2005 Skip the pre-send status/window check. The on-chain guards still apply — this only gives up the clearer client-side error (and its three reads). #### Default ```ts false ``` *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2011 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/VoidMarketParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VoidMarketParams # Interface: VoidMarketParams Defined in: packages/sdk/src/trade.ts:2232 Inputs to [Trader.voidMarket](Trader.md#voidmarket) — void a market via the FakeOracle (demo/dev resolver only). Each side then redeems against the payout vector the market stores: a half per side under the `UNIFORM` void policy, and `[p, D−p]` at the closing YES price on a `CLOB_SNAPSHOT` void that captured a two-sided close. ## Properties ### market > **market**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2234 BinaryMarket address to void. *** ### fakeOracle? > `optional` **fakeOracle?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:2236 FakeOracle address; defaults to the configured one. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:2242 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/WatchHandle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WatchHandle # Interface: WatchHandle Defined in: packages/sdk/src/liveTail.ts:284 A live watch. `stop()` releases it (idempotent); the underlying subscription is shared and torn down when the last handle stops. ## Methods ### stop() > **stop**(): `void` Defined in: packages/sdk/src/liveTail.ts:293 Release this handle's reference on its watch scope (idempotent — extra calls are no-ops). Handles on the same scope share one subscription; stopping the LAST one tears down the scope's local materialization after a short linger (which absorbs unmount/remount without re-snapshotting): the subscription is dropped and the market's fills/orders are purged, so `getLive*` reads for it return empty again. The market row itself is kept for list views. #### Returns `void` --- # /docs/typescript/api/index/interfaces/WatchPerpMarketsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WatchPerpMarketsOptions # Interface: WatchPerpMarketsOptions Defined in: packages/sdk/src/liveTail.ts:310 Options for [SomniaMarketsClient.watchPerpMarkets](SomniaMarketsClient.md#watchperpmarkets). ## Extended by - [`UseWatchPerpMarketsOptions`](../../react/interfaces/UseWatchPerpMarketsOptions.md) ## Properties ### marginBank? > `optional` **marginBank?**: `string` Defined in: packages/sdk/src/liveTail.ts:323 The MarginBank to read the plane's wiring from, normally UNNECESSARY: the address comes from an indexed perp market row, and `MarginBank.getSystemConfig()` reports the LiquidationEngine from there. Pass it for the one case that cannot cover — an indexer with no perp rows at all, where there is nothing to ask. It fills in wiring the plane LACKS, and only that: it is used when the indexer names no bank, including on a scope a read hook hydrated moments earlier with no hint to give. It never overrides a bank the indexer DID name — the hydrated rows are that bank's plane, so streaming another one would splice two venues into one feed — and it never switches a plane that is already streaming. --- # /docs/typescript/api/index/interfaces/WithdrawMarginParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WithdrawMarginParams # Interface: WithdrawMarginParams Defined in: packages/sdk/src/trade.ts:1038 Inputs to [Trader.withdrawMargin](Trader.md#withdrawmargin) — pull free collateral back out of the MarginBank (the bank margin-checks the withdrawal on-chain). ## Properties ### marginBank? > `optional` **marginBank?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1040 MarginBank address (from the PerpMarket row), or pass `pool` to resolve it. *** ### pool? > `optional` **pool?**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1042 A PerpPool — its `marginBank()` is read (and cached) when `marginBank` is omitted. *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1044 Collateral amount to withdraw, raw units. Must be ≤ withdrawable (margin-checked on-chain). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1050 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/WithdrawMyCreditParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WithdrawMyCreditParams # Interface: WithdrawMyCreditParams Defined in: packages/sdk/src/oracleHub.ts:416 Parameters for [OracleHubAdmin.withdrawMyCredit](OracleHubAdmin.md#withdrawmycredit). ## Properties ### amountWei > **amountWei**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:422 Wei to withdraw from the CALLER's own accrued A1 payer credit (must be ≤ `payerCreditOf(caller)`, else the hub reverts). msg.sender-gated — the connected signer draws only its own credit. *** ### to > **to**: `` `0x${string}` `` Defined in: packages/sdk/src/oracleHub.ts:424 Recipient of the native transfer. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:426 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/WithdrawParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WithdrawParams # Interface: WithdrawParams Defined in: packages/sdk/src/oracleHub.ts:397 Parameters for [OracleHubAdmin.withdraw](OracleHubAdmin.md#withdraw). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/oracleHub.ts:399 Operator whose WITHDRAWABLE credit to draw down. OWNER-gated on-chain. *** ### amountWei > **amountWei**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:404 Wei to withdraw from the operator's accrued surplus credit (must be ≤ `withdrawableOf(operatorId)`, else the hub reverts `InsufficientCredit`). *** ### to > **to**: `` `0x${string}` `` Defined in: packages/sdk/src/oracleHub.ts:406 Recipient of the native transfer. *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/oracleHub.ts:408 Gas-limit override for this tx (defaults to the admin config's `gas`). --- # /docs/typescript/api/index/interfaces/WithdrawVaultParams [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WithdrawVaultParams # Interface: WithdrawVaultParams Defined in: packages/sdk/src/trade.ts:1215 Claim a payout that fell back to a pool's internal ERC20Vault (a `PayoutFallbackToVault` credit) back to the caller's wallet. ## Properties ### vault > **vault**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1220 The ERC20Vault to withdraw from — the pool address (BinaryPool/SpotPool ARE ERC20Vaults). *** ### token > **token**: `` `0x${string}` `` Defined in: packages/sdk/src/trade.ts:1222 Token to withdraw (ERC-20 address, or the vault's native sentinel). *** ### amount > **amount**: `bigint` Defined in: packages/sdk/src/trade.ts:1227 Amount to withdraw, raw units. Must be ≤ the vault's withdrawable balance (read it with `client.getVaultBalance`). *** ### gas? > `optional` **gas?**: `bigint` Defined in: packages/sdk/src/trade.ts:1233 Gas ceiling for this tx. #### Default [TraderConfig.gas](TraderConfig.md#gas) (10,000,000) --- # /docs/typescript/api/index/interfaces/YesBookTop [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / YesBookTop # Interface: YesBookTop Defined in: packages/sdk/src/units.ts:137 Best YES bid/ask of a binary book (raw quote units), for marking a position. Either side may be absent on a one-sided book. Feed it the top level of `getBinaryOrderBook` / `getLiveBinaryOrderBook`. ## Properties ### bestBid? > `optional` **bestBid?**: `bigint` Defined in: packages/sdk/src/units.ts:139 Best resting YES bid (raw), if any. *** ### bestAsk? > `optional` **bestAsk?**: `bigint` Defined in: packages/sdk/src/units.ts:141 Best resting YES ask (raw), if any. --- # /docs/typescript/api/index/type-aliases/AccountAuthorizationTypedData [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AccountAuthorizationTypedData # Type Alias: AccountAuthorizationTypedData > **AccountAuthorizationTypedData** = `ReturnType`\<*typeof* `Accounts.accountAuthorizationTypedData`\> Defined in: packages/sdk/src/smartAccounts.ts:42 The EIP-712 payload an account authorization is signed over — what [SmartAccountsClient.buildAccountAuthorization](../interfaces/SmartAccountsClient.md#buildaccountauthorization) hands back beside the authorization itself. --- # /docs/typescript/api/index/type-aliases/AssertCallsOnChainError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / AssertCallsOnChainError # Type Alias: AssertCallsOnChainError > **AssertCallsOnChainError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/executor/guard.ts:13 Failures from [assertCallsOnChain](../functions/assertCallsOnChain.md): an empty call list, or a call that names a chain other than the executor's. --- # /docs/typescript/api/index/type-aliases/BaseMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BaseMarket # Type Alias: BaseMarket > **BaseMarket** = `object` Defined in: packages/sdk/src/markets.ts:54 Fields every market has, regardless of type. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/markets.ts:56 Primary key (lowercased): bytes32 marketId for binary, pool address for spot. *** ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/markets.ts:67 Numeric chain id the market lives on. Set on every row a [SomniaMarketsClient](../interfaces/SomniaMarketsClient.md) or the [SomniaMarkets](../classes/SomniaMarkets.md) facade returns, including rows the live tail materializes. Absent only on rows built by the internal data-first mappers, which know the indexer but not the chain; the owning client stamps it at its boundary. A market is unique to one chain, so `(chainId, id)` names it globally where `id` alone names it only on that chain. *** ### marketType > **marketType**: [`MarketType`](MarketType.md) Defined in: packages/sdk/src/markets.ts:69 Discriminator — narrow on this (or the `is*Market` guards). *** ### poolAddress > **poolAddress**: `Address` Defined in: packages/sdk/src/markets.ts:74 The pool serving this market (lowercased; == id for SPOT/PERP). For binary, a TIME-VARYING binding — see the recycle caveat on [BinaryMarket.nonce](BinaryMarket.md). *** ### lastPrice > **lastPrice**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:76 Last fill price (raw). For binary, ≈ YES probability × 10^decimals. Null until first fill. *** ### lastTradeAt > **lastTradeAt**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:78 Timestamp (unix seconds) of the last fill; null until first fill. *** ### cumulativeBaseVolume > **cumulativeBaseVolume**: `string` Defined in: packages/sdk/src/markets.ts:80 Cumulative base/outcome-token volume (raw, decimal string). *** ### cumulativeQuoteVolume > **cumulativeQuoteVolume**: `string` Defined in: packages/sdk/src/markets.ts:82 Cumulative quote/collateral volume (raw, decimal string). *** ### tradeCount > **tradeCount**: `string` Defined in: packages/sdk/src/markets.ts:84 Lifetime fill count (decimal string). *** ### baseDecimals > **baseDecimals**: `number` Defined in: packages/sdk/src/markets.ts:86 Base-token decimals (binary: outcome tokens mirror the collateral's decimals). *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/markets.ts:91 Quote-token decimals (binary: the collateral's — per-venue, e.g. 6dp TestUSDC vs 18dp USDso). Format prices/amounts with this. *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/markets.ts:93 Timestamp (unix seconds) the market was created/indexed. *** ### createdAtBlock > **createdAtBlock**: `string` Defined in: packages/sdk/src/markets.ts:102 Block the market was created in. Carried for the same reason as `resolvedAtBlock`: a market is bracketed by two reads of an off-chain feed and only a BLOCK identifies which print each one saw — a `"fixed"`-mode market's `strike` IS the feed's spot at THIS block (see [BinaryMarket.mode](BinaryMarket.md)), and that print lands before `tradingStart` far more often than on it, so `createdAtTimestamp` cannot find it. --- # /docs/typescript/api/index/type-aliases/BinaryBuySide [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryBuySide # Type Alias: BinaryBuySide > **BinaryBuySide** = `"BUY_YES"` \| `"BUY_NO"` Defined in: packages/sdk/src/derivedReads.ts:1022 The buy sides of [BinarySide](BinarySide.md) — what a stake converts into. --- # /docs/typescript/api/index/type-aliases/BinaryFillKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryFillKind # Type Alias: BinaryFillKind > **BinaryFillKind** = `"DIRECT_YES"` \| `"DIRECT_NO"` \| `"MINT_A_PAIR"` \| `"BURN_A_PAIR"` Defined in: packages/sdk/src/store.ts:60 How a binary fill settled: direct outcome trade, or a mint/burn of a YES+NO pair. --- # /docs/typescript/api/index/type-aliases/BinaryMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryMarket # Type Alias: BinaryMarket > **BinaryMarket** = [`BaseMarket`](BaseMarket.md) & `object` Defined in: packages/sdk/src/markets.ts:248 A binary (YES/NO outcome) order-book market — the binary CLOB. ## Type Declaration ### marketType > **marketType**: `"BINARY"` Discriminator (narrowed). ### marketId > **marketId**: `Hex` bytes32 marketId (== id). ### marketAddress > **marketAddress**: `Address` The BinaryMarket clone contract's address (lowercased). ### yesTokenId > **yesTokenId**: `string` This market's YES/NO position ids on the ERC-6909 outcome-token singleton, as decimal strings (the indexer stores uint256 ids as strings). ### noTokenId > **noTokenId**: `string` The NO position id — see BinaryMarket.yesTokenId. ### collateral > **collateral**: `Address` Collateral ERC-20 backing the market (lowercased; per-venue). ### asset > **asset**: `string` Underlying asset symbol (e.g. "BTC"). ### question > **question**: `string` Display question text. May differ from BinaryMarket.oracleQuestion. ### status > **status**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Lifecycle status (aliased from the indexer's `clobStatus`). Derived from lifecycle EVENTS only — the timestamp-implicit Listed→Trading→Settling transitions emit none, so derive the live trading state from `tradingStart`/`expiry` between events rather than trusting this alone. ### oracleQuestion > **oracleQuestion**: `string` \| `null` The canonical oracle question string (as registered on-chain); may differ from the display `question`. Null on markets indexed before this field. ### oracleQuestionId? > `optional` **oracleQuestionId?**: `string` \| `null` Oracle question id the market binds to (uint256 as a decimal string, from `BinaryMarketsModule.MarketCreated`). `null` when discovered via the realtime tail or indexed before this field (filled on the next snapshot). ### strike > **strike**: `string` \| `null` Strike the question resolves against (raw, in the oracle's price scale). `null` on a market the SDK has only ever seen on chain — a chain-seeded watch (`watchMarket(pool, { seed: "chain" })`), whose pool contract does not carry the strike. It is unknown, not 0: 0 is the protocol's sentinel for reference mode, so serving it would relabel a fixed-strike market as up/down. An indexer-sourced row always carries it. ### mode > **mode**: [`BinaryResolutionMode`](BinaryResolutionMode.md) \| `null` How this market's threshold is established — the distinction every consumer of a binary market eventually needs, served rather than sniffed. - `"reference"` — an up/down market. `strike` is 0 because the threshold IS another question's answer ("ETH closes at or above its opening price"), reached through `MarketReferenceLink` → `OracleAnswer`. Read it with `getOpeningPrices` / `getMarketResolution().openingAnswer`. - `"fixed"` — the threshold was set at creation ("at or above 77036.65") and is `strike` itself. There is no reference question, so an opening price does not exist and never will. Derived from `strike` alone (see [binaryResolutionMode](../functions/binaryResolutionMode.md)), so it costs no extra query. Before it existed consumers inferred the mode from a LOOKUP MISS — "no opening answer, so it must be fixed-strike" — which conflates "no reference question" with "the reference question has not been answered yet". That reads as working code right up until an oracle is slow. `null` when `strike` is — a chain-seeded market row, where the mode is genuinely unknown rather than `"reference"`. ### tradingStart > **tradingStart**: `string` Timestamp (unix seconds) trading opens. ### expiry > **expiry**: `string` Timestamp (unix seconds) trading ends and the outcome is decided. ### winningOutcome > **winningOutcome**: `number` \| `null` Winning outcome (0 = YES, 1 = NO) — DERIVED by the indexer from a one-hot payout vector (Oracle v2 resolves with vectors; a one-hot vector has a unique winner). Null until Resolved and on non-one-hot (void/partial) vectors — the binary-compat field, kept alongside the vector below. ### payoutNumerators? > `optional` **payoutNumerators?**: `string`[] \| `null` Per-outcome payout numerators the market settled to (Oracle v2 vector resolution; uint256s as decimal strings — one-hot on a win; on a void, the vector the frozen void policy produced: uniform under `UNIFORM`, and `[p, D−p]` at the closing YES price on a `CLOB_SNAPSHOT` void that captured a two-sided close. Raw Σ == payoutDenominator). This vector, not BinaryMarket.voidPolicy, is what a void actually pays: every snapshot fallback stores the uniform vector. Null until Resolved / on markets indexed before the vector fields existed. ### payoutDenominator? > `optional` **payoutDenominator?**: `string` \| `null` Denominator the numerators are scaled against (`PAYOUT_VECTOR_DENOMINATOR` = 10_000_000; decimal string). Null until Resolved. ### resolvedAtBlock > **resolvedAtBlock**: `string` \| `null` Block the market resolved at; null until Resolved. ### resolvedAtTimestamp > **resolvedAtTimestamp**: `string` \| `null` Timestamp (unix seconds) the market resolved at; null until Resolved. ### createdByTx > **createdByTx**: `Hex` \| `null` Tx hash the market was created in; null on markets indexed before this field. ### creator? > `optional` **creator?**: `Address` \| `null` Wallet that invoked createMarket (lowercased, from `BinaryMarketsModule.MarketCreated`). `null` when discovered via the realtime tail or indexed before this field (filled on the next snapshot). ### voided > **voided**: `boolean` True once the market voided (payout per the frozen void policy; `payoutNumerators` carries the actual vector). ### voidPolicy? > `optional` **voidPolicy?**: `number` \| `null` Void payout policy frozen at creation (from `BinaryMarketsModule.MarketCreated`): 0 UNIFORM (both sides redeem 1/N on a void), 2 CLOB_SNAPSHOT (a void pays `[p, D-p]` at the market's closing YES price; falls back to uniform when no two-sided close exists). `null` on pre-policy markets or tail-discovered rows. ### backing > **backing**: `string` Collateral backing complete sets on the LIVE pool (raw). Reads 0 once finalized — prefer BinaryMarket.netBacking after finalize. ### nonce? > `optional` **nonce?**: `string` \| `null` The pool's market nonce this market is bound to (settlement-extraction v2). A pool serves successive markets; `(poolAddress, nonce)` disambiguates them and encodes the outcome ids. `null` on markets indexed before v2 / discovered via a live event that doesn't carry it (filled on the next snapshot). RECYCLE CAVEAT: `poolAddress` is a TIME-VARYING 1:1 binding — the same pool address serves different markets over time (never concurrently). Always key a market by `marketId`, never by `poolAddress` alone; use `nonce` to tell which of a pool's markets a given outcome id belongs to. ### finalized? > `optional` **finalized?**: `boolean` \| `null` Whether this market's backing has been finalized onto the BinarySettlement singleton (settlement-extraction v2). True once `finalizeMarket` swept the pool's backing over; redemption is served by settlement thereafter. `null` when unknown (pre-v2 / not yet snapshotted). ### netBacking? > `optional` **netBacking?**: `string` \| `null` The NET collateral backing recorded on the settlement singleton after finalize (post fee-skim on resolution; gross on void), decimal string. This is the authoritative post-finalize backing: `BinaryMarket.backing()` reads 0 once finalized, so redemption UIs should prefer `netBacking` when set. `null` until finalize / on pre-v2 markets. ### context? > `optional` **context?**: `Hex` \| `null` Opaque creator-supplied metadata bytes (hex, 0x-prefixed; '0x' when empty). The chain attaches no semantics — off-chain data only. Set once at creation. `null` on non-binary markets / markets indexed before this field existed. ### intervalSec? > `optional` **intervalSec?**: `string` \| `null` Series cadence in seconds (60=1m, 300=5m, 900=15m, 3600=1h, 14400=4h, 86400=24h) — APPROXIMATE, see [BinaryMarketFilter.intervalSec](BinaryMarketFilter.md#intervalsec). DERIVED by the indexer from the market's own window (`expiry − tradingStart`) — a series' FIRST market is a bootstrap partial whose window is shorter than the steady-state cadence. `null` on SPOT / PERP. ### interval? > `optional` **interval?**: `string` \| `null` Human timeframe label for this series — `"1m"` / `"5m"` / `"15m"` / `"1h"` / `"4h"` / `"24h"` — DERIVED by the SDK from BinaryMarket.intervalSec (falling back to `expiry − tradingStart`) and snapped to its [CADENCE\_LADDER\_SEC](../variables/CADENCE_LADDER_SEC.md) rung, so a roll that opened late reads as the cadence it belongs to rather than as its own (`56` → `"1m"`, not `"56s"`). A window matching no rung keeps its own value. Served ready-to-render so consumers stop re-deriving it; see [marketIntervalLabel](../functions/marketIntervalLabel.md). `null` on SPOT / PERP or when no cadence is determinable. ### operatorId? > `optional` **operatorId?**: `number` \| `null` Origin operator id the market was created under (from `BinaryMarketsModule.MarketCreated`). `null` when discovered via the realtime tail (filled on the next snapshot). ### venueId? > `optional` **venueId?**: `Hex` \| `null` Origin venue id within the operator, contract-generated opaque bytes32 hex. `null` when discovered via the realtime tail (filled on the next snapshot — the live `MarketCreator.MarketCreated` event doesn't carry it). --- # /docs/typescript/api/index/type-aliases/BinaryMarketCountOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryMarketCountOptions # Type Alias: BinaryMarketCountOptions > **BinaryMarketCountOptions** = [`BinaryMarketFilter`](BinaryMarketFilter.md) & `object` Defined in: packages/sdk/src/markets.ts:1181 Options for `countBinaryMarkets` / `countBinaryMarketsBounded` — the [BinaryMarketFilter](BinaryMarketFilter.md) plus an optional lifecycle phase and a `now` override. ## Type Declaration ### phase? > `optional` **phase?**: `"live"` \| `"past"` Lifecycle phase to count: `"live"` = `expiry > now`, `"past"` = `expiry <= now`. OMITTED counts across both — every binary market the filter matches, whatever its expiry. Omit it for a count keyed on something other than expiry, such as [BinaryMarketFilter.resolvedSince](BinaryMarketFilter.md#resolvedsince), so an early void is not dropped by a phase it is not in yet. ### nowSec? > `optional` **nowSec?**: `number` Override "now" (unix seconds) for the phase cut; defaults to `Date.now()`. --- # /docs/typescript/api/index/type-aliases/BinaryMarketFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryMarketFilter # Type Alias: BinaryMarketFilter > **BinaryMarketFilter** = `object` Defined in: packages/sdk/src/markets.ts:848 Filters shared by the binary-market list queries (`listBinaryMarkets`, `listLiveBinaryMarkets`, `listPastBinaryMarkets`). Every field is optional; an omitted field does NOT constrain the query. Applied server-side (Hasura `where`), so `venueId` / `intervalSec` hit their indexes. ## Properties ### operatorId? > `optional` **operatorId?**: `number` Defined in: packages/sdk/src/markets.ts:850 Origin operator id (from `BinaryMarketsModule.MarketCreated`). *** ### venueId? > `optional` **venueId?**: `string` Defined in: packages/sdk/src/markets.ts:852 Origin venue id within the operator (contract-generated bytes32 hex). *** ### asset? > `optional` **asset?**: `string` Defined in: packages/sdk/src/markets.ts:854 Underlying asset symbol, e.g. `"BTC"` | `"ETH"`. *** ### intervalSec? > `optional` **intervalSec?**: `number` Defined in: packages/sdk/src/markets.ts:864 Series cadence in seconds — a rung of [CADENCE\_LADDER\_SEC](../variables/CADENCE_LADDER_SEC.md): `60` (1m) | `300` (5m) | `900` (15m) | `3600` (1h) | `14400` (4h) | `86400` (24h). Matched as a BAND of ± [CADENCE\_TOLERANCE\_SEC](../variables/CADENCE_TOLERANCE_SEC.md), not exactly: a rolled market's indexed window is `expiry − tradingStart` and trading routinely opens a second or two late, so a 15m series is indexed at 898s and 899s as well as 900s. Passing `900` returns all three. *** ### status? > `optional` **status?**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Defined in: packages/sdk/src/markets.ts:869 Lifecycle status — `"Trading"` is active; `"Locked"` / `"Settling"` / `"Resolved"` / `"Voided"` are the not-active states. *** ### resolved? > `optional` **resolved?**: `boolean` Defined in: packages/sdk/src/markets.ts:885 Whether a TERMINAL event is indexed for the market — `false` narrows to markets with no indexed terminal event yet, `true` to markets with one. Omitted does not constrain. Server-side on `resolvedAtTimestamp`, which every terminal path writes. Resolution and void both stamp it, on the module event and on the market contract's own; `voidExpired()` stamps it too even when no oracle answer arrived. That is why this is a separate facet rather than a [BinaryMarketFilter.status](#status) value — `status` is derived from lifecycle EVENTS, and the timestamp-implicit Listed→Trading→Settling transitions emit none, so a market whose oracle never answers stays indexed as `"Trading"` forever. Filtering an unanswered market by status therefore finds nothing; filtering by this finds it. *** ### voided? > `optional` **voided?**: `boolean` Defined in: packages/sdk/src/markets.ts:900 Whether the market settled by VOID — `true` narrows to voided markets, `false` to every other market, settled or not. Omitted does not constrain. Server-side on `Market.voided`, the explicit flag every void path writes: the oracle's void answer delivered through the module, the market's own `voidMarket()`, and the permissionless `voidExpired()` backstop. Prefer it to `status: "Voided"` for the question "did this market void" — `status` is the event-derived lifecycle state, while this flag is written on the void itself and never cleared. With [BinaryMarketFilter.resolvedSince](#resolvedsince) it counts the voids inside a window: the numerator of a void rate. *** ### resolvedSince? > `optional` **resolvedSince?**: `number` \| `bigint` Defined in: packages/sdk/src/markets.ts:920 Lower bound, in unix seconds and inclusive, on when the market reached its terminal state: `resolvedAtTimestamp >= resolvedSince`. Omitted does not constrain. Takes either encoding, like `binaryResolutionMode` does: a `bigint` carried straight from a chain read or an indexed row, or a `number` derived from the clock. The value is sent to Hasura verbatim as a decimal string, so neither encoding is rounded on the way. Server-side on the same `resolvedAtTimestamp` column as [BinaryMarketFilter.resolved](#resolved), so it implies `resolved: true` — a market with no terminal event has no timestamp to compare and never matches. `resolved: false` beside it selects nothing. A bound on the TERMINAL timestamp, not on `expiry`, and the difference matters for a window: the protocol permits a void before expiry, so a window keyed on `expiry` misses exactly the early voids a void-rate monitor exists to count. `countBinaryMarkets` with `resolvedSince` and no `phase` counts every market that settled inside the window, whatever its expiry. *** ### search? > `optional` **search?**: `string` Defined in: packages/sdk/src/markets.ts:926 Free-text needle matched (case-insensitive) against the asset symbol and the question text. Server-side (`_ilike`), AND-combined with the other facets so it narrows within them. *** ### creator? > `optional` **creator?**: `string` Defined in: packages/sdk/src/markets.ts:931 Wallet that invoked createMarket (from `BinaryMarketsModule.MarketCreated`). Case-insensitive (lowercased server-side). *** ### orderBy? > `optional` **orderBy?**: [`BinaryMarketOrderBy`](BinaryMarketOrderBy.md) Defined in: packages/sdk/src/markets.ts:938 Server-side sort (Hasura `order_by`). `"newest"` → createdAtTimestamp desc; `"closingSoon"` → expiry asc; `"volume"` → cumulativeQuoteVolume desc; `"tradeCount"` → tradeCount desc. Omitted → each list keeps its own default (`listBinaryMarkets` newest-first; `listLiveBinaryMarkets` closingSoon). --- # /docs/typescript/api/index/type-aliases/BinaryMarketOrderBy [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryMarketOrderBy # Type Alias: BinaryMarketOrderBy > **BinaryMarketOrderBy** = `"newest"` \| `"closingSoon"` \| `"volume"` \| `"tradeCount"` Defined in: packages/sdk/src/markets.ts:946 Sort keys for the binary-market list queries — see [BinaryMarketFilter.orderBy](BinaryMarketFilter.md#orderby). --- # /docs/typescript/api/index/type-aliases/BinaryMarketStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryMarketStatus # Type Alias: BinaryMarketStatus > **BinaryMarketStatus** = `"Listed"` \| `"Trading"` \| `"Locked"` \| `"Settling"` \| `"Resolved"` \| `"Voided"` \| `"Finalized"` Defined in: packages/sdk/src/store.ts:78 Binary-market lifecycle (mirror of the indexer's `ClobMarketStatus` enum). The first six mirror the on-chain `MarketStatus` enum; `"Finalized"` is an INDEXER-DERIVED terminal state (no on-chain enum member) set when the market's backing + resolution snapshot are swept to the BinarySettlement singleton — it supersedes Resolved/Voided once finalize lands, and redemptions are served by settlement thereafter. --- # /docs/typescript/api/index/type-aliases/BinaryResolutionMode [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinaryResolutionMode # Type Alias: BinaryResolutionMode > **BinaryResolutionMode** = `"reference"` \| `"fixed"` Defined in: packages/sdk/src/markets.ts:817 How a binary market's threshold is established. See [BinaryMarket.mode](BinaryMarket.md). Not a chain enum — it is a reading of `strike`, whose 0 is the protocol's own sentinel for "this market resolves against another question's answer". --- # /docs/typescript/api/index/type-aliases/BinarySellSide [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinarySellSide # Type Alias: BinarySellSide > **BinarySellSide** = `"SELL_YES"` \| `"SELL_NO"` Defined in: packages/sdk/src/derivedReads.ts:1029 The sell sides of [BinarySide](BinarySide.md) — what unwinds a position. --- # /docs/typescript/api/index/type-aliases/BinarySide [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BinarySide # Type Alias: BinarySide > **BinarySide** = `"BUY_YES"` \| `"SELL_YES"` \| `"BUY_NO"` \| `"SELL_NO"` Defined in: packages/sdk/src/store.ts:54 A side on a binary book: buy/sell the YES or NO outcome token. --- # /docs/typescript/api/index/type-aliases/BlockActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockActivity # Type Alias: BlockActivity > **BlockActivity** = `object` Defined in: packages/sdk/src/activity.ts:657 Everything the protocol traded in one block, grouped by market. ## Properties ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/activity.ts:659 The block, as the caller asked for it. *** ### timestamp > **timestamp**: `bigint` Defined in: packages/sdk/src/activity.ts:661 The block timestamp the reads were anchored on (unix seconds). *** ### markets > **markets**: [`BlockMarketActivity`](BlockMarketActivity.md)[] Defined in: packages/sdk/src/activity.ts:666 The markets this block touched, in descending order of activity. EMPTY is the normal case: most blocks contain no markets activity at all. *** ### marketsById > **marketsById**: `Record`\<`string`, [`Market`](Market.md)\> Defined in: packages/sdk/src/activity.ts:671 Market rows for every id in `markets`, keyed by lowercased id — so a caller can NAME each group without a lookup per group. *** ### truncated > **truncated**: `boolean` Defined in: packages/sdk/src/activity.ts:680 True when a stream came back exactly `limit` rows and the block may hold more. A block's activity is not a bounded set — a busy block can outrun any page — so the cap is reported rather than hidden. Page with `offset` while this is true; see [BlockActivityOptions](BlockActivityOptions.md). --- # /docs/typescript/api/index/type-aliases/BlockActivityOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockActivityOptions # Type Alias: BlockActivityOptions > **BlockActivityOptions** = `object` Defined in: packages/sdk/src/activity.ts:683 ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/activity.ts:685 Max rows per stream (default 500). *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/activity.ts:693 Rows to skip per stream (default 0). Paging is PER STREAM, not over the grouped result: the three streams are independent reads and a page of one does not line up with a page of another. Use it to walk a block that reports `truncated`. --- # /docs/typescript/api/index/type-aliases/BlockMarketActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockMarketActivity # Type Alias: BlockMarketActivity > **BlockMarketActivity** = `object` Defined in: packages/sdk/src/activity.ts:643 One market's slice of a block. ## Properties ### market > **market**: `string` Defined in: packages/sdk/src/activity.ts:645 Lowercased market id. *** ### fills > **fills**: [`MarketTradeActivity`](MarketTradeActivity.md)[] Defined in: packages/sdk/src/activity.ts:647 Trades matched on this market in this block, in log order. *** ### placed > **placed**: [`BlockOrder`](BlockOrder.md)[] Defined in: packages/sdk/src/activity.ts:649 Orders placed on this market in this block. *** ### touched > **touched**: [`BlockOrder`](BlockOrder.md)[] Defined in: packages/sdk/src/activity.ts:651 Resting orders this block filled or removed. --- # /docs/typescript/api/index/type-aliases/BlockOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockOrder # Type Alias: BlockOrder > **BlockOrder** = `object` Defined in: packages/sdk/src/activity.ts:609 An order event that happened in one block. Deliberately carries NO `status`, `filledQuantity` or `quantityRemaining`. `Order` is a mutable row — those three columns are as-of-now, not as-of-this block — so the query does not select them and this type cannot leak them into a historical view. The block's own traded quantity comes from `fills`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/activity.ts:611 Indexer row id. *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/activity.ts:613 On-chain order id (decimal string). *** ### market > **market**: `string` Defined in: packages/sdk/src/activity.ts:615 Lowercased market id. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/activity.ts:617 Order owner. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/activity.ts:618 *** ### side > **side**: [`BinarySide`](BinarySide.md) \| `null` Defined in: packages/sdk/src/activity.ts:619 *** ### price > **price**: `string` Defined in: packages/sdk/src/activity.ts:621 Raw quote units per whole base. *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/activity.ts:623 Raw base units the order was placed for. *** ### placedAtBlock > **placedAtBlock**: `bigint` Defined in: packages/sdk/src/activity.ts:629 Block the order was PLACED in. Equal to the viewed block for a `placed` row; earlier than it for most `touched` rows, since a resting order is usually quoted in one block and removed in another. *** ### placedTxHash > **placedTxHash**: `string` Defined in: packages/sdk/src/activity.ts:631 Transaction that placed the order. *** ### cancelReason > **cancelReason**: `string` \| `null` Defined in: packages/sdk/src/activity.ts:637 Why the protocol removed the order, when the protocol (not the owner) did. Null for an owner cancel and for an order that was never cancelled — so a null here does NOT mean "still open". *** ### touch > **touch**: [`BlockOrderTouch`](BlockOrderTouch.md) \| `null` Defined in: packages/sdk/src/activity.ts:639 Set on `touched` rows only; null on `placed` rows. --- # /docs/typescript/api/index/type-aliases/BlockOrderTouch [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockOrderTouch # Type Alias: BlockOrderTouch > **BlockOrderTouch** = `"FILLED"` \| `"REMOVED"` Defined in: packages/sdk/src/activity.ts:599 How a resting order was touched IN the block being viewed. DERIVED from the block's own fills, never read off `Order.status`: status is the row's CURRENT value, so an order placed in this block and cancelled three blocks later reads `Cancelled` here — a state from this block's future. See [BlockOrder](BlockOrder.md). - `FILLED` — the order is a maker or taker of a fill in this block. - `REMOVED` — it is not, so this block cancelled or amended it. --- # /docs/typescript/api/index/type-aliases/BlockTimestampResolver [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BlockTimestampResolver # Type Alias: BlockTimestampResolver > **BlockTimestampResolver** = (`blockNumber`) => `Promise`\<`bigint`\> Defined in: packages/sdk/src/activity.ts:586 Reads a block's timestamp from the chain. The block-scoped reads need an anchor the indexer can serve from — no block column is indexed — and the block's own timestamp is it. This module stays indexer-only, so the owner injects the one chain read it needs rather than the module reaching for a transport of its own. ## Parameters ### blockNumber `bigint` ## Returns `Promise`\<`bigint`\> --- # /docs/typescript/api/index/type-aliases/BookTop [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BookTop # Type Alias: BookTop > **BookTop** = `object` Defined in: packages/sdk/src/orders.ts:482 Top of one market's resting book — ANY market kind. Prices are RAW and in that market's own terms: quote units per whole base on SPOT and PERP, YES probability on BINARY (there, the same scale as `BinaryMarket.lastPrice`). Comparable within a market, never across kinds or against another market's quote asset. `mid` is (bestBid + bestAsk) / 2, null unless BOTH sides rest — a one-sided book has no meaningful mid. ## Properties ### bestBid > **bestBid**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:484 Best (highest) resting bid price (raw); null when no bid rests. *** ### bestAsk > **bestAsk**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:486 Best (lowest) resting ask price (raw); null when no ask rests. *** ### mid > **mid**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:488 (bestBid + bestAsk) / 2, floored (raw); null unless BOTH sides rest. --- # /docs/typescript/api/index/type-aliases/BuilderApproval [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BuilderApproval # Type Alias: BuilderApproval > **BuilderApproval** = `object` Defined in: packages/sdk/src/fees.ts:222 A user→builder fee approval (mirror of the indexer `BuilderApproval` entity) — the directory counterpart to the on-chain point read `client.getBuilderApproval`. `maxFeeBpsTimes1k` is the pool bps×1000 cap. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fees.ts:224 Approval id (`${market}_${user}_${builder}` — one row per triple, upserted). *** ### market > **market**: `string` Defined in: packages/sdk/src/fees.ts:226 Market id the approval applies to (lowercased). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/fees.ts:228 Pool hosting that market's book (lowercased; joined via the market row). *** ### user > **user**: `string` Defined in: packages/sdk/src/fees.ts:230 Granting user (lowercased). *** ### builder > **builder**: `string` Defined in: packages/sdk/src/fees.ts:232 Approved builder/routing frontend (lowercased). *** ### maxFeeBpsTimes1k > **maxFeeBpsTimes1k**: `string` Defined in: packages/sdk/src/fees.ts:234 Max per-order builder fee the user approved (pool bps×1000; 0 = revoked). *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/fees.ts:236 Block of the last BuilderApproved upsert (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/fees.ts:238 Timestamp (unix seconds) of the last BuilderApproved upsert. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/fees.ts:240 Tx hash of the last BuilderApproved upsert. --- # /docs/typescript/api/index/type-aliases/BuilderFeeRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / BuilderFeeRecord # Type Alias: BuilderFeeRecord > **BuilderFeeRecord** = `object` Defined in: packages/sdk/src/fees.ts:61 A realized builder/routing-fee record (mirror of the indexer `BuilderFeeRecord` entity). Amounts are raw collateral units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fees.ts:63 Record id (`${blockNumber}_${logIndex}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/fees.ts:65 uint128 OrderId the fee was charged on (decimal string). *** ### builder > **builder**: `string` Defined in: packages/sdk/src/fees.ts:67 Builder/routing frontend that received the fee (lowercased). *** ### payer > **payer**: `string` \| `null` Defined in: packages/sdk/src/fees.ts:69 Order owner who paid the fee (lowercased); null on pre-payer records. *** ### token > **token**: `string` Defined in: packages/sdk/src/fees.ts:71 Fee token (lowercased). *** ### amount > **amount**: `string` Defined in: packages/sdk/src/fees.ts:73 Fee routed to the builder (raw collateral units). *** ### market > **market**: `string` \| `null` Defined in: packages/sdk/src/fees.ts:75 Market id the fee's pool belongs to (lowercased); null when unlinked. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/fees.ts:77 Pool the fee was charged on (lowercased). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/fees.ts:79 Timestamp (unix seconds) the fee was charged. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/fees.ts:81 Tx hash the charge landed in. --- # /docs/typescript/api/index/type-aliases/CancelAllOrdersResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CancelAllOrdersResult # Type Alias: CancelAllOrdersResult > **CancelAllOrdersResult** = [`CancelAllOrdersEmpty`](../interfaces/CancelAllOrdersEmpty.md) \| [`CancelAllOrdersSent`](../interfaces/CancelAllOrdersSent.md) Defined in: packages/sdk/src/trade.ts:765 Result of [Trader.cancelAllOrders](../interfaces/Trader.md#cancelallorders). Branch on `sent`: `false` means nothing was resting and no transaction went out. --- # /docs/typescript/api/index/type-aliases/Candle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Candle # Type Alias: Candle > **Candle** = `object` Defined in: packages/sdk/src/candles.ts:22 One OHLCV candle (mirror of the indexer `Candle` entity). Candles exist for ANY pool — spot or binary — so this is unprefixed, not binary-specific. Prices are raw quote units per whole base (binary: the YES-probability scale, same as `lastPrice`); volumes are raw. ## Properties ### bucketStart > **bucketStart**: `string` Defined in: packages/sdk/src/candles.ts:24 Bucket-open timestamp (unix seconds), aligned to the interval. *** ### openPrice > **openPrice**: `string` Defined in: packages/sdk/src/candles.ts:26 First fill price in the bucket (raw). *** ### high > **high**: `string` Defined in: packages/sdk/src/candles.ts:28 Highest fill price in the bucket (raw). *** ### low > **low**: `string` Defined in: packages/sdk/src/candles.ts:30 Lowest fill price in the bucket (raw). *** ### closePrice > **closePrice**: `string` Defined in: packages/sdk/src/candles.ts:32 Last fill price in the bucket (raw). *** ### baseVolume > **baseVolume**: `string` Defined in: packages/sdk/src/candles.ts:34 Base/outcome-token volume in the bucket (raw). *** ### quoteVolume > **quoteVolume**: `string` Defined in: packages/sdk/src/candles.ts:36 Quote/collateral volume in the bucket (raw). *** ### tradeCount > **tradeCount**: `number` Defined in: packages/sdk/src/candles.ts:38 Number of fills in the bucket. *** ### lastFillId > **lastFillId**: `string` Defined in: packages/sdk/src/candles.ts:40 Newest fill id in the bucket (`${blockNumber}_${logIndex}`), for exact open-bucket reconciliation. --- # /docs/typescript/api/index/type-aliases/ChainBinding [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ChainBinding # Type Alias: ChainBinding > **ChainBinding** = [`ClientConfig`](../interfaces/ClientConfig.md) Defined in: packages/sdk/src/config.ts:566 One chain's engine configuration inside a multi-chain [SomniaMarkets](../classes/SomniaMarkets.md). Exactly a [ClientConfig](../interfaces/ClientConfig.md): the chain, its indexer, its socket, its protocol addresses and its fee envelope. The facade builds one engine per binding and keeps their sockets, indexer connections, nonce lanes and fee envelopes separate. --- # /docs/typescript/api/index/type-aliases/ClaimableFromError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClaimableFromError # Type Alias: ClaimableFromError > **ClaimableFromError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/derivedReads.ts:935 Errors raised by [claimableFrom](../functions/claimableFrom.md). --- # /docs/typescript/api/index/type-aliases/ClientQueryKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ClientQueryKey # Type Alias: ClientQueryKey > **ClientQueryKey** = readonly [`QueryKeyElement`](QueryKeyElement.md)[] Defined in: packages/sdk/src/queryKeys.ts:53 A cache key for one client read: `["somnia-markets", , …inputs]`. --- # /docs/typescript/api/index/type-aliases/CollateralReadError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CollateralReadError # Type Alias: CollateralReadError > **CollateralReadError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/errors.ts:610 Failures retained from collateral balance reads. --- # /docs/typescript/api/index/type-aliases/ComputeBinaryPnlError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ComputeBinaryPnlError # Type Alias: ComputeBinaryPnlError > **ComputeBinaryPnlError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/units.ts:505 Errors raised by [computeBinaryPnl](../functions/computeBinaryPnl.md). --- # /docs/typescript/api/index/type-aliases/ComputePortfolioAnalyticsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ComputePortfolioAnalyticsError # Type Alias: ComputePortfolioAnalyticsError > **ComputePortfolioAnalyticsError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:434 Every error [computePortfolioAnalytics](../functions/computePortfolioAnalytics.md) can throw. The fold is pure and touches no network or chain, so a bad argument is the only way it fails. --- # /docs/typescript/api/index/type-aliases/ComputePositionPnLError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ComputePositionPnLError # Type Alias: ComputePositionPnLError > **ComputePositionPnLError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/derivedReads.ts:737 Errors raised by [computePositionPnL](../functions/computePositionPnL.md). --- # /docs/typescript/api/index/type-aliases/CountResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CountResult # Type Alias: CountResult > **CountResult** = `object` Defined in: packages/sdk/src/indexerRead.ts:288 A row count plus whether the read was cut short — same `truncated` vocabulary as [FundingRateSeries](FundingRateSeries.md) and the `hasMore` pagers, so a caller reads one convention across the SDK rather than two. `truncated: false` — a real total, from Hasura `_aggregate` or from a fallback scan that finished inside the cap. `truncated: true` — `count` is a LOWER BOUND (10,000 rows, the fallback cap); the true total is at least that. Render it as "10,000+", and do not treat it as the last page when paginating: a `rows.length < count` gate goes false while rows remain. ## Properties ### count > **count**: `number` Defined in: packages/sdk/src/indexerRead.ts:290 Rows matched, or the fallback cap (10,000) when `truncated`. *** ### truncated > **truncated**: `boolean` Defined in: packages/sdk/src/indexerRead.ts:292 True when the bounded fallback hit its cap, so `count` is a lower bound. --- # /docs/typescript/api/index/type-aliases/DebugEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DebugEvent # Type Alias: DebugEvent > **DebugEvent** = \{ `kind`: `"log"`; `level`: `"debug"` \| `"warn"`; `scope`: `string`; `message`: `string`; `data?`: `Record`\<`string`, `unknown`\>; \} \| \{ `kind`: `"span"`; `phase`: `"start"`; `id`: `number`; `parentId?`: `number`; `name`: `string`; `data?`: `Record`\<`string`, `unknown`\>; \} \| \{ `kind`: `"span"`; `phase`: `"annotate"`; `id`: `number`; `name`: `string`; `data`: `Record`\<`string`, `unknown`\>; \} \| \{ `kind`: `"span"`; `phase`: `"end"`; `id`: `number`; `name`: `string`; `durationMs`: `number`; `error?`: `unknown`; \} Defined in: packages/sdk/src/debug.ts:62 One event on the client's opt-in debug channel — either a structured log line or one phase of a span. Wire a sink with [ClientConfig.debug](../interfaces/ClientConfig.md#debug) and every event the client produces flows through it. **Details** Events are data, not display strings: `data` carries raw values (counts, addresses, bigints) and rendering/filtering is entirely the sink's job — see [consoleDebugSink](../functions/consoleDebugSink.md) for a ready-made renderer and [debugCollector](../functions/debugCollector.md) for test capture. A span arrives as a `start`/`end` pair sharing an `id` (unique within one client instance), with any number of `annotate` events in between attaching data to the still-open span. The shape maps 1:1 onto OpenTelemetry, so a real tracer is just another sink: `name` ↔ span name, `data` ↔ attributes, `error` ↔ span status / recorded exception, `annotate` ↔ `setAttribute`, `parentId` ↔ context link. **Gotchas** Parenting is EXPLICIT — a span event carries `parentId` only when the call site passed the parent handle — so interleaved events from concurrent operations always attribute correctly; never infer nesting from event order. **Example** (Handling debug events) A minimal custom sink — narrow on `kind`/`phase` and the union does the rest: ```ts const sink = (e: DebugEvent): void => { if (e.kind === "log") console.log(e.scope, e.message, e.data); else if (e.phase === "end" && e.error !== undefined) console.error(e.name, e.error); else if (e.phase === "end" && e.durationMs > 500) console.log("slow:", e.name, e.durationMs); }; const exchange = new SomniaMarkets({ ...config, debug: sink }); ``` ## Union Members ### Type Literal \{ `kind`: `"log"`; `level`: `"debug"` \| `"warn"`; `scope`: `string`; `message`: `string`; `data?`: `Record`\<`string`, `unknown`\>; \} #### kind > **kind**: `"log"` #### level > **level**: `"debug"` \| `"warn"` `"warn"` for conditions worth surfacing (a failed watch); `"debug"` for tracing. #### scope > **scope**: `string` Emitting module, e.g. `"liveTail"` — filter on it in the sink. #### message > **message**: `string` Stable, human-readable event description, e.g. `"applying logs"`. #### data? > `optional` **data?**: `Record`\<`string`, `unknown`\> Raw values for the sink to render (counts, block numbers, addresses, bigints). *** ### Type Literal \{ `kind`: `"span"`; `phase`: `"start"`; `id`: `number`; `parentId?`: `number`; `name`: `string`; `data?`: `Record`\<`string`, `unknown`\>; \} #### kind > **kind**: `"span"` #### phase > **phase**: `"start"` #### id > **id**: `number` Span id — matches the `annotate`/`end` events of the same span. Unique per client. #### parentId? > `optional` **parentId?**: `number` The enclosing span's `id`; absent on a root span. Only ever set explicitly. #### name > **name**: `string` Span name, `"."` — e.g. `"trade.execute"`, `"trader.placeOrder"`. #### data? > `optional` **data?**: `Record`\<`string`, `unknown`\> The operation's input, as raw values (a trader call's params object, …). *** ### Type Literal \{ `kind`: `"span"`; `phase`: `"annotate"`; `id`: `number`; `name`: `string`; `data`: `Record`\<`string`, `unknown`\>; \} #### kind > **kind**: `"span"` #### phase > **phase**: `"annotate"` #### id > **id**: `number` The still-open span this data belongs to. #### name > **name**: `string` The annotated span's name (so sinks need no id → name lookup). #### data > **data**: `Record`\<`string`, `unknown`\> Values that only exist mid-span — e.g. the tx hash once broadcast returns. *** ### Type Literal \{ `kind`: `"span"`; `phase`: `"end"`; `id`: `number`; `name`: `string`; `durationMs`: `number`; `error?`: `unknown`; \} #### kind > **kind**: `"span"` #### phase > **phase**: `"end"` #### id > **id**: `number` Matches the span's `start` event. #### name > **name**: `string` Same name as the `start` event. #### durationMs > **durationMs**: `number` Wall-clock start-to-settle: for an async span, until the promise settles. #### error? > `optional` **error?**: `unknown` The thrown value / rejection reason when the span failed; absent on success. --- # /docs/typescript/api/index/type-aliases/DecodeAmendOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DecodeAmendOrdersError # Type Alias: DecodeAmendOrdersError > **DecodeAmendOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/decode/orders.ts:185 Failures from [decodeAmendOrders](../functions/decodeAmendOrders.md): an `amendmentCount` that is not a non-negative safe integer. --- # /docs/typescript/api/index/type-aliases/EstPayoutForError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / EstPayoutForError # Type Alias: EstPayoutForError > **EstPayoutForError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/derivedReads.ts:843 Errors raised by [estPayoutFor](../functions/estPayoutFor.md). --- # /docs/typescript/api/index/type-aliases/ExchangeBridgeTransferError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExchangeBridgeTransferError # Type Alias: ExchangeBridgeTransferError > **ExchangeBridgeTransferError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`BridgeLiquidityError`](../classes/BridgeLiquidityError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/unified/bridge.ts:171 Failures from [ExchangeBridge.transfer](../interfaces/ExchangeBridge.md#transfer). --- # /docs/typescript/api/index/type-aliases/ExecutorExecuteError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExecutorExecuteError # Type Alias: ExecutorExecuteError > **ExecutorExecuteError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`TransactionOutcomeUnknownError`](../classes/TransactionOutcomeUnknownError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/executor/types.ts:92 Failures from [Executor.execute](../interfaces/Executor.md#execute): a call list the chain guard refuses (empty, or a call for another chain), missing transport configuration, a transport / signer / node failure with the original as `cause`, a signed transaction whose receipt was not observed ([TransactionOutcomeUnknownError](../classes/TransactionOutcomeUnknownError.md)), or a revert the send surfaced with data (a wallet's pre-send simulation, a decoded rejection). A built-in never throws anything else; a custom executor should hold to the same set — `asExecuteError` does it in one line, and passes a `TransactionOutcomeUnknownError` it is given through unchanged. --- # /docs/typescript/api/index/type-aliases/ExecutorSignTypedDataError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExecutorSignTypedDataError # Type Alias: ExecutorSignTypedDataError > **ExecutorSignTypedDataError** = [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/executor/types.ts:105 Failures from [Executor.signTypedData](../interfaces/Executor.md#signtypeddata): the signer failed or refused (a wallet rejection, a custom signer's own error), the original as `cause`. --- # /docs/typescript/api/index/type-aliases/ExecutorSpec [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ExecutorSpec # Type Alias: ExecutorSpec > **ExecutorSpec** = \{ `privateKey`: `Hex`; \} \| \{ `account`: `LocalAccount`; \} \| \{ `walletClient`: `WalletClient`; `account?`: `Account` \| `Address`; \} \| \{ `sessionSeed`: `Hex`; \} \| \{ `smartAccount`: `Address`; `inner`: [`Executor`](../interfaces/Executor.md); `through?`: readonly `Address`[]; `signer?`: [`SmartAccountSigner`](../interfaces/SmartAccountSigner.md); \} Defined in: packages/sdk/src/executor/create.ts:74 Which built-in executor to build, and the authority it acts with. One variant per actor kind; the engine supplies everything else. - `{ privateKey }` / `{ account }` — the SDK signs locally and sends via `eth_sendRawTransactionSync` (the fast path). - `{ walletClient }` — an injected browser / wagmi signer sends; the SDK confirms off the socket. - `{ sessionSeed }` — a Somnia node-side session account; the node signs, submits and returns the receipt. The seed goes to the node with every write, so use it only for an account that holds gas dust. It cannot be the `inner` of a smart account. - `{ smartAccount, inner }` — a factory account from `@somnia-chain/accounts-sdk` is the actor; `inner` sends the outer transaction. Batching needs no configuration (the accounts SDK resolves its own MultiSend batcher), and `through` reaches an account owned by other accounts, at any depth. **The smart-account variant needs an authorized `inner`.** With no `signer` and no `through`, the outer transaction carries a pre-validated signature for `inner.actor` — a direct owner of a threshold-1 account that sends its own transaction signs nothing. A `signer`, or a `through` chain of parent accounts, switches to a real signature the accounts SDK nests level by level. The chain must be one the accounts SDK covers, or the spec is refused at construction. **An account's `inner` signs locally.** A smart-account spec whose `inner` was built by `{ sessionSeed }` is refused with [InvalidInputError](../classes/InvalidInputError.md): that executor sends the seed to the node on every write, and behind an account the seed controls the account's funds. Build the inner with `{ privateKey }` instead. For a Somnia session seed, the key is `sessionPrivateKey(seed)`; across chains, `exchange.accounts.accountFor(accountId, index, { sessionSeed })` does this for you. A hand-written [Executor](../interfaces/Executor.md) that calls the session RPC itself is outside this check. A private key and a session seed are validated on construction: 32 bytes of hex, or [InvalidInputError](../classes/InvalidInputError.md). A spec names exactly ONE actor: an object that carries the selectors of two variants (a spread that merged a `privateKey` into a `smartAccount` spec, say) is refused with [InvalidInputError](../classes/InvalidInputError.md) rather than silently acting as one of them. --- # /docs/typescript/api/index/type-aliases/FillDetail [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillDetail # Type Alias: FillDetail > **FillDetail** = [`OrderFillRow`](OrderFillRow.md) & `object` Defined in: packages/sdk/src/fills.ts:655 [OrderFillRow](OrderFillRow.md) plus the market it executed on — one fill, fully framed. The embed is `marketRef`, not `market`, because the name is already taken: [FillRow.market](FillRow.md#market) is the bytes32 marketId STRING (aliased from `market_id` in `FillQueryFields`, load-bearing for binary-PnL market scoping). Two fields cannot share it — GraphQL refuses to select the `market` relationship alongside the `market: market_id` alias, and the TS intersection `string & MarketRef` is uninhabitable. ## Type Declaration ### marketRef > **marketRef**: [`MarketRef`](MarketRef.md) --- # /docs/typescript/api/index/type-aliases/FillOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillOrder # Type Alias: FillOrder > **FillOrder** = `object` Defined in: packages/sdk/src/fills.ts:809 One side's order on a fill — the resting order, or the one that crossed it. A narrower shape than [OrderRow](OrderRow.md): this describes an order in the context of a fill whose market is already known, so it carries no market labelling. Amounts are raw units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fills.ts:811 Order id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/fills.ts:813 uint128 OrderId as a decimal string. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/fills.ts:815 Owner wallet, lowercased. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/fills.ts:820 True = bid (buy). Set on every market kind, unlike `side`, which the indexer fills in only for binary. *** ### side > **side**: [`BinarySide`](BinarySide.md) \| `null` Defined in: packages/sdk/src/fills.ts:822 BINARY only — the YES/NO side; null on spot and perp. *** ### price > **price**: `string` Defined in: packages/sdk/src/fills.ts:824 Limit price, raw quote units per whole base. *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/fills.ts:826 Original size, raw base/outcome units. *** ### filledQuantity > **filledQuantity**: `string` Defined in: packages/sdk/src/fills.ts:828 Cumulative filled size, raw base/outcome units. *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/fills.ts:830 Unfilled remainder, raw base/outcome units. *** ### status > **status**: [`OrderStatus`](OrderStatus.md) Defined in: packages/sdk/src/fills.ts:832 Reconciled lifecycle status (Open/Filled/Cancelled/Expired/Closed). *** ### rested > **rested**: `boolean` Defined in: packages/sdk/src/fills.ts:834 Whether the order ever rested on the book (an `OrderRested` fired). *** ### cancelReason > **cancelReason**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:840 WHY the PROTOCOL cancelled the order, when it was not the owner. Null for an owner cancel and for an order that was never cancelled — so a `Cancelled` status with a null reason means the owner did it. *** ### placedAtTimestamp > **placedAtTimestamp**: `string` Defined in: packages/sdk/src/fills.ts:842 Timestamp (unix seconds) the order was placed. *** ### placedTxHash > **placedTxHash**: `string` Defined in: packages/sdk/src/fills.ts:844 Transaction the order was PLACED in — usually not the fill's transaction. --- # /docs/typescript/api/index/type-aliases/FillRow [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillRow # Type Alias: FillRow > **FillRow** = `object` Defined in: packages/sdk/src/fills.ts:526 One fill as the indexer recorded it (mirror of the unified `Fill` entity — spot, perp and binary fills share it). ## Properties ### blockNumber? > `optional` **blockNumber?**: `string` Defined in: packages/sdk/src/fills.ts:528 Source block as an exact decimal string. SDK reads populate it; caller-built rows may omit it. *** ### logIndex? > `optional` **logIndex?**: `number` Defined in: packages/sdk/src/fills.ts:530 Source log position. SDK reads populate it; caller-built rows may omit it. *** ### id > **id**: `string` Defined in: packages/sdk/src/fills.ts:532 Fill id (`${blockNumber}_${logIndex}`). *** ### market > **market**: `string` Defined in: packages/sdk/src/fills.ts:543 The market's bytes32 marketId — the STABLE identity of the market this fill executed in. Group and label by this, never by `pool` alone: a binary pool is recycled across successive markets, so fills from a pool's earlier life carry the same pool address as the market currently on it. On SPOT/PERP the pool address IS the market id. Pass it to [client.getMarket](../interfaces/SomniaMarketsClient.md#getmarket) for the full row. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/fills.ts:548 Lowercased pool address the fill executed on. A TIME-VARYING binding — see `market` for the identity that does not move. *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/fills.ts:553 Execution price, raw quote units per whole base (binary: YES-probability scale). SPOT/PERP: the maker's limit price. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/fills.ts:555 Base/outcome-token quantity filled, raw units. *** ### quoteQuantity > **quoteQuantity**: `string` Defined in: packages/sdk/src/fills.ts:557 Quote/collateral value = quantity × fillPrice / 10^baseDecimals (raw, floored). *** ### maker > **maker**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:559 Maker (resting) wallet, lowercased; null when unknown. *** ### makerSide > **makerSide**: [`BinarySide`](BinarySide.md) \| `null` Defined in: packages/sdk/src/fills.ts:561 BINARY only — the maker's YES/NO side; null on SPOT/PERP. *** ### taker > **taker**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:566 Taker wallet, lowercased. Denormalized from the taker's OrderPlaced (which fires after the fill in the same tx) — null until that bridge lands. *** ### takerSide > **takerSide**: [`BinarySide`](BinarySide.md) \| `null` Defined in: packages/sdk/src/fills.ts:571 BINARY only — the taker's YES/NO side; null on SPOT/PERP or until the taker's OrderPlaced is bridged. *** ### kind > **kind**: [`BinaryFillKind`](BinaryFillKind.md) \| `null` Defined in: packages/sdk/src/fills.ts:576 BINARY only — how the fill settled (direct trade vs mint/burn of a pair); null on SPOT/PERP or until the taker side is known. *** ### takerIsBid > **takerIsBid**: `boolean` \| `null` Defined in: packages/sdk/src/fills.ts:581 True when the taker bought the base/YES (the maker was the ask); null until the taker side is known. *** ### takerOrder > **takerOrder**: \{ `owner`: `string`; `side`: [`BinarySide`](BinarySide.md) \| `null`; \} \| `null` Defined in: packages/sdk/src/fills.ts:589 The taker's ORDER (owner + side), when the indexer has it. Prefer `takerOrder.side` over [FillRow.takerSide](#takerside) on binary: the latter is a denormalized copy the taker bridge backfills, so it lags and can be null on a row that already names its taker. *** ### makerOrderId > **makerOrderId**: `string` Defined in: packages/sdk/src/fills.ts:591 uint128 id of the resting (maker) order, decimal string. *** ### takerOrderId > **takerOrderId**: `string` Defined in: packages/sdk/src/fills.ts:593 uint128 id of the aggressing (taker) order, decimal string. *** ### takerRemainingQuantity > **takerRemainingQuantity**: `string` Defined in: packages/sdk/src/fills.ts:602 The taker order's unfilled remainder AFTER this fill, raw base/outcome units. `"0"` means this fill completed the order. The chain's own number, as `OrderFilled` carries it — so a caller reconciling partial fills from the tape sees exactly what an event subscriber sees, without re-deriving it from the running quantity. *** ### makerRemainingQuantity > **makerRemainingQuantity**: `string` Defined in: packages/sdk/src/fills.ts:604 The maker order's unfilled remainder AFTER this fill, on the same terms as [FillRow.takerRemainingQuantity](#takerremainingquantity). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/fills.ts:606 Timestamp (unix seconds) of the fill. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/fills.ts:608 Tx hash the fill landed in. --- # /docs/typescript/api/index/type-aliases/FillsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillsOptions # Type Alias: FillsOptions > **FillsOptions** = `object` Defined in: packages/sdk/src/fills.ts:37 Options for [SomniaMarketsClient.getFills](../interfaces/SomniaMarketsClient.md#getfills) / [SomniaMarketsClient.getUserFills](../interfaces/SomniaMarketsClient.md#getuserfills). All optional. ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/fills.ts:39 Max rows (default 50). *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/fills.ts:41 Row offset for paging the tape (default 0). *** ### since? > `optional` **since?**: `number` Defined in: packages/sdk/src/fills.ts:43 Only fills at/after this unix-seconds timestamp. *** ### until? > `optional` **until?**: `number` Defined in: packages/sdk/src/fills.ts:45 Only fills at/before this unix-seconds timestamp. *** ### sinceBlock? > `optional` **sinceBlock?**: `number` \| `bigint` Defined in: packages/sdk/src/fills.ts:59 Only fills from this block onwards (`Fill.blockNumber`), inclusive. The exact resume bound a reader wants after processing up to a known block: two blocks can share a timestamp, so a `since` bound in seconds either repeats or skips those rows. Accepts the `bigint` a transaction receipt carries. On these pool- and account-scoped reads the bound is a filter, not an access path: the plan rides the pool or account index and tests the block. [SomniaMarketsClient.getFillsPage](../interfaces/SomniaMarketsClient.md#getfillspage) is the read that has an index behind the range itself. *** ### toBlock? > `optional` **toBlock?**: `number` \| `bigint` Defined in: packages/sdk/src/fills.ts:68 Only fills up to this block (`Fill.blockNumber`), inclusive. The upper half of [FillsOptions.sinceBlock](#sinceblock), and inclusive for the same reason: a reader that walks the chain in ranges wants the boundary to be exact and repeatable, so `[a, b]` followed by `[b + 1, c]` covers every fill exactly once. Supplying it alone bounds the tape from above only. --- # /docs/typescript/api/index/type-aliases/FillsPage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillsPage # Type Alias: FillsPage > **FillsPage** = `object` Defined in: packages/sdk/src/fills.ts:146 One page of a block range, oldest first. Not a coverage guarantee: the range is served from what the indexer has processed, which [SomniaMarketsClient.getLatestFillBlock](../interfaces/SomniaMarketsClient.md#getlatestfillblock) reports. ## Properties ### fills > **fills**: [`OrderFillRow`](OrderFillRow.md)[] Defined in: packages/sdk/src/fills.ts:152 Fills in this page, ascending by `(blockNumber, logIndex)`. Typed as [OrderFillRow](OrderFillRow.md) so the block position the order and the cursor rest on is required rather than optional. *** ### nextCursor > **nextCursor**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:158 Pass to the next call to continue the SAME range. Present whenever the page is full, so a range ending exactly on a page boundary costs one empty final page. Null means the range is drained, not that the chain is. --- # /docs/typescript/api/index/type-aliases/FillsPageOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillsPageOptions # Type Alias: FillsPageOptions > **FillsPageOptions** = `object` Defined in: packages/sdk/src/fills.ts:119 Scope and bounded continuation for [SomniaMarketsClient.getFillsPage](../interfaces/SomniaMarketsClient.md#getfillspage) — an inclusive block range over one market kind, across every pool of it. Every field but `limit` and `cursor` is required, and that is the point of the read: the range is what bounds it, and `marketType` is the leading column of the index the range is served from, so neither has a safe default. ## Properties ### marketType > **marketType**: [`MarketType`](MarketType.md) Defined in: packages/sdk/src/fills.ts:124 Market kind whose pools to read. One index seek covers every pool of that kind, so a caller never enumerates pools to span them. *** ### sinceBlock > **sinceBlock**: `number` \| `bigint` Defined in: packages/sdk/src/fills.ts:126 First block of the range, inclusive. *** ### toBlock > **toBlock**: `number` \| `bigint` Defined in: packages/sdk/src/fills.ts:128 Last block of the range, inclusive. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/fills.ts:134 Max rows per page (default 500, 1 to 1000). Higher than the account tape's 50 because this read exists to be drained: a range is walked to its end, not browsed a screen at a time. *** ### cursor? > `optional` **cursor?**: `string` Defined in: packages/sdk/src/fills.ts:136 Opaque cursor from the preceding page. Omit for the first page of the range. --- # /docs/typescript/api/index/type-aliases/FillsScope [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FillsScope # Type Alias: FillsScope > **FillsScope** = [`FillsOptions`](FillsOptions.md) & `object` Defined in: packages/sdk/src/fills.ts:83 Scope for the per-account fill reads ([SomniaMarketsClient.getUserFills](../interfaces/SomniaMarketsClient.md#getuserfills) / [SomniaMarketsClient.countUserFills](../interfaces/SomniaMarketsClient.md#countuserfills)): a `market` (or `markets`) and/or `pool` predicate on top of [FillsOptions](FillsOptions.md). Prefer `market` on binary. A binary pool is recycled by successive markets, so `pool` selects every life of that pool, while `market` selects exactly one market. On spot/perp the market id IS the pool address, so the two agree. ## Type Declaration ### market? > `optional` **market?**: `string` Only fills in this market (bytes32 marketId, case-insensitive). ### markets? > `optional` **markets?**: readonly `string`[] Only fills in ANY of these markets (bytes32 marketIds, case-insensitive) — the batched form of `market`, for folding several markets from one read. An empty array matches nothing. Supplying `market` as well narrows to both (the intersection), so neither silently overrides the other. ### pool? > `optional` **pool?**: `string` Only fills on this pool address (case-insensitive). --- # /docs/typescript/api/index/type-aliases/FundingPayment [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingPayment # Type Alias: FundingPayment > **FundingPayment** = `object` Defined in: packages/sdk/src/perp/history.ts:48 A signed funding payment (mirror of the indexer `FundingPayment` entity). `amount` is signed raw collateral: **positive is what the account pays**, negative is what it receives. **Details.** The sign is the on-chain one, passed straight through from `MarginBank.FundingSettled`'s `int256 payment` — the indexer does not negate it, and neither does this type. `MarginBank` debits the account when `payment > 0` and credits it when `payment < 0`, and `IMarginBank` documents the event parameter as "positive = paid by account, negative = received by account". Keeping the pass-through is what lets a caller reconcile the value against the chain and against the cumulative funding index. It is the same direction as [PerpPositionMetrics.accruedFunding](../interfaces/PerpPositionMetrics.md#accruedfunding), which is a cost subtracted from equity, and as `docs/PERPS.md`'s `fundingSettled`. **Gotchas.** To display "paid" or "received" to a user, branch on `amount > 0n` meaning paid. A row read as though positive meant received labels every funding transfer the wrong way round. ## Example **Label a settled funding row for a user** ```ts // Positive `amount` = the account PAID this much funding. const paid: Pick = { amount: "2226" }; const label = BigInt(paid.amount) > 0n ? "paid" : "received"; // label === "paid" ``` ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:50 Payment id (`${txHash}_${logIndex}`). *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/perp/history.ts:57 Chain the row came from: the chain of the engine that read or built it. The indexer row has no chain column, so the SDK stamps it. `id` is unique on one chain only, so a caller that merges two chains keys on `(chainId, id)`. *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/history.ts:59 Account (lowercased). *** ### pool > **pool**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:61 Perp pool (lowercased); null when unlinked. *** ### amount > **amount**: `string` Defined in: packages/sdk/src/perp/history.ts:63 Signed funding payment (raw collateral; positive = paid by the account, negative = received). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:65 Timestamp (unix seconds) the funding settled. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:67 Tx hash the settlement landed in. --- # /docs/typescript/api/index/type-aliases/FundingRateCandle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingRateCandle # Type Alias: FundingRateCandle > **FundingRateCandle** = `object` Defined in: packages/sdk/src/perp/history.ts:437 A funding-rate rollup bucket (mirror of the indexer `FundingRateCandle`) — for charting ranges the raw series is too dense for. Each bucket is built by distributing every settlement across the buckets its covered span overlaps, weighted by seconds and normalized to a fixed per-8h axis. That is not an implementation detail: crediting a lazily-settled emit to the bucket containing its log renders a phantom spike of however many intervals it accrued, while the buckets the funding actually applied to render as paused. At the live hourly cadence an hourly bucket holds exactly ONE interval, so even a two-interval emit doubles one bucket and empties its neighbour. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:439 Bucket id (`${pool}_${intervalSeconds}_${bucketStart}`). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/history.ts:440 *** ### intervalSeconds > **intervalSeconds**: `number` Defined in: packages/sdk/src/perp/history.ts:442 3600 | 14400 | 86400. *** ### bucketStart > **bucketStart**: `string` Defined in: packages/sdk/src/perp/history.ts:444 Bucket start (unix seconds). *** ### avgFundingRate8h > **avgFundingRate8h**: `string` Defined in: packages/sdk/src/perp/history.ts:451 Seconds-weighted mean rate, already on a per-8h basis, and zero-filled: seconds no settlement covered pull the mean toward zero rather than being dropped. So a partially covered bucket reads BELOW the rate that was in force — read `coverage` to tell that apart from a genuinely small rate. *** ### minFundingRate8h > **minFundingRate8h**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:457 Extremes over CONTRIBUTING settlements only — undiluted by coverage and NOT zero-filled, so they can legitimately sit outside `avgFundingRate8h` on a thinly covered bucket. Null when no settlement's span reached this bucket. *** ### maxFundingRate8h > **maxFundingRate8h**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:458 *** ### coverage > **coverage**: `string` Defined in: packages/sdk/src/perp/history.ts:464 Covered seconds / bucket seconds, 1e18-scaled — a true ratio in [0, 1]. This is what a chart should hatch or grey on: a bucket at `avgFundingRate8h: 0` with low coverage is a PAUSE, not a measurement of zero funding. *** ### cumulativeFundingStart > **cumulativeFundingStart**: `string` Defined in: packages/sdk/src/perp/history.ts:482 Cumulative funding index at this bucket's wall-clock START and END, attributed by covered seconds — the same basis as `avgFundingRate8h`. Two exact properties follow, and both are what this pair is for: - **Sparse buckets telescope.** `cumulativeFundingEnd` equals the next existing bucket's `cumulativeFundingStart`, even across a gap no settlement covered — the index is flat over uncovered time, so there is nothing to attribute. - **Range sums are exact.** `sum(end - start)` over any set of buckets is the funding that accrued over them; see [realizedFundingPerBase](../functions/realizedFundingPerBase.md). These are ATTRIBUTION values, not chain samples. A catch-up settlement's whole span is spread across the buckets it covered rather than booked at its log, so an interior edge deliberately will NOT equal any `FundingRateUpdate.cumulativeFundingPerUnit`. Use [client.listFundingRateHistory](../interfaces/SomniaMarketsClient.md#listfundingratehistory) when you want the sampled series itself. *** ### cumulativeFundingEnd > **cumulativeFundingEnd**: `string` Defined in: packages/sdk/src/perp/history.ts:483 *** ### fundingWindowSec > **fundingWindowSec**: `number` Defined in: packages/sdk/src/perp/history.ts:485 Params at the bucket's last settlement; `paramsChangedInBucket` flags a mid-bucket change. *** ### fundingIntervalSec > **fundingIntervalSec**: `number` Defined in: packages/sdk/src/perp/history.ts:486 *** ### paramsChangedInBucket > **paramsChangedInBucket**: `boolean` Defined in: packages/sdk/src/perp/history.ts:487 *** ### indexPriceEnd > **indexPriceEnd**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:488 *** ### openInterestEnd > **openInterestEnd**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:489 *** ### updateCount > **updateCount**: `number` Defined in: packages/sdk/src/perp/history.ts:491 How many settlements contributed to this bucket. --- # /docs/typescript/api/index/type-aliases/FundingRateSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingRateSeries # Type Alias: FundingRateSeries\ > **FundingRateSeries**\<`T`\> = `object` Defined in: packages/sdk/src/funding.ts:318 Chart-ready funding buckets plus pagination evidence for the requested window. **Details** Buckets are oldest-first and gapless from the first returned real bucket. `truncated` reports whether older source rows were omitted by the page limit. **Gotchas** A truncated series can start after the requested `from` value. Use `firstBucketStart` and fetch another page instead of drawing the missing history as zero funding. ## Type Parameters ### T `T` *extends* [`FundingBucketLike`](../interfaces/FundingBucketLike.md) = [`FundingBucketLike`](../interfaces/FundingBucketLike.md) ## Properties ### buckets > **buckets**: [`FundingSeriesBucket`](FundingSeriesBucket.md)\<`T`\>[] Defined in: packages/sdk/src/funding.ts:320 Oldest-first and gapless on the interval grid — chart order. *** ### truncated > **truncated**: `boolean` Defined in: packages/sdk/src/funding.ts:325 The read hit its `limit`, so buckets older than `firstBucketStart` exist and were NOT returned. Page with `offset` for the rest. *** ### firstBucketStart > **firstBucketStart**: `number` \| `null` Defined in: packages/sdk/src/funding.ts:327 First bucketStart present, unix seconds. Above the requested `from` when truncated. --- # /docs/typescript/api/index/type-aliases/FundingRateUpdate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingRateUpdate # Type Alias: FundingRateUpdate > **FundingRateUpdate** = `object` Defined in: packages/sdk/src/perp/history.ts:341 A funding-rate history point (mirror of the indexer `FundingRateUpdate` entity) — the append-only counterpart to the market row's overwrite-only funding fields. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:343 Update id (`${pool}_${block}_${logIndex}`). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/history.ts:345 Perp pool (lowercased). *** ### fundingRate > **fundingRate**: `string` Defined in: packages/sdk/src/perp/history.ts:351 Rate applied to THIS settlement, per CALCULATION WINDOW, 1e18-scaled, signed. Normalize with `fundingWindowSec` on this same row — see [normalizeFundingRate](../functions/normalizeFundingRate.md). *** ### cumulativeFundingPerUnit > **cumulativeFundingPerUnit**: `string` Defined in: packages/sdk/src/perp/history.ts:358 Cumulative funding index AFTER this settlement (1e18 x quote units per whole base, signed, NOT monotonic). The ground truth for accrual: realized funding over any range is exactly `(end - start) / 1e18` raw quote units per whole base, with no interpolation and no gap reasoning. See [realizedFundingPerBase](../functions/realizedFundingPerBase.md). *** ### indexPrice > **indexPrice**: `string` Defined in: packages/sdk/src/perp/history.ts:360 Oracle index price at the update (raw quote per whole base, 18dp). *** ### markPrice > **markPrice**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:368 Best-effort mark-price cross-check. NULL when the contract emitted its 0 sentinel for a stale/reverting mark feed — never a price of zero. Unrelated to the premium driving the rate, which since DEX-2252 is the time-weighted IMPACT-price premium (quantity-weighted fill price at a configured notional on each side, deadbanded against the index), not a book midpoint. *** ### intervalsSettled > **intervalsSettled**: `string` Defined in: packages/sdk/src/perp/history.ts:380 Intervals SPANNED, unclamped, as emitted — the timeline the anchor advanced over, not what accrued. **This alone does not tell you whether anything was forgiven.** Compare it against `intervalsAccrued`: they are equal when the settlement charged its whole span, and `intervalsAccrued` is lower when the rest was forgiven at zero. A value above 1 is not enough on its own, because rows from before the one-interval horizon can have BOTH counts above 1 — a row spanning 264 intervals and accruing 96 forgave 168, and a row spanning 96 and accruing 96 forgave nothing. *** ### intervalsAccrued > **intervalsAccrued**: `string` Defined in: packages/sdk/src/perp/history.ts:393 What actually accrued, which is **not** `min(intervalsSettled, n)` — do not re-derive it that way. The contract's catch-up horizon charges at most **one interval** per settlement however long the gap, so a value below `intervalsSettled` means the excess was FORGIVEN at zero funding rather than deferred. The forgiven intervals are the OLDEST ones. The indexer recovers this from the cumulative-index delta the settlement actually moved, rather than reading it off `intervalsSettled`, because the horizon belongs to the deployed contract and has changed more than once. So a row is correct for the implementation that produced it, anywhere in backfilled history. *** ### fundingWindowSec > **fundingWindowSec**: `number` Defined in: packages/sdk/src/perp/history.ts:395 The rate's denominator in seconds, in force at this emit. Makes the row self-normalizing. *** ### fundingIntervalSec > **fundingIntervalSec**: `number` Defined in: packages/sdk/src/perp/history.ts:397 Settlement cadence in seconds, in force at this emit. *** ### spanStart > **spanStart**: `string` Defined in: packages/sdk/src/perp/history.ts:408 Wall-clock span this settlement's accrual covers — the last `intervalsAccrued` intervals ending at the settlement anchor. It reaches BACKWARDS from the emit, which is why a funding chart must distribute a row across the buckets its span overlaps rather than credit it to the bucket containing it. At the deployed one-interval horizon that span is usually one interval wide, so the distribution matters most for older rows: under the earlier horizons one lazily settled emit could cover a full calculation window. *** ### spanEnd > **spanEnd**: `string` Defined in: packages/sdk/src/perp/history.ts:409 *** ### anchorResynced > **anchorResynced**: `boolean` Defined in: packages/sdk/src/perp/history.ts:416 True when the settlement anchor had to be re-derived because the chain advanced it with NO event — the stale-oracle-with-zero-open-interest branch, where funding is permanently forgiven at zero and nothing is logged. A run of these means some funding time is covered by no row at all. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:418 Timestamp (unix seconds) of the update. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/history.ts:419 *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:420 --- # /docs/typescript/api/index/type-aliases/FundingSeriesBucket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FundingSeriesBucket # Type Alias: FundingSeriesBucket\ > **FundingSeriesBucket**\<`T`\> = `T` & `object` \| \{ `bucketStart`: `string`; `intervalSeconds`: `number`; `avgFundingRate8h`: `"0"`; `coverage`: `"0"`; `filled`: `true`; \} Defined in: packages/sdk/src/funding.ts:292 One grid slot: either a real rollup row, or a slot no settlement covered. ## Type Parameters ### T `T` *extends* [`FundingBucketLike`](../interfaces/FundingBucketLike.md) = [`FundingBucketLike`](../interfaces/FundingBucketLike.md) --- # /docs/typescript/api/index/type-aliases/GetLiquidationsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetLiquidationsOptions # ~~Type Alias: GetLiquidationsOptions~~ > **GetLiquidationsOptions** = [`ListLiquidationsOptions`](../interfaces/ListLiquidationsOptions.md) Defined in: packages/sdk/src/perp/history.ts:720 ## Deprecated Renamed to [ListLiquidationsOptions](../interfaces/ListLiquidationsOptions.md). --- # /docs/typescript/api/index/type-aliases/GetUserFillsPageOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / GetUserFillsPageOptions # Type Alias: GetUserFillsPageOptions > **GetUserFillsPageOptions** = `Omit`\<[`FillsScope`](FillsScope.md), `"offset"`\> & `object` Defined in: packages/sdk/src/fills.ts:98 Scope and bounded continuation for [SomniaMarketsClient.getUserFillsPage](../interfaces/SomniaMarketsClient.md#getuserfillspage). ## Type Declaration ### marketType? > `optional` **marketType?**: [`MarketType`](MarketType.md) Only fills of this market kind (`Fill.marketType`, a direct indexed column). Omit to read every kind. The kind is part of the cursor scope, so a cursor from one kind, or from no kind, does not continue another. ### cursor? > `optional` **cursor?**: `string` Opaque cursor from the preceding page. Omit for the newest page. --- # /docs/typescript/api/index/type-aliases/IndexedBlockWait [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedBlockWait # Type Alias: IndexedBlockWait > **IndexedBlockWait** = `object` Defined in: packages/sdk/src/syncStatus.ts:189 What a completed [SomniaMarketsClient.waitForIndexedBlock](../interfaces/SomniaMarketsClient.md#waitforindexedblock) observed. ## Properties ### targetBlock > `readonly` **targetBlock**: `number` Defined in: packages/sdk/src/syncStatus.ts:191 Block the caller waited for. *** ### latestProcessedBlock > `readonly` **latestProcessedBlock**: `number` Defined in: packages/sdk/src/syncStatus.ts:193 Processed height when the wait cleared; at or above `targetBlock`. *** ### initialLagBlocks > `readonly` **initialLagBlocks**: `number` Defined in: packages/sdk/src/syncStatus.ts:199 Blocks the indexer was short of the target at the FIRST poll, floored at zero — the lag the wait actually had to absorb. A chain row that had processed nothing counts as lag from block 0. *** ### waitedMs > `readonly` **waitedMs**: `number` Defined in: packages/sdk/src/syncStatus.ts:204 Elapsed milliseconds from starting the wait through the metadata reply that cleared it, including the first request's latency. *** ### polls > `readonly` **polls**: `number` Defined in: packages/sdk/src/syncStatus.ts:206 Metadata reads performed, including the one that cleared the wait. --- # /docs/typescript/api/index/type-aliases/IndexedMarketCreator [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedMarketCreator # Type Alias: IndexedMarketCreator > **IndexedMarketCreator** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:699 A MarketCreator as the indexer sees it (mirror of the `MarketCreator` entity) — one per (operator, venue) machinery instance. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:701 MarketCreator address (== entity id, lowercased). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:703 Owner address (lowercased). *** ### policy > **policy**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:705 The creator's MarketCreatorPolicy address (lowercased). *** ### core > **core**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:707 The core BinaryMarketsModule the creator binds to (lowercased). *** ### adapter > **adapter**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:709 The oracle adapter the creator's markets resolve against (lowercased). *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:711 The operator the creator is bound to. *** ### venueId > **venueId**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:713 Opaque bytes32 venue id the creator is bound to. *** ### factory > **factory**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:718 The MarketCreatorFactory that minted this creator (lowercased). `null` for a creator observed before/without its factory event. *** ### createdAtBlock > **createdAtBlock**: `number` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:720 Block the creator was deployed in (decimal string); null when not yet observed. *** ### createdAtTimestamp > **createdAtTimestamp**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:722 Timestamp (unix seconds) the creator was deployed; null when not yet observed. *** ### series > **series**: [`IndexedSeries`](IndexedSeries.md)[] Defined in: packages/sdk/src/marketCreatorAdmin.ts:724 The series registered under this creator (nested relationship). --- # /docs/typescript/api/index/type-aliases/IndexedMarketCreatorPolicy [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedMarketCreatorPolicy # Type Alias: IndexedMarketCreatorPolicy > **IndexedMarketCreatorPolicy** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:761 A MarketCreatorPolicy as the indexer sees it (mirror of the `MarketCreatorPolicy` entity). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:763 Policy address (== entity id, lowercased). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:765 Owner address (lowercased). *** ### creator > **creator**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:767 The MarketCreator this policy gates (lowercased). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:769 Timestamp (unix seconds) the policy was deployed. --- # /docs/typescript/api/index/type-aliases/IndexedOperator [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedOperator # Type Alias: IndexedOperator > **IndexedOperator** = `object` Defined in: packages/sdk/src/operatorAdmin.ts:439 An operator as the indexer sees it (mirror of the `Operator` entity). ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:441 operatorId (uint32) as a number — the on-chain id AND the entity primary key. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:443 Owner address (lowercased). *** ### feeRecipient > **feeRecipient**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:445 Default fee recipient for the operator's venues (lowercased). *** ### enabled > **enabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:447 The registry-level kill switch — false disables the operator. *** ### policy > **policy**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:449 Operator-wide IVenuePolicy (lowercased); zero-address = none. *** ### context > **context**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:454 Opaque operator-supplied metadata bytes (hex, 0x-prefixed; '0x' when empty). The chain attaches no semantics — off-chain data only. *** ### pendingOwner > **pendingOwner**: `string` \| `null` Defined in: packages/sdk/src/operatorAdmin.ts:456 Pending incoming owner staged by a two-step transfer (lowercased); null if none in flight. *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:458 Timestamp (unix seconds) the operator was registered. *** ### updatedAtTimestamp > **updatedAtTimestamp**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:462 Timestamp (unix seconds) of the last update to the row. Somnia blocks are ~100ms, so roughly ten consecutive blocks share one value — use [updatedAtBlock](#updatedatblock) when you need to tell two writes apart. *** ### updatedAtBlock > **updatedAtBlock**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:486 Block number of the last CONTROL-PLANE update to the row — NON-DECREASING, and finer-grained than the second-granularity timestamp beside it, which about ten consecutive Somnia blocks share. Not every write to the row moves it, and a consumer must not read it as "the row was not written". The indexer stamps it on `OperatorRegistered`, `OperatorUpdated`, `OperatorEnabledChanged`, the three ownership-transfer events, and `VenueCreated` — that last one because creating a venue bumps this row's `venueCount`. It is NOT stamped on the denormalized rollups — market counts, cumulative volume, collected fees — which rewrite the row with this column carried through unchanged. It is not a write counter and does not identify a write: two updates in the SAME block carry the same number, so this distinguishes updates ACROSS blocks and nothing narrower. A consumer that must not miss a write in a single block needs the events, not this column. `bigint`, unlike the raw-string columns beside it, because SDK-TYPE-007 requires protocol integers to be exact at the boundary — the generated wire string is mapped here rather than exposed. The neighbouring strings predate that seam. *** ### venueCount > **venueCount**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:488 Number of venues created under the operator (soft-disabled included). *** ### marketCount > **marketCount**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:490 Number of markets created under the operator. *** ### cumulativeQuoteVolume > **cumulativeQuoteVolume**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:492 Cumulative binary quote/collateral volume across the operator's markets (raw). *** ### protocolFeesCollected > **protocolFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:494 Cumulative protocol fees collected across the operator's markets (raw). *** ### settlementFeesCollected > **settlementFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:496 Cumulative settlement fees collected across the operator's markets (raw). *** ### builderFeesCollected > **builderFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:498 Cumulative builder fees routed across the operator's markets (raw). --- # /docs/typescript/api/index/type-aliases/IndexedOracleAdapter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedOracleAdapter # Type Alias: IndexedOracleAdapter > **IndexedOracleAdapter** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:732 An OracleAdapter as the indexer sees it (mirror of the `OracleAdapter` entity). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:734 Adapter address (== entity id, lowercased). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:736 Owner address (lowercased). *** ### factory > **factory**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:741 The OracleAdapterFactory that minted it (lowercased); null for the protocol's shared adapter (deployed outside the factory). *** ### approved > **approved**: `boolean` Defined in: packages/sdk/src/marketCreatorAdmin.ts:743 Whether the module has approved the adapter (the inert→live gate). *** ### approvedAtTimestamp > **approvedAtTimestamp**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:745 Timestamp the adapter was approved (null if never approved). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:752 Timestamp (unix seconds) the adapter was deployed/first indexed. `null` when the approval event was indexed BEFORE the creation event — the handler carries `prior?.createdAtTimestamp` forward, so an approve-first ordering leaves it unset (see indexer/src/handlers/machinery.ts). --- # /docs/typescript/api/index/type-aliases/IndexedPerpPosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedPerpPosition # Type Alias: IndexedPerpPosition > **IndexedPerpPosition** = `object` Defined in: packages/sdk/src/perp/state.ts:514 One account's position in one perp pool as the INDEXER has it — the mirror of the `PerpPosition` entity, and the batch counterpart to the per-pool chain read `client.getPerpPosition`. **This is a snapshot, not the live position.** The row is upserted on each `MarginBank.PositionUpdated`, so it is current as of [updatedAtBlock](#updatedatblock) and no fresher. Everything mark-dependent — unrealized PnL, liquidation price, margin health — needs a chain read on top; nothing here is marked to market. Numeric fields are decimal STRINGS of raw units (the indexer wire format), unlike [PerpPosition](../interfaces/PerpPosition.md), whose chain reads are `bigint`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/state.ts:516 Row id (`${pool}_${account}`). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/state.ts:518 Perp pool the position is in (lowercased). *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/state.ts:520 Position owner (lowercased). *** ### size > **size**: `string` Defined in: packages/sdk/src/perp/state.ts:529 SIGNED position size in raw base units: positive = long, negative = short. Normalized to match [PerpPosition.size](../interfaces/PerpPosition.md#size). The entity itself stores an absolute `size` plus a separate `isLong` flag; carrying that second field here would mean two exported position types whose `size` means different things, which reads correctly for longs and silently inverts every short. *** ### avgEntryPrice > **avgEntryPrice**: `string` \| `null` Defined in: packages/sdk/src/perp/state.ts:538 Volume-weighted average entry price, raw quote units per whole base. The same quantity as [PerpPosition.avgEntryPrice](../interfaces/PerpPosition.md#avgentryprice), written straight from the event. (The underlying entity column is named `entryPriceX18`, which is a misnomer — the value is NOT 1e18-scaled. Renamed at this boundary so the name cannot imply a rescale that never happened.) *** ### lastUpdateRealizedPnl > **lastUpdateRealizedPnl**: `string` \| `null` Defined in: packages/sdk/src/perp/state.ts:548 Realized PnL from the MOST RECENT position update only (signed; zero for opens and increases). **Not cumulative, and never summable.** There is one row per position, not one per update, and each update OVERWRITES this field — so prior values are gone and neither summing across positions nor accumulating over time yields lifetime realized PnL. It is a property of the last update, nothing more. *** ### updatedAt > **updatedAt**: `string` Defined in: packages/sdk/src/perp/state.ts:553 Unix SECONDS of the last update. ([PerpPosition](../interfaces/PerpPosition.md) is NANOseconds — the two are 1e9 apart, so never compare them without converting.) *** ### updatedAtBlock > **updatedAtBlock**: `number` \| `null` Defined in: packages/sdk/src/perp/state.ts:555 Block of the last update — the row is current as of this height, not head. --- # /docs/typescript/api/index/type-aliases/IndexedSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedSeries # Type Alias: IndexedSeries > **IndexedSeries** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:669 A Series as the indexer sees it (mirror of the `Series` entity) — one rolling up/down market spec registered under a creator. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:671 Entity id: `${creatorLower}_${seriesId}`. *** ### creatorAddress > **creatorAddress**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:673 The MarketCreator this series belongs to (lowercased). *** ### seriesId > **seriesId**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:675 Per-creator series id (uint32). *** ### collateral > **collateral**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:677 Per-series collateral ERC-20 (lowercased). *** ### asset > **asset**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:679 Underlying asset label (e.g. "BTC/USDT"). *** ### intervalSec > **intervalSec**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:681 Roll interval in seconds (raw bigint as string). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:688 Timestamp (unix seconds) the series was registered. `null` when the row was first written by an event that carries no creation block (the handlers pass `prior?.createdAtTimestamp` through) — the indexer schema declares it nullable, so this mirrors the wire. *** ### updatedAtTimestamp > **updatedAtTimestamp**: `string` \| `null` Defined in: packages/sdk/src/marketCreatorAdmin.ts:690 Timestamp (unix seconds) of the last update (a re-register overwrites); null until first update. --- # /docs/typescript/api/index/type-aliases/IndexedVenue [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexedVenue # Type Alias: IndexedVenue > **IndexedVenue** = `object` Defined in: packages/sdk/src/operatorAdmin.ts:506 A venue as the indexer sees it (mirror of the `Venue` entity). ## Properties ### venueId > **venueId**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:508 Opaque bytes32 venue id (== entity id); NOT a human label. *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:510 The operator the venue belongs to. *** ### marketType > **marketType**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:512 bytes4 market-type id the venue is pinned to, forever (hex). *** ### feeParams > **feeParams**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:514 Type-specific fee params, opaque to the registry (bytes hex). *** ### feeRecipientOverride > **feeRecipientOverride**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:516 Per-venue fee recipient override (lowercased); zero-address falls back to the operator's. *** ### policy > **policy**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:518 Per-venue IVenuePolicy (lowercased); zero-address = none. *** ### signer > **signer**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:520 Per-venue EIP-712 signer (lowercased); non-zero ⇒ creation requires a venue sig. *** ### creationEnabled > **creationEnabled**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:522 Whether new markets may currently be created under the venue. *** ### context > **context**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:527 Opaque venue-supplied metadata bytes (hex, 0x-prefixed; '0x' when empty). The chain attaches no semantics — off-chain data only. *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:529 Timestamp (unix seconds) the venue was created. *** ### updatedAtTimestamp > **updatedAtTimestamp**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:533 Timestamp (unix seconds) of the last update to the row. Somnia blocks are ~100ms, so roughly ten consecutive blocks share one value — use [updatedAtBlock](#updatedatblock) when you need to tell two writes apart. *** ### updatedAtBlock > **updatedAtBlock**: `bigint` Defined in: packages/sdk/src/operatorAdmin.ts:559 Block number of the last CONTROL-PLANE update to the row — NON-DECREASING, and finer-grained than the second-granularity timestamp beside it, which about ten consecutive Somnia blocks share. Not every write to the row moves it, and a consumer must not read it as "the row was not written". The indexer stamps it on `VenueCreated`, `VenueUpdated` and `VenueEnabledChanged` — and on NO operator event. An ownership transfer or an operator update moves [IndexedOperator.updatedAtBlock](IndexedOperator.md#updatedatblock) and leaves this marker exactly where it was, so do not difference a venue marker expecting to see one. It is NOT stamped on the denormalized rollups either — market counts, cumulative volume, collected fees — which rewrite the row with this column carried through unchanged. It is not a write counter and does not identify a write: two updates in the SAME block carry the same number, so this distinguishes updates ACROSS blocks and nothing narrower. A consumer that must not miss a write in a single block needs the events, not this column. `bigint`, unlike the raw-string columns beside it, because SDK-TYPE-007 requires protocol integers to be exact at the boundary — the generated wire string is mapped here rather than exposed. The neighbouring strings predate that seam. *** ### marketCount > **marketCount**: `number` Defined in: packages/sdk/src/operatorAdmin.ts:561 Number of markets created under the venue. *** ### cumulativeQuoteVolume > **cumulativeQuoteVolume**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:563 Cumulative binary quote/collateral volume across the venue's markets (raw). *** ### protocolFeesCollected > **protocolFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:565 Cumulative protocol fees collected across the venue's markets (raw). *** ### settlementFeesCollected > **settlementFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:567 Cumulative settlement fees collected across the venue's markets (raw). *** ### builderFeesCollected > **builderFeesCollected**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:569 Cumulative builder fees routed across the venue's markets (raw). --- # /docs/typescript/api/index/type-aliases/IndexerFreshness [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerFreshness # Type Alias: IndexerFreshness > **IndexerFreshness** = [`IndexerSyncStatus`](IndexerSyncStatus.md) & `object` Defined in: packages/sdk/src/syncStatus.ts:355 Indexer metadata compared to an independently requested chain head. ## Type Declaration ### independentHead > `readonly` **independentHead**: [`IndependentHead`](../interfaces/IndependentHead.md) Independent RPC observation. RPC recency itself is not asserted. ### processedBlockTimestamp > `readonly` **processedBlockTimestamp**: `bigint` \| `null` Processed block's Unix time; null when the processed height is unknown. ### lagBlocks > `readonly` **lagBlocks**: `bigint` \| `null` Independent head minus processed height, clamped to zero. A lead within 10,000 blocks reads as zero; past that the read throws instead. ### lagSeconds > `readonly` **lagSeconds**: `bigint` \| `null` Difference between chain timestamps in seconds, clamped to zero. ### reportedLagBlocks > `readonly` **reportedLagBlocks**: `bigint` \| `null` Indexer's own reported head minus processed height, clamped to zero. ### observedAt > `readonly` **observedAt**: `number` Wall-clock completion time in milliseconds. --- # /docs/typescript/api/index/type-aliases/IndexerRefusalReason [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerRefusalReason # Type Alias: IndexerRefusalReason > **IndexerRefusalReason** = `"breaker-open"` \| `"breaker-trial"` \| `"queue-full"` \| `"live-reset"` Defined in: packages/sdk/src/errors.ts:618 Which gate refused an indexer read, and so what the caller should do next. See [IndexerUnavailableError](../classes/IndexerUnavailableError.md) for the per-reason table. --- # /docs/typescript/api/index/type-aliases/IndexerSyncStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IndexerSyncStatus # Type Alias: IndexerSyncStatus > **IndexerSyncStatus** = `object` Defined in: packages/sdk/src/syncStatus.ts:27 The indexer's own sync state for one chain (envio `chain_metadata`). These self-reported heights can freeze together. Use IndexerFreshness for independent lag. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/syncStatus.ts:29 Chain id the row describes. *** ### latestProcessedBlock > **latestProcessedBlock**: `number` \| `null` Defined in: packages/sdk/src/syncStatus.ts:31 Last block the indexer fully processed; null before the first block lands. *** ### blockHeight > **blockHeight**: `number` \| `null` Defined in: packages/sdk/src/syncStatus.ts:33 Chain head height as the indexer last saw it; null until first fetched. *** ### numEventsProcessed > **numEventsProcessed**: `number` \| `null` Defined in: packages/sdk/src/syncStatus.ts:39 Lifetime count of events the indexer has processed on this chain. `null` on the rare row where envio has not populated the counter yet — Hasura declares the column nullable, so this is the wire's shape, not a defensive guess. --- # /docs/typescript/api/index/type-aliases/IntervalSource [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / IntervalSource # Type Alias: IntervalSource > **IntervalSource** = `object` Defined in: packages/sdk/src/interval.ts:28 The minimal market shape needed to resolve a cadence — a structural subset of [BinaryMarket](BinaryMarket.md), so these helpers stay dependency-free (no import cycle with the concept modules) and accept either the indexed row or a hand-built object. Fields accept the indexer's decimal strings OR plain numbers. ## Properties ### intervalSec? > `optional` **intervalSec?**: `string` \| `number` \| `null` Defined in: packages/sdk/src/interval.ts:31 Series cadence in seconds, as the indexer derived it (may be null on a row that predates the field, or on SPOT/PERP). *** ### tradingStart? > `optional` **tradingStart?**: `string` \| `number` \| `null` Defined in: packages/sdk/src/interval.ts:33 Unix seconds trading opened. *** ### expiry? > `optional` **expiry?**: `string` \| `number` \| `null` Defined in: packages/sdk/src/interval.ts:35 Unix seconds trading ends / the outcome is decided. --- # /docs/typescript/api/index/type-aliases/LatestFillBlock [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LatestFillBlock # Type Alias: LatestFillBlock > **LatestFillBlock** = `object` Defined in: packages/sdk/src/fills.ts:167 The newest block carrying an indexed fill of one market kind, with that block's timestamp. ## Properties ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/fills.ts:169 Block height of the newest indexed fill of this kind. *** ### timestamp > **timestamp**: `bigint` Defined in: packages/sdk/src/fills.ts:171 That fill's block timestamp, unix seconds. --- # /docs/typescript/api/index/type-aliases/LenderConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LenderConfig # Type Alias: LenderConfig > **LenderConfig** = [`OracleHubAdminConfig`](../interfaces/OracleHubAdminConfig.md) Defined in: packages/sdk/src/lend/lender.ts:31 Signer config for the lend entry's `createLender` — same signer doctrine as every SDK write surface (a `privateKey`, a local `account`, or a browser `walletClient`). --- # /docs/typescript/api/index/type-aliases/LiquidationEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiquidationEvent # Type Alias: LiquidationEvent > **LiquidationEvent** = `object` Defined in: packages/sdk/src/perp/history.ts:153 A liquidation event (mirror of the indexer `LiquidationEvent` entity). All numeric fields are raw units; any may be null when the source event didn't carry it. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:155 Event id (`${txHash}_${logIndex}`). *** ### chainId > **chainId**: `number` Defined in: packages/sdk/src/perp/history.ts:162 Chain the row came from: the chain of the engine that read or built it. The indexer row has no chain column, so the SDK stamps it. `id` is unique on one chain only, so a caller that merges two chains keys on `(chainId, id)`. *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/history.ts:164 Liquidated account (lowercased). *** ### pool > **pool**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:166 Perp pool (lowercased); null on account-scoped rows. *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/history.ts:197 WHICH stage of the liquidation/deleveraging waterfall this row is. **Read this first** — the rows are stages of one mechanism, not repetitions of one event, and without it an ADL leg is indistinguishable from a liquidation: AccountLiquidated account-level summary (positionsProcessed, stageReached) PositionLiquidated per-position liquidation (size, price) PositionSkipped below min quantity, left in place (size) PositionTakenOver stage-4 backstop takeover (counterparty = bidder, price) AutoDeleveraged ADL leg (counterparty absorbed it; price = bankruptcy price) Throttled DEFERRED by the pool's per-block volume cap KeeperReward paid to the keeper that ran it (counterparty = keeper) OrderPanicked the liquidation IOC reverted with a Solidity PANIC PositionTransferred stage-4 transfer (counterparty, size) CloseOutMarginSettled stage-4 close-out margin flow (counterparty) BadDebtAbsorbed the fund was ASKED to cover (insuranceCovered, deficit, counterparty = fund). It fires on the request, not on the payment: `insuranceCovered` may be 0. Read that field before you conclude the fund paid. ResidualBadDebt uncovered, INSOLVENT hole after the waterfall (badDebt) AdlPriceCapacityExhausted terminal: hole exceeds aggregate position capacity (badDebt) ResidualBackedByOpenPnl hole fully backed by the account's OWN open PnL (deficit, equity) CoverageDeclined coverage the equity cap DEFERRED (coverageDeclined) AdlSessionDiscarded ADL session abandoned; amount is on the same-tx BadDebtAbsorbed row AdlCapacityShortfall ADL could not source enough capacity (size) A `string`, not [LiquidationKind](LiquidationKind.md): the row carries what the DEPLOYED indexer wrote, which can outrun a pinned SDK. [isLiquidationKind](../functions/isLiquidationKind.md) narrows it for an exhaustive switch or to pass back into the filter. *** ### size > **size**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:204 Signed size for the leg, where the event carries one (raw base units). Signed, not absolute: `PositionLiquidated` emits a signed `sizeDelta`, and the sign is the side being closed. *** ### price > **price**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:209 Price for the leg (raw quote per whole base) — mark price, takeover price, or ADL bankruptcy price depending on `kind`. *** ### counterparty > **counterparty**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:219 The other side of the leg: the ADL counterparty who absorbed it, the takeover bidder, the transfer/close-out peer, or — on `BadDebtAbsorbed` — the Insurance Fund the engine ASKED to cover. Null on rows with no counterparty. On `BadDebtAbsorbed` this names the fund that was asked, not one that paid. The address is recorded even when `insuranceCovered` is 0, so read that field to see whether any value moved. *** ### penalty > **penalty**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:221 Penalty charged (raw collateral; reserved — not carried by current events). *** ### badDebt > **badDebt**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:242 The LEVEL of the account's uncovered, genuinely insolvent realized hole after this `liquidate()` call — `ResidualBadDebt`, or `AdlPriceCapacityExhausted` for the terminal price-capacity case (raw collateral). **A level, not a flow — never SUM this across rows.** The underlying `residual` is a post-call state sample, so a later call on the same account re-reports the same (possibly changed) hole, and a stage-5 residual can co-fire with a terminal ADL one in a single call: two samples of one hole at two stages. Sound aggregates: the **latest row per account** is that account's currently known uncovered hole (an upper bound — a deposit can repay it with no row here, see [MarginEvent](MarginEvent.md)), and the **sum of those latest rows across accounts** is point-in-time system bad debt. Deliberately narrow: what the fund actually paid is [LiquidationEvent.insuranceCovered](#insurancecovered), a gross pre-coverage hole is [LiquidationEvent.deficit](#deficit), and a deferred coverage decision is [LiquidationEvent.coverageDeclined](#coveragedeclined). Collateral that merely MOVED between accounts is in `collateralAmount`. *** ### insuranceCovered > **insuranceCovered**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:256 Wei the Insurance Fund ACTUALLY moved — `BadDebtAbsorbed` only (raw collateral). A **flow**, and the only summable amount here: rows are disjoint payments, so a SUM over any slice is exact fund outflow. A `insuranceCovered` below the same row's `deficit` does NOT mean the fund was underfunded — part of a hole is unattributable (a pre-existing balance, or funding owed), and that remainder surfaces as a `ResidualBadDebt` row instead. `AdlSessionDiscarded` deliberately leaves this null: its absorption is the same `absorbBadDebt` call that emits `BadDebtAbsorbed` in the same transaction, so counting both would double the outflow. Join on `txHash`. *** ### deficit > **deficit**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:269 The GROSS realized hole a stage reported, before coverage (raw collateral) — `BadDebtAbsorbed` (the full negative balance) and `ResidualBackedByOpenPnl` (a hole the account's own open profit fully backs, so it is NOT bad debt; read `equity` alongside it, and note it becomes bad debt if the position reverses). **A level, and overlapping per-stage views of one hole — never SUM, and never add to `badDebt`.** When `BadDebtAbsorbed` and `ResidualBadDebt` both fire in one call the balance moved only by what the fund paid, so `badDebt == deficit - insuranceCovered` for that call: a useful cross-row audit check, and the direct proof that summing the gross figure with the residual double-counts. *** ### coverageDeclined > **coverageDeclined**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:280 Attributable coverage the stage-5 equity cap did NOT pay — `CoverageDeclined` only (raw collateral). A **flow** and summable as "total coverage deferred", but NOT a loss: the fund underwrites insolvency and the account was not insolvent by that much at that moment. If the backing later evaporates the hole returns as a pre-existing negative balance, which is unattributable by definition, so it is written off rather than re-declined (accepted policy, OQ-13). *** ### collateralAmount > **collateralAmount**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:286 Collateral that MOVED rather than was lost — `PositionTransferred` (collateral following the position) and `CloseOutMarginSettled`. Kept separate from `badDebt` so neither aggregate contaminates the other. *** ### equity > **equity**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:288 Account equity where the event reports it (`ResidualBackedByOpenPnl`; signed). *** ### positionsProcessed > **positionsProcessed**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:290 Positions processed (`AccountLiquidated` only). *** ### stageReached > **stageReached**: `number` \| `null` Defined in: packages/sdk/src/perp/history.ts:323 The deepest waterfall stage that ACTED (`AccountLiquidated` only). The protocol enum is 0-indexed and has six members. The published waterfall numbers its stages 1 to 6. The two do not line up, so map them with this table: 0 OrderCancellation before stage 3 — cancelling the account's resting orders alone restored health 1 CLOBPartial stage 3 2 BidderTakeover stage 4 3 InsuranceFund stage 5 4 ADL stage 6 5 Deferred not a stage — stage 3 hit its per-block rate limit, and stages 4 to 6 were not consulted. Ships dormant, so it does not appear yet Published stages 1 (Healthy) and 2 (Margin Call) are account states, not actions. The engine cannot reach them, so no value maps to them. Two rules the number does not state on its own: It names the deepest stage that ACTED, not the deepest stage consulted. A stage that ran and moved nothing does not promote it. So `BidderTakeover` (2) beside a `BadDebtAbsorbed` row is consistent, and means the fund was asked and paid nothing. Check `insuranceCovered` on that row to confirm. `CLOBPartial` (1) is a fall-through marker. It means stages 4 to 6 were consulted and none of them acted. It does NOT prove stage 3 filled anything. Against an empty book you get `CLOBPartial` with a `positionsProcessed` of 0, which means the account's orders were cancelled and no position was closed. Always read `positionsProcessed` with this field. *** ### marginStatusBefore > **marginStatusBefore**: `number` \| `null` Defined in: packages/sdk/src/perp/history.ts:325 Margin status before / after (`AccountLiquidated` only). *** ### marginStatusAfter > **marginStatusAfter**: `number` \| `null` Defined in: packages/sdk/src/perp/history.ts:326 *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:328 Timestamp (unix seconds) of the row. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/history.ts:329 *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:331 Tx hash the row landed in. Stages of one liquidation share it. --- # /docs/typescript/api/index/type-aliases/LiquidationKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiquidationKind # Type Alias: LiquidationKind > **LiquidationKind** = *typeof* [`LIQUIDATION_KIND`](../variables/LIQUIDATION_KIND.md)\[`number`\] Defined in: packages/sdk/src/perp/history.ts:126 One stage of the liquidation waterfall. --- # /docs/typescript/api/index/type-aliases/ListSeriesLatestMarketsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ListSeriesLatestMarketsOptions # Type Alias: ListSeriesLatestMarketsOptions > **ListSeriesLatestMarketsOptions** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:958 Paging for [SomniaMarketsClient.listSeriesLatestMarkets](../interfaces/SomniaMarketsClient.md#listserieslatestmarkets): a page of SERIES (the distinct rows), not of markets. ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:960 Rows per page; default 100. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:962 Rows to skip; default 0. --- # /docs/typescript/api/index/type-aliases/LiveBinaryMarketsFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiveBinaryMarketsFilter # Type Alias: LiveBinaryMarketsFilter > **LiveBinaryMarketsFilter** = [`BinaryMarketFilter`](BinaryMarketFilter.md) & `object` Defined in: packages/sdk/src/markets.ts:1403 Filters for `listLiveBinaryMarkets`. Every field is optional; an omitted field does NOT constrain the query. Applied server-side (Hasura `where`), so `venueId` / `intervalSec` hit their indexes. ## Type Declaration ### limit? > `optional` **limit?**: `number` Page size (default 50). Live is unbounded at scale (thousands of venues × cadences), so it is ALWAYS paginated — never fetch the whole live set. ### offset? > `optional` **offset?**: `number` Row offset for cursoring the live board (default 0). ### nowSec? > `optional` **nowSec?**: `number` Override "now" (unix seconds); defaults to `Date.now()`. Mostly for tests. --- # /docs/typescript/api/index/type-aliases/LiveMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LiveMarket # Type Alias: LiveMarket > **LiveMarket** = [`Market`](Market.md) Defined in: packages/sdk/src/store.ts:248 The live market shape IS the read-surface market union — spot and binary rows materialize into the exact shape `client.listMarkets` serves. --- # /docs/typescript/api/index/type-aliases/MarginEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarginEvent # Type Alias: MarginEvent > **MarginEvent** = `object` Defined in: packages/sdk/src/perp/history.ts:75 A margin-account movement (mirror of the indexer `MarginEvent` entity). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:77 Event id (`${txHash}_${logIndex}`). *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/history.ts:79 Account (lowercased). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/history.ts:81 Deposit | Withdraw | Locked | Unlocked | Credited. *** ### pool > **pool**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:87 Perp pool the (un)lock targets (lowercased); null on Deposit/Withdraw/Credited, which are account-scoped. Was omitted from the query selection despite existing on the entity, so it read as always-null. *** ### amount > **amount**: `string` Defined in: packages/sdk/src/perp/history.ts:89 Collateral moved (raw units). *** ### granter > **granter**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:91 Who granted the credit (`Credited` only) — the voucher/credit rail. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:93 Timestamp (unix seconds) of the movement. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:95 Tx hash the movement landed in. --- # /docs/typescript/api/index/type-aliases/MarginStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarginStatus # Type Alias: MarginStatus > **MarginStatus** = `"Healthy"` \| `"MarginCall"` \| `"PartialLiquidation"` \| `"CloseOut"` Defined in: packages/sdk/src/perp/margin.ts:28 Cross-margin health status (mirror of the on-chain `MarginStatus` enum): `"Healthy"` (equity ≥ IM) · `"MarginCall"` (IM > equity ≥ MM) · `"PartialLiquidation"` (MM > equity ≥ CM) · `"CloseOut"` (equity < CM). --- # /docs/typescript/api/index/type-aliases/MarkSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarkSeries # Type Alias: MarkSeries > **MarkSeries** = `ReadonlyArray`\ Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:166 A market's mark-price series: [timestampMs, price][], oldest first. --- # /docs/typescript/api/index/type-aliases/Market [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Market # Type Alias: Market > **Market** = [`SpotMarket`](SpotMarket.md) \| [`PerpMarket`](PerpMarket.md) \| [`BinaryMarket`](BinaryMarket.md) Defined in: packages/sdk/src/markets.ts:442 A market of any type, discriminated by `marketType`. --- # /docs/typescript/api/index/type-aliases/MarketActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketActivity # Type Alias: MarketActivity > **MarketActivity** = [`MarketTradeActivity`](MarketTradeActivity.md) \| [`MarketSupplyActivity`](MarketSupplyActivity.md) \| [`MarketResolutionActivity`](MarketResolutionActivity.md) \| [`MarketStatusActivity`](MarketStatusActivity.md) Defined in: packages/sdk/src/activity.ts:184 One row of a market's activity feed. Narrow on `kind`. ```ts for (const row of await client.getMarketActivity(marketId)) { if (row.kind === "TRADE") console.log(row.fillPrice, row.quantity); else if (row.kind === "RESOLUTION") console.log(row.outcome); } ``` --- # /docs/typescript/api/index/type-aliases/MarketActivityBase [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketActivityBase # Type Alias: MarketActivityBase > **MarketActivityBase** = `object` Defined in: packages/sdk/src/activity.ts:58 The fields every [MarketActivity](MarketActivity.md) row carries, whatever its kind. Sort and page on `timestamp`. Group by `txHash` to recover the rows that one transaction produced — a taker order that also minted a set writes a `TRADE` and a `MINT_SET` under the same hash. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/activity.ts:66 Feed-unique row id, `${kind}:${entityId}`. Prefixed because the source entities number their ids independently: a `Fill` and a `MarketStatusUpdate` in the same block and log position share an entity id. Stable across reads, so it is safe as a list key. *** ### kind > **kind**: [`MarketActivityKind`](MarketActivityKind.md) Defined in: packages/sdk/src/activity.ts:68 Kind discriminator — narrow on this. *** ### market > **market**: `string` Defined in: packages/sdk/src/activity.ts:70 The market's bytes32 marketId, lowercased. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/activity.ts:72 Timestamp (unix seconds) of the block the row landed in. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/activity.ts:74 Block the row landed in (decimal string). *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/activity.ts:76 Transaction the row landed in. --- # /docs/typescript/api/index/type-aliases/MarketActivityKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketActivityKind # Type Alias: MarketActivityKind > **MarketActivityKind** = `"TRADE"` \| `"MINT_SET"` \| `"MERGE_SET"` \| `"REDEEM"` \| `"RESOLUTION"` \| `"STATUS"` Defined in: packages/sdk/src/activity.ts:37 What a [MarketActivity](MarketActivity.md) row records. `TRADE` occurs on every market kind. The other five are binary-only, because complete sets, oracle resolution and the market lifecycle exist only there — a spot or perp market yields `TRADE` rows and nothing else. --- # /docs/typescript/api/index/type-aliases/MarketActivityOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketActivityOptions # Type Alias: MarketActivityOptions > **MarketActivityOptions** = `object` Defined in: packages/sdk/src/activity.ts:191 Options for [SomniaMarketsClient.getMarketActivity](../interfaces/SomniaMarketsClient.md#getmarketactivity). All optional. ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/activity.ts:199 Max rows to return (default 50). Each source stream is asked for this many rows, and the merge keeps the newest `limit` of the union. So the result is the market's newest `limit` events, whichever kinds they are. *** ### kinds? > `optional` **kinds?**: readonly [`MarketActivityKind`](MarketActivityKind.md)[] Defined in: packages/sdk/src/activity.ts:206 Which kinds to read (default: every kind). A kind left out is excluded at the indexer, not dropped afterwards. An empty array therefore reads nothing and returns `[]`. *** ### since? > `optional` **since?**: `number` Defined in: packages/sdk/src/activity.ts:208 Only rows at/after this unix-seconds timestamp. *** ### until? > `optional` **until?**: `number` Defined in: packages/sdk/src/activity.ts:231 Only rows at/before this unix-seconds timestamp. This is the paging cursor. To read the page before the one you hold, pass the `timestamp` of its last row. There is no `offset`, because a row offset cannot page a merged feed: each stream would skip its own `offset` rows, so the second page would omit whatever the first page did not have room for. KNOWN LIMIT — the cursor has one-second resolution, and the bound is inclusive, so the boundary second is re-read on the next page: expect a few duplicate ids across a page edge and de-duplicate by `id` if that matters. A second holding `limit` or more rows cannot be paged past at all, because the next request returns that same second again. Tightening this needs a composite (timestamp, blockNumber, logIndex) cursor. The entity schema now carries `logIndex` on all four streams — this release adds it to the three that lacked it — so the cursor is expressible as soon as a REINDEXED deployment serves the column. It is not adopted here on purpose: ordering on a column the live Hasura does not serve is a validation error that fails the whole read, not a null, so the SDK would break against every indexer that has not caught up yet. *** ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/activity.ts:242 The market's pool address, when the caller already knows it. An optimization, and safe to omit. Trades are selected by market id either way; supplying the pool adds the predicate that lets the indexer read them through the `(pool, timestamp)` index instead of sorting the market's fills. It cannot widen the result — on binary a recycled pool's earlier markets are still excluded by the market-id predicate, and on spot and perp the pool address IS the market id. --- # /docs/typescript/api/index/type-aliases/MarketCreatorFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketCreatorFilter # Type Alias: MarketCreatorFilter > **MarketCreatorFilter** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:819 Server-side filter for the MarketCreator directory. Every field optional. ## Properties ### owner? > `optional` **owner?**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:821 Restrict to creators owned by this address (case-insensitive). *** ### operatorId? > `optional` **operatorId?**: `number` Defined in: packages/sdk/src/marketCreatorAdmin.ts:823 Restrict to one operator id. *** ### venueId? > `optional` **venueId?**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:825 Restrict to one bytes32 venue id (case-insensitive). --- # /docs/typescript/api/index/type-aliases/MarketFees [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketFees # Type Alias: MarketFees > **MarketFees** = `object` Defined in: packages/sdk/src/markets.ts:1260 The origin attribution + fee config frozen into a market at creation, mirrored from `BinaryMarketsModule.MarketCreated` / `MarketFeeConfig` into the indexer's `MarketVenue` entity. Rates are standard basis points (1 = 0.01%, 100 = 1%, 10_000 = 100%). Fee fields are null for markets indexed before the fee plumbing existed. ## Properties ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/markets.ts:1262 Origin operator id the market was created under. *** ### venueId > **venueId**: `string` Defined in: packages/sdk/src/markets.ts:1264 Origin venue id within the operator (bytes32 hex). *** ### feeRecipient > **feeRecipient**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1266 Fee recipient frozen at creation (lowercased); null on pre-plumbing markets. *** ### makerFeeBps > **makerFeeBps**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1268 Maker fee rate (bps, decimal string); null on pre-plumbing markets. *** ### takerFeeBps > **takerFeeBps**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1270 Taker fee rate (bps, decimal string); null on pre-plumbing markets. *** ### maxBuilderFeeBps > **maxBuilderFeeBps**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1272 Cap on the per-order builder fee (bps, decimal string); null pre-plumbing. *** ### routingFeeBps > **routingFeeBps**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1274 Routing fee rate (bps, decimal string); null on pre-plumbing markets. *** ### settlementFeeBps > **settlementFeeBps**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1276 Settlement fee skimmed from the winning payout at redeem (bps). *** ### settlementFeesCollected > **settlementFeesCollected**: `string` \| `null` Defined in: packages/sdk/src/markets.ts:1278 Realized settlement fee collected on winning redemptions so far (raw collateral). --- # /docs/typescript/api/index/type-aliases/MarketHandle [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketHandle # Type Alias: MarketHandle > **MarketHandle** = `string` \| [`ChainMarketRef`](../interfaces/ChainMarketRef.md) Defined in: packages/sdk/src/chainRef.ts:54 What every unified verb accepts as a market handle: a bare symbol / address / id string, or a [ChainMarketRef](../interfaces/ChainMarketRef.md). --- # /docs/typescript/api/index/type-aliases/MarketRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketRef # Type Alias: MarketRef > **MarketRef** = `object` Defined in: packages/sdk/src/fills.ts:627 The market a fill/order belongs to, as detail reads embed it — enough to label and scale the row (symbols + decimals) and route to the market's page, without dragging in the full per-kind [Market](Market.md) union. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fills.ts:629 Market entity id (pool address for SPOT/PERP; marketId bytes32 for BINARY). *** ### marketType > **marketType**: `"SPOT"` \| `"PERP"` \| `"BINARY"` Defined in: packages/sdk/src/fills.ts:630 *** ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/fills.ts:632 Lowercased pool address serving the market. *** ### marketAddress > **marketAddress**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:634 BinaryMarket contract address; null on SPOT/PERP. *** ### baseSymbol > **baseSymbol**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:635 *** ### quoteSymbol > **quoteSymbol**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:636 *** ### baseDecimals > **baseDecimals**: `number` Defined in: packages/sdk/src/fills.ts:637 *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/fills.ts:638 *** ### asset > **asset**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:640 Underlying asset label (BINARY); null on SPOT/PERP. *** ### question > **question**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:642 The market's question text (BINARY); null on SPOT/PERP. --- # /docs/typescript/api/index/type-aliases/MarketReferenceLink [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketReferenceLink # Type Alias: MarketReferenceLink > **MarketReferenceLink** = `object` Defined in: packages/sdk/src/binary/settlement.ts:460 The oracle reference a market binds to (mirror of the indexer `MarketReferenceLink` entity). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/settlement.ts:462 Entity id (== the lowercased marketId). *** ### market > **market**: `string` Defined in: packages/sdk/src/binary/settlement.ts:464 Market id (lowercased bytes32). *** ### oracleQuestionId > **oracleQuestionId**: `string` Defined in: packages/sdk/src/binary/settlement.ts:466 Reference question id the market resolves against (decimal string). *** ### pending > **pending**: `boolean` Defined in: packages/sdk/src/binary/settlement.ts:471 True once the market has its own answer but the reference question is not yet final (resolution still pending on the reference). *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/binary/settlement.ts:473 Block of the most recent write to this link (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/binary/settlement.ts:479 Timestamp (unix seconds) of the most recent write to this link. While `pending` is true this is when the market went pending, so it is the age of the stall rather than the age of the link. --- # /docs/typescript/api/index/type-aliases/MarketResolutionActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketResolutionActivity # Type Alias: MarketResolutionActivity > **MarketResolutionActivity** = [`MarketActivityBase`](MarketActivityBase.md) & `object` Defined in: packages/sdk/src/activity.ts:148 The oracle acting on the market. BINARY only. `outcome` is the indexer's own word for what happened, so a caller can show a market that failed to resolve as distinct from one that resolved. ## Type Declaration ### kind > **kind**: `"RESOLUTION"` ### outcome > **outcome**: `string` `Resolved`, `Skipped` or `Failed`. ### outcomeIdx > **outcomeIdx**: `number` \| `null` The winning outcome index (0 = YES, 1 = NO), derived from a one-hot payout vector. Null on a void, a `Skipped` and a `Failed`. ### voided > **voided**: `boolean` \| `null` True when the market resolved void. Null when the event carried no verdict. --- # /docs/typescript/api/index/type-aliases/MarketResolutionEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketResolutionEvent # Type Alias: MarketResolutionEvent > **MarketResolutionEvent** = `object` Defined in: packages/sdk/src/binary/settlement.ts:421 One market-resolution lifecycle event (mirror of the indexer `MarketResolutionEvent` entity). Oracle v2: resolution is delivered as a payout VECTOR (`MarketResolved(marketId, qid, payoutDenominator, payoutNumerators, voided)`); `winningOutcome` stays as the binary-compat derivation of a one-hot vector. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/settlement.ts:423 Event id (`${blockNumber}_${logIndex}`). *** ### market > **market**: `string` Defined in: packages/sdk/src/binary/settlement.ts:425 Market id (lowercased bytes32). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/binary/settlement.ts:427 Resolution kind, e.g. "Resolved" | "Skipped" | "Failed" (indexer-defined). *** ### winningOutcome > **winningOutcome**: `number` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:432 Winning outcome (0 = YES, 1 = NO), derived from a one-hot payout vector; null on void / skip / non-one-hot vectors. *** ### payoutNumerators? > `optional` **payoutNumerators?**: `string`[] \| `null` Defined in: packages/sdk/src/binary/settlement.ts:438 Per-outcome payout numerators delivered with the event (decimal strings; raw Σ == payoutDenominator). Null on events indexed before the vector wire / kinds that carry none. *** ### payoutDenominator? > `optional` **payoutDenominator?**: `string` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:443 Vector denominator (`PAYOUT_VECTOR_DENOMINATOR` = 10_000_000; decimal string). Null when no vector was carried. *** ### voided? > `optional` **voided?**: `boolean` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:445 True when the market was voided (uniform vector) rather than resolved. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/binary/settlement.ts:447 Block the event landed in (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/binary/settlement.ts:449 Timestamp (unix seconds) of the event. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/binary/settlement.ts:451 Tx hash the event landed in. --- # /docs/typescript/api/index/type-aliases/MarketResolutionKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketResolutionKind # Type Alias: MarketResolutionKind > **MarketResolutionKind** = `"Resolved"` \| `"Skipped"` \| `"Failed"` Defined in: packages/sdk/src/binary/settlement.ts:592 The `kind` discriminator on [MarketResolutionEvent](MarketResolutionEvent.md), as a union — the three outcomes `BinaryMarketsModule` can record for one delivery attempt. `Resolved` is the success. The other two both leave the market UNRESOLVED with no on-chain retry: `Skipped` is an answer the market could not consume (wrong denominator, wrong vector length, or a raw sum that differs from the denominator), and `Failed` is a per-market `resolve` / `voidMarket` call that reverted inside the module's fan-out over one oracle question. Used as the FILTER type on [ListMarketResolutionEventsOptions.kinds](../interfaces/ListMarketResolutionEventsOptions.md#kinds) rather than on the row, deliberately. [MarketResolutionEvent.kind](MarketResolutionEvent.md#kind) stays a `string` because it mirrors an indexer-defined column and narrowing a value callers already read would break them for no gain. The filter is where a typo is dangerous: it is matched exactly and never lowercased, so `"skipped"` would match nothing and the empty page would read as "no market failed to resolve" — the reading this exists to make impossible. --- # /docs/typescript/api/index/type-aliases/MarketStatusActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketStatusActivity # Type Alias: MarketStatusActivity > **MarketStatusActivity** = [`MarketActivityBase`](MarketActivityBase.md) & `object` Defined in: packages/sdk/src/activity.ts:166 A lifecycle transition, such as Trading to Locked. BINARY only. ## Type Declaration ### kind > **kind**: `"STATUS"` ### oldStatus > **oldStatus**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Status before the transition. ### newStatus > **newStatus**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Status after the transition. --- # /docs/typescript/api/index/type-aliases/MarketStatusUpdate [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketStatusUpdate # Type Alias: MarketStatusUpdate > **MarketStatusUpdate** = `object` Defined in: packages/sdk/src/markets.ts:1332 One entry in a market's lifecycle audit trail (from the indexer's MarketStatusUpdate entity). ## Properties ### oldStatus > **oldStatus**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Defined in: packages/sdk/src/markets.ts:1334 Status before the transition. *** ### newStatus > **newStatus**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Defined in: packages/sdk/src/markets.ts:1336 Status after the transition. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/markets.ts:1338 Block the transition landed in (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/markets.ts:1340 Timestamp (unix seconds) of the transition. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/markets.ts:1342 Tx hash the transition landed in. --- # /docs/typescript/api/index/type-aliases/MarketSupplyActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketSupplyActivity # Type Alias: MarketSupplyActivity > **MarketSupplyActivity** = [`MarketActivityBase`](MarketActivityBase.md) & `object` Defined in: packages/sdk/src/activity.ts:123 A complete-set mint, a merge, or a redemption — collateral crossing into or out of outcome tokens. BINARY only. Amounts are raw units. ## Type Declaration ### kind > **kind**: `"MINT_SET"` \| `"MERGE_SET"` \| `"REDEEM"` ### account > **account**: `string` Acting wallet, lowercased. ### amount > **amount**: `string` `REDEEM`: outcome tokens burned. `MINT_SET` / `MERGE_SET`: the size of the complete set, meaning the amount of EACH outcome. Raw outcome-token units. ### payout > **payout**: `string` \| `null` `REDEEM` only: collateral paid out, raw units. Null on a mint or a merge. ### routedVia > **routedVia**: `string` \| `null` The periphery entry the flow used — `NativeMint`, `Permit2Mint` or `NativeRedeem`. Null on a direct call to the module. --- # /docs/typescript/api/index/type-aliases/MarketTradeActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketTradeActivity # Type Alias: MarketTradeActivity > **MarketTradeActivity** = [`MarketActivityBase`](MarketActivityBase.md) & `object` Defined in: packages/sdk/src/activity.ts:85 A trade: one fill of one resting order by one incoming order. Amounts are raw units. `fillPrice` is quote units per whole base — on binary, the YES-probability scale. ## Type Declaration ### kind > **kind**: `"TRADE"` ### pool > **pool**: `string` Pool the fill executed on, lowercased. ### fillPrice > **fillPrice**: `string` Execution price, raw quote units per whole base. ### quantity > **quantity**: `string` Base/outcome quantity filled, raw units. ### quoteQuantity > **quoteQuantity**: `string` Quote/collateral value of the fill, raw units. ### maker > **maker**: `string` \| `null` Maker (resting) wallet, lowercased; null when the indexer has not joined it. ### makerSide > **makerSide**: [`BinarySide`](BinarySide.md) \| `null` BINARY only — the maker's YES/NO side; null on spot and perp. ### taker > **taker**: `string` \| `null` Taker (aggressing) wallet, lowercased; null when the indexer has not joined it yet. Read from the taker's ORDER when the fill's own denormalized copy is absent. `Fill.taker` is populated only on spot, by a bridge that runs after the fill, so a binary trade names its taker through the order or not at all. ### takerSide > **takerSide**: [`BinarySide`](BinarySide.md) \| `null` BINARY only — the taker's YES/NO side; null on spot and perp. ### takerIsBid > **takerIsBid**: `boolean` \| `null` True when the taker bought the base (or YES) and the maker held the ask — the aggressor's direction. Null until the taker side is known. --- # /docs/typescript/api/index/type-aliases/MarketType [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MarketType # Type Alias: MarketType > **MarketType** = `"SPOT"` \| `"PERP"` \| `"BINARY"` Defined in: packages/sdk/src/markets.ts:34 The discriminator the whole market surface keys on — mirror of the indexer's `MarketType` enum. See the [Market](Market.md) union. --- # /docs/typescript/api/index/type-aliases/ObservedReadMethods [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadMethods # Type Alias: ObservedReadMethods > **ObservedReadMethods** = `Pick`\<[`SomniaMarketsClient`](../interfaces/SomniaMarketsClient.md), [`ObservedReadOperation`](ObservedReadOperation.md)\> Defined in: packages/sdk/src/observedReads.ts:127 Domain method contracts supported by observed read requests. These retain the owner client's argument and data types. --- # /docs/typescript/api/index/type-aliases/ObservedReadOperation [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadOperation # Type Alias: ObservedReadOperation > **ObservedReadOperation** = `"quoteBinaryStake"` \| `"quoteBinarySell"` \| `"getMarketStats24h"` \| `"getBinaryPositionPnL"` \| `"getOpenPositionsWithPnL"` \| `"getClaimable"` \| `"listMarkets"` \| `"listRegistryMarkets"` \| `"listRegistryMarketsChecked"` \| `"countMarkets"` \| `"countMarketsBounded"` \| `"getMarket"` \| `"listBinaryMarkets"` \| `"listLiveBinaryMarkets"` \| `"listBinaryVenueIds"` \| `"listBinaryAssets"` \| `"countBinaryMarkets"` \| `"countBinaryMarketsBounded"` \| `"listPastBinaryMarkets"` \| `"getBinaryMarket"` \| `"getBinaryMarketByAddress"` \| `"getMarketFees"` \| `"listSpotMarkets"` \| `"getSpotMarket"` \| `"getMarketStatusHistory"` \| `"listPerpMarkets"` \| `"getPerpMarket"` \| `"getCandles"` \| `"getMarketActivity"` \| `"getTransactionActivity"` \| `"getBlockActivity"` \| `"getLatestActiveBlock"` \| `"getAdjacentActiveBlocks"` \| `"getFills"` \| `"getTradeContext"` \| `"getUserFills"` \| `"getUserFillsPage"` \| `"getFillsPage"` \| `"getLatestFillBlock"` \| `"getFill"` \| `"getOrderFills"` \| `"getOrder"` \| `"getOpenOrders"` \| `"getOrders"` \| `"listSweepableOrders"` \| `"getOutcomeBalances"` \| `"getPortfolio"` \| `"getSpotPortfolio"` \| `"getSpotStopOrders"` \| `"getPerpPortfolio"` \| `"listPerpStopOrders"` \| `"listPerpOrderHistory"` \| `"getMarketByPool"` \| `"listMarketsByPool"` \| `"countOrders"` \| `"countUserFills"` \| `"getRouterActions"` \| `"getMarketResolution"` \| `"listMarketResolutionEvents"` \| `"listMarketReferenceLinks"` \| `"getOpeningPrices"` \| `"getResolutionPrices"` \| `"getBookTops"` \| `"listProtocolFees"` \| `"listBuilderFees"` \| `"listSettlementFees"` \| `"listBuilderApprovals"` \| `"getVaultPayoutFallbacks"` \| `"listVaultPayoutFallbacks"` \| `"getFundingPayments"` \| `"getMarginEvents"` \| `"listLiquidations"` \| `"getLiquidations"` \| `"getFundingRateHistory"` \| `"listFundingRateHistory"` \| `"listFundingRateCandles"` \| `"getOpenInterestHistory"` \| `"listPerpFees"` \| `"listPerpOrderRejections"` \| `"listPerpPositions"` \| `"listPerpInsuranceFundEvents"` \| `"listPerpWalletLinkEvents"` \| `"listPerpMarginPulls"` \| `"listPerpMainFundingEvents"` \| `"listPoolBindings"` \| `"getPool"` \| `"listOperators"` \| `"countOperators"` \| `"getOperator"` \| `"listVenues"` \| `"countVenues"` \| `"getVenue"` \| `"listMarketCreators"` \| `"getMarketCreator"` \| `"listOracleAdapters"` \| `"getOracleAdapter"` \| `"listSeries"` \| `"listSeriesLatestMarkets"` \| `"getSeries"` \| `"getOracleQuestion"` \| `"listOracleQuestions"` \| `"getOperatorHubAccount"` \| `"listOperatorHubAccounts"` \| `"listOracleBinds"` \| `"listOracleCallbacks"` Defined in: packages/sdk/src/observedReads.ts:19 Supported main-indexer operations. Price/oracle-service reads have no main-indexer watermark. --- # /docs/typescript/api/index/type-aliases/ObservedReadRequest [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadRequest # Type Alias: ObservedReadRequest\ > **ObservedReadRequest**\<`K`\> = `{ [P in K]: { operation: P; args: Parameters } }`\[`K`\] Defined in: packages/sdk/src/observedReads.ts:129 Arguments retain each existing domain method's parameter contract. ## Type Parameters ### K `K` *extends* [`ObservedReadOperation`](ObservedReadOperation.md) = [`ObservedReadOperation`](ObservedReadOperation.md) --- # /docs/typescript/api/index/type-aliases/ObservedReadsBatchError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadsBatchError # Type Alias: ObservedReadsBatchError > **ObservedReadsBatchError** = [`ObservedReadsReadError`](ObservedReadsReadError.md) Defined in: packages/sdk/src/observedReads.ts:163 A batch rejects on the first failed member; no partial success is fabricated. --- # /docs/typescript/api/index/type-aliases/ObservedReadsReadError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ObservedReadsReadError # Type Alias: ObservedReadsReadError > **ObservedReadsReadError** = [`IndexerError`](../classes/IndexerError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) \| [`FillHistoryUnavailableError`](../classes/FillHistoryUnavailableError.md) \| [`FillHistoryRestartRequiredError`](../classes/FillHistoryRestartRequiredError.md) \| [`InvariantError`](../classes/InvariantError.md) Defined in: packages/sdk/src/observedReads.ts:153 Failures of observed reads, including mixed-tier domain methods and their validation. --- # /docs/typescript/api/index/type-aliases/OpenInterestSnapshot [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OpenInterestSnapshot # Type Alias: OpenInterestSnapshot > **OpenInterestSnapshot** = `object` Defined in: packages/sdk/src/perp/history.ts:561 An open-interest snapshot (mirror of the indexer `OpenInterestSnapshot` entity). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:563 Snapshot id (`${pool}_${block}_${logIndex}`). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/history.ts:565 Perp pool (lowercased). *** ### openInterest > **openInterest**: `string` Defined in: packages/sdk/src/perp/history.ts:570 TOTAL open interest (raw base units) — one counter, not a long/short pair; see the `openInterest` field on [PerpMarket](PerpMarket.md) for why. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:572 Timestamp (unix seconds) of the snapshot. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/history.ts:574 Block the snapshot came from. --- # /docs/typescript/api/index/type-aliases/OpenOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OpenOrder # Type Alias: OpenOrder > **OpenOrder** = `object` Defined in: packages/sdk/src/orders.ts:138 A currently-open resting order (subset of the indexer `Order` entity), as returned by [SomniaMarketsClient.getOpenOrders](../interfaces/SomniaMarketsClient.md#getopenorders). [OrderRow](OrderRow.md) extends it with the lifecycle/fill-progress fields for order history. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/orders.ts:140 Order id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/orders.ts:142 uint128 OrderId as a decimal string (pass to trader.cancelOrder). *** ### market > **market**: `string` Defined in: packages/sdk/src/orders.ts:153 The market's bytes32 marketId — the STABLE identity of the market this order belonged to, and the key to label a historical row by. Use this, never `pool` alone: a binary pool is recycled across successive markets, so the same `pool` names a different market depending on when the order was placed. On SPOT/PERP the pool address IS the market id, so the two agree there. Pass it straight to [client.getMarket](../interfaces/SomniaMarketsClient.md#getmarket) for the full row. *** ### marketInfo > **marketInfo**: [`OrderMarket`](OrderMarket.md) \| `null` Defined in: packages/sdk/src/orders.ts:158 The market's labelling context, so a row can be NAMED without a second query. Null only if the indexer has no market row for the order. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/orders.ts:163 Lower-cased pool address the order rests on. A TIME-VARYING binding — see `market` for the identity that does not move. *** ### side > **side**: [`BinarySide`](BinarySide.md) \| `null` Defined in: packages/sdk/src/orders.ts:168 BINARY YES/NO classification; NULL on spot orders (the indexer only sets it for binary). For a buy/sell distinction that works on BOTH kinds use `isBid`. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/orders.ts:173 True = bid (buy), false = ask (sell). The canonical buy/sell flag — set for spot AND binary, unlike `side` which is null on spot. Colour/label off this. *** ### price > **price**: `string` Defined in: packages/sdk/src/orders.ts:175 Limit price, raw quote units per whole base (binary: YES-probability scale). *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/orders.ts:177 Unfilled remainder, raw base/outcome units. *** ### userData > **userData**: `string` Defined in: packages/sdk/src/orders.ts:187 The opaque uint64 tag the PLACEMENT carried, as a decimal string; `"0"` when the placement set none. The protocol stores it and never reads it, so its meaning is the caller's — it is how a client correlates a returned row with the order it sent, without keeping its own map from order ids. A decimal string rather than a number: the full uint64 range does not fit a JavaScript number. Filter on it with [OrdersOptions.userData](OrdersOptions.md#userdata). --- # /docs/typescript/api/index/type-aliases/OpenPositionPnL [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OpenPositionPnL # Type Alias: OpenPositionPnL > **OpenPositionPnL** = [`BinaryPositionPnL`](../interfaces/BinaryPositionPnL.md) & `object` Defined in: packages/sdk/src/binary/portfolio.ts:141 An open binary position joined with its reliable avg-cost PnL — the batched, positions-list companion to `getBinaryPositionPnL` (which is per market). `costBasis` / `avgCost` / `markValue` / `unrealizedPnl` / `realizedPnl` are RAW collateral units; format with `market.quoteDecimals`. Those fields are BLENDED across both outcomes; the inherited `outcomes` pair carries each book on its own. ## Type Declaration ### market > **market**: [`PortfolioMarket`](PortfolioMarket.md) The market the position is in (id / addresses / quoteDecimals / status / …). --- # /docs/typescript/api/index/type-aliases/OperatorFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OperatorFilter # Type Alias: OperatorFilter > **OperatorFilter** = `object` Defined in: packages/sdk/src/operatorAdmin.ts:578 Server-side filter for the operator directory. Every field optional (an omitted field does not constrain). Applied as a Hasura `where`. ## Properties ### owner? > `optional` **owner?**: `string` Defined in: packages/sdk/src/operatorAdmin.ts:580 Restrict to operators owned by this address (case-insensitive). *** ### enabled? > `optional` **enabled?**: `boolean` Defined in: packages/sdk/src/operatorAdmin.ts:582 Restrict to enabled (true) / disabled (false) operators. --- # /docs/typescript/api/index/type-aliases/OperatorHubAccountRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OperatorHubAccountRecord # Type Alias: OperatorHubAccountRecord > **OperatorHubAccountRecord** = `object` Defined in: packages/sdk/src/oracleHub.ts:924 An operator's hub account (mirror of the indexer `OperatorHubAccount` entity; id = operatorId decimal string) — the earmark-at-creation surface. Running totals derived from the hub events: `earmarked` (LOCKED, never withdrawable; == `outstanding × resolveReserve`), `credit` (WITHDRAWABLE surplus), and `outstanding` (bound-but-unresolved market count). Live/authoritative figures are the chain reads `earmarkedOf`/`creditOf`/`outstandingOf`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/oracleHub.ts:926 operatorId (decimal string == entity id). *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/oracleHub.ts:928 The operator the account belongs to (numeric form of `id`). *** ### earmarked > **earmarked**: `string` Defined in: packages/sdk/src/oracleHub.ts:930 Native LOCKED for outstanding markets (wei); Σ ReserveEarmarked − Σ released. *** ### credit > **credit**: `string` Defined in: packages/sdk/src/oracleHub.ts:932 Withdrawable surplus (wei): Σ SurplusCredited − Σ CreditWithdrawn. *** ### outstanding > **outstanding**: `string` Defined in: packages/sdk/src/oracleHub.ts:934 Bound-but-unresolved market count (binds − resolutions). *** ### createdAtBlock > **createdAtBlock**: `string` Defined in: packages/sdk/src/oracleHub.ts:936 Block the account first appeared in (decimal string). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/oracleHub.ts:938 Timestamp (unix seconds) the account first appeared. *** ### updatedAtBlock > **updatedAtBlock**: `string` Defined in: packages/sdk/src/oracleHub.ts:940 Block of the last update to the running totals (decimal string). *** ### updatedAtTimestamp > **updatedAtTimestamp**: `string` Defined in: packages/sdk/src/oracleHub.ts:942 Timestamp (unix seconds) of the last update to the running totals. --- # /docs/typescript/api/index/type-aliases/OracleAnswer [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleAnswer # Type Alias: OracleAnswer > **OracleAnswer** = `object` Defined in: packages/sdk/src/binary/settlement.ts:488 The numeric answer the oracle posted for a question (mirror of the indexer `OracleAnswer` entity). ## Properties ### oracleQuestionId > **oracleQuestionId**: `string` Defined in: packages/sdk/src/binary/settlement.ts:490 oracleQuestionId (decimal string == entity id). *** ### numericValue > **numericValue**: `string` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:492 Numeric answer the oracle posted (raw; interpretation is question-specific). *** ### outcomeLabel > **outcomeLabel**: `string` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:494 Human outcome label the oracle posted, if any. *** ### voidReason > **voidReason**: `number` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:496 Void reason code (non-null only on a voided answer). *** ### resolvedAt > **resolvedAt**: `string` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:498 Timestamp (unix seconds) the answer was posted; null until posted. *** ### txHash > **txHash**: `string` \| `null` Defined in: packages/sdk/src/binary/settlement.ts:500 Tx hash the answer was posted in; null until posted. --- # /docs/typescript/api/index/type-aliases/OracleBindRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleBindRecord # Type Alias: OracleBindRecord > **OracleBindRecord** = `object` Defined in: packages/sdk/src/oracleHub.ts:954 One market's bind on a question (mirror of the indexer `OracleBind` entity, Oracle v2 §8e). Opens with `MarketBound` (operator attribution; the paired `ReserveEarmarked` locks the reserve), stamped at resolution with `MarketResolveCharged` (exact metered charge + subsidy; a surplus is credited via `SurplusCredited`). Per-market conservation: `charged + subsidy == cost`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/oracleHub.ts:956 Bind id (`${oracleQuestionId}_${bindIndex}`). *** ### oracleQuestionId > **oracleQuestionId**: `string` Defined in: packages/sdk/src/oracleHub.ts:958 Question the bind belongs to (decimal string). *** ### bindIndex > **bindIndex**: `number` Defined in: packages/sdk/src/oracleHub.ts:960 1-based lifetime bind sequence on the question. *** ### operatorId > **operatorId**: `number` Defined in: packages/sdk/src/oracleHub.ts:962 Operator whose earmark funds this market's resolve. *** ### measuredGas > **measuredGas**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:964 gasleft()-wrapped measured gas of the resolve slice; null until resolved. *** ### overheadShare > **overheadShare**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:966 Pro-rata share of the callback overhead gas; null until resolved. *** ### cost > **cost**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:968 Exact wei the resolve cost worked out to; null until resolved. *** ### charged > **charged**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:973 Wei actually charged against this market's earmark; null until resolved (== min(cost, reserve)). *** ### subsidy > **subsidy**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:978 cost − charged: the reserve-capped shortfall the hub subsidised; null until resolved. *** ### resolvedAt > **resolvedAt**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:983 Timestamp the resolve cost was charged (`MarketResolveCharged`); null until resolved — the resolved flag is simply `resolvedAt != null`. *** ### boundAtBlock > **boundAtBlock**: `string` Defined in: packages/sdk/src/oracleHub.ts:985 Block the bind landed in (decimal string). *** ### boundAtTimestamp > **boundAtTimestamp**: `string` Defined in: packages/sdk/src/oracleHub.ts:987 Timestamp (unix seconds) of the bind. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/oracleHub.ts:989 Tx hash of the bind (the market-creation tx). --- # /docs/typescript/api/index/type-aliases/OracleCallbackRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleCallbackRecord # Type Alias: OracleCallbackRecord > **OracleCallbackRecord** = `object` Defined in: packages/sdk/src/oracleHub.ts:1003 One resolution callback's conservation record (mirror of the indexer `OracleCallback` entity ← the hub's `CallbackAccounted` event). NOT per-question (a callback drains across many qids). Invariants: `totalCost == (measuredGas + overheadGasAttributed) * gasPrice`; Σ of the callback's `OracleBindRecord.charged == totalCharged`; `totalCharged + subsidy == totalCost` (the subsidy is the hub's explicit reserve-capped shortfall). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/oracleHub.ts:1005 Callback id (`${blockNumber}_${logIndex}`). *** ### marketsResolved > **marketsResolved**: `string` Defined in: packages/sdk/src/oracleHub.ts:1007 Number of markets resolved in this callback. *** ### gasPrice > **gasPrice**: `string` Defined in: packages/sdk/src/oracleHub.ts:1009 `tx.gasprice` of the callback (wei). *** ### measuredGas > **measuredGas**: `string` Defined in: packages/sdk/src/oracleHub.ts:1011 Σ `gasleft()`-wrapped measured gas across the resolved markets. *** ### overheadGasAttributed > **overheadGasAttributed**: `string` Defined in: packages/sdk/src/oracleHub.ts:1013 The governance-calibrated `callbackBaseGas` term attributed on top. *** ### totalCost > **totalCost**: `string` Defined in: packages/sdk/src/oracleHub.ts:1015 Exact wei distributed: `(measuredGas + overhead) * gasPrice`. *** ### totalCharged > **totalCharged**: `string` Defined in: packages/sdk/src/oracleHub.ts:1017 Σ wei actually charged against market earmarks. *** ### subsidy > **subsidy**: `string` Defined in: packages/sdk/src/oracleHub.ts:1019 `totalCost − totalCharged`: the hub's explicit reserve-capped subsidy. *** ### pendingRemaining > **pendingRemaining**: `string` Defined in: packages/sdk/src/oracleHub.ts:1021 Markets still queued after this callback (0 = drain complete). *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/oracleHub.ts:1023 Block the callback landed in (decimal string). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/oracleHub.ts:1025 Timestamp (unix seconds) of the callback. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/oracleHub.ts:1027 Tx hash of the callback. --- # /docs/typescript/api/index/type-aliases/OracleQuestionRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OracleQuestionRecord # Type Alias: OracleQuestionRecord > **OracleQuestionRecord** = `object` Defined in: packages/sdk/src/oracleHub.ts:889 A hub-scheduled oracle question (mirror of the indexer `OracleQuestion` entity; id = oracleQuestionId as a decimal string). Tracks the content-addressed dedup state: the canonical key, who paid the oracle submission, and how many markets bound to it. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/oracleHub.ts:891 oracleQuestionId (decimal string == entity id). *** ### questionKey > **questionKey**: `string` \| `null` Defined in: packages/sdk/src/oracleHub.ts:896 Canonical dedup key (bytes32 hex); zero/null for non-template definitions that bypassed dedup. *** ### scheduler > **scheduler**: `string` Defined in: packages/sdk/src/oracleHub.ts:898 Caller that paid the oracle submission cost (lowercased). *** ### oracleCost > **oracleCost**: `string` Defined in: packages/sdk/src/oracleHub.ts:900 Native wei forwarded to the oracle for this submission. *** ### bindCount > **bindCount**: `number` Defined in: packages/sdk/src/oracleHub.ts:902 Lifetime bind count (from `MarketBound.bindCount`, monotonic). *** ### reuseCount > **reuseCount**: `number` Defined in: packages/sdk/src/oracleHub.ts:907 Times an identical definition deduplicated onto this question (`QuestionReused` count). *** ### createdAtBlock > **createdAtBlock**: `string` Defined in: packages/sdk/src/oracleHub.ts:909 Block the question was scheduled in (decimal string). *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/oracleHub.ts:911 Timestamp (unix seconds) the question was scheduled. --- # /docs/typescript/api/index/type-aliases/OrderDetail [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderDetail # Type Alias: OrderDetail > **OrderDetail** = [`OrderRow`](OrderRow.md) & `object` Defined in: packages/sdk/src/orders.ts:354 [OrderRow](OrderRow.md) plus placement attribution and the market it lives on — what [SomniaMarketsClient.getOrder](../interfaces/SomniaMarketsClient.md#getorder) returns for an order detail view. ## Type Declaration ### owner > **owner**: `string` Wallet that owns the order, lowercased. ### placedAtBlock > **placedAtBlock**: `string` Block the order was placed in (decimal string). ### lastUpdatedAtTimestamp > **lastUpdatedAtTimestamp**: `string` Timestamp (unix seconds) of the last indexed mutation to this order. ### marketRef > **marketRef**: [`MarketRef`](MarketRef.md) The market the order's pool serves. Named `marketRef` because main's `OpenOrder.market` is the bytes32 marketId string — see the note on [Fills.FillDetail](FillDetail.md). --- # /docs/typescript/api/index/type-aliases/OrderFillRow [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderFillRow # Type Alias: OrderFillRow > **OrderFillRow** = [`FillRow`](FillRow.md) & `object` Defined in: packages/sdk/src/fills.ts:615 A fill with its position in the chain — [FillRow](FillRow.md) plus the block and log index. What [SomniaMarketsClient.getOrderFills](../interfaces/SomniaMarketsClient.md#getorderfills) returns. ## Type Declaration ### blockNumber > **blockNumber**: `string` Block the fill landed in (decimal string). ### logIndex > **logIndex**: `number` Log index within the block (with blockNumber: the fill's id). --- # /docs/typescript/api/index/type-aliases/OrderMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderMarket # Type Alias: OrderMarket > **OrderMarket** = `object` Defined in: packages/sdk/src/orders.ts:76 The market context carried on every order row — enough to LABEL the row (asset, question, expiry, decimals) without a second read. For the full market pass the row's `market` id to [client.getMarket](../interfaces/SomniaMarketsClient.md#getmarket). The binary-only fields are null on SPOT and PERP, which is how the indexer stores them — an order read is not scoped by market kind, so a caller sees rows of every kind mixed together. ## Properties ### marketAddress > **marketAddress**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:78 The BinaryMarket clone contract's address (lowercased); null on SPOT/PERP. *** ### asset > **asset**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:80 Underlying asset symbol (e.g. "BTC"); null on SPOT/PERP. *** ### question > **question**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:82 Display question text; null on SPOT/PERP. *** ### expiry > **expiry**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:84 Timestamp (unix seconds) trading ends; null on SPOT/PERP. *** ### tradingStart > **tradingStart**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:86 Timestamp (unix seconds) trading opened; null on SPOT/PERP. *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/orders.ts:91 Collateral decimals (per-market — e.g. 6dp TestUSDC vs 18dp USDso). Format this row's `price` and quantities with it, never a hard-coded 6. *** ### intervalSec > **intervalSec**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:93 Series cadence in seconds, as the indexer derived it; null on SPOT/PERP and on legacy rows. *** ### interval > **interval**: `string` \| `null` Defined in: packages/sdk/src/orders.ts:99 Compact cadence label ("15m" / "1h" / "4h" / "24h") — DERIVED by the SDK from [OrderMarket.intervalSec](#intervalsec), matching `PortfolioMarket.interval`. Null when unknown. --- # /docs/typescript/api/index/type-aliases/OrderRow [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderRow # Type Alias: OrderRow > **OrderRow** = [`OpenOrder`](OpenOrder.md) & `object` Defined in: packages/sdk/src/orders.ts:301 An order row with its lifecycle status + fill progress (from [SomniaMarketsClient.getOrders](../interfaces/SomniaMarketsClient.md#getorders)). ## Type Declaration ### status > **status**: [`OrderStatus`](OrderStatus.md) Reconciled lifecycle status (Open/Filled/Cancelled/Expired/Closed). ### fullQuantity > **fullQuantity**: `string` Original order size, raw base/outcome units. ### filledQuantity > **filledQuantity**: `string` Cumulative filled quantity, raw base/outcome units. ### rested > **rested**: `boolean` Whether the order ever rested on the book (an `OrderRested` fired). ### expireTimestampNs > **expireTimestampNs**: `string` Order expiry as a uint64 nanosecond timestamp (decimal string). There is no GTC sentinel — the contract treats any future expiry as live, and this SDK writes GTC as now + 50 years (`farFutureNs`). The matcher rejects a 0/past expiry at placement, so "0" is never a live value. ### placedTxHash > **placedTxHash**: `string` Tx hash the order was placed in. ### placedAtTimestamp > **placedAtTimestamp**: `string` Timestamp (unix seconds) the order was placed. ### cancelReason > **cancelReason**: `string` \| `null` WHY the order was cancelled, when the PROTOCOL removed it rather than the owner. Null for an owner cancel and for orders that were never cancelled — so a `Cancelled` status with a null reason means the owner did it. SelfMatch same-owner match (the CancelMaker path) ExceedsPosition perps guard: the fill would push the maker past maxPositionSize NegativeEquity perps guard: the maker's equity would go negative StaleMark perps guard: the mark feed became unreadable, so an OPENING maker was pulled rather than filled against a dead reference price. A purely reducing maker is unaffected and still fills. PreFill the base pre-fill guard fired with no more specific tag `SelfMatch` is set on every pool type (spot, perp, binary); the perps-specific guards are perp-only by construction. On spot it also covers the pre-upgrade removals the indexer reconstructs for blocks before the pool emitted `OrderCancelledSelfMatch` (DEX-1236) — reconstructed and reported removals are deliberately indistinguishable here. ### amendedFromOrderId > **amendedFromOrderId**: `string` \| `null` Amendment linkage: the order this one REPLACED, and the one that replaced it. Lets an amend chain be followed rather than read as unrelated place/cancel pairs. Both null on an order that was never amended. ### amendedToOrderId > **amendedToOrderId**: `string` \| `null` --- # /docs/typescript/api/index/type-aliases/OrderStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrderStatus # Type Alias: OrderStatus > **OrderStatus** = `"Open"` \| `"Closed"` \| `"Filled"` \| `"Cancelled"` \| `"Expired"` Defined in: packages/sdk/src/store.ts:67 Order lifecycle — shared by spot and binary orders. Spot orders are born "Closed" and promoted to "Open" by OrderRested (mirror of the indexer). --- # /docs/typescript/api/index/type-aliases/OrdersOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OrdersOptions # Type Alias: OrdersOptions > **OrdersOptions** = `object` Defined in: packages/sdk/src/orders.ts:199 Options for [SomniaMarketsClient.getOpenOrders](../interfaces/SomniaMarketsClient.md#getopenorders) / [SomniaMarketsClient.getOrders](../interfaces/SomniaMarketsClient.md#getorders). All optional. ## Properties ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/orders.ts:201 Restrict to one pool. *** ### pools? > `optional` **pools?**: readonly `string`[] Defined in: packages/sdk/src/orders.ts:212 Restrict to orders on ANY of these pools (case-insensitive) — the batched form of `pool`, for folding several venues into one read. An empty array matches nothing. Supplying `pool` as well narrows to both (the intersection), so neither silently overrides the other. The list accepts at most 100 entries. A longer list rejects with [InvalidInputError](../classes/InvalidInputError.md). Each pool is resolved to its market scope, so a recycled BINARY pool still selects every market life of that pool, exactly as `pool` does. *** ### market? > `optional` **market?**: `string` Defined in: packages/sdk/src/orders.ts:219 Restrict to orders in one market (bytes32 marketId, case-insensitive). Prefer this over `pool` on binary, where one pool hosts successive markets: a market id names exactly one of them. *** ### markets? > `optional` **markets?**: readonly `string`[] Defined in: packages/sdk/src/orders.ts:226 Restrict to orders in ANY of these markets (bytes32 marketIds, case-insensitive) — the batched form of `market`. Same empty-array and intersection rules as `pools`. The list accepts at most 100 entries. A longer list rejects with [InvalidInputError](../classes/InvalidInputError.md). *** ### status? > `optional` **status?**: [`OrderStatus`](OrderStatus.md) Defined in: packages/sdk/src/orders.ts:228 Order status. [SomniaMarketsClient.getOrders](../interfaces/SomniaMarketsClient.md#getorders) only — [SomniaMarketsClient.getOpenOrders](../interfaces/SomniaMarketsClient.md#getopenorders) is always "Open". *** ### side? > `optional` **side?**: [`OpenOrder`](OpenOrder.md)\[`"side"`\] Defined in: packages/sdk/src/orders.ts:230 Restrict to one side. *** ### userData? > `optional` **userData?**: `bigint` \| `string` Defined in: packages/sdk/src/orders.ts:239 Restrict to orders placed with this client order id — the uint64 tag the placement carried (see [OpenOrder.userData](OpenOrder.md#userdata)). Pass a `bigint`, or a decimal string when the value came from a row and never needs arithmetic. The column is not indexed, so this filter is a scan on a large `Order` table. Narrow it with `pool`/`pools` and a status where the caller can. *** ### sinceBlock? > `optional` **sinceBlock?**: `number` \| `bigint` Defined in: packages/sdk/src/orders.ts:255 Restrict to orders PLACED at or after this block (`Order.placedAtBlock`). It selects orders by their placement block only. It does NOT select a later fill, reduction or cancellation of an older order: the entity has no last-mutation block column, so this is not an account order-change stream. An amend places a replacement under a new id, which this filter can select by that replacement's placement block. For an order placed before the bound, a fill read recovers only executions. Reconcile the known order's indexed lifecycle with `getOrder(pool, orderId)`, or use `getOrderOnchain(pool, orderId)` when only current active state is needed. The column is not indexed, so bound it with `pool`/`pools` where the caller can. Accepts the `bigint` a transaction receipt carries. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/orders.ts:257 Max rows. *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/orders.ts:259 Row offset (default 0). --- # /docs/typescript/api/index/type-aliases/OutcomeBalances [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OutcomeBalances # Type Alias: OutcomeBalances > **OutcomeBalances** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:30 A user's indexed YES/NO outcome-token balances in one binary market. Raw outcome-token units (same decimals as the market's collateral); "0" when the indexer has never seen the account touch that side. ## Properties ### yes > **yes**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:32 Raw YES balance ("0" if never held). *** ### no > **no**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:34 Raw NO balance ("0" if never held). --- # /docs/typescript/api/index/type-aliases/OutcomeIdx [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OutcomeIdx # Type Alias: OutcomeIdx > **OutcomeIdx** = `0` \| `1` Defined in: packages/sdk/src/ids.ts:36 A binary outcome index: 0 = YES, 1 = NO. --- # /docs/typescript/api/index/type-aliases/PastBinaryMarketsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PastBinaryMarketsOptions # Type Alias: PastBinaryMarketsOptions > **PastBinaryMarketsOptions** = [`BinaryMarketFilter`](BinaryMarketFilter.md) & `object` Defined in: packages/sdk/src/markets.ts:1446 Options for `listPastBinaryMarkets` — the [BinaryMarketFilter](BinaryMarketFilter.md) plus pagination + a `now` override. ## Type Declaration ### limit? > `optional` **limit?**: `number` Page size (default 50). ### offset? > `optional` **offset?**: `number` Row offset for cursoring the historical tail (default 0). ### nowSec? > `optional` **nowSec?**: `number` Override "now" (unix seconds); defaults to `Date.now()`. --- # /docs/typescript/api/index/type-aliases/PerpClosePreview [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpClosePreview # Type Alias: PerpClosePreview > **PerpClosePreview** = \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} \| \{ `priceable`: `true`; `asOfBlock`: `bigint`; `requestedQuantity`: `bigint`; `closedQuantity`: `bigint`; `remainingSize`: `bigint`; `fullClose`: `boolean`; `realizedPnl`: `bigint`; `fundingSettled`: `bigint`; `fee`: `bigint`; `netProceeds`: `bigint`; `placeable`: `boolean`; `fillPrice`: `bigint`; `markPrice`: `bigint`; `avgEntryPrice`: `bigint`; `lotSize`: `bigint`; `minQuantity`: `bigint`; \} Defined in: packages/sdk/src/perp/margin.ts:3347 What closing part or all of a position would realise. ## Union Members ### Type Literal \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero, so nothing can be marked. #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. *** ### Type Literal \{ `priceable`: `true`; `asOfBlock`: `bigint`; `requestedQuantity`: `bigint`; `closedQuantity`: `bigint`; `remainingSize`: `bigint`; `fullClose`: `boolean`; `realizedPnl`: `bigint`; `fundingSettled`: `bigint`; `fee`: `bigint`; `netProceeds`: `bigint`; `placeable`: `boolean`; `fillPrice`: `bigint`; `markPrice`: `bigint`; `avgEntryPrice`: `bigint`; `lotSize`: `bigint`; `minQuantity`: `bigint`; \} #### priceable > **priceable**: `true` #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. #### requestedQuantity > **requestedQuantity**: `bigint` What the caller asked to close, raw base units — **already normalised**. An omitted `quantity` or a `0n` one means "all", and both arrive here as `|size|` rather than `0n`, so an "all" request is not distinguishable from an explicit full-size one on the way out. Compare against closedQuantity to see what the lot grid took off. #### closedQuantity > **closedQuantity**: `bigint` What would ACTUALLY close: clamped to the position, then **aligned down to the pool's lot grid**. Below requestedQuantity whenever the position is not a lot multiple, which is what leaves a remainder open on a "close all". #### remainingSize > **remainingSize**: `bigint` SIGNED size still open afterwards. `0n` on a full close. #### fullClose > **fullClose**: `boolean` Whether closedQuantity takes the position all the way to flat. #### realizedPnl > **realizedPnl**: `bigint` Realised price PnL on the closed share, signed. `floor((fill − entry) × sign(size) × closedQuantity / oneBase)` — the port of `MarginBank._realizedPnlForClose`, which FLOORS toward −∞ so a gain is credited at most true and a loss debited at least true. A partial close leaves `avgEntryPrice` untouched, so the remainder keeps its original basis. #### fundingSettled > **fundingSettled**: `bigint` Funding settled by the close, signed and **positive means the account pays**. Measured on the **whole** position, not the closed share — `settleTrade` settles funding before it touches the position. This is the term a close modal most often gets wrong. #### fee > **fee**: `bigint` The fill's fee, signed — negative is a maker rebate. #### netProceeds > **netProceeds**: `bigint` The close's total effect on collateral: `realizedPnl − fundingSettled − fee`. The number to show. Funding and fee are costs, so they subtract; showing `realizedPnl` alone reports a position as more profitable to close than it is. #### placeable > **placeable**: `boolean` Whether closedQuantity clears the pool's `minQuantity`. `false` means the close cannot be placed at all — not that it is small. A dust position below the minimum can only leave via liquidation or ADL. It is the pool minimum and **nothing else**: `true` is not a promise the placement is accepted. See the note on reducing capacity in [SomniaMarketsClient.previewPerpClosePnl](../interfaces/SomniaMarketsClient.md#previewperpclosepnl). #### fillPrice > **fillPrice**: `bigint` The price the close was quoted at. #### markPrice > **markPrice**: `bigint` Current mark. #### avgEntryPrice > **avgEntryPrice**: `bigint` The position's entry basis, untouched by a partial close. #### lotSize > **lotSize**: `bigint` The pool's quantity grid — the value closedQuantity was aligned to, floored at `1n` so a pool reporting `0n` cannot hand back a divisor that throws. #### minQuantity > **minQuantity**: `bigint` The pool's minimum order quantity. --- # /docs/typescript/api/index/type-aliases/PerpFeeRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpFeeRecord # Type Alias: PerpFeeRecord > **PerpFeeRecord** = `object` Defined in: packages/sdk/src/perp/history.ts:504 A realized perp fee, rebate, or builder credit (mirror of the indexer `PerpFeeRecord` entity). The perps fee rail, which is NOT the binary/spot one — [client.listBuilderFees](../interfaces/SomniaMarketsClient.md#listbuilderfees) and friends read `BuilderFeeRecord` / `ProtocolFeeRecord`, written by the market modules. These rows come off `MarginBank`, and `kind` says which rail within it. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:506 Record id (`${txHash}_${logIndex}`). *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/history.ts:508 Account charged or credited (lowercased). *** ### pool > **pool**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:510 Perp pool (lowercased); null on account-scoped rows. *** ### amount > **amount**: `string` Defined in: packages/sdk/src/perp/history.ts:512 Amount moved (raw collateral, unsigned — read `isRebate` for the direction). *** ### isRebate > **isRebate**: `boolean` Defined in: packages/sdk/src/perp/history.ts:514 True on `Rebate` (a credit TO the account); false on `Fee` / `BuilderFee` (a debit). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/history.ts:529 Which rail: Fee taker/maker fee charged on a fill Rebate maker rebate paid back BuilderFee routing credit to a builder — the perps builder rail, previously unindexed while the spot and binary ones were not LiquidationFee stage-3 health-preserving liquidation fee, routed WHOLLY to an Insurance Fund tier (see `tier` / `fillNotional`) No `LiquidationFee` rows exist yet: the event is in the protocol ABI but not in the deployed implementation, and the subscription is staged ahead of the upgrade that brings it. *** ### insurancePortion > **insurancePortion**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:538 Portion of this fee routed to the Insurance Fund; null on `Rebate` / `BuilderFee`. A component OF `amount`, never an addition to it — summing both double-counts. On `Fee` it is a split of a larger fee; on `LiquidationFee` it equals `amount`, because that fee goes wholly to a tier. Written on both so `SUM(insurancePortion)` is the fund's fee inflow without special-casing the kind. *** ### tier > **tier**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:540 Insurance Fund tier credited (`LiquidationFee` only; `"0"` = general/unallocated). *** ### fillNotional > **fillNotional**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:546 The liquidation IOC's quote fill notional, which the fee's rate cap applied to (`LiquidationFee` only) — so the effective rate is reconstructible per row without tracking the penalty-bps admin parameter. *** ### builder > **builder**: `string` \| `null` Defined in: packages/sdk/src/perp/history.ts:548 Builder credited (`BuilderFee` only; lowercased). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:550 Timestamp (unix seconds). *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:552 Tx hash the fee landed in. --- # /docs/typescript/api/index/type-aliases/PerpFundingPayer [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpFundingPayer # Type Alias: PerpFundingPayer > **PerpFundingPayer** = \{ `funded`: `true`; `payer`: `Address`; \} \| \{ `funded`: `false`; `reason`: `"dormant"` \| `"unlinked"` \| `"isMain"`; \} Defined in: packages/sdk/src/perp/linkedWallet.ts:76 Whether a child's next position-increasing order would draw on a main's wallet, and whose. A discriminated union rather than a bare address, because zero from `quoteFundingPayer` collapses three genuinely different situations that a UI must not render identically: the rail is dormant, this wallet is unlinked, or this wallet IS a main. Narrow on `funded` first. ## Union Members ### Type Literal \{ `funded`: `true`; `payer`: `Address`; \} #### funded > **funded**: `true` A main would be debited for whatever this account's own wallet cannot cover. #### payer > **payer**: `Address` The main whose wallet would be debited. This is the live resolution, not the snapshot a past pull recorded — see [PerpMainFunding.payer](../interfaces/PerpMainFunding.md#payer) for that, and note the two can differ after an unlink and re-link. *** ### Type Literal \{ `funded`: `false`; `reason`: `"dormant"` \| `"unlinked"` \| `"isMain"`; \} #### funded > **funded**: `false` No main would be debited. `reason` says which of the three cases applies; only `unlinked` is something the user can change by linking. #### reason > **reason**: `"dormant"` \| `"unlinked"` \| `"isMain"` - `dormant` — the bank holds no registry address, so the feature is off for everyone on this deployment. Linking would not help. - `unlinked` — the rail is armed but this wallet has no main. - `isMain` — this wallet resolves to itself. Mains fund children, not the reverse; funding flows main->child only. --- # /docs/typescript/api/index/type-aliases/PerpHealthSnapshot [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpHealthSnapshot # Type Alias: PerpHealthSnapshot > **PerpHealthSnapshot** = \{ `priceable`: `true`; `oneBase`: `bigint`; `markPrice`: `bigint`; `projectedCumulativeFunding`: `bigint`; `effectiveImfBps`: `bigint`; `maintenanceMarginBps`: `bigint`; `closeOutMarginBps`: `bigint`; \} \| \{ `priceable`: `false`; \} Defined in: packages/sdk/src/perp/margin.ts:195 Every per-market input a margin or health calculation needs, sampled together. A discriminated union rather than a nullable struct because the contract's non-reverting variant returns an ALL-ZERO snapshot when the market is not priceable — and a `maintenanceMarginBps` of 0 silently reads as "no maintenance requirement", which is far more dangerous than a missing price. Narrow on `priceable` and the zeros are unreachable. ## Union Members ### Type Literal \{ `priceable`: `true`; `oneBase`: `bigint`; `markPrice`: `bigint`; `projectedCumulativeFunding`: `bigint`; `effectiveImfBps`: `bigint`; `maintenanceMarginBps`: `bigint`; `closeOutMarginBps`: `bigint`; \} #### priceable > **priceable**: `true` The pool's mark feed is fresh; every field below is real. #### oneBase > **oneBase**: `bigint` 10^decimals of the synthetic base asset — the divisor for notional math. #### markPrice > **markPrice**: `bigint` Fresh mark price, raw quote units per whole base. #### projectedCumulativeFunding > **projectedCumulativeFunding**: `bigint` Cumulative funding per unit INCLUDING unsettled intervals (1e18-scaled, signed). #### effectiveImfBps > **effectiveImfBps**: `bigint` The initial-margin factor actually in force, bps — OI-scaled when dynamic IMF is enabled, otherwise equal to [PerpRiskParams.initialMarginBps](../interfaces/PerpRiskParams.md#initialmarginbps). This, not the static base, is what the pool charges a new order. #### maintenanceMarginBps > **maintenanceMarginBps**: `bigint` Maintenance-margin threshold, bps (does not scale with OI). #### closeOutMarginBps > **closeOutMarginBps**: `bigint` Close-out / takeover threshold, bps. *** ### Type Literal \{ `priceable`: `false`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero, so the contract declined to produce a snapshot. Skip this market — do NOT substitute zeros or a previous reading. --- # /docs/typescript/api/index/type-aliases/PerpInsuranceFundEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpInsuranceFundEvent # Type Alias: PerpInsuranceFundEvent > **PerpInsuranceFundEvent** = `object` Defined in: packages/sdk/src/perp/system.ts:327 One movement in the InsuranceFund's tier ledger (mirror of the indexer `PerpInsuranceFundEvent` entity). Eight kinds share this row, and they are NOT interchangeable — most fields are populated for some kinds and null for the rest, so [PerpInsuranceFundEvent.kind](#kind) is the field to branch on first: | `kind` | What it records | Effect on the fund total | |---|---|---| | `BadDebtAuthorised` | coverage asked for and granted, per account | none — a summary | | `TierFunded` | a plain top-up | inflow | | `TierFundedFromSource` | a top-up drawn from the configured funding source | inflow | | `TierCredited` | the insurance share of a fee, booked by MarginBank | inflow | | `TierDebited` | the liquidation waterfall drew from a tier | outflow | | `TierWithdrawn` | an admin withdrawal | outflow | | `TierWithdrawnToTreasury` | an admin withdrawal routed to the treasury | outflow | | `TierAllocated` | a transfer from `tier` to `toTier` | **none** | **Gotchas.** - **Never sum `amount` bare.** It is populated on inflows, outflows and the internal move alike, so a plain total is gross turnover rather than a net position. Fold it BY `kind` using the table above, and remember `TierAllocated` nets to zero across the fund even though it moves wei between two tiers. - **`covered` is not an independent flow.** On a `BadDebtAuthorised` row it is the SUM of the `TierDebited` rows in the same transaction, so counting both double-counts the same wei. `requested > covered` is a PARTIAL grant, and `covered === "0"` is a REFUSAL — the only record the protocol keeps of one. - **`TierCredited` is a cross-plane duplicate.** It restates wei already recorded as `insurancePortion` on the fee plane ([client.listPerpFees](../interfaces/SomniaMarketsClient.md#listperpfees)), because `MarginBank._chargeFee` transfers the insurance share and then books the tier credit for the same amount. What this row adds is WHICH TIER received it, which the fee plane does not carry. Do not add the two together. - `kind` is a raw string, not a decoded union, for the same reason `Order.cancelReason` is: the vocabulary is the indexer's own — eight distinct events rather than a contract enum arriving as a `uint8` — so there is nothing to decode, and a kind a newer indexer emits reaches a consumer intact rather than becoming null. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/system.ts:329 Row id (`${txHash}_${logIndex}`). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/system.ts:331 Which of the eight movements this row is — branch on this before reading any other field. *** ### tier > **tier**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:336 The tier this row moves, or the SOURCE tier on `TierAllocated`. Null on `BadDebtAuthorised`, which is account-scoped rather than tier-scoped. *** ### toTier > **toTier**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:338 The DESTINATION tier (`TierAllocated` only). *** ### amount > **amount**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:343 Wei that actually MOVED, raw collateral units. Null on `BadDebtAuthorised`. Fold by `kind` — see the type note; a bare sum is turnover, not a balance. *** ### requested > **requested**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:345 Coverage ASKED FOR (`BadDebtAuthorised` only). *** ### covered > **covered**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:350 Coverage GRANTED (`BadDebtAuthorised` only) — the sum of the same-transaction `TierDebited` rows rather than an independent flow. `"0"` is a refusal. *** ### account > **account**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:352 The account whose bad debt was authorised (`BadDebtAuthorised` only), lowercased. *** ### counterparty > **counterparty**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:354 The funding source or the treasury, where the event names one (lowercased). *** ### caller > **caller**: `string` \| `null` Defined in: packages/sdk/src/perp/system.ts:356 Who triggered it, where the event names a caller distinct from the counterparty. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/system.ts:358 Timestamp (unix seconds) of the movement. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/system.ts:360 Block the movement landed in. *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/perp/system.ts:366 Position within the block. Load-bearing for ordering, not decoration: one authorisation debits SEVERAL tiers in the same block and transaction, and `id` leads with an unordered transaction hash, so nothing else can rank them. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/system.ts:368 Tx hash the movement landed in. --- # /docs/typescript/api/index/type-aliases/PerpLiquidationPreview [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpLiquidationPreview # Type Alias: PerpLiquidationPreview > **PerpLiquidationPreview** = \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} \| \{ `priceable`: `true`; `asOfBlock`: `bigint`; `markPrice`: `bigint`; `currentSize`: `bigint`; `currentLiquidationPrice`: `bigint` \| `null`; `projectedSize`: `bigint`; `projectedEntryPrice`: `bigint`; `realizedPnl`: `bigint`; `fee`: `bigint`; `projectedEquity`: `bigint`; `projectedMmReq`: `bigint`; `projectedLiquidationPrice`: `bigint` \| `null`; `projectedPositionLeverageBps`: `bigint` \| `null`; \} Defined in: packages/sdk/src/perp/margin.ts:3053 Where an order would put the liquidation price if it filled — and where it sits now, for the comparison that is the actual question. A discriminated union: an unpriceable market yields no preview, because the mark is an input to every field below. Narrow on `priceable` first. ## Union Members ### Type Literal \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero, so there is nothing to project against — and an order with an increasing leg would revert on the contract's own freshness gate anyway. #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. *** ### Type Literal \{ `priceable`: `true`; `asOfBlock`: `bigint`; `markPrice`: `bigint`; `currentSize`: `bigint`; `currentLiquidationPrice`: `bigint` \| `null`; `projectedSize`: `bigint`; `projectedEntryPrice`: `bigint`; `realizedPnl`: `bigint`; `fee`: `bigint`; `projectedEquity`: `bigint`; `projectedMmReq`: `bigint`; `projectedLiquidationPrice`: `bigint` \| `null`; `projectedPositionLeverageBps`: `bigint` \| `null`; \} #### priceable > **priceable**: `true` #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. A projection is a statement about THIS block, not about the block the order fills in. Every field moves with the mark, so re-quote near send time for anything close to the edge. #### markPrice > **markPrice**: `bigint` Mark price the whole projection is measured against. #### currentSize > **currentSize**: `bigint` SIGNED position size before the fill, raw base units. #### currentLiquidationPrice > **currentLiquidationPrice**: `bigint` \| `null` Liquidation price of the position as it stands NOW, or `null` when flat. Identical to `client.getLiquidationPrice` at this block — same kernel, same inputs — so the two can be shown side by side without them disagreeing. #### projectedSize > **projectedSize**: `bigint` SIGNED position size after the fill; `0n` when the order closes out exactly. #### projectedEntryPrice > **projectedEntryPrice**: `bigint` Volume-weighted average entry price after the fill, raw quote per whole base. Follows `MarginBank.settleTrade`: the order's price on an OPEN or a FLIP, the floored VWAP of old and new on an INCREASE, and untouched on a reduce (a partial close does not re-price what remains). `0n` when the fill closes the position out, matching `_clearPosition`. #### realizedPnl > **realizedPnl**: `bigint` Realized PnL the fill books into the collateral balance (signed). Non-zero only for a reduce, close, or flip — an open or an increase realizes nothing. Floored toward −∞, matching `_realizedPnlForClose`. #### fee > **fee**: `bigint` Trading fee the fill would charge, raw collateral units — NEGATIVE for a maker rebate, which is a credit. Charged on fill notional at the pool's taker rate by default; pass `asMaker` for the maker rate. It reduces equity, so it moves the liquidation price, which is why it is modelled here even though [SomniaMarketsClient.previewPerpOrderMargin](../interfaces/SomniaMarketsClient.md#previewperpordermargin) (a question about the LOCK) has no reason to. #### projectedEquity > **projectedEquity**: `bigint` Account equity after the fill (signed) — the projection's numerator. `equity − uPnlBefore + uPnlAfter + realizedPnl − fee`, all at the current mark. Re-marking is what makes an adverse entry cost equity immediately: a position opens at the order's price but is marked at the mark, so the gap lands here. #### projectedMmReq > **projectedMmReq**: `bigint` Aggregate maintenance requirement after the fill — this market's contribution recomputed on the new size, with every other market's left exactly as the bank reported it. #### projectedLiquidationPrice > **projectedLiquidationPrice**: `bigint` \| `null` Liquidation price after the fill, or `null` when the order leaves the account flat in this market (nothing left to liquidate). Compare against currentLiquidationPrice: a same-side add moves it toward the mark, a reduce away from it. #### projectedPositionLeverageBps > **projectedPositionLeverageBps**: `bigint` \| `null` This position's leverage after the fill, bps of 1x — post-fill notional over post-fill equity. `null` on non-positive projected equity, as on [PerpLeverage.positionLeverageBps](../interfaces/PerpLeverage.md#positionleveragebps). --- # /docs/typescript/api/index/type-aliases/PerpMainFundingEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMainFundingEvent # Type Alias: PerpMainFundingEvent > **PerpMainFundingEvent** = `object` Defined in: packages/sdk/src/perp/linkedWallet.ts:452 One movement of a main's claim against a child (mirror of the indexer `PerpMainFundingEvent` entity). **Bank side**, and the running principal. - `Funded` — a main's wallet was debited for the child. `amount` moved; `payer` is the main; `outstandingPrincipal` is the claim after. - `Settled` — the child's own losses discharged part of the claim at a flat moment. **NO money moved**, so `amount` is null and `previousPrincipal` → `outstandingPrincipal` is the whole content. `payer` is null: a settle has no counterparty. - `Returned` — principal went home, by either signed route (`repayFunding` by the child or `recallFromChild` by the payer). Both settle against the SNAPSHOTTED payer, which is why `payer` here can differ from the child's current main. **Gotchas.** - **`amount` is null on `Settled`, and that is not missing data** — it is the point. Treating null as zero is right for a cash total and wrong for a claim total; the claim still fell, which `outstandingPrincipal` records. - Do not add these to [PerpMarginPull](PerpMarginPull.md) rows. Same wei, two sides. See the module header. - The live claim is [client.getPerpMainFunding](../interfaces/SomniaMarketsClient.md#getperpmainfunding) — a bank read. This is how it got there, not what it is now. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:454 Row id (`${txHash}_${logIndex}`). *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:456 The child account the claim is against (lowercased). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:458 `Funded` | `Settled` | `Returned`. *** ### payer > **payer**: `string` \| `null` Defined in: packages/sdk/src/perp/linkedWallet.ts:460 The main on the other side (lowercased). Null on `Settled`, which has no counterparty. *** ### amount > **amount**: `string` \| `null` Defined in: packages/sdk/src/perp/linkedWallet.ts:462 Wei that actually moved, raw collateral units. **Null on `Settled`** — see the type note. *** ### previousPrincipal > **previousPrincipal**: `string` \| `null` Defined in: packages/sdk/src/perp/linkedWallet.ts:464 The claim BEFORE this event (`Settled` only). *** ### outstandingPrincipal > **outstandingPrincipal**: `string` \| `null` Defined in: packages/sdk/src/perp/linkedWallet.ts:466 The claim after this event. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:468 Timestamp (unix seconds) of the movement. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:470 Block the movement landed in. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:472 Tx hash the movement landed in. --- # /docs/typescript/api/index/type-aliases/PerpMarginPull [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMarginPull # Type Alias: PerpMarginPull > **PerpMarginPull** = `object` Defined in: packages/sdk/src/perp/linkedWallet.ts:403 One leg of margin pulled to fund a placement (mirror of the indexer `PerpMarginPull` entity). **Pool side.** `source` names which wallet paid, and one placement can produce BOTH legs, in this order: - `OwnWallet` — the owner's own wallet funded it, sized by `min(balance, allowance)`. - `Main` — the residual reached the owner's linked MAIN, whose address is `payer`. So a child with no approval of its own contributes zero and the whole requirement arrives as one `Main` leg, while a partly-funded child produces two rows for one order. `amount` is what THIS leg pulled, never the order's total requirement — sum the legs sharing an `orderId` for that. **Gotcha.** Do not add these to [PerpMainFundingEvent](PerpMainFundingEvent.md) rows: the same wei appears on both sides. See the module header. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:405 Row id (`${txHash}_${logIndex}`). *** ### account > **account**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:407 The account credited, and whose position the order was for (lowercased). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:409 The PerpPool that pulled (lowercased). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:411 The order whose placement caused the pull — decimal string, matches `Order.orderId`. *** ### source > **source**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:413 `OwnWallet` | `Main` — which wallet paid this leg. *** ### amount > **amount**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:415 Wei pulled by THIS leg, raw collateral units — not the order's total requirement. *** ### payer > **payer**: `string` \| `null` Defined in: packages/sdk/src/perp/linkedWallet.ts:417 The main whose wallet was debited (`Main` only; null for `OwnWallet`), lowercased. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:419 Timestamp (unix seconds) of the pull. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:421 Block the pull landed in. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:423 Tx hash the pull landed in. --- # /docs/typescript/api/index/type-aliases/PerpMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMarket # Type Alias: PerpMarket > **PerpMarket** = [`BaseMarket`](BaseMarket.md) & `object` Defined in: packages/sdk/src/markets.ts:147 A perpetual-futures order-book market. Rides the same OrderBook core as spot (base/quote book, raw quote units per whole base), with a synthetic base: positions + collateral live cross-margin in the MarginBank, and the pool tracks funding against an oracle index price. ## Type Declaration ### marketType > **marketType**: `"PERP"` Discriminator (narrowed). ### baseToken > **baseToken**: `Address` Wrapper token standing in for the synthetic base (e.g. WBTC). ### quoteToken > **quoteToken**: `Address` The MarginBank collateral token (e.g. USDso). ### baseSymbol > **baseSymbol**: `string` \| `null` Synthetic-base symbol (e.g. "WBTC"); null when the wrapper exposes none. ### quoteSymbol > **quoteSymbol**: `string` \| `null` Collateral token symbol (e.g. "USDso"); null when the token exposes none. ### baseIsNative > **baseIsNative**: `boolean` Always false — the perp base is synthetic, never native. Kept so spot-shaped base/quote code paths can treat SPOT and PERP uniformly. ### tickSize > **tickSize**: `string` Price increment, raw quote units per whole base (decimal string). ### lotSize > **lotSize**: `string` Quantity increment, raw base units (decimal string). ### minQuantity > **minQuantity**: `string` Minimum order quantity, raw base units (decimal string). ### marginBank > **marginBank**: `Address` Cross-margin MarginBank holding collateral + positions (lowercased). ### initialMarginBps > **initialMarginBps**: `number` Initial margin requirement in bps (500 = 5% = 20x max leverage). ### stopRegistry > **stopRegistry**: `Address` \| `null` Per-pool PerpStopOrderRegistry (lowercased); null on pools without one. The registry is per-pool and every stop-order write takes it as an explicit `registry` argument ([Trader.placePerpStopOrder](../interfaces/Trader.md#placeperpstoporder), [Trader.cancelPerpStopOrder](../interfaces/Trader.md#cancelperpstoporder), [Trader.cancelPerpStopOrders](../interfaces/Trader.md#cancelperpstoporders)), so this is where that address comes from — same as `stopRegistry` on a [SpotMarket](SpotMarket.md). Null means the pool has no registry deployed, and TP/SL is unavailable on it rather than merely unfound. ### markPrice > **markPrice**: `string` \| `null` Mark price sampled at FUNDING cadence (raw quote per whole base). Shares the column with the spot mark price but is a different quantity, and the difference matters: - It advances only when funding settles — hourly on every live pool — not per trade. For a live mark, read the chain (`getPerpState().markPrice`, which also reports `markPriceOk`). - It is null whenever the contract emitted its 0 sentinel for a stale/reverting mark feed. A stale feed leaves the PREVIOUS value in place rather than zeroing it, so a non-null value here is not by itself evidence of freshness — compare `markPriceUpdatedAt` against the settlement cadence. - It is NOT what drives funding, and not mark versus index either — the two routinely disagree in sign. The premium is the time-weighted IMPACT-price premium (quantity-weighted fill price at a configured notional on each side, deadbanded against the index). Read `getPerpState().emaPremium` for the quantity funding actually uses. ### markPriceUpdatedAt > **markPriceUpdatedAt**: `string` \| `null` When `markPrice` last advanced (unix seconds); null until the first settlement. ### fundingRate > **fundingRate**: `string` \| `null` Funding rate for the last settlement window (1e18-scaled fraction, signed). Null until the first FundingUpdated is indexed. ### cumulativeFundingPerUnit > **cumulativeFundingPerUnit**: `string` \| `null` Cumulative funding per base unit since inception (1e18-scaled, signed). ### indexPrice > **indexPrice**: `string` \| `null` Oracle index price at the last funding update (raw quote per whole base). ### fundingUpdatedAt > **fundingUpdatedAt**: `string` \| `null` Timestamp (unix seconds) of the last FundingUpdated; null until the first. ### fundingWindowSec > **fundingWindowSec**: `number` \| `null` The rate's DENOMINATOR in seconds (`fundingCalculationWindowSec`), 28800 on every live pool. `fundingRate` above is per THIS window — not per settlement interval and not annualized. Pass it to [normalizeFundingRate](../functions/normalizeFundingRate.md) and friends; a hardcoded denominator produces a plausible-looking wrong chart rather than an error. ### fundingIntervalSec > **fundingIntervalSec**: `number` \| `null` Settlement cadence in seconds. **3600 on every live pool**, so `fundingWindowSec / fundingIntervalSec` is 8. It has been 300 (n = 96), and the same rate value means a 12x different per-interval accrual across that boundary — which is why this is carried per row and never assumed. Indexed history still spans it. ### openInterest > **openInterest**: `string` \| `null` TOTAL open interest in base units. Replaces `longOpenInterest` / `shortOpenInterest`. The contract keeps ONE counter because the short side is provably equal in a matched CLOB, and the removed pair was null on every row anyway — the subscription feeding it was dead. ### openInterestUpdatedAt > **openInterestUpdatedAt**: `string` \| `null` Timestamp (unix seconds) of the last OpenInterestUpdated; null until the first. --- # /docs/typescript/api/index/type-aliases/PerpMarketFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMarketFilter # Type Alias: PerpMarketFilter > **PerpMarketFilter** = `object` Defined in: packages/sdk/src/markets.ts:1362 Filters for [SomniaMarketsClient.listPerpMarkets](../interfaces/SomniaMarketsClient.md#listperpmarkets). All optional; applied server-side. ## Properties ### baseSymbol? > `optional` **baseSymbol?**: `string` Defined in: packages/sdk/src/markets.ts:1364 Synthetic-base token symbol, e.g. `"WBTC"`. *** ### quoteSymbol? > `optional` **quoteSymbol?**: `string` Defined in: packages/sdk/src/markets.ts:1366 Collateral (quote) token symbol, e.g. `"USDso"`. --- # /docs/typescript/api/index/type-aliases/PerpMaxOrderSize [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMaxOrderSize # Type Alias: PerpMaxOrderSize > **PerpMaxOrderSize** = \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} \| \{ `priceable`: `true`; `asOfBlock`: `bigint`; `maxQuantity`: `bigint`; `unalignedMaxQuantity`: `bigint`; `increasingQuantity`: `bigint`; `reducingQuantity`: `bigint`; `lockAmount`: `bigint`; `topUpRequired`: `bigint`; `wallet`: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null`; `fundingPayer`: `Address` \| `null`; `mainWalletCapacity`: `bigint` \| `null`; `mainFundingBlocked`: `boolean`; `ownWalletPull`: `bigint`; `mainWalletPull`: `bigint`; `placeable`: `boolean`; `limitedBy`: [`PerpMaxOrderSizeLimit`](PerpMaxOrderSizeLimit.md); `lotSize`: `bigint`; `minQuantity`: `bigint`; `maxPositionSize`: `bigint`; `positionSize`: `bigint`; `markPrice`: `bigint`; `effectiveImfBps`: `bigint`; \} Defined in: packages/sdk/src/perp/margin.ts:2515 The largest order the account can actually place, or an unpriceable market. ## Union Members ### Type Literal \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero, so no size can be quoted. #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. *** ### Type Literal \{ `priceable`: `true`; `asOfBlock`: `bigint`; `maxQuantity`: `bigint`; `unalignedMaxQuantity`: `bigint`; `increasingQuantity`: `bigint`; `reducingQuantity`: `bigint`; `lockAmount`: `bigint`; `topUpRequired`: `bigint`; `wallet`: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null`; `fundingPayer`: `Address` \| `null`; `mainWalletCapacity`: `bigint` \| `null`; `mainFundingBlocked`: `boolean`; `ownWalletPull`: `bigint`; `mainWalletPull`: `bigint`; `placeable`: `boolean`; `limitedBy`: [`PerpMaxOrderSizeLimit`](PerpMaxOrderSizeLimit.md); `lotSize`: `bigint`; `minQuantity`: `bigint`; `maxPositionSize`: `bigint`; `positionSize`: `bigint`; `markPrice`: `bigint`; `effectiveImfBps`: `bigint`; \} #### priceable > **priceable**: `true` #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. A max size is a statement about THIS block. The adverse-gap term moves one-for-one with the mark, so a limit bid above a falling mark can afford less than quoted a block later. Re-quote near send time. #### maxQuantity > **maxQuantity**: `bigint` The largest quantity that passes every placement gate, **aligned down to the pool's lot grid** — what a Max button should fill in. `0n` when nothing can be placed. Check placeable before offering it: a size below the pool's `minQuantity` is not a small order, it is a revert. #### unalignedMaxQuantity > **unalignedMaxQuantity**: `bigint` maxQuantity before lot alignment. Diagnostic only — placing it would revert `InvalidQuantity`. #### increasingQuantity > **increasingQuantity**: `bigint` The part of maxQuantity that increases the position, and so locks. #### reducingQuantity > **reducingQuantity**: `bigint` The part absorbed by existing exposure, which locks nothing. This is why a max on the opposite side can exceed anything the collateral would fund: a reducing order trips neither gate, so the answer starts at the reducing capacity and only then adds what the margin can carry. #### lockAmount > **lockAmount**: `bigint` The collateral the pool would lock at maxQuantity. #### topUpRequired > **topUpRequired**: `bigint` What auto-pull would REQUEST in total at maxQuantity — `0n` unless `autoPull` was passed. **Show it beside the size**: at a wallet-limited max this is essentially the whole approved balance, and a trader clicking Max deserves to see the transfer before they sign it. Split it into ownWalletPull and mainWalletPull when a main is linked, so the trader sees which wallet pays what rather than reading the total as their own debit. #### wallet > **wallet**: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null` The owner's collateral-token balance and MarginBank allowance, `null` unless `autoPull` was passed. Read limitedBy to see which one bound. #### fundingPayer > **fundingPayer**: `Address` \| `null` The linked MAIN eligible to fund the residual, or `null` when the account funds itself. A funded child's max is bigger than its own wallet would allow, and this names the wallet that makes up the difference. Eligibility, not a debit — see [PerpOrderMarginPreview](PerpOrderMarginPreview.md) for the full contract. #### mainWalletCapacity > **mainWalletCapacity**: `bigint` \| `null` What fundingPayer can spend, `null` whenever the payer is. #### mainFundingBlocked > **mainFundingBlocked**: `boolean` The main's leg was withheld because the account owes a prior payer, so this max is what the owner's own funding reaches. See [PerpMaxOrderSizeLimit](PerpMaxOrderSizeLimit.md) `"mainFundingBlocked"`. #### ownWalletPull > **ownWalletPull**: `bigint` The share of topUpRequired the owner's own wallet supplies at maxQuantity. #### mainWalletPull > **mainWalletPull**: `bigint` The share fundingPayer supplies at maxQuantity, `0n` with no main. #### placeable > **placeable**: `boolean` Whether maxQuantity clears the pool's `minQuantity`. #### limitedBy > **limitedBy**: [`PerpMaxOrderSizeLimit`](PerpMaxOrderSizeLimit.md) Which gate stopped it going one lot higher. #### lotSize > **lotSize**: `bigint` The pool's quantity grid — every order must be a multiple. The value maxQuantity was actually aligned to, floored at `1n`. A pool reporting `0n` has no grid to speak of, and handing that back would give a caller a divisor that throws. #### minQuantity > **minQuantity**: `bigint` The pool's minimum order quantity. #### maxPositionSize > **maxPositionSize**: `bigint` The market's per-account position cap. #### positionSize > **positionSize**: `bigint` SIGNED existing position size. #### markPrice > **markPrice**: `bigint` The mark the adverse gap was measured against. #### effectiveImfBps > **effectiveImfBps**: `bigint` The OI-scaled IMF used, bps. --- # /docs/typescript/api/index/type-aliases/PerpMaxOrderSizeLimit [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpMaxOrderSizeLimit # Type Alias: PerpMaxOrderSizeLimit > **PerpMaxOrderSizeLimit** = `"collateral"` \| `"initialMargin"` \| `"maxPositionSize"` \| `"voucherBlocked"` \| `"walletBalance"` \| `"walletAllowance"` \| `"mainWallet"` \| `"mainFundingBlocked"` \| `"restricted"` \| `"isolated"` Defined in: packages/sdk/src/perp/margin.ts:2454 Which gate stopped the size going one lot higher. --- # /docs/typescript/api/index/type-aliases/PerpOrderHistoryRow [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderHistoryRow # Type Alias: PerpOrderHistoryRow > **PerpOrderHistoryRow** = [`PerpPortfolioOrder`](PerpPortfolioOrder.md) & `object` Defined in: packages/sdk/src/perp/portfolio.ts:286 A terminal (no longer working) perp order — the history counterpart to [PerpPortfolioOrder](PerpPortfolioOrder.md), which is open-orders only. Same fields plus the lifecycle ones that only matter once an order has stopped working: how it ended and when. ## Type Declaration ### status > **status**: [`OrderStatus`](OrderStatus.md) How the order ended. `Closed` is terminal, not transitional: every pool places an order as `Closed` and a following `OrderRested` promotes it to `Open`, so an IOC that partially filled without resting stays `Closed` forever. Reading it as "still working" would show a finished order as live. ### rested > **rested**: `boolean` Whether the order ever rested on the book (an `OrderRested` fired). ### expireTimestampNs > **expireTimestampNs**: `string` Expiry as a uint64 NANOsecond timestamp (decimal string) — note the unit, the rest of this row is unix seconds. GTC carries `type(uint64).max`. ### lastUpdatedAtTimestamp > **lastUpdatedAtTimestamp**: `string` Unix seconds of the last state change — effectively when the order ended. --- # /docs/typescript/api/index/type-aliases/PerpOrderMarginPreview [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderMarginPreview # Type Alias: PerpOrderMarginPreview > **PerpOrderMarginPreview** = \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} \| \{ `priceable`: `true`; `asOfBlock`: `bigint`; `increasingQuantity`: `bigint`; `reducingQuantity`: `bigint`; `lockAmount`: `bigint`; `initialMarginPortion`: `bigint`; `adverseGapPortion`: `bigint`; `leverageSurcharge`: `bigint`; `effectiveImfBps`: `bigint`; `markPrice`: `bigint`; `unlockedCollateral`: `bigint`; `equity`: `bigint`; `imRequirement`: `bigint`; `feeHeadroom`: `bigint`; `topUpRequired`: `bigint`; `wallet`: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null`; `fundingPayer`: `Address` \| `null`; `mainWalletCapacity`: `bigint` \| `null`; `mainFundingBlocked`: `boolean`; `walletCoversTopUp`: `boolean`; `ownWalletPull`: `bigint`; `mainWalletPull`: `bigint`; `hasCollateralForLock`: `boolean`; `meetsInitialMargin`: `boolean`; `voucherBlocked`: `boolean`; `restrictedBlocked`: `boolean`; `isolationBlocked`: `boolean`; `sufficient`: `boolean`; \} Defined in: packages/sdk/src/perp/margin.ts:1549 What a perp order will cost and whether it will be accepted, computed BEFORE sending it. A discriminated union: an unpriceable market yields no preview at all, because every component below needs the mark. Narrow on `priceable` first. ## Union Members ### Type Literal \{ `priceable`: `false`; `asOfBlock`: `bigint`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero. Placement of any order with an increasing leg would revert on the contract's own freshness gate, so there is nothing to preview — and no field here could be trusted if there were. #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. *** ### Type Literal \{ `priceable`: `true`; `asOfBlock`: `bigint`; `increasingQuantity`: `bigint`; `reducingQuantity`: `bigint`; `lockAmount`: `bigint`; `initialMarginPortion`: `bigint`; `adverseGapPortion`: `bigint`; `leverageSurcharge`: `bigint`; `effectiveImfBps`: `bigint`; `markPrice`: `bigint`; `unlockedCollateral`: `bigint`; `equity`: `bigint`; `imRequirement`: `bigint`; `feeHeadroom`: `bigint`; `topUpRequired`: `bigint`; `wallet`: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null`; `fundingPayer`: `Address` \| `null`; `mainWalletCapacity`: `bigint` \| `null`; `mainFundingBlocked`: `boolean`; `walletCoversTopUp`: `boolean`; `ownWalletPull`: `bigint`; `mainWalletPull`: `bigint`; `hasCollateralForLock`: `boolean`; `meetsInitialMargin`: `boolean`; `voucherBlocked`: `boolean`; `restrictedBlocked`: `boolean`; `isolationBlocked`: `boolean`; `sufficient`: `boolean`; \} #### priceable > **priceable**: `true` #### asOfBlock > **asOfBlock**: `bigint` The block every read was pinned to. A preview is a statement about THIS block, not about the block the order lands in. The adverse-gap component moves one-for-one with the mark, so a limit bid above a falling mark locks more than quoted and either gate can flip. Re-quote near send time for anything close to the edge. #### increasingQuantity > **increasingQuantity**: `bigint` The part of the order that increases the position — the only part that locks. #### reducingQuantity > **reducingQuantity**: `bigint` The part absorbed by existing exposure. Locks nothing. #### lockAmount > **lockAmount**: `bigint` Total collateral the pool will lock (raw quote units) — the honest "margin required". #### initialMarginPortion > **initialMarginPortion**: `bigint` The initial-margin component of lockAmount, at the effective (OI-scaled) IMF. #### adverseGapPortion > **adverseGapPortion**: `bigint` The adverse mark-to-entry component of lockAmount, zero on a favourable entry. A position opens at the order's price but is marked at the current mark, so a buy above mark (or sell below) is born underwater by that gap; the pool reserves it on top of initial margin. This is the term a naive `notional × IMF` estimate misses, and the usual reason a "max" order sized that way gets rejected. #### leverageSurcharge > **leverageSurcharge**: `bigint` Extra margin demanded because the account set a per-market leverage cap STRICTER than the market's effective IMF. Zero when unset or looser. Charged on post-fill notional, and unlike the lock it comes out of free equity rather than being reserved. #### effectiveImfBps > **effectiveImfBps**: `bigint` The OI-scaled IMF actually applied, bps — not the static `initialMarginBps`. #### markPrice > **markPrice**: `bigint` Mark price the adverse gap was measured against. #### unlockedCollateral > **unlockedCollateral**: `bigint` Free collateral available to be locked. #### equity > **equity**: `bigint` Account equity (signed) before the lock. #### imRequirement > **imRequirement**: `bigint` Initial-margin requirement of EXISTING positions. #### feeHeadroom > **feeHeadroom**: `bigint` The pool's worst-case fee reserve for this order — an auto-pull addend, never part of lockAmount. See [PerpOrderMarginQuote.feeHeadroom](../interfaces/PerpOrderMarginQuote.md#feeheadroom). #### topUpRequired > **topUpRequired**: `bigint` What auto-pull would REQUEST in total, `0n` unless `autoPull` was passed. **Not the wallet spend once a main is in play** — that is ownWalletPull for the owner and mainWalletPull for the main, and an order form showing this figure as the child's debit over-states it by the main's leg. With no main the two coincide. See [PerpOrderMarginQuote.topUpRequired](../interfaces/PerpOrderMarginQuote.md#topuprequired), including the three cases where the pool declines and this reads `0n` for a reason other than "nothing needed". #### wallet > **wallet**: \{ `balance`: `bigint`; `allowance`: `bigint`; \} \| `null` The owner's collateral-token balance and MarginBank allowance, `null` unless `autoPull` was passed. Both bind on topUpRequired, and which one is short decides whether the fix is "approve more" or "fund the wallet". #### fundingPayer > **fundingPayer**: `Address` \| `null` The linked MAIN ELIGIBLE to fund what the owner's wallet cannot, or `null` when the account funds itself (unlinked, a main itself, or the rail is dormant) or `autoPull` was not passed. **Eligibility, not a debit.** This is resolved for every linked account on the `autoPull` path, including an order that needs no top-up at all and one whose own wallet covers the whole pull. Read mainWalletPull `> 0n` for the wallet that actually moves, and show THAT before the trader signs. #### mainWalletCapacity > **mainWalletCapacity**: `bigint` \| `null` What fundingPayer can spend — `MarginBank.quoteWalletCapacity(payer)`, i.e. `min(balance, allowance)`. `null` whenever fundingPayer is. #### mainFundingBlocked > **mainFundingBlocked**: `boolean` The main's leg is withheld because the account still owes a PRIOR payer, so `MarginBank.depositForFromMain` would revert `PriorFundingPayerOutstanding`. mainWalletPull is `0n` while this holds, whatever mainWalletCapacity says. Clear the old claim with `trader.repayPerpMainFunding`. #### walletCoversTopUp > **walletCoversTopUp**: `boolean` Both funding wallets together cover topUpRequired. See [PerpOrderMarginQuote.walletCoversTopUp](../interfaces/PerpOrderMarginQuote.md#walletcoverstopup). #### ownWalletPull > **ownWalletPull**: `bigint` The share of topUpRequired the owner's own wallet would supply — it pays first. See [PerpOrderMarginQuote.ownWalletPull](../interfaces/PerpOrderMarginQuote.md#ownwalletpull). #### mainWalletPull > **mainWalletPull**: `bigint` The share fundingPayer would supply, `0n` with no main. See [PerpOrderMarginQuote.mainWalletPull](../interfaces/PerpOrderMarginQuote.md#mainwalletpull). #### hasCollateralForLock > **hasCollateralForLock**: `boolean` Gate 1 — the unlocked balance covers the lock, after any auto-pull. Failing it reverts `InsufficientCollateral` before margin is even checked. Vacuously true when nothing is locked: the pool calls `lockCollateral` only `if (lockAmount > 0)`, so a purely reducing order never touches this gate even from a negative unlocked balance. Without `autoPull` it is measured against unlockedCollateral alone — see [PerpOrderMarginQuote.hasCollateralForLock](../interfaces/PerpOrderMarginQuote.md#hascollateralforlock). #### meetsInitialMargin > **meetsInitialMargin**: `boolean` Gate 2 — post-lock equity still covers the requirement: `equity + topUpRequired - lockAmount >= imRequirement + leverageSurcharge`. Vacuously true for a purely reducing order, which the pool exempts outright (`if (increasingQuantity > 0)`) on the grounds that closing can only improve account health. An account below initial margin can therefore always reduce. #### voucherBlocked > **voucherBlocked**: `boolean` The account holds a credit-voucher floor and this increasing order is barred outright — the market is not on the voucher allowlist, or the protocol's voucher leverage cap is unset. Placement reverts `VoucherMarketNotAllowed` / `VoucherLeverageCapNotSet`, whatever the margin numbers say. Distinct from the margin gates: when the market IS allowlisted, the voucher cap instead feeds the ordinary leverage path and shows up in leverageSurcharge rather than here. #### restrictedBlocked > **restrictedBlocked**: `boolean` The market is close-only and this order has an increasing leg, so placement reverts `MarketRestricted`. See [PerpOrderMarginQuote.restrictedBlocked](../interfaces/PerpOrderMarginQuote.md#restrictedblocked). #### isolationBlocked > **isolationBlocked**: `boolean` Isolated margin bars this market for this account, so placement reverts `IsolatedMarketBlocked` — the one gate here that blocks a reduce too. See [PerpOrderMarginQuote.isolationBlocked](../interfaces/PerpOrderMarginQuote.md#isolationblocked). #### sufficient > **sufficient**: `boolean` Every gate. The order should be accepted. --- # /docs/typescript/api/index/type-aliases/PerpOrderRejection [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderRejection # Type Alias: PerpOrderRejection > **PerpOrderRejection** = `object` Defined in: packages/sdk/src/perp/history.ts:1024 One order refused inside a batch placement (mirror of the indexer `PerpOrderRejection` entity). **Batch placements only.** `placeOrder` / `placeOrderFor` REVERT on the same conditions, and a reverted transaction discards its logs, so a singular placement leaves no row here — its reason arrives as a decoded revert instead. A batch keeps the accepted orders and records the refused ones, which is the only reason this history exists. There is no `Order` row to join to: a rejected request never rested and never filled. `requestIndex` is its position in the submitted batch, which is how a caller maps the row back to the request it sent. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/history.ts:1026 Row id (`${txHash}_${logIndex}`). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/perp/history.ts:1028 The order's owner (lowercased). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/perp/history.ts:1030 The PerpPool the batch was submitted to (lowercased). *** ### reason > **reason**: [`PerpOrderRejectionReason`](PerpOrderRejectionReason.md) \| `null` Defined in: packages/sdk/src/perp/history.ts:1041 The reason as a NAME, or `null` when the pool reported a member this SDK version does not know. Null rather than a default member, deliberately, and for the same reason the `intent` field on [PerpStopOrder](PerpStopOrder.md) does it: the enum appends — `DropReason` gained `NoFill` — and naming an unrecognized index would tell a caller the order was refused for a reason it was not. [PerpOrderRejection.reasonRaw](#reasonraw) still carries the index, so a null is never a lost row. *** ### reasonRaw > **reasonRaw**: `number` Defined in: packages/sdk/src/perp/history.ts:1050 The raw enum index, always present. Kept beside the decoded name because the indexer deliberately stores this un-decoded: a member added after the reindex still lands intact, and no row is ever lost to a name the indexer did not know. A consumer that wants to handle a newer-than-SDK reason reads this. *** ### requestIndex > **requestIndex**: `string` Defined in: packages/sdk/src/perp/history.ts:1052 The order's position in the submitted batch — how to map the row back to the request. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/history.ts:1054 Timestamp (unix seconds) of the rejection. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/history.ts:1056 Block the rejection landed in. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/history.ts:1058 Tx hash the batch landed in. --- # /docs/typescript/api/index/type-aliases/PerpOrderRejectionReason [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpOrderRejectionReason # Type Alias: PerpOrderRejectionReason > **PerpOrderRejectionReason** = *typeof* [`PERP_ORDER_REJECTION_REASON`](../variables/PERP_ORDER_REJECTION_REASON.md)\[`number`\] Defined in: packages/sdk/src/perp/history.ts:1006 A decoded [PerpOrderRejection.reason](PerpOrderRejection.md#reason). --- # /docs/typescript/api/index/type-aliases/PerpPoolStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPoolStatus # Type Alias: PerpPoolStatus > **PerpPoolStatus** = `object` Defined in: packages/sdk/src/perp/registry.ts:62 One factory-deployed perp market and whether it can actually be traded. **`restricted` and `registered` are independent gates that fail for unrelated reasons.** A market can be perfectly registered with the bank and still be close-only, or unrestricted and never activated. Both have to pass, which is what [tradeable](#tradeable) folds together. ## Properties ### pool > **pool**: `Address` Defined in: packages/sdk/src/perp/registry.ts:64 The PerpPool beacon proxy. *** ### baseToken > **baseToken**: `Address` Defined in: packages/sdk/src/perp/registry.ts:66 The synthetic base ERC-20 the market tracks. *** ### marginBank > **marginBank**: `Address` Defined in: packages/sdk/src/perp/registry.ts:76 The MarginBank this pool settles against, read from the pool itself. Effectively a per-network singleton, but taken per-pool because the pool is what the settlement path actually uses — so this is the bank a later `getMarginAccount` / `getPerpPosition` / `getLiquidationPrice` for this market must be addressed to. Carrying it here means a consumer never has to source it separately, and never has to hardcode it per chain. *** ### restricted > **restricted**: `boolean` Defined in: packages/sdk/src/perp/registry.ts:86 True when the market is CLOSE-ONLY: position-increasing orders revert `MarketRestricted`, while closes, reduces and cancels still work. Restricted markets stay visible on purpose — holders still have to close positions, cancel orders and withdraw collateral, and liquidation runs on them unchanged. Reversible: a restriction can be a temporary wind-down rather than a retirement. *** ### registered > **registered**: `boolean` \| `null` Defined in: packages/sdk/src/perp/registry.ts:104 Whether [marginBank](#marginbank) has this pool registered — the ACTIVATION gate. Coming from the factory only proves a pool is authentic; `addPerpPool` is the separate step that makes it usable, and `removePerpPool` revokes it. An unregistered pool rejects every settlement callback and every quote view while still reading as an ordinary market from the factory. `null` when the gate is genuinely unreadable, from either of two causes: the pool's MarginBank predates `isPerpPoolRegistered`, or that pool's bank reads failed while other pools' succeeded. Nothing substitutes for it — `getPoolTier` is itself gated on registration (so it collapses to 0 for both an uncovered-but-registered market and an unregistered one) and `getActivePerpPools` is per-account, not the registry. On the read-failure cause, [marginBank](#marginbank) is the zero address: the pool's own bank could not be established either, so do not address a settlement read to it. *** ### tradeable > **tradeable**: `boolean` \| `null` Defined in: packages/sdk/src/perp/registry.ts:112 Both gates passed — not restricted AND registered. The list to show as tradeable. `null` when [registered](#registered) is unknown: with one of the two gates unreadable, tradeability is genuinely undetermined, and reporting `false` would hide live markets while `true` would advertise dead ones. --- # /docs/typescript/api/index/type-aliases/PerpPortfolio [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPortfolio # Type Alias: PerpPortfolio > **PerpPortfolio** = `object` Defined in: packages/sdk/src/perp/portfolio.ts:126 A wallet's perp portfolio — the shape [SomniaMarketsClient.getPerpPortfolio](../interfaces/SomniaMarketsClient.md#getperpportfolio) returns. ## Properties ### account > **account**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:128 The queried account (lowercased). *** ### openOrders > **openOrders**: [`PerpPortfolioOrder`](PerpPortfolioOrder.md)[] Defined in: packages/sdk/src/perp/portfolio.ts:130 Currently-open perp orders, newest first. *** ### trades > **trades**: [`PerpPortfolioTrade`](PerpPortfolioTrade.md)[] Defined in: packages/sdk/src/perp/portfolio.ts:132 Recent perp fills the account participated in, newest first. *** ### tradesTruncated > **tradesTruncated**: `boolean` Defined in: packages/sdk/src/perp/portfolio.ts:140 The read hit its `tradesLimit`, so fills older than the last entry in `trades` exist and were NOT returned. Raise `tradesLimit` for the rest. A total folded from a truncated `trades` covers part of the history only. False when the page was short, and false for `tradesLimit: 0`, which asks for no trades at all. *** ### tradesSince > **tradesSince**: `number` Defined in: packages/sdk/src/perp/portfolio.ts:146 The lower time bound the trades leg was read with, unix seconds — `since` when passed, otherwise now minus seven days (`DEFAULT_TRADES_SINCE_SEC`). Echoed so a UI can label the list and a caller can page further back. Orders are not windowed. --- # /docs/typescript/api/index/type-aliases/PerpPortfolioMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPortfolioMarket # Type Alias: PerpPortfolioMarket > **PerpPortfolioMarket** = `object` Defined in: packages/sdk/src/perp/portfolio.ts:24 Perp market context attached to perp portfolio rows. id == poolAddress. ## Properties ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:26 Pool address (lowercased; == the market id for perp). *** ### baseSymbol > **baseSymbol**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:28 Synthetic-base symbol (e.g. "WBTC"); null when the wrapper exposes none. *** ### quoteSymbol > **quoteSymbol**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:30 Collateral token symbol (e.g. "USDso"); null when the token exposes none. *** ### baseDecimals > **baseDecimals**: `number` Defined in: packages/sdk/src/perp/portfolio.ts:32 Base-token decimals — format base quantities with this. *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/perp/portfolio.ts:34 Collateral decimals — format prices/collateral amounts with this. *** ### tickSize > **tickSize**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:36 Price increment, raw quote units per whole base (decimal string). *** ### lotSize > **lotSize**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:38 Quantity increment, raw base units (decimal string). *** ### minQuantity > **minQuantity**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:40 Minimum order quantity, raw base units (decimal string). *** ### lastPrice > **lastPrice**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:42 Last fill price (raw quote per whole base); null until first fill. *** ### marginBank > **marginBank**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:44 Cross-margin MarginBank holding collateral + positions (lowercased). *** ### initialMarginBps > **initialMarginBps**: `number` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:46 Initial margin requirement in bps (500 = 5% = 20x max leverage). *** ### fundingRate > **fundingRate**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:51 Funding rate for the last settlement window (1e18-scaled fraction, signed); null until the first FundingUpdated. *** ### indexPrice > **indexPrice**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:53 Oracle index price at the last funding update (raw quote per whole base). *** ### stopRegistry > **stopRegistry**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:62 Per-pool PerpStopOrderRegistry address (lowercased); null if the pool has none. Here for the same reason it is on [SpotPortfolioMarket](SpotPortfolioMarket.md): attaching a TP/SL to a row in this view needs the registry address, and every perp stop write takes it explicitly. The same column reaches a full market row as `stopRegistry` on [PerpMarket](PerpMarket.md). --- # /docs/typescript/api/index/type-aliases/PerpPortfolioOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPortfolioOrder # Type Alias: PerpPortfolioOrder > **PerpPortfolioOrder** = `object` Defined in: packages/sdk/src/perp/portfolio.ts:70 One currently-open order in a wallet's perp portfolio. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:72 Order id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:74 uint128 OrderId as a decimal string (pass to trader.cancelOrder). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/perp/portfolio.ts:76 True = bid (long), false = ask (short). *** ### price > **price**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:78 Limit price, raw quote units per whole base. *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:80 Unfilled remainder, raw base units. *** ### filledQuantity > **filledQuantity**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:82 Cumulative filled quantity, raw base units. *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:84 Original order size, raw base units. *** ### placedAtTimestamp > **placedAtTimestamp**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:86 Timestamp (unix seconds) the order was placed. *** ### placedTxHash > **placedTxHash**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:88 Tx hash the order was placed in. *** ### market > **market**: [`PerpPortfolioMarket`](PerpPortfolioMarket.md) Defined in: packages/sdk/src/perp/portfolio.ts:90 The market the order rests on. --- # /docs/typescript/api/index/type-aliases/PerpPortfolioTrade [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPortfolioTrade # Type Alias: PerpPortfolioTrade > **PerpPortfolioTrade** = `object` Defined in: packages/sdk/src/perp/portfolio.ts:98 One recent fill the wallet participated in (perp portfolio view). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:100 Fill id (`${blockNumber}_${logIndex}`). *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:102 Execution price, raw quote units per whole base. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:104 Base quantity filled, raw units. *** ### quoteQuantity > **quoteQuantity**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:106 Collateral value of the fill (raw, floored). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:108 Timestamp (unix seconds) of the fill. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/portfolio.ts:110 Tx hash the fill landed in. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/perp/portfolio.ts:112 Whether the account bought (went long) on this fill. *** ### asMaker > **asMaker**: `boolean` Defined in: packages/sdk/src/perp/portfolio.ts:114 Whether the account was the maker (resting) on this fill. *** ### counterparty > **counterparty**: `string` \| `null` Defined in: packages/sdk/src/perp/portfolio.ts:116 The other party's address, if known. *** ### market > **market**: [`PerpPortfolioMarket`](PerpPortfolioMarket.md) Defined in: packages/sdk/src/perp/portfolio.ts:118 The market the fill happened on. --- # /docs/typescript/api/index/type-aliases/PerpPositionAnalytics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpPositionAnalytics # Type Alias: PerpPositionAnalytics > **PerpPositionAnalytics** = `object` & [`PerpPositionMetrics`](../interfaces/PerpPositionMetrics.md) \| \{ `priceable`: `false`; `asOfBlock`: `bigint`; `pool`: `Address`; `size`: `bigint`; \} Defined in: packages/sdk/src/perp/margin.ts:947 One position's analytics as of a block, or the market reporting itself unpriceable. ## Union Members `object` & [`PerpPositionMetrics`](../interfaces/PerpPositionMetrics.md) *** ### Type Literal \{ `priceable`: `false`; `asOfBlock`: `bigint`; `pool`: `Address`; `size`: `bigint`; \} #### priceable > **priceable**: `false` The pool's mark feed is stale or zero, so nothing here can be marked. Render the row blank — do NOT substitute zeros, which would show a live position as flat — or drop it when `size` is `0n`. #### asOfBlock > **asOfBlock**: `bigint` The block the attempt was pinned to. #### pool > **pool**: `Address` The pool that could not be priced. #### size > **size**: `bigint` SIGNED position size, raw base units — the one figure that survives a dead mark feed, because the MarginBank read succeeded and only the pool's price read failed. `0n` means the account genuinely holds no position here: `activePerpPools` is has-position OR has-orders, so an order-only pool appears in this list with nothing to show. Use it to tell "a position nobody can price" from "no position at all" — nothing else here can. --- # /docs/typescript/api/index/type-aliases/PerpStopDropReason [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopDropReason # Type Alias: PerpStopDropReason > **PerpStopDropReason** = *typeof* [`PERP_STOP_DROP_REASON`](../variables/PERP_STOP_DROP_REASON.md)\[`number`\] Defined in: packages/sdk/src/perp/stops.ts:100 A drop reason, decoded from the on-chain enum index. --- # /docs/typescript/api/index/type-aliases/PerpStopIntent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopIntent # Type Alias: PerpStopIntent > **PerpStopIntent** = `"reduceOnly"` \| `"opening"` Defined in: packages/sdk/src/trade.ts:1482 Whether a triggered perp stop may only REDUCE the signer's position, or may open and increase one. Omitting it means `"reduceOnly"` — a take-profit or stop-loss, which is what every perp stop was before intent existed. `"opening"` is a stop-entry or breakout: it acquires exposure rather than shedding it, so the registry gates it on initial margin at creation instead of on holding a reducible position. --- # /docs/typescript/api/index/type-aliases/PerpStopOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrder # Type Alias: PerpStopOrder > **PerpStopOrder** = `object` Defined in: packages/sdk/src/perp/stops.ts:128 One take-profit / stop-loss order on a perp market. Rows from `listPerpStopOrders` don't include `limitPrice`. Fetch it for live stops with `getPerpStopOrders`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/stops.ts:130 Row id (`${registry}_${orderId}`). *** ### registry > **registry**: `string` Defined in: packages/sdk/src/perp/stops.ts:132 The PerpStopOrderRegistry holding it (lowercased). *** ### orderIdRaw > **orderIdRaw**: `string` Defined in: packages/sdk/src/perp/stops.ts:134 uint128 registry OrderId as a decimal string — pass to `trader.cancelStopOrder`. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/perp/stops.ts:136 The order's owner (lowercased). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/perp/stops.ts:138 True = the triggered order buys, false = sells. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/perp/stops.ts:140 Quantity in raw base units. *** ### triggerPrice > **triggerPrice**: `string` Defined in: packages/sdk/src/perp/stops.ts:142 The MARK price at which it fires, raw quote units per whole base. *** ### triggerOperator > **triggerOperator**: `number` Defined in: packages/sdk/src/perp/stops.ts:148 Which way the mark must cross `triggerPrice` to fire: `0` = GTE (fires at or above), `1` = LTE (fires at or below). This, not the side, is what makes a stop a take-profit or a stop-loss. *** ### orderType > **orderType**: `number` Defined in: packages/sdk/src/perp/stops.ts:150 `0` = LIMIT, `1` = MARKET — the type of order placed when it fires. *** ### builder > **builder**: `string` Defined in: packages/sdk/src/perp/stops.ts:152 Builder tagged on the resulting order (lowercased); zero address for none. *** ### builderFeeBpsTimes1k > **builderFeeBpsTimes1k**: `string` Defined in: packages/sdk/src/perp/stops.ts:160 The builder fee the triggered order will charge, in bps x 1000 — so `1500` is 1.5bps, not 1500bps. `"0"` when no builder is tagged. Only knowable from the creation event: the registry deletes a pending order on every fire, so after a trigger nothing on chain can say what fee was agreed. *** ### status > **status**: [`StopOrderStatus`](StopOrderStatus.md) Defined in: packages/sdk/src/perp/stops.ts:162 Lifecycle state — see [StopOrderStatus](StopOrderStatus.md). *** ### placedOrderId > **placedOrderId**: `string` \| `null` Defined in: packages/sdk/src/perp/stops.ts:164 The PerpPool order id created on a successful trigger; null otherwise. *** ### dropReason > **dropReason**: [`PerpStopDropReason`](PerpStopDropReason.md) \| `null` Defined in: packages/sdk/src/perp/stops.ts:173 Why a trigger placed nothing, decoded — null on a pending or successful order. Read it before calling a `TRIGGER_FAILED` order a failure: a reduce-only drop means the stop was overtaken by events (position already closed, flipped, or below minimum), which is ordinary. Only `PlacementFailed` is a rejection. SOMI is consumed on every fire regardless of outcome. *** ### siblingOrderId > **siblingOrderId**: `string` \| `null` Defined in: packages/sdk/src/perp/stops.ts:191 The LIVE OCO sibling's registry id, as a decimal string — null when this stop is unlinked, and null on every terminal row. Live is the whole contract, which is why every terminal write clears it. A pair's two rows leave at different times, so a pointer surviving on a departed row names an order whose own state has moved on: a client acting on "cancel the pair" would tear down a stop the trader deliberately kept armed. A leg that fires WITHOUT filling leaves its partner live and unlinked (back to null) — that is what lets the survivor be re-paired. Provenance is deliberately not here. Which leg retired this one is [PerpStopOrder.cancelReason](#cancelreason)'s job; overloading one column with "my live partner" and "the leg that retired me" is what would make a client act on the wrong one. *** ### intent > **intent**: [`PerpStopIntent`](PerpStopIntent.md) \| `null` Defined in: packages/sdk/src/perp/stops.ts:202 Whether the triggered order may only REDUCE the owner's position (`"reduceOnly"` — a take-profit / stop-loss) or may open and increase one (`"opening"` — a stop-entry / breakout, gated on initial margin at creation). `null` means the registry reported a member this SDK version does not know, and it is deliberately not folded into `"reduceOnly"`: calling an unknown member reduce-only would promise a caller that an order cannot increase their position when a newer member might let it. Treat null as "upgrade the SDK before acting on this". *** ### cancelReason > **cancelReason**: `string` \| `null` Defined in: packages/sdk/src/perp/stops.ts:224 WHY this stop reached `CANCELLED` — `"Owner"`, `"LinkedFill"` or `"Inert"`. Null on every row that is not cancelled. All three end the same way for the trader — the order is no longer working — but they are three different stories and **two different refunds**, so a UI that renders CANCELLED as "you cancelled this, SOMI refunded to your wallet" is wrong for two of them: - `"Owner"` — the owner cancelled it, and the SOMI is pushed back to them in that same transaction. - `"LinkedFill"` — the protocol retired it because its OCO sibling FILLED. - `"Inert"` — a keeper swept it after the registry's Schedule chain wound down. The last two only CREDIT `unclaimedSomi`; the trader recovers it via `claimSomi()`. A raw string rather than a decoded union, matching `Order.cancelReason`. The vocabulary is the indexer's own — three distinct events, not a contract enum arriving as a uint8 — so there is nothing to decode, and a value this SDK version has not heard of should reach a consumer intact rather than become null. *** ### createdAt > **createdAt**: `string` Defined in: packages/sdk/src/perp/stops.ts:226 Timestamp (unix seconds) the stop was created. *** ### updatedAt > **updatedAt**: `string` Defined in: packages/sdk/src/perp/stops.ts:228 Timestamp (unix seconds) of the last state change. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/stops.ts:230 Tx hash the stop was created in. *** ### market > **market**: [`PerpStopOrderMarket`](PerpStopOrderMarket.md) Defined in: packages/sdk/src/perp/stops.ts:232 The perp market it targets. --- # /docs/typescript/api/index/type-aliases/PerpStopOrderMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderMarket # Type Alias: PerpStopOrderMarket > **PerpStopOrderMarket** = `object` Defined in: packages/sdk/src/perp/stops.ts:107 The perp market a stop order targets. ## Properties ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/perp/stops.ts:109 Pool address (lowercased; == the market id for perp). *** ### baseSymbol > **baseSymbol**: `string` \| `null` Defined in: packages/sdk/src/perp/stops.ts:111 Synthetic-base symbol (e.g. "WBTC"); null when the wrapper exposes none. *** ### quoteSymbol > **quoteSymbol**: `string` \| `null` Defined in: packages/sdk/src/perp/stops.ts:113 Collateral token symbol; null when the token exposes none. *** ### baseDecimals > **baseDecimals**: `number` Defined in: packages/sdk/src/perp/stops.ts:115 Base-token decimals — format quantities with this. *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/perp/stops.ts:117 Collateral decimals — format the trigger price with this. --- # /docs/typescript/api/index/type-aliases/PerpStopOrderOnChain [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderOnChain # Type Alias: PerpStopOrderOnChain > **PerpStopOrderOnChain** = `object` Defined in: packages/sdk/src/perp/stops.ts:402 One stored perp stop, read straight from the registry. ## Properties ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/perp/stops.ts:404 True = the triggered order buys. *** ### owner > **owner**: `Address` Defined in: packages/sdk/src/perp/stops.ts:406 Owner (checksummed as the contract stores it). *** ### quantity > **quantity**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:408 Raw base units; `0n` means "the whole position at trigger". *** ### triggerPrice > **triggerPrice**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:410 Mark price that arms it. *** ### triggerOperator > **triggerOperator**: `number` Defined in: packages/sdk/src/perp/stops.ts:412 0 = GTE, 1 = LTE. *** ### orderType > **orderType**: `number` Defined in: packages/sdk/src/perp/stops.ts:414 0 = LIMIT, 1 = MARKET. *** ### limitPrice > **limitPrice**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:416 The LIMIT price — the one field the indexer cannot see, since no event carries it. *** ### builder > **builder**: `Address` Defined in: packages/sdk/src/perp/stops.ts:418 Builder tagged on the triggered order; zero address for none. *** ### builderFeeBpsTimes1k > **builderFeeBpsTimes1k**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:420 Builder fee in bps x 1000. *** ### somiPaid > **somiPaid**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:422 SOMI paid at creation. *** ### siblingOrderId > **siblingOrderId**: `bigint` Defined in: packages/sdk/src/perp/stops.ts:424 The linked sibling's id, or `0n` when unlinked. *** ### intent > **intent**: [`PerpStopIntent`](PerpStopIntent.md) \| `null` Defined in: packages/sdk/src/perp/stops.ts:434 `"reduceOnly"` or `"opening"` — `null` if the registry reported an intent this SDK version does not know. Null is deliberately not folded into `"reduceOnly"`. The registry appends to its enums, and calling an unknown member reduce-only would tell a caller an order cannot increase their position when a newer member might let it. Treat null as "upgrade the SDK before acting on this", not as a default. --- # /docs/typescript/api/index/type-aliases/PerpStopOrderRead [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderRead # Type Alias: PerpStopOrderRead > **PerpStopOrderRead** = \{ `status`: `"present"`; `order`: [`PerpStopOrderOnChain`](PerpStopOrderOnChain.md); \} \| \{ `status`: `"absent"`; \} \| \{ `status`: `"failed"`; `error`: [`PerpStopOrderReadError`](PerpStopOrderReadError.md); \} Defined in: packages/sdk/src/perp/stops.ts:454 One result from [SomniaMarketsClient.getPerpStopOrders](../interfaces/SomniaMarketsClient.md#getperpstoporders). A non-live stop is known absent. A failed chain call stays distinct because the caller cannot safely treat an unreadable stop as cancelled or triggered. --- # /docs/typescript/api/index/type-aliases/PerpStopOrderReadError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderReadError # Type Alias: PerpStopOrderReadError > **PerpStopOrderReadError** = [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/perp/stops.ts:446 A failed member of [PerpStopOrderRead](PerpStopOrderRead.md). --- # /docs/typescript/api/index/type-aliases/PerpStopOrderRef [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpStopOrderRef # Type Alias: PerpStopOrderRef > **PerpStopOrderRef** = `object` Defined in: packages/sdk/src/perp/stops.ts:438 One registry stop identifier for a batched chain read. ## Properties ### registry > **registry**: `Address` Defined in: packages/sdk/src/perp/stops.ts:440 The PerpStopOrderRegistry that owns the stop. *** ### orderId > **orderId**: `bigint` \| `string` Defined in: packages/sdk/src/perp/stops.ts:442 The registry's uint128 order identifier. --- # /docs/typescript/api/index/type-aliases/PerpVoucherEligibility [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpVoucherEligibility # Type Alias: PerpVoucherEligibility > **PerpVoucherEligibility** = \{ `eligible`: `true`; `grantAmount`: `bigint`; \} \| \{ `eligible`: `false`; `reason`: [`PerpVoucherIneligibleReason`](PerpVoucherIneligibleReason.md); \} Defined in: packages/sdk/src/perp/voucher.ts:102 Whether an account can claim a voucher now. Narrow on `eligible` first. ## Union Members ### Type Literal \{ `eligible`: `true`; `grantAmount`: `bigint`; \} #### eligible > **eligible**: `true` A claim sent now would succeed, unless state changes before it lands. #### grantAmount > **grantAmount**: `bigint` What the claim would credit, in raw collateral units. *** ### Type Literal \{ `eligible`: `false`; `reason`: [`PerpVoucherIneligibleReason`](PerpVoucherIneligibleReason.md); \} #### eligible > **eligible**: `false` A claim sent now would revert. #### reason > **reason**: [`PerpVoucherIneligibleReason`](PerpVoucherIneligibleReason.md) The first check that fails. See [PerpVoucherIneligibleReason](PerpVoucherIneligibleReason.md). --- # /docs/typescript/api/index/type-aliases/PerpVoucherIneligibleReason [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpVoucherIneligibleReason # Type Alias: PerpVoucherIneligibleReason > **PerpVoucherIneligibleReason** = `"dormant"` \| `"notStarted"` \| `"ended"` \| `"notFlat"` \| `"mainFunded"` \| `"alreadyClaimed"` \| `"budgetExhausted"` Defined in: packages/sdk/src/perp/voucher.ts:88 Why an account cannot claim a voucher right now. The reasons are checked in the order `VoucherDistributor.claim()` checks them, so the reason names the revert a claim would produce at the same block. - `dormant` — the bank has no credit granter. The programme is off for everyone. - `notStarted` — the campaign window has not opened (`CampaignInactive`). - `ended` — the campaign window has closed (`CampaignInactive`). - `notFlat` — the account holds a position or a resting order (`ClaimantNotFlat`). A voucher is starting capital for a new account, not a margin top-up. - `mainFunded` — the account carries principal from a linked main wallet (`ClaimantIsMainFunded`). The two programmes cannot share one balance. - `alreadyClaimed` — this address has claimed from this distributor before (`AlreadyClaimed`). The limit is once per address for the distributor's life. - `budgetExhausted` — the budget is below one grant (`BudgetExhausted`). --- # /docs/typescript/api/index/type-aliases/PerpWalletLinkEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PerpWalletLinkEvent # Type Alias: PerpWalletLinkEvent > **PerpWalletLinkEvent** = `object` Defined in: packages/sdk/src/perp/linkedWallet.ts:364 One state change in the linked-wallet consent graph (mirror of the indexer `PerpWalletLinkEvent` entity). Four kinds, and one of them is the only record that exists: - `Proposed` — a main offered a link. **The registry has no getter for a pending proposal**, so this row is the ONLY way a child learns one was made. Without it a pending offer is invisible to everything off-chain. - `ProposalCancelled` — the main withdrew the offer before it was accepted. A client showing an inbox must apply this, or it keeps offering a link that no longer stands. - `Linked` — the child accepted; the group exists from here. - `Unlinked` — either side tore the link down. Consent for the funding rail IS the link plus the allowance, with no separate opt-out flag, so this is the revocation event. **Gotcha.** This is the CONSENT graph, not the money layer. A `Linked` row grants no authority over funds by itself — the rail is dormant until the bank's `getLinkedWalletRegistry()` is non-zero and the main has given an allowance. Ask [client.quotePerpFundingPayer](../interfaces/SomniaMarketsClient.md#quoteperpfundingpayer) whether an order would actually spend a main's wallet; do not infer it from a link. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:366 Row id (`${txHash}_${logIndex}`). *** ### kind > **kind**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:368 `Proposed` | `ProposalCancelled` | `Linked` | `Unlinked`. *** ### main > **main**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:370 The main side of the pair (lowercased) — present on every kind. *** ### child > **child**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:372 The child side of the pair (lowercased) — present on every kind. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:374 Timestamp (unix seconds) of the change. *** ### blockNumber > **blockNumber**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:376 Block the change landed in. *** ### logIndex > **logIndex**: `number` Defined in: packages/sdk/src/perp/linkedWallet.ts:378 Position within the block — needed to order two changes to the same pair in one block. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/perp/linkedWallet.ts:380 Tx hash the change landed in. --- # /docs/typescript/api/index/type-aliases/PnlEventsForError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PnlEventsForError # Type Alias: PnlEventsForError > **PnlEventsForError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/derivedReads.ts:698 Errors raised by [pnlEventsFor](../functions/pnlEventsFor.md). --- # /docs/typescript/api/index/type-aliases/Portfolio [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / Portfolio # Type Alias: Portfolio > **Portfolio** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:318 A wallet's binary portfolio — the shape [SomniaMarketsClient.getPortfolio](../interfaces/SomniaMarketsClient.md#getportfolio) returns. ## Properties ### account > **account**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:320 The queried account (lowercased). *** ### positions > **positions**: [`PortfolioPosition`](PortfolioPosition.md)[] Defined in: packages/sdk/src/binary/portfolio.ts:322 Non-zero outcome-token positions (up to 200, largest balance first). *** ### openOrders > **openOrders**: [`PortfolioOrder`](PortfolioOrder.md)[] Defined in: packages/sdk/src/binary/portfolio.ts:324 Currently-open binary orders, newest first. *** ### trades > **trades**: [`PortfolioTrade`](PortfolioTrade.md)[] Defined in: packages/sdk/src/binary/portfolio.ts:326 Recent binary fills the account participated in, newest first. *** ### tradesTruncated > **tradesTruncated**: `boolean` Defined in: packages/sdk/src/binary/portfolio.ts:334 The read hit its `tradesLimit`, so fills older than the last entry in `trades` exist and were NOT returned. Raise `tradesLimit` for the rest. A total folded from a truncated `trades` covers part of the history only. False when the page was short, and false for `tradesLimit: 0`, which asks for no trades at all. *** ### tradesSince > **tradesSince**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:340 The lower time bound the trades leg was read with, unix seconds — `since` when passed, otherwise now minus seven days (`DEFAULT_TRADES_SINCE_SEC`). Echoed so a UI can label the list and a caller can page further back. Positions and orders are not windowed. --- # /docs/typescript/api/index/type-aliases/PortfolioFlowEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioFlowEvent # Type Alias: PortfolioFlowEvent > **PortfolioFlowEvent** = [`PortfolioTradeEvent`](../interfaces/PortfolioTradeEvent.md) \| [`PortfolioFundingEvent`](../interfaces/PortfolioFundingEvent.md) Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:159 One portfolio-affecting event, human USD-quote units. --- # /docs/typescript/api/index/type-aliases/PortfolioMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioMarket # Type Alias: PortfolioMarket > **PortfolioMarket** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:59 A market context attached to portfolio rows (subset of [BinaryMarket](BinaryMarket.md)). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:64 The market's bytes32 marketId (== `BinaryMarket.id`). Key positions by this, never by `poolAddress` alone (a pool is recycled across markets). *** ### marketAddress > **marketAddress**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:66 The BinaryMarket clone contract's address (lowercased). *** ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:68 The pool serving the market (lowercased; a time-varying binding — see `id`). *** ### asset > **asset**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:70 Underlying asset symbol (e.g. "BTC"). *** ### question > **question**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:72 Display question text. *** ### status > **status**: [`BinaryMarketStatus`](BinaryMarketStatus.md) Defined in: packages/sdk/src/binary/portfolio.ts:74 Lifecycle status (aliased from the indexer's `clobStatus`). *** ### lastPrice > **lastPrice**: `string` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:76 Last fill price (raw, ≈ YES probability × 10^quoteDecimals); null until first fill. *** ### strike > **strike**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:78 Strike the question resolves against (raw, oracle price scale). *** ### expiry > **expiry**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:80 Timestamp (unix seconds) trading ends. *** ### winningOutcome? > `optional` **winningOutcome?**: `number` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:82 Winning outcome (0 = YES, 1 = NO); null until Resolved / on a void. *** ### voided > **voided**: `boolean` Defined in: packages/sdk/src/binary/portfolio.ts:89 True once the market voided. A void redeems against [PortfolioMarket.payoutNumerators](#payoutnumerators) — a half per side under the `UNIFORM` void policy, `[p, D−p]` on a `CLOB_SNAPSHOT` void that captured a two-sided close. *** ### payoutNumerators? > `optional` **payoutNumerators?**: `string`[] \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:95 Per-outcome payout numerators the market settled to (decimal strings); what a void actually pays. Null until Resolved / on markets indexed before the vector fields existed. *** ### payoutDenominator? > `optional` **payoutDenominator?**: `string` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:97 Denominator the numerators are scaled against (decimal string); null with them. *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:103 Collateral decimals (per-market — collateral is per-venue, e.g. 6dp TestUSDC vs 18dp USDso). Format prices/balances with this, never a hard-coded 6. Outcome-token amounts mirror the same decimals. *** ### intervalSec > **intervalSec**: `string` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:105 Series cadence in seconds, as the indexer derived it; null on legacy rows. *** ### interval > **interval**: `string` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:111 Compact series-cadence label ("15m" / "1h" / "4h" / "24h") — DERIVED by the SDK from [PortfolioMarket.intervalSec](#intervalsec), so a positions/orders row can show the contract duration without re-deriving it. `null` when unknown. --- # /docs/typescript/api/index/type-aliases/PortfolioOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioOptions # Type Alias: PortfolioOptions > **PortfolioOptions** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:356 Paging/window options shared by the portfolio queries ([SomniaMarketsClient.getPortfolio](../interfaces/SomniaMarketsClient.md#getportfolio) / [SomniaMarketsClient.getSpotPortfolio](../interfaces/SomniaMarketsClient.md#getspotportfolio) / [SomniaMarketsClient.getPerpPortfolio](../interfaces/SomniaMarketsClient.md#getperpportfolio)). All optional. ## Properties ### ordersLimit? > `optional` **ordersLimit?**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:364 Max open orders to fetch (default 200). On SPOT this ALSO bounds `pendingStopOrders`: the spot query binds one limit variable to both sets, so a small value here shortens the stop-order list too, not just the open orders you asked about. *** ### tradesLimit? > `optional` **tradesLimit?**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:372 Max recent trades to fetch (default 50). The reads page newest-first, so this cap drops the OLDEST fills. Check `tradesTruncated` on the returned portfolio to see whether it did: the flag is true when `trades.length` reaches this limit. *** ### since? > `optional` **since?**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:378 Only trades at/after this unix-seconds timestamp. Defaults to now minus seven days (`DEFAULT_TRADES_SINCE_SEC`) — see that constant for why a bound is always applied. The bound actually used comes back as `tradesSince`. --- # /docs/typescript/api/index/type-aliases/PortfolioOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioOrder # Type Alias: PortfolioOrder > **PortfolioOrder** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:244 One currently-open order in a wallet's binary portfolio. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:246 Order id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:248 uint128 OrderId as a decimal string (pass to trader.cancelOrder). *** ### side > **side**: [`OpenOrder`](OpenOrder.md)\[`"side"`\] Defined in: packages/sdk/src/binary/portfolio.ts:250 YES/NO classification of the order. *** ### price > **price**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:252 Limit price, raw quote units (YES-probability scale). *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:254 Unfilled remainder, raw outcome units. *** ### filledQuantity > **filledQuantity**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:256 Cumulative filled quantity, raw outcome units. *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:258 Original order size, raw outcome units. *** ### placedAtTimestamp > **placedAtTimestamp**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:260 Timestamp (unix seconds) the order was placed. *** ### placedTxHash > **placedTxHash**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:262 Tx hash the order was placed in. *** ### market > **market**: [`PortfolioMarket`](PortfolioMarket.md) Defined in: packages/sdk/src/binary/portfolio.ts:264 The market the order rests on. --- # /docs/typescript/api/index/type-aliases/PortfolioPosition [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioPosition # Type Alias: PortfolioPosition > **PortfolioPosition** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:119 One outcome-token position in a wallet's binary portfolio. ## Properties ### market > **market**: [`PortfolioMarket`](PortfolioMarket.md) Defined in: packages/sdk/src/binary/portfolio.ts:121 The market the position is in. *** ### outcomeIndex > **outcomeIndex**: `number` Defined in: packages/sdk/src/binary/portfolio.ts:123 0 = YES, 1 = NO. *** ### tokenId > **tokenId**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:125 ERC-6909 position id on the outcome-token singleton (decimal string). *** ### balance > **balance**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:127 Raw outcome-token balance. --- # /docs/typescript/api/index/type-aliases/PortfolioTimeframe [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioTimeframe # Type Alias: PortfolioTimeframe > **PortfolioTimeframe** = `"24h"` \| `"7d"` \| `"30d"` \| `"all"` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:43 Time window for the metrics. --- # /docs/typescript/api/index/type-aliases/PortfolioTrade [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PortfolioTrade # Type Alias: PortfolioTrade > **PortfolioTrade** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:272 One recent fill the wallet participated in (binary portfolio view). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:274 Fill id (`${blockNumber}_${logIndex}`). *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:276 Execution price, raw quote units (YES-probability scale). *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:278 Outcome-token quantity filled, raw units. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:280 Timestamp (unix seconds) of the fill. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:282 Tx hash the fill landed in. *** ### side > **side**: [`OpenOrder`](OpenOrder.md)\[`"side"`\] \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:284 The queried account's side on this fill (maker or taker side), if known. *** ### asMaker > **asMaker**: `boolean` Defined in: packages/sdk/src/binary/portfolio.ts:286 Whether the account was the maker (resting) on this fill. *** ### counterparty > **counterparty**: `string` \| `null` Defined in: packages/sdk/src/binary/portfolio.ts:288 The other party's address, if known. *** ### market > **market**: `object` Defined in: packages/sdk/src/binary/portfolio.ts:290 Minimal market context for rendering the trade row. #### marketAddress > **marketAddress**: `string` The BinaryMarket clone contract's address (lowercased). #### asset > **asset**: `string` Underlying asset symbol (e.g. "BTC"). #### quoteDecimals > **quoteDecimals**: `number` Collateral decimals — format `fillPrice`/`quantity` with this. #### intervalSec > **intervalSec**: `string` \| `null` Series cadence in seconds, as the indexer derived it; null on legacy rows. #### interval > **interval**: `string` \| `null` Human timeframe label — `"15m"` / `"1h"` / `"4h"` / `"24h"` — DERIVED by the SDK from `intervalSec` (falling back to `expiry − tradingStart`) and snapped to its canonical unit. The "which timeframe was the trade for" value. Null when no cadence is determinable. #### tradingStart > **tradingStart**: `string` \| `null` Unix seconds trading opened; null on legacy rows. #### expiry > **expiry**: `string` \| `null` Unix seconds trading ends / the outcome is decided; null on legacy rows. --- # /docs/typescript/api/index/type-aliases/PositionMarkState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PositionMarkState # Type Alias: PositionMarkState > **PositionMarkState** = `"live"` \| `"won"` \| `"lost"` \| `"voided"` \| `"settling"` Defined in: packages/sdk/src/derivedReads.ts:1435 How a position should be marked, given its market's lifecycle: - `"live"` — still trading; mark to the live book. - `"won"` / `"lost"` — resolved; this outcome pays 1 or 0. - `"voided"` — cancelled; collateral refunds, zero PnL. - `"settling"` — expired but unresolved; no reliable mark exists. --- # /docs/typescript/api/index/type-aliases/PriceCandleResolution [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceCandleResolution # Type Alias: PriceCandleResolution > **PriceCandleResolution** = `"M1"` \| `"H1"` \| `"D1"` Defined in: packages/sdk/src/priceFeed/types.ts:33 Candle rollup resolutions the price-feed indexer maintains (60s / 3600s / 86400s). --- # /docs/typescript/api/index/type-aliases/PriceFeedHealth [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceFeedHealth # Type Alias: PriceFeedHealth > **PriceFeedHealth** = `"unwatched"` \| `"hydrating"` \| `"hydrated"` \| `"streaming"` \| `"stale"` \| `"error"` Defined in: packages/sdk/src/priceFeed/types.ts:232 Per-asset watch state: `"unwatched"` (no active watch — live reads return null/empty), `"hydrating"` (snapshot/subscribe in progress), `"hydrated"` (snapshot ready), `"streaming"` (both subscriptions delivered valid data), `"stale"` (known delivery loss; last values remain), `"error"` (the server rejected or terminated this asset's subscription). Treat `"error"` as "the data has stopped and will not resume on its own". Reads keep answering with the last values they held, so a view that renders them without checking the status shows a frozen price as a live one. The server sends this for a validation failure (a schema change) or a permission denial, so it will not heal by itself: stop the watch and start a new one. Each rejection is also emitted as a `warn` event on the client's debug channel (see `ClientConfig.debug`) with the server payload. --- # /docs/typescript/api/index/type-aliases/PriceFeedStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PriceFeedStatus # Type Alias: PriceFeedStatus > **PriceFeedStatus** = `"unwatched"` \| `"hydrating"` \| `"live"` \| `"error"` Defined in: packages/sdk/src/priceFeed/types.ts:213 Per-asset watch state: `"unwatched"` (no active watch — live reads return null/empty), `"hydrating"` (snapshot/subscribe in progress), `"live"` (streaming; reads are current to the last pushed tick), `"error"` (the server rejected or terminated this asset's subscription). Treat `"error"` as "the data has stopped and will not resume on its own". Reads keep answering with the last values they held, so a view that renders them without checking the status shows a frozen price as a live one. The server sends this for a validation failure (a schema change) or a permission denial, so it will not heal by itself: stop the watch and start a new one. Each rejection is also emitted as a `warn` event on the client's debug channel (see `ClientConfig.debug`) with the server payload. --- # /docs/typescript/api/index/type-aliases/ProtocolFeeRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ProtocolFeeRecord # Type Alias: ProtocolFeeRecord > **ProtocolFeeRecord** = `object` Defined in: packages/sdk/src/fees.ts:27 A realized protocol-fee record (mirror of the indexer `ProtocolFeeRecord` entity). Amounts are raw collateral units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fees.ts:29 Record id (`${blockNumber}_${logIndex}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/fees.ts:31 uint128 OrderId the fee was charged on (decimal string). *** ### recipient > **recipient**: `string` Defined in: packages/sdk/src/fees.ts:33 Fee recipient (lowercased). *** ### payer > **payer**: `string` \| `null` Defined in: packages/sdk/src/fees.ts:38 Order owner who paid the fee (lowercased); null on records indexed before the payer field existed. *** ### token > **token**: `string` Defined in: packages/sdk/src/fees.ts:40 Fee token (lowercased). *** ### amount > **amount**: `string` Defined in: packages/sdk/src/fees.ts:42 Fee charged (raw collateral units). *** ### isTakerSide > **isTakerSide**: `boolean` Defined in: packages/sdk/src/fees.ts:44 true = taker rate (direct fill); false = maker rate (burn-a-pair leg). *** ### market > **market**: `string` \| `null` Defined in: packages/sdk/src/fees.ts:46 Market id the fee's pool belongs to (lowercased); null when unlinked. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/fees.ts:48 Pool the fee was charged on (lowercased). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/fees.ts:50 Timestamp (unix seconds) the fee was charged. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/fees.ts:52 Tx hash the charge landed in. --- # /docs/typescript/api/index/type-aliases/QueryKeyElement [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QueryKeyElement # Type Alias: QueryKeyElement > **QueryKeyElement** = `string` \| `number` \| `boolean` \| `null` \| `Readonly`\<`Record`\<`string`, `string` \| `number` \| `boolean`\>\> Defined in: packages/sdk/src/queryKeys.ts:46 One element of a [ClientQueryKey](ClientQueryKey.md) — JSON-serializable by construction. --- # /docs/typescript/api/index/type-aliases/QuoteDenomination [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QuoteDenomination # Type Alias: QuoteDenomination > **QuoteDenomination** = `"base"` \| `"quote"` Defined in: packages/sdk/src/unified/quotes.ts:26 Which unit an order size is expressed in. --- # /docs/typescript/api/index/type-aliases/RawGridDirection [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RawGridDirection # Type Alias: RawGridDirection > **RawGridDirection** = `"down"` \| `"up"` Defined in: packages/sdk/src/units.ts:621 Which way [snapRawToGrid](../functions/snapRawToGrid.md) moves a value that is off the grid. --- # /docs/typescript/api/index/type-aliases/RouterActionKind [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RouterActionKind # Type Alias: RouterActionKind > **RouterActionKind** = `"Redeem"` \| `"MintCompleteSet"` \| `"MergeCompleteSet"` Defined in: packages/sdk/src/router.ts:27 Kinds of `RouterMinter` action the indexer records (mirror of the indexer RouterActionRecord.kind enum). --- # /docs/typescript/api/index/type-aliases/RouterActionRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RouterActionRecord # Type Alias: RouterActionRecord > **RouterActionRecord** = `object` Defined in: packages/sdk/src/router.ts:35 One RouterMinter action for an account (mirror of the indexer `RouterActionRecord` entity). Amounts are raw collateral/outcome units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/router.ts:37 Record id (`${blockNumber}_${logIndex}`). *** ### kind > **kind**: [`RouterActionKind`](RouterActionKind.md) Defined in: packages/sdk/src/router.ts:39 Redeem | MintCompleteSet | MergeCompleteSet. *** ### account > **account**: `string` Defined in: packages/sdk/src/router.ts:41 Acting wallet (lowercased). *** ### market > **market**: `string` \| `null` Defined in: packages/sdk/src/router.ts:43 Binary market id the action targeted (lowercased bytes32); null if unlinked. *** ### amount > **amount**: `string` Defined in: packages/sdk/src/router.ts:48 Redeem: winning tokens burned; Mint/Merge: amount of EACH outcome minted / merged (a complete set). Raw outcome-token units. *** ### payout > **payout**: `string` \| `null` Defined in: packages/sdk/src/router.ts:50 Collateral paid out (Redeem); null on Mint/Merge. Raw units. *** ### routedVia > **routedVia**: `string` \| `null` Defined in: packages/sdk/src/router.ts:55 Periphery entry the flow routed through (NativeMint | Permit2Mint | NativeRedeem); null on a direct module call. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/router.ts:57 Timestamp (unix seconds) of the action. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/router.ts:59 Tx hash the action landed in. --- # /docs/typescript/api/index/type-aliases/RouterActionsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RouterActionsOptions # Type Alias: RouterActionsOptions > **RouterActionsOptions** = `object` Defined in: packages/sdk/src/router.ts:82 Options for [SomniaMarketsClient.getRouterActions](../interfaces/SomniaMarketsClient.md#getrouteractions). All optional. ## Properties ### market? > `optional` **market?**: `string` Defined in: packages/sdk/src/router.ts:84 Only actions in this market (bytes32 marketId, case-insensitive). *** ### markets? > `optional` **markets?**: readonly `string`[] Defined in: packages/sdk/src/router.ts:89 Only actions in ANY of these markets — the batched form of `market`. Supplying both narrows to the intersection. An empty array matches nothing. *** ### kind? > `optional` **kind?**: [`RouterActionKind`](RouterActionKind.md) Defined in: packages/sdk/src/router.ts:91 Only this action kind. *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/router.ts:93 Max rows (default 50). *** ### offset? > `optional` **offset?**: `number` Defined in: packages/sdk/src/router.ts:95 Row offset (default 0). --- # /docs/typescript/api/index/type-aliases/SeedSource [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SeedSource # Type Alias: SeedSource > **SeedSource** = `"indexer"` \| `"chain"` Defined in: packages/sdk/src/store.ts:43 Where a watch took its book seed. `"indexer"` reads one consistent `MarketsSnapshot`; `"chain"` drains the pool's resting orders from the pool contract at one pinned block, so startup needs no indexer. --- # /docs/typescript/api/index/type-aliases/SeriesLatestMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SeriesLatestMarket # Type Alias: SeriesLatestMarket > **SeriesLatestMarket** = `object` Defined in: packages/sdk/src/marketCreatorAdmin.ts:943 The most recent market minted under one rolling series - one row per series that has rolled at least once, whichever creator owns it. **When to use** When the question is "when did this series LAST roll", asked for every series at once - a stall monitor, a scheduler dashboard. A series' own row ([IndexedSeries](IndexedSeries.md)) says how often it should roll and nothing about whether it did; a market row says when it was created and not which series it belongs to. This is that join, taken once and server-side: Hasura's `distinct_on: series_id` over markets ordered newest-first within each series. A series that has never rolled has NO row here. Absence means "no market yet", not "stalled", and nothing indexed says when the first roll is due: `armFirstRoll` accepts any future interval-aligned boundary and emits no event, and a re-register keeps the original `createdAtTimestamp`, so neither [IndexedSeries.createdAtTimestamp](IndexedSeries.md#createdattimestamp) nor `updatedAtTimestamp` is a deadline. A caller that cannot judge a series should say so rather than anchor on either. ## Properties ### series > **series**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:945 The series' entity id, `${creatorLower}_${seriesId}` - [IndexedSeries.id](IndexedSeries.md#id). *** ### market > **market**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:947 Id of the most recently created market under the series. *** ### createdAtTimestamp > **createdAtTimestamp**: `string` Defined in: packages/sdk/src/marketCreatorAdmin.ts:949 When that market was created (unix seconds, decimal string). --- # /docs/typescript/api/index/type-aliases/SettlementFeeRecord [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SettlementFeeRecord # Type Alias: SettlementFeeRecord > **SettlementFeeRecord** = `object` Defined in: packages/sdk/src/fees.ts:91 A realized settlement-fee record (mirror of the indexer `SettlementFeeRecord` entity) — the fee skimmed from a winning payout at redeem. Amounts are raw collateral units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/fees.ts:93 Record id (`${blockNumber}_${logIndex}`). *** ### recipient > **recipient**: `string` Defined in: packages/sdk/src/fees.ts:95 Fee recipient (lowercased). *** ### amount > **amount**: `string` Defined in: packages/sdk/src/fees.ts:97 Settlement fee skimmed from the winning backing (raw). *** ### winningBacking > **winningBacking**: `string` Defined in: packages/sdk/src/fees.ts:99 Winning backing at charge time, before the fee (raw). *** ### market > **market**: `string` \| `null` Defined in: packages/sdk/src/fees.ts:101 Market id the settlement fee belongs to (lowercased); null when unlinked. *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/fees.ts:103 Timestamp (unix seconds) the fee was charged (at finalize). *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/fees.ts:105 Tx hash the charge landed in. --- # /docs/typescript/api/index/type-aliases/SmartAccountInner [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SmartAccountInner # Type Alias: SmartAccountInner > **SmartAccountInner** = \{ `sessionSeed`: `Hex`; \} \| ((`chainId`) => [`Executor`](../interfaces/Executor.md)) Defined in: packages/sdk/src/unified/smartAccounts.ts:39 Who sends a multi-chain account's outer transactions on each chain: a Somnia session seed (the same seed derives the same session address on every chain, so ONE key owns the account everywhere), or a factory that names an executor per chain for anything more particular. **Gotchas** - A seed signs locally. `accountFor` derives the seed's key (`sessionPrivateKey(seed)`) and builds each chain's inner as that engine's local signer, so the seed never goes to a node. The session address is the same one the node derives. - Use one sending mode per address. Local and node-side sends from the same address share one nonce space. Do not also send node-side from this seed. - A factory must not return a `createExecutor({ sessionSeed })` executor. It sends the seed to the node on every write, so `accountFor` refuses it with [InvalidInputError](../classes/InvalidInputError.md). --- # /docs/typescript/api/index/type-aliases/SmartAccountsBuildError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SmartAccountsBuildError # Type Alias: SmartAccountsBuildError > **SmartAccountsBuildError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/smartAccounts.ts:120 Failures from the capability's pure builders: an input the accounts SDK refuses — nothing here touches the network. --- # /docs/typescript/api/index/type-aliases/SmartAccountsReadError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SmartAccountsReadError # Type Alias: SmartAccountsReadError > **SmartAccountsReadError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/smartAccounts.ts:112 Failures from the capability's reads: an input the accounts SDK refuses (including a chain it has no deployment for), or a transport failure with the original as `cause`. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientCountOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientCountOrdersError # Type Alias: SomniaMarketsClientCountOrdersError > **SomniaMarketsClientCountOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:421 Failures from [SomniaMarketsClient.countOrders](../interfaces/SomniaMarketsClient.md#countorders). Same union as the order list reads. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientCountUserFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientCountUserFillsError # Type Alias: SomniaMarketsClientCountUserFillsError > **SomniaMarketsClientCountUserFillsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:443 Failures from [SomniaMarketsClient.countUserFills](../interfaces/SomniaMarketsClient.md#countuserfills): an unusable account or option value, or a failed read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientCreateExecutorError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientCreateExecutorError # Type Alias: SomniaMarketsClientCreateExecutorError > **SomniaMarketsClientCreateExecutorError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:289 Failures from [SomniaMarketsClient.createExecutor](../interfaces/SomniaMarketsClient.md#createexecutor): a spec that names no actor or more than one, a malformed private key or session seed, a wallet spec with no account to act as, a smart-account spec that the SDK refuses (its inner executor sends on another chain or is a node-side session executor, the accounts SDK has no deployment on the chain, or `through` has no way to sign), or no chain transport for a variant that sends through this client. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientCreateObservedReadsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientCreateObservedReadsError # Type Alias: SomniaMarketsClientCreateObservedReadsError > **SomniaMarketsClientCreateObservedReadsError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/observedReads.ts:165 Creating the capability observes the owner's head once. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientCreateTraderError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientCreateTraderError # Type Alias: SomniaMarketsClientCreateTraderError > **SomniaMarketsClientCreateTraderError** = [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:278 Failures from [SomniaMarketsClient.createTrader](../interfaces/SomniaMarketsClient.md#createtrader): no usable signer in the config, a malformed private key, an executor bound to another chain, or no chain transport to send through. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientError # Type Alias: SomniaMarketsClientError > **SomniaMarketsClientError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/unified/exchange.ts:230 Failures from reading [SomniaMarkets.client](../classes/SomniaMarkets.md#client): the exchange spans more than one chain. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetBinaryOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetBinaryOrderBookError # Type Alias: SomniaMarketsClientGetBinaryOrderBookError > **SomniaMarketsClientGetBinaryOrderBookError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4165 Failures from a native binary chain book read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetBinaryPositionPnLError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetBinaryPositionPnLError # Type Alias: SomniaMarketsClientGetBinaryPositionPnLError > **SomniaMarketsClientGetBinaryPositionPnLError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:259 Failures from [SomniaMarketsClient.getBinaryPositionPnL](../interfaces/SomniaMarketsClient.md#getbinarypositionpnl). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetClaimableError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetClaimableError # Type Alias: SomniaMarketsClientGetClaimableError > **SomniaMarketsClientGetClaimableError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:292 Failures from [SomniaMarketsClient.getClaimable](../interfaces/SomniaMarketsClient.md#getclaimable). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetFillsError # Type Alias: SomniaMarketsClientGetFillsError > **SomniaMarketsClientGetFillsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:424 Failures from [SomniaMarketsClient.getFills](../interfaces/SomniaMarketsClient.md#getfills): an unusable pool or option value, or a failed read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetFillsPageError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetFillsPageError # Type Alias: SomniaMarketsClientGetFillsPageError > **SomniaMarketsClientGetFillsPageError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:437 Failures from [SomniaMarketsClient.getFillsPage](../interfaces/SomniaMarketsClient.md#getfillspage): an unusable bound, kind, limit or cursor, or a read that did not complete or returned unusable block positions. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetIndexerFreshnessError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetIndexerFreshnessError # Type Alias: SomniaMarketsClientGetIndexerFreshnessError > **SomniaMarketsClientGetIndexerFreshnessError** = [`IndexerError`](../classes/IndexerError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/observedReads.ts:167 Independent sync reads can reject validation, configuration or either service. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetLatestFillBlockError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetLatestFillBlockError # Type Alias: SomniaMarketsClientGetLatestFillBlockError > **SomniaMarketsClientGetLatestFillBlockError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:440 Failures from [SomniaMarketsClient.getLatestFillBlock](../interfaces/SomniaMarketsClient.md#getlatestfillblock): an unusable market kind, or a failed read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetLiquidationsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetLiquidationsError # ~~Type Alias: SomniaMarketsClientGetLiquidationsError~~ > **SomniaMarketsClientGetLiquidationsError** = [`SomniaMarketsClientListLiquidationsError`](SomniaMarketsClientListLiquidationsError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:339 Failures from [SomniaMarketsClient.getLiquidations](../interfaces/SomniaMarketsClient.md#getliquidations), the deprecated alias — the same union, because it forwards verbatim. ## Deprecated Use [SomniaMarketsClientListLiquidationsError](SomniaMarketsClientListLiquidationsError.md). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetOpenOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetOpenOrdersError # Type Alias: SomniaMarketsClientGetOpenOrdersError > **SomniaMarketsClientGetOpenOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:415 Failures from the owner-scoped order reads [SomniaMarketsClient.getOpenOrders](../interfaces/SomniaMarketsClient.md#getopenorders), [SomniaMarketsClient.getOrders](../interfaces/SomniaMarketsClient.md#getorders) and [SomniaMarketsClient.countOrders](../interfaces/SomniaMarketsClient.md#countorders): an unusable option value, or a read that did not complete. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetOpenPositionsWithPnLError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetOpenPositionsWithPnLError # Type Alias: SomniaMarketsClientGetOpenPositionsWithPnLError > **SomniaMarketsClientGetOpenPositionsWithPnLError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:267 Failures from [SomniaMarketsClient.getOpenPositionsWithPnL](../interfaces/SomniaMarketsClient.md#getopenpositionswithpnl). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetOrderFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetOrderFillsError # Type Alias: SomniaMarketsClientGetOrderFillsError > **SomniaMarketsClientGetOrderFillsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:427 Failures from [SomniaMarketsClient.getOrderFills](../interfaces/SomniaMarketsClient.md#getorderfills): an unusable pool or order id, or a failed read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetOrderOnchainError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetOrderOnchainError # Type Alias: SomniaMarketsClientGetOrderOnchainError > **SomniaMarketsClientGetOrderOnchainError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4177 Failures from one on-chain order read, at head or pinned. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetOrdersError # Type Alias: SomniaMarketsClientGetOrdersError > **SomniaMarketsClientGetOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:418 Failures from [SomniaMarketsClient.getOrders](../interfaces/SomniaMarketsClient.md#getorders). Same union as the open-order read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpFeedStatusError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpFeedStatusError # Type Alias: SomniaMarketsClientGetPerpFeedStatusError > **SomniaMarketsClientGetPerpFeedStatusError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:382 Failures from [SomniaMarketsClient.getPerpFeedStatus](../interfaces/SomniaMarketsClient.md#getperpfeedstatus). Three chain reads under one block pin, and no input validation, so the chain is most of it: transport (the pin included — it is normalized at the read boundary like the calls below it) or a revert from the pool. The INDEX leg is the exception that never reaches a caller: its revert is swallowed on purpose, because a dead oracle is what this read reports rather than fails on. `NotConfiguredError` is reachable BEFORE any of that. `wsRpcUrl` is validly optional, and `createClient` defers the check to the first chain touch — which this read performs when it resolves the client for its block pin. A config with no WebSocket endpoint is supported right up until a chain read is attempted, so the union has to carry it. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpStopOrderError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpStopOrderError # Type Alias: SomniaMarketsClientGetPerpStopOrderError > **SomniaMarketsClientGetPerpStopOrderError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:308 Failures from the chain read for one known perp stop. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpStopOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpStopOrdersError # Type Alias: SomniaMarketsClientGetPerpStopOrdersError > **SomniaMarketsClientGetPerpStopOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:315 Failures from the batched chain read for known perp stops. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpVoucherCampaignError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpVoucherCampaignError # Type Alias: SomniaMarketsClientGetPerpVoucherCampaignError > **SomniaMarketsClientGetPerpVoucherCampaignError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:389 Failures from [SomniaMarketsClient.getPerpVoucherCampaign](../interfaces/SomniaMarketsClient.md#getperpvouchercampaign). Chain reads only. `NotConfiguredError` comes from the deferred WebSocket check on the first chain touch, as for [SomniaMarketsClientGetPerpFeedStatusError](SomniaMarketsClientGetPerpFeedStatusError.md). A bank with no credit granter is NOT an error: the read returns `null`. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpVoucherEligibilityError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpVoucherEligibilityError # Type Alias: SomniaMarketsClientGetPerpVoucherEligibilityError > **SomniaMarketsClientGetPerpVoucherEligibilityError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) \| [`InvariantError`](../classes/InvariantError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:397 Failures from [SomniaMarketsClient.getPerpVoucherEligibility](../interfaces/SomniaMarketsClient.md#getperpvouchereligibility). Chain reads under one block pin. `NotConfiguredError` comes from the deferred WebSocket check on the first chain touch. `InvariantError` means the node returned a latest block with no number. An ineligible account is NOT an error: the read returns `eligible: false` with a reason. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetPerpVoucherError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetPerpVoucherError # Type Alias: SomniaMarketsClientGetPerpVoucherError > **SomniaMarketsClientGetPerpVoucherError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:408 Failures from [SomniaMarketsClient.getPerpVoucher](../interfaces/SomniaMarketsClient.md#getperpvoucher). Chain reads only. `NotConfiguredError` comes from the deferred WebSocket check on the first chain touch. A bank with no credit granter is NOT an error: the read returns `null`. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetSpotOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetSpotOrderBookError # Type Alias: SomniaMarketsClientGetSpotOrderBookError > **SomniaMarketsClientGetSpotOrderBookError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:4171 Failures from a native spot/perp chain book read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetSyncStatusError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetSyncStatusError # Type Alias: SomniaMarketsClientGetSyncStatusError > **SomniaMarketsClientGetSyncStatusError** = [`IndexerError`](../classes/IndexerError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/observedReads.ts:173 Metadata-only reads need no chain transport. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetUserFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetUserFillsError # Type Alias: SomniaMarketsClientGetUserFillsError > **SomniaMarketsClientGetUserFillsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:430 Failures from [SomniaMarketsClient.getUserFills](../interfaces/SomniaMarketsClient.md#getuserfills): an unusable account or option value, or a failed read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientGetUserFillsPageError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientGetUserFillsPageError # Type Alias: SomniaMarketsClientGetUserFillsPageError > **SomniaMarketsClientGetUserFillsPageError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`FillHistoryUnavailableError`](../classes/FillHistoryUnavailableError.md) \| [`FillHistoryRestartRequiredError`](../classes/FillHistoryRestartRequiredError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:299 Failures from bounded historical fill reads and cursor validation. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientListLiquidationsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientListLiquidationsError # Type Alias: SomniaMarketsClientListLiquidationsError > **SomniaMarketsClientListLiquidationsError** = [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:324 Failures from [SomniaMarketsClient.listLiquidations](../interfaces/SomniaMarketsClient.md#listliquidations). One indexed read, no chain call and no input validation, so the indexer is the only thing that can fail. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientListPoolBindingsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientListPoolBindingsError # Type Alias: SomniaMarketsClientListPoolBindingsError > **SomniaMarketsClientListPoolBindingsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:353 Failures from [SomniaMarketsClient.listPoolBindings](../interfaces/SomniaMarketsClient.md#listpoolbindings). One indexed read, paged, with no chain call: the indexer can fail, and so can the caller's own page bounds, which are validated before the request. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientListRegistryMarketsCheckedError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientListRegistryMarketsCheckedError # Type Alias: SomniaMarketsClientListRegistryMarketsCheckedError > **SomniaMarketsClientListRegistryMarketsCheckedError** = [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:345 Failures from [SomniaMarketsClient.listRegistryMarketsChecked](../interfaces/SomniaMarketsClient.md#listregistrymarketschecked). One indexed read, paged, with no chain call and no input validation — so the indexer is the only thing that can fail. A row the SDK cannot parse is NOT a failure: it is counted in `dropped` and the read succeeds. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientListSeriesLatestMarketsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientListSeriesLatestMarketsError # Type Alias: SomniaMarketsClientListSeriesLatestMarketsError > **SomniaMarketsClientListSeriesLatestMarketsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:363 Failures from [SomniaMarketsClient.listSeriesLatestMarkets](../interfaces/SomniaMarketsClient.md#listserieslatestmarkets). One indexed read, paged, with no chain call: the indexer can fail, and so can the caller's own page bounds, which are validated before the request so an unbounded or rejected page cannot be blamed on the indexer. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientListVaultPayoutFallbacksError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientListVaultPayoutFallbacksError # Type Alias: SomniaMarketsClientListVaultPayoutFallbacksError > **SomniaMarketsClientListVaultPayoutFallbacksError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:330 Failures from [SomniaMarketsClient.listVaultPayoutFallbacks](../interfaces/SomniaMarketsClient.md#listvaultpayoutfallbacks). One indexed read, paged, with no chain call: the indexer can fail, and so can the caller's own page bounds, which are validated before the request so an unbounded or rejected page cannot be blamed on the indexer. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientWaitForIndexedBlockError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientWaitForIndexedBlockError # Type Alias: SomniaMarketsClientWaitForIndexedBlockError > **SomniaMarketsClientWaitForIndexedBlockError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerWaitTimeoutError`](../classes/IndexerWaitTimeoutError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:451 Failures from [SomniaMarketsClient.waitForIndexedBlock](../interfaces/SomniaMarketsClient.md#waitforindexedblock): an unusable argument, a deadline that passed with the indexer still behind, a metadata read that did not complete or named no row for the chain, an indexer that is absent, misbound or past the RPC head, and a failed RPC head read. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsClientWatchPerpMarketsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsClientWatchPerpMarketsError # Type Alias: SomniaMarketsClientWatchPerpMarketsError > **SomniaMarketsClientWatchPerpMarketsError** = [`ContractRevertError`](../classes/ContractRevertError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/somniaMarketsClient.ts:490 Failures from [SomniaMarketsClient.watchPerpMarkets](../interfaces/SomniaMarketsClient.md#watchperpmarkets). One per stage of the hydration, and they call for different responses: - [InvalidInputError](../classes/InvalidInputError.md) — `opts.marginBank` is not an address. Refused before any network work, so nothing was fetched and nothing subscribed. - [IndexerError](../classes/IndexerError.md) — the plane snapshot did not complete. Retry, or open the watch later; nothing has been subscribed. - [RpcError](../classes/RpcError.md) — the `MarginBank.getSystemConfig()` wiring read, or the head read that bounds the seam backfill, did not complete. The LiquidationEngine is then unknown, and the watch is refused rather than opened over the bank alone, which would stream funding settlements and no liquidations — indistinguishable from a venue with none. - [ContractRevertError](../classes/ContractRevertError.md) — the resolved MarginBank REVERTED on `getSystemConfig()`. Reachable for either source of the address: a caller-supplied `opts.marginBank` that is not a MarginBank (or not one of this version), or an indexed bank whose deployment no longer answers the call. Distinct from [RpcError](../classes/RpcError.md), which is a transport failure on the same read. - [NotConfiguredError](../classes/NotConfiguredError.md) — the client was built without `wsRpcUrl` or `indexerUrl`, so there is no socket to tail or no snapshot to hydrate from, or its indexer does not index the client's chain. A config fix, not a retry. The reference is released on every one of them, so a failed call leaves no refcount behind and a retry hydrates from scratch. Its sibling reads [SomniaMarketsClient.listLiveLiquidations](../interfaces/SomniaMarketsClient.md#listliveliquidations) and [SomniaMarketsClient.listLiveFundingPayments](../interfaces/SomniaMarketsClient.md#listlivefundingpayments) have NO union, which is SDK-ERR-002's "proven unable to fail" case rather than an omission: both are synchronous reads over rows the store already holds, with no transport and no decoding, returning empty for an unwatched plane. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsConfig [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsConfig # Type Alias: SomniaMarketsConfig > **SomniaMarketsConfig** = [`ClientConfig`](../interfaces/ClientConfig.md) \| [`SomniaMarketsChainsConfig`](../interfaces/SomniaMarketsChainsConfig.md) & [`SomniaMarketsSignerConfig`](../interfaces/SomniaMarketsSignerConfig.md) Defined in: packages/sdk/src/unified/exchange.ts:174 Config for [SomniaMarkets](../classes/SomniaMarkets.md): either one chain's [ClientConfig](../interfaces/ClientConfig.md) (the single-chain form, which behaves as a one-element `chains` list) or a [SomniaMarketsChainsConfig](../interfaces/SomniaMarketsChainsConfig.md), plus (optionally) a signer — authenticated methods throw without one. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsConstructorError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsConstructorError # Type Alias: SomniaMarketsConstructorError > **SomniaMarketsConstructorError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/unified/exchange.ts:228 Failures from validating owner configuration. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsFetchDataStatusError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchDataStatusError # Type Alias: SomniaMarketsFetchDataStatusError > **SomniaMarketsFetchDataStatusError** = [`SomniaMarketsClientGetIndexerFreshnessError`](SomniaMarketsClientGetIndexerFreshnessError.md) Defined in: packages/sdk/src/unified/exchange.ts:42 Status observes RPC and indexer once; either service can reject. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsFetchMyTradesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchMyTradesError # Type Alias: SomniaMarketsFetchMyTradesError > **SomniaMarketsFetchMyTradesError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/unified/exchange.ts:270 Historical account trade read failures. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsFetchOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchOrderBookError # Type Alias: SomniaMarketsFetchOrderBookError > **SomniaMarketsFetchOrderBookError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/unified/exchange.ts:226 Failures from selecting a tradable or reading its pinned book. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsFetchPortfolioAnalyticsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchPortfolioAnalyticsError # Type Alias: SomniaMarketsFetchPortfolioAnalyticsError > **SomniaMarketsFetchPortfolioAnalyticsError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`IndexerUnavailableError`](../classes/IndexerUnavailableError.md) \| [`FillHistoryRestartRequiredError`](../classes/FillHistoryRestartRequiredError.md) \| [`FillHistoryUnavailableError`](../classes/FillHistoryUnavailableError.md) \| [`IncompleteHistoryError`](../classes/IncompleteHistoryError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/unified/exchange.ts:276 Historical portfolio analytics read failures. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsFetchTradesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsFetchTradesError # Type Alias: SomniaMarketsFetchTradesError > **SomniaMarketsFetchTradesError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/unified/exchange.ts:268 Historical public trade read failures. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsGetOrderHistoryPageError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsGetOrderHistoryPageError # Type Alias: SomniaMarketsGetOrderHistoryPageError > **SomniaMarketsGetOrderHistoryPageError** = [`SomniaMarketsGetOrdersPageError`](SomniaMarketsGetOrdersPageError.md) Defined in: packages/sdk/src/unified/exchange.ts:398 Failures from [SomniaMarkets.getOrderHistoryPage](../classes/SomniaMarkets.md#getorderhistorypage). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsGetOrderHistoryPageOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsGetOrderHistoryPageOptions # Type Alias: SomniaMarketsGetOrderHistoryPageOptions > **SomniaMarketsGetOrderHistoryPageOptions** = [`SomniaMarketsGetOrdersPageOptions`](SomniaMarketsGetOrdersPageOptions.md) Defined in: packages/sdk/src/unified/exchange.ts:353 Filters and pagination for [SomniaMarkets.getOrderHistoryPage](../classes/SomniaMarkets.md#getorderhistorypage). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsGetOrdersPageError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsGetOrdersPageError # Type Alias: SomniaMarketsGetOrdersPageError > **SomniaMarketsGetOrdersPageError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) Defined in: packages/sdk/src/unified/exchange.ts:392 Failures from [SomniaMarkets.getOrdersPage](../classes/SomniaMarkets.md#getorderspage). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsGetOrdersPageOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsGetOrdersPageOptions # Type Alias: SomniaMarketsGetOrdersPageOptions > **SomniaMarketsGetOrdersPageOptions** = [`SomniaMarketsChainFilter`](../interfaces/SomniaMarketsChainFilter.md) & `object` Defined in: packages/sdk/src/unified/exchange.ts:341 Filters and pagination for [SomniaMarkets.getOrdersPage](../classes/SomniaMarkets.md#getorderspage). ## Type Declaration ### ref? > `optional` **ref?**: [`MarketHandle`](MarketHandle.md) Restrict the page to one tradable. Omit it for account-wide raw orders (paged PER CHAIN). ### status? > `optional` **status?**: [`OrderStatus`](OrderStatus.md) Restrict the indexer read to one native order lifecycle status. ### limit? > `optional` **limit?**: `number` Maximum raw rows to read. The default is 100. ### offset? > `optional` **offset?**: `number` Raw indexer row offset. The default is 0. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsLoadMarketsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsLoadMarketsError # Type Alias: SomniaMarketsLoadMarketsError > **SomniaMarketsLoadMarketsError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`InvariantError`](../classes/InvariantError.md) Defined in: packages/sdk/src/unified/exchange.ts:265 Registry load failures. Short, because BOTH reads that can fail the whole load are contained and reported instead of thrown: the indexer registry read through [SomniaMarkets.registryReadError](../classes/SomniaMarkets.md#registryreaderror) and perp discovery — the collateral `decimals()` read included, since it sits inside discovery — through [SomniaMarkets.perpDiscoveryError](../classes/SomniaMarkets.md#perpdiscoveryerror). Every remaining chain read in the load swallows its own failure to a documented fallback. What is left throws BEFORE any request goes out, or cannot happen at all: `NotConfiguredError` when the load needs a chain read (ERC-20 metadata for an unlabeled token, or a binary pool's grid) and the owner has neither a `wsRpcUrl` nor a chain carrying a WebSocket endpoint — `createClient` defers that check to the first chain touch, which is this one. `InvariantError` reports an SDK defect, never a caller or operational condition. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsRedeemError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsRedeemError # Type Alias: SomniaMarketsRedeemError > **SomniaMarketsRedeemError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`TransactionOutcomeUnknownError`](../classes/TransactionOutcomeUnknownError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/unified/exchange.ts:473 Failures from [SomniaMarkets.redeem](../classes/SomniaMarkets.md#redeem). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsSetSignerError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsSetSignerError # Type Alias: SomniaMarketsSetSignerError > **SomniaMarketsSetSignerError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/unified/exchange.ts:246 Failures from [SomniaMarkets.setSigner](../classes/SomniaMarkets.md#setsigner): a [SomniaMarketsAccount](../interfaces/SomniaMarketsAccount.md) whose executors do not fit this exchange. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsTraderError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsTraderError # Type Alias: SomniaMarketsTraderError > **SomniaMarketsTraderError** = [`SomniaMarketsTraderForError`](SomniaMarketsTraderForError.md) Defined in: packages/sdk/src/unified/exchange.ts:241 Failures from reading [SomniaMarkets.trader](../classes/SomniaMarkets.md#trader): the exchange spans more than one chain, or any [SomniaMarketsTraderForError](SomniaMarketsTraderForError.md). --- # /docs/typescript/api/index/type-aliases/SomniaMarketsTraderForError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsTraderForError # Type Alias: SomniaMarketsTraderForError > **SomniaMarketsTraderForError** = [`SomniaMarketsClientCreateTraderError`](SomniaMarketsClientCreateTraderError.md) Defined in: packages/sdk/src/unified/exchange.ts:236 Failures from [SomniaMarkets.traderFor](../classes/SomniaMarkets.md#traderfor): a chain the exchange does not span or an account with no executor there, no signer, or a signer the engine refuses. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsUnwatchMarketError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsUnwatchMarketError # Type Alias: SomniaMarketsUnwatchMarketError > **SomniaMarketsUnwatchMarketError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/unified/exchange.ts:44 [SomniaMarkets.unwatchMarket](../classes/SomniaMarkets.md#unwatchmarket) rejects only for an on-chain ref (an address, a market id or a `{ chainId, id }` ref) that does not resolve. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsWatchMyTradesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsWatchMyTradesError # Type Alias: SomniaMarketsWatchMyTradesError > **SomniaMarketsWatchMyTradesError** = [`SomniaMarketsWatchTradesError`](SomniaMarketsWatchTradesError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) Defined in: packages/sdk/src/unified/exchange.ts:310 Account trade watch initialization and mapping failures. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsWatchOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsWatchOrderBookError # Type Alias: SomniaMarketsWatchOrderBookError > **SomniaMarketsWatchOrderBookError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/unified/exchange.ts:312 Live book watch initialization failures. --- # /docs/typescript/api/index/type-aliases/SomniaMarketsWatchTradesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SomniaMarketsWatchTradesError # Type Alias: SomniaMarketsWatchTradesError > **SomniaMarketsWatchTradesError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`IndexerError`](../classes/IndexerError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/unified/exchange.ts:303 Live trade watch initialization and mapping failures. --- # /docs/typescript/api/index/type-aliases/SpotMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotMarket # Type Alias: SpotMarket > **SpotMarket** = [`BaseMarket`](BaseMarket.md) & `object` Defined in: packages/sdk/src/markets.ts:110 A spot (base/quote) order-book market. ## Type Declaration ### marketType > **marketType**: `"SPOT"` Discriminator (narrowed). ### baseToken > **baseToken**: `Address` Base ERC-20 address (lowercased). ### quoteToken > **quoteToken**: `Address` Quote ERC-20 address (lowercased). ### baseSymbol > **baseSymbol**: `string` \| `null` Base token symbol (e.g. "SOMI"); null when the token exposes none. ### quoteSymbol > **quoteSymbol**: `string` \| `null` Quote token symbol (e.g. "USDso"); null when the token exposes none. ### baseIsNative > **baseIsNative**: `boolean` True when the base is the chain's native token (wrapped for the book). ### tickSize > **tickSize**: `string` Price increment, raw quote units per whole base (decimal string). ### lotSize > **lotSize**: `string` Quantity increment, raw base units (decimal string). ### minQuantity > **minQuantity**: `string` Minimum order quantity, raw base units (decimal string). ### markPrice > **markPrice**: `string` \| `null` EMA-smoothed mark price (raw quote per whole base); null until first set. ### rawMidpoint > **rawMidpoint**: `string` \| `null` Unsmoothed book midpoint feeding the mark-price EMA; null until first set. ### markPriceUpdatedAt > **markPriceUpdatedAt**: `string` \| `null` Timestamp (unix seconds) the mark price last advanced; null until first set. ### stopRegistry > **stopRegistry**: `Address` \| `null` Per-pool SpotStopOrderRegistry (lowercased); null on pools without one. --- # /docs/typescript/api/index/type-aliases/SpotMarketFilter [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotMarketFilter # Type Alias: SpotMarketFilter > **SpotMarketFilter** = `object` Defined in: packages/sdk/src/markets.ts:1295 Filters for [SomniaMarketsClient.listSpotMarkets](../interfaces/SomniaMarketsClient.md#listspotmarkets). All optional; applied server-side. ## Properties ### baseSymbol? > `optional` **baseSymbol?**: `string` Defined in: packages/sdk/src/markets.ts:1297 Base token symbol, e.g. `"SOMI"` | `"WBTC"`. *** ### quoteSymbol? > `optional` **quoteSymbol?**: `string` Defined in: packages/sdk/src/markets.ts:1299 Quote token symbol, e.g. `"USDso"`. --- # /docs/typescript/api/index/type-aliases/SpotPortfolio [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotPortfolio # Type Alias: SpotPortfolio > **SpotPortfolio** = `object` Defined in: packages/sdk/src/spot/portfolio.ts:117 A wallet's spot portfolio — the shape [SomniaMarketsClient.getSpotPortfolio](../interfaces/SomniaMarketsClient.md#getspotportfolio) returns. ## Properties ### account > **account**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:119 The queried account (lowercased). *** ### openOrders > **openOrders**: [`SpotPortfolioOrder`](SpotPortfolioOrder.md)[] Defined in: packages/sdk/src/spot/portfolio.ts:121 Currently-open spot orders, newest first. *** ### stopOrders > **stopOrders**: [`SpotStopOrder`](SpotStopOrder.md)[] Defined in: packages/sdk/src/spot/portfolio.ts:123 Currently-PENDING stop orders across the wallet's spot markets. *** ### trades > **trades**: [`SpotPortfolioTrade`](SpotPortfolioTrade.md)[] Defined in: packages/sdk/src/spot/portfolio.ts:125 Recent spot fills the account participated in, newest first. *** ### tradesTruncated > **tradesTruncated**: `boolean` Defined in: packages/sdk/src/spot/portfolio.ts:133 The read hit its `tradesLimit`, so fills older than the last entry in `trades` exist and were NOT returned. Raise `tradesLimit` for the rest. A total folded from a truncated `trades` covers part of the history only. False when the page was short, and false for `tradesLimit: 0`, which asks for no trades at all. *** ### tradesSince > **tradesSince**: `number` Defined in: packages/sdk/src/spot/portfolio.ts:139 The lower time bound the trades leg was read with, unix seconds — `since` when passed, otherwise now minus seven days (`DEFAULT_TRADES_SINCE_SEC`). Echoed so a UI can label the list and a caller can page further back. Orders are not windowed. --- # /docs/typescript/api/index/type-aliases/SpotPortfolioMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotPortfolioMarket # Type Alias: SpotPortfolioMarket > **SpotPortfolioMarket** = `object` Defined in: packages/sdk/src/spot/portfolio.ts:25 Spot market context attached to spot portfolio rows. id == poolAddress. ## Properties ### poolAddress > **poolAddress**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:27 Pool address (lowercased; == the market id for spot). *** ### baseSymbol > **baseSymbol**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:29 Base token symbol; null when the token exposes none. *** ### quoteSymbol > **quoteSymbol**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:31 Quote token symbol; null when the token exposes none. *** ### baseToken > **baseToken**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:33 Base ERC-20 address (lowercased). *** ### quoteToken > **quoteToken**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:35 Quote ERC-20 address (lowercased). *** ### baseDecimals > **baseDecimals**: `number` Defined in: packages/sdk/src/spot/portfolio.ts:37 Base-token decimals — format base quantities with this. *** ### quoteDecimals > **quoteDecimals**: `number` Defined in: packages/sdk/src/spot/portfolio.ts:39 Quote-token decimals — format prices/quote amounts with this. *** ### baseIsNative > **baseIsNative**: `boolean` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:41 True when the base is the chain's native token. *** ### tickSize > **tickSize**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:43 Price increment, raw quote units per whole base (decimal string). *** ### lotSize > **lotSize**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:45 Quantity increment, raw base units (decimal string). *** ### minQuantity > **minQuantity**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:47 Minimum order quantity, raw base units (decimal string). *** ### lastPrice > **lastPrice**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:49 Last fill price (raw quote per whole base); null until first fill. *** ### markPrice > **markPrice**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:51 EMA-smoothed mark price (raw quote per whole base); null until first set. *** ### stopRegistry > **stopRegistry**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:53 Per-pool SpotStopOrderRegistry address (lowercased); null if the pool has none. --- # /docs/typescript/api/index/type-aliases/SpotPortfolioOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotPortfolioOrder # Type Alias: SpotPortfolioOrder > **SpotPortfolioOrder** = `object` Defined in: packages/sdk/src/spot/portfolio.ts:61 One currently-open order in a wallet's spot portfolio. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:63 Order id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:65 uint128 OrderId as a decimal string (pass to trader.cancelOrder). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/spot/portfolio.ts:67 True = bid (buy base), false = ask (sell base). *** ### price > **price**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:69 Limit price, raw quote units per whole base. *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:71 Unfilled remainder, raw base units. *** ### filledQuantity > **filledQuantity**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:73 Cumulative filled quantity, raw base units. *** ### fullQuantity > **fullQuantity**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:75 Original order size, raw base units. *** ### placedAtTimestamp > **placedAtTimestamp**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:77 Timestamp (unix seconds) the order was placed. *** ### placedTxHash > **placedTxHash**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:79 Tx hash the order was placed in. *** ### market > **market**: [`SpotPortfolioMarket`](SpotPortfolioMarket.md) Defined in: packages/sdk/src/spot/portfolio.ts:81 The market the order rests on. --- # /docs/typescript/api/index/type-aliases/SpotPortfolioTrade [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotPortfolioTrade # Type Alias: SpotPortfolioTrade > **SpotPortfolioTrade** = `object` Defined in: packages/sdk/src/spot/portfolio.ts:89 One recent fill the wallet participated in (spot portfolio view). ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:91 Fill id (`${blockNumber}_${logIndex}`). *** ### fillPrice > **fillPrice**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:93 Execution price, raw quote units per whole base. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:95 Base quantity filled, raw units. *** ### quoteQuantity > **quoteQuantity**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:97 Quote value of the fill (raw, floored). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:99 Timestamp (unix seconds) of the fill. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/spot/portfolio.ts:101 Tx hash the fill landed in. *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/spot/portfolio.ts:103 Whether the account bought the base asset on this fill. *** ### asMaker > **asMaker**: `boolean` Defined in: packages/sdk/src/spot/portfolio.ts:105 Whether the account was the maker (resting) on this fill. *** ### counterparty > **counterparty**: `string` \| `null` Defined in: packages/sdk/src/spot/portfolio.ts:107 The other party's address, if known. *** ### market > **market**: [`SpotPortfolioMarket`](SpotPortfolioMarket.md) Defined in: packages/sdk/src/spot/portfolio.ts:109 The market the fill happened on. --- # /docs/typescript/api/index/type-aliases/SpotStopOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SpotStopOrder # Type Alias: SpotStopOrder > **SpotStopOrder** = `object` Defined in: packages/sdk/src/spot/stops.ts:27 A pending/historical spot stop order (mirror of the indexer StopOrder entity). There is no limit price on this row: a spot LIMIT stop's limit price can't be read back after placement. Show it as unknown, never as zero. If you need to display it, keep the value you submitted. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/spot/stops.ts:29 StopOrder id (`${registry}_${orderId}`). *** ### registry > **registry**: `string` Defined in: packages/sdk/src/spot/stops.ts:31 SpotStopOrderRegistry the order lives on (lowercased). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/spot/stops.ts:33 uint128 pending-order id as a decimal string (pass to trader.cancelStopOrder). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/spot/stops.ts:35 True = buy base (pay quote), false = sell base. *** ### quantity > **quantity**: `string` Defined in: packages/sdk/src/spot/stops.ts:37 Base quantity, raw units. *** ### triggerPrice > **triggerPrice**: `string` Defined in: packages/sdk/src/spot/stops.ts:39 Mark price that arms the trigger (raw quote per whole base). *** ### triggerOperator > **triggerOperator**: `number` Defined in: packages/sdk/src/spot/stops.ts:41 0 = GTE (trigger when mark ≥ trigger), 1 = LTE (mark ≤ trigger). *** ### orderType > **orderType**: `number` Defined in: packages/sdk/src/spot/stops.ts:43 0 = LIMIT, 1 = MARKET. *** ### status > **status**: [`StopOrderStatus`](StopOrderStatus.md) Defined in: packages/sdk/src/spot/stops.ts:45 Lifecycle status — see [StopOrderStatus](StopOrderStatus.md). *** ### placedOrderId > **placedOrderId**: `string` \| `null` Defined in: packages/sdk/src/spot/stops.ts:47 Resulting spot order id once successfully triggered, else null. *** ### createdAt > **createdAt**: `string` Defined in: packages/sdk/src/spot/stops.ts:49 Timestamp (unix seconds) the stop order was created. *** ### market > **market**: [`SpotPortfolioMarket`](SpotPortfolioMarket.md) Defined in: packages/sdk/src/spot/stops.ts:51 The spot market the stop order targets. --- # /docs/typescript/api/index/type-aliases/StopOrderStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / StopOrderStatus # Type Alias: StopOrderStatus > **StopOrderStatus** = `"PENDING"` \| `"TRIGGERED"` \| `"TRIGGER_FAILED"` \| `"CANCELLED"` Defined in: packages/sdk/src/spot/stops.ts:16 Spot stop-order lifecycle (mirror of the indexer StopOrderStatus enum). --- # /docs/typescript/api/index/type-aliases/SweepableOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SweepableOrder # Type Alias: SweepableOrder > **SweepableOrder** = `object` Defined in: packages/sdk/src/orders.ts:1416 A resting order that is PAST ITS EXPIRY but has not been cleaned off the book — the target of a permissionless sweep. Carries exactly what the two sweep verbs need: `orderId` for [SomniaMarketsClient.createTrader](../interfaces/SomniaMarketsClient.md#createtrader)'s `cancelExpiredOrders`, and `isBid` + `price` for `sweepExpiredAtLevel`. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/orders.ts:1418 Row id (`${pool}_${orderId}`). *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/orders.ts:1420 uint128 OrderId as a decimal string — pass to `cancelExpiredOrders`. *** ### market > **market**: `string` Defined in: packages/sdk/src/orders.ts:1429 The market's bytes32 marketId — the market this order rests on, stably. A sweepable order is by definition still RESTING, and a pool's book is emptied before the pool is recycled, so this read cannot be mislabelled the way order HISTORY can. It is carried anyway so all three order reads name a market the same way. *** ### marketInfo > **marketInfo**: [`OrderMarket`](OrderMarket.md) \| `null` Defined in: packages/sdk/src/orders.ts:1431 The market's labelling context. Null only if the indexer has no market row. *** ### pool > **pool**: `string` Defined in: packages/sdk/src/orders.ts:1433 The pool the order rests on (lowercased). A time-varying binding — see `market`. *** ### marketType > **marketType**: [`MarketType`](MarketType.md) Defined in: packages/sdk/src/orders.ts:1435 Which market kind the pool is — sweeping works the same on all of them. *** ### owner > **owner**: `string` Defined in: packages/sdk/src/orders.ts:1437 The order's owner (lowercased). *** ### isBid > **isBid**: `boolean` Defined in: packages/sdk/src/orders.ts:1439 True = bid side, false = ask — pass to `sweepExpiredAtLevel`. *** ### price > **price**: `string` Defined in: packages/sdk/src/orders.ts:1441 The exact price level, raw pool units — pass to `sweepExpiredAtLevel`. *** ### quantityRemaining > **quantityRemaining**: `string` Defined in: packages/sdk/src/orders.ts:1443 Unfilled remainder that would be released, raw base/outcome units. *** ### expireTimestampNs > **expireTimestampNs**: `string` Defined in: packages/sdk/src/orders.ts:1445 Expiry as a uint64 NANOsecond timestamp (decimal string). *** ### placedAtTimestamp > **placedAtTimestamp**: `string` Defined in: packages/sdk/src/orders.ts:1447 Timestamp (unix seconds) the order was placed. --- # /docs/typescript/api/index/type-aliases/TailMode [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TailMode # Type Alias: TailMode > **TailMode** = `"init"` \| `"tailing"` Defined in: packages/sdk/src/store.ts:34 Data-source mode of the live tail: `"init"` until the first watch has hydrated, `"tailing"` once the store is fed by the chain event stream. --- # /docs/typescript/api/index/type-aliases/TerminalOrderStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TerminalOrderStatus # Type Alias: TerminalOrderStatus > **TerminalOrderStatus** = `Exclude`\<[`OrderStatus`](OrderStatus.md), `"Open"`\> Defined in: packages/sdk/src/perp/portfolio.ts:275 An order status that means the order has stopped working. `OrderStatus` minus `"Open"`, so a history read cannot be asked for working orders in the first place — the guard is the type, not a comment. --- # /docs/typescript/api/index/type-aliases/TradeContext [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TradeContext # Type Alias: TradeContext > **TradeContext** = `object` Defined in: packages/sdk/src/fills.ts:861 Everything the indexer knows about ONE fill: the trade itself, the market it executed in, both sides' orders, the fees it paid, and the other fills its transaction produced. The shape of a trade detail view. Each piece may be absent on its own terms — see the field docs — and absence is normal rather than an error. Distinct from [FillDetail](FillDetail.md), which is the one-query lookup behind [SomniaMarketsClient.getFill](../interfaces/SomniaMarketsClient.md#getfill): that names the fill and its market, this adds the surrounding CONTEXT — both orders resolved, the fees, the rest of the transaction — at the cost of a second round-trip. A caller that only needs to render the trade wants `getFill`. ## Properties ### fill > **fill**: [`OrderFillRow`](OrderFillRow.md) Defined in: packages/sdk/src/fills.ts:863 The fill, with its block position and post-fill remainders. *** ### market > **market**: [`Market`](Market.md) \| `null` Defined in: packages/sdk/src/fills.ts:868 The market the fill executed in; null only when the indexer has no market row for it (an unregistered pool). *** ### makerOrder > **makerOrder**: [`FillOrder`](FillOrder.md) \| `null` Defined in: packages/sdk/src/fills.ts:873 The resting order that was filled; null until the indexer has that order's row. *** ### takerOrder > **takerOrder**: [`FillOrder`](FillOrder.md) \| `null` Defined in: packages/sdk/src/fills.ts:875 The aggressing order that crossed the book; null until its row is indexed. *** ### siblings > **siblings**: [`OrderFillRow`](OrderFillRow.md)[] Defined in: packages/sdk/src/fills.ts:880 The OTHER fills of the same transaction, newest first — the rest of a taker's sweep. Empty when this fill was the whole trade. Excludes this fill. *** ### protocolFees > **protocolFees**: [`ProtocolFeeRecord`](ProtocolFeeRecord.md)[] Defined in: packages/sdk/src/fills.ts:890 Protocol fees charged in the same transaction. BINARY only, and empty when no fee was skimmed. Transaction-scoped, not fill-scoped: a fee record names the ORDER it was charged on, not the fill, so a multi-fill sweep cannot be split into per-fill fees. Match `orderId` against the fill's `makerOrder`/`takerOrder` to attribute what can be attributed. *** ### builderFees > **builderFees**: [`BuilderFeeRecord`](BuilderFeeRecord.md)[] Defined in: packages/sdk/src/fills.ts:892 Builder fees charged in the same transaction, on the same terms as [TradeContext.protocolFees](#protocolfees). --- # /docs/typescript/api/index/type-aliases/TraderBuildCancelOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderBuildCancelOrdersError # Type Alias: TraderBuildCancelOrdersError > **TraderBuildCancelOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/trade.ts:2264 Failures from [Trader.buildCancelOrders](../interfaces/Trader.md#buildcancelorders). --- # /docs/typescript/api/index/type-aliases/TraderBuildClaimPerpVoucherError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderBuildClaimPerpVoucherError # Type Alias: TraderBuildClaimPerpVoucherError > **TraderBuildClaimPerpVoucherError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/trade.ts:2297 Failures from [Trader.buildClaimPerpVoucher](../interfaces/Trader.md#buildclaimperpvoucher): a bad target, a bank with no credit granter, or a resolution read that did not complete or reverted. --- # /docs/typescript/api/index/type-aliases/TraderBuildPlaceSpotOrderError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderBuildPlaceSpotOrderError # Type Alias: TraderBuildPlaceSpotOrderError > **TraderBuildPlaceSpotOrderError** = [`InvalidInputError`](../classes/InvalidInputError.md) \| [`RpcError`](../classes/RpcError.md) \| [`ContractRevertError`](../classes/ContractRevertError.md) Defined in: packages/sdk/src/trade.ts:2250 Failures from [Trader.buildPlaceSpotOrder](../interfaces/Trader.md#buildplacespotorder). --- # /docs/typescript/api/index/type-aliases/TraderBuildReduceOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderBuildReduceOrdersError # Type Alias: TraderBuildReduceOrdersError > **TraderBuildReduceOrdersError** = [`InvalidInputError`](../classes/InvalidInputError.md) Defined in: packages/sdk/src/trade.ts:2271 Failures from [Trader.buildReduceOrders](../interfaces/Trader.md#buildreduceorders). --- # /docs/typescript/api/index/type-aliases/TraderCancelAllOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderCancelAllOrdersError # Type Alias: TraderCancelAllOrdersError > **TraderCancelAllOrdersError** = [`ExecutorExecuteError`](ExecutorExecuteError.md) Defined in: packages/sdk/src/trade.ts:2257 Failures from [Trader.cancelAllOrders](../interfaces/Trader.md#cancelallorders). --- # /docs/typescript/api/index/type-aliases/TraderClaimPerpVoucherError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderClaimPerpVoucherError # Type Alias: TraderClaimPerpVoucherError > **TraderClaimPerpVoucherError** = [`ExecutorExecuteError`](ExecutorExecuteError.md) Defined in: packages/sdk/src/trade.ts:2289 Failures from [Trader.claimPerpVoucher](../interfaces/Trader.md#claimperpvoucher): a bad target, a bank with no credit granter, a resolution read that did not complete, an unobserved receipt, or the distributor's revert. --- # /docs/typescript/api/index/type-aliases/TraderSignRedeemAuthError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TraderSignRedeemAuthError # Type Alias: TraderSignRedeemAuthError > **TraderSignRedeemAuthError** = [`NotConfiguredError`](../classes/NotConfiguredError.md) \| [`SignerRequiredError`](../classes/SignerRequiredError.md) \| [`RpcError`](../classes/RpcError.md) Defined in: packages/sdk/src/trade.ts:2280 Failures from [Trader.signRedeemAuth](../interfaces/Trader.md#signredeemauth): no module address configured, an executor that cannot sign typed data as the actor (a safe, a session key), or the signer itself failing / refusing. --- # /docs/typescript/api/index/type-aliases/TransactionActivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransactionActivity # Type Alias: TransactionActivity > **TransactionActivity** = `object` Defined in: packages/sdk/src/activity.ts:354 Everything the protocol did in ONE transaction. The transaction-scoped counterpart of [SomniaMarketsClient.getMarketActivity](../interfaces/SomniaMarketsClient.md#getmarketactivity): same event union, same row ids, but selected by transaction rather than by market. A transaction that touched nothing the indexer follows comes back with empty collections and a null `blockNumber` — that is "not a protocol transaction", not a failure. ## Properties ### txHash > **txHash**: `string` Defined in: packages/sdk/src/activity.ts:356 The transaction hash, LOWER-CASED — not necessarily as the caller spelled it. *** ### blockNumber > **blockNumber**: `string` \| `null` Defined in: packages/sdk/src/activity.ts:362 Block the transaction landed in; null when the indexer has nothing for this hash. Read off the events, so it is the indexer's view of the block rather than the chain's. *** ### timestamp > **timestamp**: `string` \| `null` Defined in: packages/sdk/src/activity.ts:364 Block timestamp (unix seconds); null on the same terms as `blockNumber`. *** ### events > **events**: [`MarketActivity`](MarketActivity.md)[] Defined in: packages/sdk/src/activity.ts:370 What the transaction did, in LOG ORDER — earliest first, the order the chain executed it in. The opposite of [SomniaMarketsClient.getMarketActivity](../interfaces/SomniaMarketsClient.md#getmarketactivity), which is a feed and reads newest-first. *** ### ordersPlaced > **ordersPlaced**: [`TransactionOrder`](TransactionOrder.md)[] Defined in: packages/sdk/src/activity.ts:376 Orders PLACED in this transaction. A taker order that filled immediately appears here AND as the taker of a `TRADE` event; a maker order that only rested appears here alone. *** ### protocolFees > **protocolFees**: [`ProtocolFeeRecord`](ProtocolFeeRecord.md)[] Defined in: packages/sdk/src/activity.ts:378 Protocol fees charged in this transaction. BINARY only. *** ### builderFees > **builderFees**: [`BuilderFeeRecord`](BuilderFeeRecord.md)[] Defined in: packages/sdk/src/activity.ts:380 Builder fees charged in this transaction. BINARY only. *** ### markets > **markets**: `Record`\<`string`, [`Market`](Market.md)\> Defined in: packages/sdk/src/activity.ts:385 The markets these events touched, keyed by lowercased market id — so a caller can NAME each row without a lookup per row. --- # /docs/typescript/api/index/type-aliases/TransactionActivityOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransactionActivityOptions # Type Alias: TransactionActivityOptions > **TransactionActivityOptions** = `object` Defined in: packages/sdk/src/activity.ts:389 Options for [SomniaMarketsClient.getTransactionActivity](../interfaces/SomniaMarketsClient.md#gettransactionactivity). ## Properties ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/activity.ts:391 Max rows per event stream (default 100). *** ### anchor? > `optional` **anchor?**: `object` Defined in: packages/sdk/src/activity.ts:415 The transaction's block and timestamp. A PERFORMANCE FIX, not a filter. Without it, a transaction that produced no event — one that only PLACED orders, common on a live book — can be found only by probing `Order.placedTxHash`, and that column carries no index: measured, the probe runs past the gateway timeout and the read fails outright. The anchor skips the probe and goes straight to the timestamp-anchored pass, which IS index-served. WHAT IT DOES NOT FIX: a transaction that only CANCELLED orders stays unreadable by hash, and no anchor can change that. The indexer stores no cancellation record and `Order` carries only `placedTxHash`, so nothing in it is keyed by a cancel's own hash — the anchor turns that read from a timeout into a fast, honest "nothing indexed". Making those transactions readable needs an append-only order-update entity in the indexer. Normally left unset. When no indexed event anchors the transaction, the configured owner resolves the anchor from its own transport. Pass it only when the block and timestamp are already in hand; both fields or neither, since the block names the transaction and the timestamp serves the query. When an indexed event exists, its block wins and this value is ignored. #### blockNumber > **blockNumber**: `bigint` #### timestamp > **timestamp**: `bigint` --- # /docs/typescript/api/index/type-aliases/TransactionOrder [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TransactionOrder # Type Alias: TransactionOrder > **TransactionOrder** = [`FillOrder`](FillOrder.md) & `object` Defined in: packages/sdk/src/activity.ts:340 One order placed in a transaction — [FillOrder](FillOrder.md) plus the market it was placed in, which a transaction view needs because one transaction can touch more than one market. ## Type Declaration ### market > **market**: `string` The market's bytes32 marketId, lowercased. --- # /docs/typescript/api/index/type-aliases/TypedDataSigner [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TypedDataSigner # Type Alias: TypedDataSigner > **TypedDataSigner** = (`typedData`) => `Promise`\<`Hex`\> Defined in: packages/sdk/src/executor/types.ts:114 EIP-712 signing, for the actors that can sign as themselves. A private key and a wallet can; a safe cannot (its "signature" is an on-chain approval), and neither can a session key. Optional on [Executor](../interfaces/Executor.md) for that reason. ## Parameters ### typedData `TypedDataDefinition` ## Returns `Promise`\<`Hex`\> --- # /docs/typescript/api/index/type-aliases/UnifiedBookLevels [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedBookLevels # Type Alias: UnifiedBookLevels > **UnifiedBookLevels** = [`UnifiedOrderBook`](../interfaces/UnifiedOrderBook.md)\[`"bids"`\] Defined in: packages/sdk/src/unified/quotes.ts:19 One side of a unified book: [price, amount] pairs, best first. --- # /docs/typescript/api/index/type-aliases/UnifiedMarketType [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedMarketType # Type Alias: UnifiedMarketType > **UnifiedMarketType** = `"spot"` \| `"swap"` \| `"binary"` \| `"categorical"` Defined in: packages/sdk/src/unified/structs.ts:24 Market kind in ccxt vocabulary: "swap" is a linear perp; "binary" / "categorical" are outcome markets ("categorical" is reserved — no market carries it yet). --- # /docs/typescript/api/index/type-aliases/UnifiedOHLCV [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOHLCV # Type Alias: UnifiedOHLCV > **UnifiedOHLCV** = \[`number`, `number`, `number`, `number`, `number`, `number`\] Defined in: packages/sdk/src/unified/structs.ts:365 An OHLCV row: [timestampMs, open, high, low, close, volume(base)]. --- # /docs/typescript/api/index/type-aliases/UnifiedOrderIdentity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrderIdentity # Type Alias: UnifiedOrderIdentity > **UnifiedOrderIdentity** = `object` Defined in: packages/sdk/src/unified/exchange.ts:356 Stable owner-qualified identity for one indexed order row. ## Properties ### chainId > **chainId**: `number` Defined in: packages/sdk/src/unified/exchange.ts:357 *** ### account > **account**: `Address` Defined in: packages/sdk/src/unified/exchange.ts:358 *** ### marketId > **marketId**: `string` Defined in: packages/sdk/src/unified/exchange.ts:359 *** ### pool > **pool**: `string` Defined in: packages/sdk/src/unified/exchange.ts:360 *** ### orderId > **orderId**: `string` Defined in: packages/sdk/src/unified/exchange.ts:361 --- # /docs/typescript/api/index/type-aliases/UnifiedOrderPageItem [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrderPageItem # Type Alias: UnifiedOrderPageItem > **UnifiedOrderPageItem** = [`UnifiedOrder`](../interfaces/UnifiedOrder.md) & `object` Defined in: packages/sdk/src/unified/exchange.ts:365 A unified display order with its immutable identity and raw indexer row. ## Type Declaration ### identity > **identity**: [`UnifiedOrderIdentity`](UnifiedOrderIdentity.md) ### info > **info**: [`OrderRow`](OrderRow.md) --- # /docs/typescript/api/index/type-aliases/UnifiedOrderStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrderStatus # Type Alias: UnifiedOrderStatus > **UnifiedOrderStatus** = `"open"` \| `"closed"` \| `"canceled"` \| `"expired"` Defined in: packages/sdk/src/unified/structs.ts:202 Unified order lifecycle: "closed" = fully filled; "canceled" covers both explicit cancels and an IOC/market remainder that couldn't rest. --- # /docs/typescript/api/index/type-aliases/UnifiedOrdersPage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedOrdersPage # Type Alias: UnifiedOrdersPage > **UnifiedOrdersPage** = `object` Defined in: packages/sdk/src/unified/exchange.ts:379 One bounded indexer-offset page of an owner's orders. The page is a partial projection. The indexer does not provide a frozen revision, so concurrent changes can make later pages skip or repeat rows. An exhausted page does not prove that the result is complete account state. ## Properties ### orders > **orders**: [`UnifiedOrderPageItem`](UnifiedOrderPageItem.md)[] Defined in: packages/sdk/src/unified/exchange.ts:380 *** ### rowsRead > **rowsRead**: `number` Defined in: packages/sdk/src/unified/exchange.ts:382 Number of raw rows read before outcome filtering or identity resolution. *** ### nextOffset > **nextOffset**: `number` \| `null` Defined in: packages/sdk/src/unified/exchange.ts:384 Next raw row offset after a full page, or null after a short page. *** ### unresolved > **unresolved**: [`UnifiedOrderIdentity`](UnifiedOrderIdentity.md)[] Defined in: packages/sdk/src/unified/exchange.ts:386 Rows whose immutable market identity is absent or inconsistent in the loaded registry. *** ### coverage > **coverage**: `"partial"` Defined in: packages/sdk/src/unified/exchange.ts:387 *** ### source > **source**: `"indexer-offset"` Defined in: packages/sdk/src/unified/exchange.ts:388 --- # /docs/typescript/api/index/type-aliases/UnifiedStopOrderStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UnifiedStopOrderStatus # Type Alias: UnifiedStopOrderStatus > **UnifiedStopOrderStatus** = `"pending"` \| `"triggered"` \| `"canceled"` \| `"failed"` Defined in: packages/sdk/src/unified/structs.ts:262 A pending stop order's lifecycle, unified vocabulary. --- # /docs/typescript/api/index/type-aliases/UserFillsPage [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / UserFillsPage # Type Alias: UserFillsPage > **UserFillsPage** = `object` Defined in: packages/sdk/src/fills.ts:175 One bounded historical page of role-visible fills. This is not a snapshot or chain-head guarantee. ## Properties ### datasetGeneration > **datasetGeneration**: `string` Defined in: packages/sdk/src/fills.ts:177 Identity of the serving Fill dataset. Discard cached pages when it changes. *** ### fills > **fills**: [`FillRow`](FillRow.md)[] Defined in: packages/sdk/src/fills.ts:179 Existing fill rows, newest first by numeric timestamp, block and log position. *** ### nextCursor > **nextCursor**: `string` \| `null` Defined in: packages/sdk/src/fills.ts:181 Continue with the same scope. Null means no older role-visible row under a positive row cap. --- # /docs/typescript/api/index/type-aliases/VaultPayoutFallback [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VaultPayoutFallback # Type Alias: VaultPayoutFallback > **VaultPayoutFallback** = `object` Defined in: packages/sdk/src/binary/portfolio.ts:560 A vault-credit fallback record (mirror of the indexer `VaultPayoutFallback` entity) — an append-only history of payouts that could not be delivered to the wallet and were credited to the owner's ERC20Vault balance instead. This is the HISTORY layer; for the live claimable amount read [client.getVaultBalance](../interfaces/SomniaMarketsClient.md#getvaultbalance). Amounts are raw token units. ## Properties ### id > **id**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:562 Record id (`${blockNumber}_${logIndex}`). *** ### owner > **owner**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:564 Credited owner (lowercased). *** ### token > **token**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:566 Credited token (lowercased). *** ### amount > **amount**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:568 Amount credited to the vault balance (raw token units). *** ### market > **market**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:570 Market id the fallback was emitted for (lowercased). *** ### pool > **pool**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:577 The pool that emitted the credit (lowercased): the market's pool address, which on SPOT is also the market id. The credit sits in THIS pool's vault, so it is the `vault` to pass to [client.getVaultBalance](../interfaces/SomniaMarketsClient.md#getvaultbalance). *** ### timestamp > **timestamp**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:579 Timestamp (unix seconds) of the credit. *** ### txHash > **txHash**: `string` Defined in: packages/sdk/src/binary/portfolio.ts:581 Tx hash the credit landed in. --- # /docs/typescript/api/index/type-aliases/VenueVoidPolicy [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / VenueVoidPolicy # Type Alias: VenueVoidPolicy > **VenueVoidPolicy** = `"UNIFORM"` \| `"CLOB_SNAPSHOT"` Defined in: packages/sdk/src/operatorReads.ts:44 Void payout policy a BINARY_V1 venue's markets are created with (mirror of the contract-side `VoidPolicy` enum; the legacy `AMM_SNAPSHOT` slot (1) is rejected on-chain and never surfaces here). - `UNIFORM` (0): a voided market pays every side 1/N — the default. - `CLOB_SNAPSHOT` (2): a voided market pays `[p, D-p]` at its closing YES price (captured or read from the lock-preserved closing book); falls back to uniform when no two-sided close exists. Frozen per market at creation after resolving against the pool's actual capability. --- # /docs/typescript/api/index/type-aliases/WaitForIndexedBlockOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WaitForIndexedBlockOptions # Type Alias: WaitForIndexedBlockOptions > **WaitForIndexedBlockOptions** = `object` Defined in: packages/sdk/src/syncStatus.ts:160 Options for [SomniaMarketsClient.waitForIndexedBlock](../interfaces/SomniaMarketsClient.md#waitforindexedblock). All optional. ## Properties ### timeoutMs? > `optional` **timeoutMs?**: `number` Defined in: packages/sdk/src/syncStatus.ts:169 Give up after this many milliseconds (default 30,000). The deadline is checked between polls, so the wait performs at least one read even at 0, and a metadata request already in flight is allowed to finish and decide: a reply that arrives late but reports the block as processed resolves rather than failing. *** ### pollMs? > `optional` **pollMs?**: `number` Defined in: packages/sdk/src/syncStatus.ts:176 Milliseconds between polls (default 500, minimum 100). Each poll is one small `chain_metadata` read, and several waiters share one indexer — 500ms keeps a waiting client at two requests per second while staying well inside the indexing delay it is waiting on. *** ### signal? > `optional` **signal?**: `AbortSignal` Defined in: packages/sdk/src/syncStatus.ts:181 Abort the wait. The caller's own abort reason is rethrown unchanged, and the owner's configured signal aborts it as well — whichever fires first. --- # /docs/typescript/api/index/type-aliases/WatchStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / WatchStatus # Type Alias: WatchStatus > **WatchStatus** = `"unwatched"` \| `"hydrating"` \| `"live"` Defined in: packages/sdk/src/liveTail.ts:303 Per-market watch state: `"unwatched"` (no active watch — `getLive*` reads return empty), `"hydrating"` (watch registered; snapshot/backfill/reconnect in progress), `"live"` (streaming with delivered-event provenance). --- # /docs/typescript/api/index/variables/ANSWER_TYPE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ANSWER\_TYPE # Variable: ANSWER\_TYPE > `const` **ANSWER\_TYPE**: `object` Defined in: packages/sdk/src/oracleHub.ts:57 `AnswerType` enum values (OracleTypes.sol). ## Type Declaration ### Numeric > `readonly` **Numeric**: `0` = `0` Resolves to a number, bucketed by `numericIntervals`. ### Discrete > `readonly` **Discrete**: `1` = `1` Resolves to one of the `discreteOutcomes` strings. --- # /docs/typescript/api/index/variables/CADENCE_LADDER_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CADENCE\_LADDER\_SEC # Variable: CADENCE\_LADDER\_SEC > `const` **CADENCE\_LADDER\_SEC**: readonly \[`60`, `300`, `900`, `3600`, `14400`, `86400`\] Defined in: packages/sdk/src/interval.ts:107 The cadences a rolling binary series is currently rolled at, ascending: 1m, 5m, 15m, 1h, 4h, 24h. A snapshot, and NARROWING. The exact cadence is not a mystery — a series knows it, and `MarketCreator.MarketCreated` emits it as `intervalSec` for exactly this purpose ("not derivable from a single market's (tradingStart, expiry) — a series' FIRST market is a bootstrap partial — so it is surfaced here for indexers/UIs"). The indexer now DOES read that event and patches the true cadence onto the Market entity, so for anything a MarketCreator rolled the cadence is exact and joins by equality — this list, [CADENCE\_TOLERANCE\_SEC](CADENCE_TOLERANCE_SEC.md), [snapToCadence](../functions/snapToCadence.md) and the banded filter are all inert on that path. They still carry every market the patch does not reach: markets created directly through the module rather than by a creator, and history indexed before the patch shipped, both of which fall back to the lossy `intervalSec = expiry − tradingStart` derivation the contract warns about. That fallback is why the indexer's distinct values run to a hundred-odd one-off windows rather than a handful of cadences. So: still needed, but no longer the primary path. A venue rolling an off-ladder cadence outside a creator still fragments, so treat the list as a deployment's current habits, not a rule. --- # /docs/typescript/api/index/variables/CADENCE_TOLERANCE_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CADENCE\_TOLERANCE\_SEC # Variable: CADENCE\_TOLERANCE\_SEC > `const` **CADENCE\_TOLERANCE\_SEC**: `5` = `5` Defined in: packages/sdk/src/interval.ts:124 How far a market's window may sit from a ladder rung and still BE that cadence — 5 seconds either side. A rolled market's window is `expiry − tradingStart`, and trading routinely opens a second or two late, so a 15m market is indexed at 898s or 899s about as often as at 900s. Treating those as their own cadence is what split one series across three groups and made a cadence filter silently miss most of its own markets. Deliberately ABSOLUTE, not proportional: the jitter is a scheduling delay measured in seconds, so it does not grow with the cadence. A genuinely different window (a 10-minute series, a 52-minute bootstrap partial) stays outside every rung and keeps its own identity. --- # /docs/typescript/api/index/variables/CANCEL_ORDER_FOR_SELECTOR [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CANCEL\_ORDER\_FOR\_SELECTOR # Variable: CANCEL\_ORDER\_FOR\_SELECTOR > `const` **CANCEL\_ORDER\_FOR\_SELECTOR**: `"0xe37b444b"` Defined in: packages/sdk/src/spot/operatorGrants.ts:46 Selector for `cancelOrderFor` — an operator cancelling an order for its owner. Grant it alongside [PLACE\_ORDER\_FOR\_SELECTOR](PLACE_ORDER_FOR_SELECTOR.md) for a bot that manages its own orders; a place-only grant leaves the owner as the only account able to cancel. --- # /docs/typescript/api/index/variables/CANDLE_INTERVALS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / CANDLE\_INTERVALS # Variable: CANDLE\_INTERVALS > `const` **CANDLE\_INTERVALS**: readonly \[`60`, `300`, `900`, `3600`, `14400`, `86400`\] Defined in: packages/sdk/src/candles.ts:73 Candle bucket sizes (seconds): 1m, 5m, 15m, 1h, 4h, 1d — the intervals the indexer rolls up. Keep in lockstep with `indexer/src/intervals.ts` (CANDLE_INTERVALS) so [SomniaMarketsClient.getCandles](../interfaces/SomniaMarketsClient.md#getcandles) is only ever asked for a bucket the indexer actually materializes. --- # /docs/typescript/api/index/variables/DECIMALS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DECIMALS # Variable: DECIMALS > `const` **DECIMALS**: `6` = `6` Defined in: packages/sdk/src/store.ts:478 Fallback outcome-token / collateral decimals (tUSDC 6dp demo stack). Real math uses the per-market baseDecimals/quoteDecimals off the Market row. --- # /docs/typescript/api/index/variables/DEFAULT_CEX_RATE_BPS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DEFAULT\_CEX\_RATE\_BPS # Variable: DEFAULT\_CEX\_RATE\_BPS > `const` **DEFAULT\_CEX\_RATE\_BPS**: `10` = `10` Defined in: packages/sdk/src/unified/portfolioAnalytics.ts:365 Default comparison taker rate for the fees-saved metric, bps. 10 bps ≈ the common CEX taker tier the gateway compared against. --- # /docs/typescript/api/index/variables/DEFAULT_FEES [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DEFAULT\_FEES # Variable: DEFAULT\_FEES > `const` **DEFAULT\_FEES**: [`FixedFees`](../interfaces/FixedFees.md) Defined in: packages/sdk/src/config.ts:287 SDK default for [ClientConfig.fees](../interfaces/ClientConfig.md#fees): 60 gwei ceiling (~10× the observed Somnia base fee of 6 gwei), zero tip — instant BFT inclusion needs no bribe. --- # /docs/typescript/api/index/variables/DEFAULT_INDEXER_LIMITS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DEFAULT\_INDEXER\_LIMITS # Variable: DEFAULT\_INDEXER\_LIMITS > `const` **DEFAULT\_INDEXER\_LIMITS**: `Readonly`\<`Required`\<[`IndexerLimits`](../interfaces/IndexerLimits.md)\>\> Defined in: packages/sdk/src/config.ts:355 Conservative defaults for [ClientConfig.indexerLimits](../interfaces/ClientConfig.md#indexerlimits): no boundary retry, a per-page-sized cap, and five endpoint failures before the breaker opens. --- # /docs/typescript/api/index/variables/DEFAULT_SLIPPAGE_BPS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DEFAULT\_SLIPPAGE\_BPS # Variable: DEFAULT\_SLIPPAGE\_BPS > `const` **DEFAULT\_SLIPPAGE\_BPS**: `300n` = `300n` Defined in: packages/sdk/src/derivedReads.ts:950 Default market-order slippage cushion, in bps of the crossing price. --- # /docs/typescript/api/index/variables/DEFAULT_SLIPPAGE_MIN_TICKS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / DEFAULT\_SLIPPAGE\_MIN\_TICKS # Variable: DEFAULT\_SLIPPAGE\_MIN\_TICKS > `const` **DEFAULT\_SLIPPAGE\_MIN\_TICKS**: `10n` = `10n` Defined in: packages/sdk/src/derivedReads.ts:959 Default minimum slippage cushion in ticks — keeps long-shot (low-priced) outcomes, where the bps fraction rounds to almost nothing, from getting near-zero slack. --- # /docs/typescript/api/index/variables/EIGHT_HOURS_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / EIGHT\_HOURS\_SEC # Variable: EIGHT\_HOURS\_SEC > `const` **EIGHT\_HOURS\_SEC**: `28800` = `28_800` Defined in: packages/sdk/src/funding.ts:39 Seconds in the 8-hour presentation axis. --- # /docs/typescript/api/index/variables/FUNDING_PRECISION [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / FUNDING\_PRECISION # Variable: FUNDING\_PRECISION > `const` **FUNDING\_PRECISION**: `1000000000000000000n` = `1_000_000_000_000_000_000n` Defined in: packages/sdk/src/funding.ts:32 Fixed-point scale for every rate and cumulative-index value (1e18). --- # /docs/typescript/api/index/variables/HUB_MIN_FREE_BALANCE_WEI [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / HUB\_MIN\_FREE\_BALANCE\_WEI # Variable: HUB\_MIN\_FREE\_BALANCE\_WEI > `const` **HUB\_MIN\_FREE\_BALANCE\_WEI**: `bigint` Defined in: packages/sdk/src/preflight.ts:67 The minimum native balance (wei) the OracleHub should hold to fund its reactivity bond — 32 STT, mirrors the deploy-runbook's funding floor. In Oracle v2 the hub holds Σ operator earmarks + accrued credit + its own reactivity-bond float in one balance; a rough floor check is the hub's total balance clearing this floor (a precise free-float split is no longer separately tracked on-chain). --- # /docs/typescript/api/index/variables/LIQUIDATION_KIND [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / LIQUIDATION\_KIND # Variable: LIQUIDATION\_KIND > `const` **LIQUIDATION\_KIND**: readonly \[`"AccountLiquidated"`, `"PositionLiquidated"`, `"PositionSkipped"`, `"PositionTakenOver"`, `"AutoDeleveraged"`, `"Throttled"`, `"KeeperReward"`, `"OrderPanicked"`, `"PositionTransferred"`, `"CloseOutMarginSettled"`, `"BadDebtAbsorbed"`, `"ResidualBadDebt"`, `"AdlPriceCapacityExhausted"`, `"ResidualBackedByOpenPnl"`, `"CoverageDeclined"`, `"AdlSessionDiscarded"`, `"AdlCapacityShortfall"`\] Defined in: packages/sdk/src/perp/history.ts:105 Every value [LiquidationEvent.kind](../type-aliases/LiquidationEvent.md#kind) can carry, in the order the waterfall emits them. The vocabulary [ListLiquidationsOptions.kind](../interfaces/ListLiquidationsOptions.md#kind) filters on, so a filter cannot be spelled wrong. --- # /docs/typescript/api/index/variables/MARGIN_STATUS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MARGIN\_STATUS # Variable: MARGIN\_STATUS > `const` **MARGIN\_STATUS**: readonly [`MarginStatus`](../type-aliases/MarginStatus.md)[] Defined in: packages/sdk/src/perp/margin.ts:35 Ordered so index == on-chain enum value (0 Healthy … 3 CloseOut). --- # /docs/typescript/api/index/variables/MARKET_TYPE_BINARY_V1 [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MARKET\_TYPE\_BINARY\_V1 # Variable: MARKET\_TYPE\_BINARY\_V1 > `const` **MARKET\_TYPE\_BINARY\_V1**: `Hex` = `"0x06c65d9f"` Defined in: packages/sdk/src/operatorReads.ts:21 `MarketTypeIds.BINARY_V1` (`bytes4(keccak256("BINARY_V1"))`) — the only market type registered today. A venue is pinned to one type forever at `createVenue`. --- # /docs/typescript/api/index/variables/MARKET_TYPE_PLUGINS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MARKET\_TYPE\_PLUGINS # Variable: MARKET\_TYPE\_PLUGINS > `const` **MARKET\_TYPE\_PLUGINS**: `Readonly`\<`Record`\<`string`, [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\>\> Defined in: packages/sdk/src/marketTypes/index.ts:19 Every registered market-type plugin, keyed by its bytes4 `marketType` (lowercased). Frozen — the registry is a static seam, not mutated at runtime. --- # /docs/typescript/api/index/variables/MIN_SERIES_INTERVAL_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / MIN\_SERIES\_INTERVAL\_SEC # Variable: MIN\_SERIES\_INTERVAL\_SEC > `const` **MIN\_SERIES\_INTERVAL\_SEC**: `60` = `60` Defined in: packages/sdk/src/preflight.ts:74 The minimum roll interval the module enforces (`InvalidSeriesConfig` below). --- # /docs/typescript/api/index/variables/NATIVE_TOKEN_SENTINEL [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / NATIVE\_TOKEN\_SENTINEL # Variable: NATIVE\_TOKEN\_SENTINEL > `const` **NATIVE\_TOKEN\_SENTINEL**: `Address` = `"0x28f34DeFd2b4CB48d9eE6d89f2Be4Bc601694c00"` Defined in: packages/sdk/src/vault/funding.ts:35 The vault's native-token sentinel — the pseudo-address every ERC20Vault uses to key native (SOMI) balances, since native has no ERC-20 contract. **Details** Mirrors `NATIVE_TOKEN` in the protocol's `common/Common.sol`. Pass it to [client.getVaultBalance](../interfaces/SomniaMarketsClient.md#getvaultbalance) or `withdrawVault` to address a native balance — but NOT to [Trader.depositVault](../interfaces/Trader.md#depositvault), which reverts `UseDepositNative`; native goes in through [Trader.depositVaultNative](../interfaces/Trader.md#depositvaultnative). --- # /docs/typescript/api/index/variables/ONE_HOUR_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ONE\_HOUR\_SEC # Variable: ONE\_HOUR\_SEC > `const` **ONE\_HOUR\_SEC**: `3600` = `3_600` Defined in: packages/sdk/src/funding.ts:45 Seconds in an hour. --- # /docs/typescript/api/index/variables/ONE_YEAR_SEC [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ONE\_YEAR\_SEC # Variable: ONE\_YEAR\_SEC > `const` **ONE\_YEAR\_SEC**: `31536000` = `31_536_000` Defined in: packages/sdk/src/funding.ts:51 Seconds in a 365-day year, for annualization. --- # /docs/typescript/api/index/variables/OPEN_ORDERS_ONCHAIN_MAX_POOLS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / OPEN\_ORDERS\_ONCHAIN\_MAX\_POOLS # Variable: OPEN\_ORDERS\_ONCHAIN\_MAX\_POOLS > `const` **OPEN\_ORDERS\_ONCHAIN\_MAX\_POOLS**: `50` = `50` Defined in: packages/sdk/src/orders.ts:1059 The maximum number of pools `client.getOpenOrdersOnchain` accepts in one call. The real ceiling is the node's `eth_call` gas cap, not this number: the pool's `getOwnOpenOrders` is an unbounded per-user loop, so one pool with a very large resting set can exhaust it on its own. This cap only keeps the fan-out of id reads bounded (SDK-IO-005). --- # /docs/typescript/api/index/variables/ORDER_KIND [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ORDER\_KIND # Variable: ORDER\_KIND > `const` **ORDER\_KIND**: `Record`\<[`BinarySide`](../type-aliases/BinarySide.md), `number`\> Defined in: packages/sdk/src/writer.ts:107 v2 OrderKind enum for `placeBinaryOrder` (0 BUY_YES, 1 SELL_YES, 2 BUY_NO, 3 SELL_NO) — the side is explicit, NOT encoded in userData. The pool maps kind onto the base book's (isBid, price) internally; the SDK just forwards the enum. --- # /docs/typescript/api/index/variables/ORDER_KIND_SIDE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ORDER\_KIND\_SIDE # Variable: ORDER\_KIND\_SIDE > `const` **ORDER\_KIND\_SIDE**: readonly [`BinarySide`](../type-aliases/BinarySide.md)[] Defined in: packages/sdk/src/store.ts:541 Index → BinarySide for the on-chain `OrderKind` enum carried by the `BinaryOrderPlaced` event (settlement-extraction v2): 0 BUY_YES, 1 SELL_YES, 2 BUY_NO, 3 SELL_NO. This is the ONLY authoritative side-attribution source — v2 no longer encodes the side in `userData` (now opaque MM bookkeeping). --- # /docs/typescript/api/index/variables/ORDER_TYPE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ORDER\_TYPE # Variable: ORDER\_TYPE > `const` **ORDER\_TYPE**: `object` Defined in: packages/sdk/src/trade.ts:444 OrderBook OrderType — shared by binary `placeOrder` and spot `placeSpotOrder` (both ride the same OrderBook core): 0 NormalOrder (limit), 1 FillOrKill, 2 ImmediateOrCancel (market), 3 PostOnly. Pass to either call's `orderType`. ## Type Declaration ### LIMIT > `readonly` **LIMIT**: `0` = `0` 0 — NormalOrder: fill what crosses, rest the remainder on the book. ### FILL\_OR\_KILL > `readonly` **FILL\_OR\_KILL**: `1` = `1` 1 — FillOrKill: fill the full quantity immediately, or place nothing. ### MARKET > `readonly` **MARKET**: `2` = `2` 2 — ImmediateOrCancel: fill what crosses now, cancel the remainder. ### POST\_ONLY > `readonly` **POST\_ONLY**: `3` = `3` 3 — PostOnly: rest only — never takes liquidity. --- # /docs/typescript/api/index/variables/PERP_ORDER_REJECTION_REASON [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PERP\_ORDER\_REJECTION\_REASON # Variable: PERP\_ORDER\_REJECTION\_REASON > `const` **PERP\_ORDER\_REJECTION\_REASON**: readonly \[`"None"`, `"AlreadyExpired"`, `"SelfMatchCancelTaker"`, `"PostOnlyWouldCross"`, `"FillOrKillUnfillable"`, `"ImmediateOrCancelNoFill"`\] Defined in: packages/sdk/src/perp/history.ts:996 The contract's `OrderRejectionReason` enum, by index — the reason a batch-placed order was refused. Index 0 is `None`, which is NOT a rejection: it means the order rested or filled. It cannot appear on a [PerpOrderRejection](../type-aliases/PerpOrderRejection.md) row, and is kept in the table only so every other member keeps its on-chain index. --- # /docs/typescript/api/index/variables/PERP_POOL_FACTORY_MARKET_STATUS_INTERFACE_ID [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PERP\_POOL\_FACTORY\_MARKET\_STATUS\_INTERFACE\_ID # Variable: PERP\_POOL\_FACTORY\_MARKET\_STATUS\_INTERFACE\_ID > `const` **PERP\_POOL\_FACTORY\_MARKET\_STATUS\_INTERFACE\_ID**: `"0xa874fb70"` Defined in: packages/sdk/src/perp/registry.ts:50 ERC-165 id of `IPerpPoolFactoryMarketStatus` — the feature-detection handle that tells an upgraded factory from one predating the market-status views. A separate interface from `IPerpPoolFactory` on purpose: two live rotation gates (`MarginBank.setPerpPoolFactory`, `OperatorPermissionsRegistry.setPerpPoolFactory`) check `type(IPerpPoolFactory).interfaceId`, so declaring these views there would have changed the advertised id and turned a one-contract upgrade into a coordinated three-contract one. --- # /docs/typescript/api/index/variables/PERP_STOP_DROP_REASON [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PERP\_STOP\_DROP\_REASON # Variable: PERP\_STOP\_DROP\_REASON > `const` **PERP\_STOP\_DROP\_REASON**: readonly \[`"None"`, `"ReduceOnlyNoPosition"`, `"ReduceOnlyWrongSide"`, `"ReduceOnlyBelowMinQty"`, `"PlacementFailed"`, `"NoFill"`\] Defined in: packages/sdk/src/perp/stops.ts:81 Why a triggered stop placed nothing. Mirrors the registry's `DropReason` enum. The distinction matters for what a UI should say. `ReduceOnly*` are ordinary outcomes of a stop that events overtook — the position was already closed, or flipped, or what remained was dust — while `PlacementFailed` is a real rejection. Collapsing them all to "failed" makes routine behaviour look broken. --- # /docs/typescript/api/index/variables/PLACE_ORDER_FOR_SELECTOR [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PLACE\_ORDER\_FOR\_SELECTOR # Variable: PLACE\_ORDER\_FOR\_SELECTOR > `const` **PLACE\_ORDER\_FOR\_SELECTOR**: `"0x80054449"` Defined in: packages/sdk/src/spot/operatorGrants.ts:36 Selector for `placeOrderFor` — an operator placing an order for its owner. Granting this is what admits a trading bot, and what `SpotRouter` requires globally. Asserted against the function signature in the test suite, so it cannot drift from the contract. --- # /docs/typescript/api/index/variables/PRICE_FEED_DECIMALS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PRICE\_FEED\_DECIMALS # Variable: PRICE\_FEED\_DECIMALS > `const` **PRICE\_FEED\_DECIMALS**: `18` = `18` Defined in: packages/sdk/src/priceFeed/types.ts:26 Price scale of the on-chain EMA oracle: prices are 1e18-scaled integers. --- # /docs/typescript/api/index/variables/PRICE_RESOLUTION_SECONDS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / PRICE\_RESOLUTION\_SECONDS # Variable: PRICE\_RESOLUTION\_SECONDS > `const` **PRICE\_RESOLUTION\_SECONDS**: `Record`\<[`PriceCandleResolution`](../type-aliases/PriceCandleResolution.md), `number`\> Defined in: packages/sdk/src/priceFeed/types.ts:40 Seconds per [PriceCandleResolution](../type-aliases/PriceCandleResolution.md). --- # /docs/typescript/api/index/variables/QUERY_KEY_SCOPE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QUERY\_KEY\_SCOPE # Variable: QUERY\_KEY\_SCOPE > `const` **QUERY\_KEY\_SCOPE**: `"somnia-markets"` = `"somnia-markets"` Defined in: packages/sdk/src/queryKeys.ts:39 First element of every [ClientQueryKey](../type-aliases/ClientQueryKey.md) — match on it to invalidate all SDK reads at once. --- # /docs/typescript/api/index/variables/QUESTION_SOURCE_TYPE [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / QUESTION\_SOURCE\_TYPE # Variable: QUESTION\_SOURCE\_TYPE > `const` **QUESTION\_SOURCE\_TYPE**: `object` Defined in: packages/sdk/src/oracleHub.ts:43 `QuestionSourceType` enum values (OracleTypes.sol). Only all-JSON definitions participate in the hub's content-addressed dedup. ## Type Declaration ### Website > `readonly` **Website**: `0` = `0` Answer scraped from a website URL. ### JSON > `readonly` **JSON**: `1` = `1` Answer fetched from a JSON endpoint — the only source type eligible for dedup. ### Contract > `readonly` **Contract**: `2` = `2` Answer read from an on-chain contract. --- # /docs/typescript/api/index/variables/RAY [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / RAY # Variable: RAY > `const` **RAY**: `bigint` Defined in: packages/sdk/src/lend/math.ts:11 One ray — Aave's 27-decimal fixed-point unit; rates and indexes are ray-scaled. --- # /docs/typescript/api/index/variables/SELF_MATCHING_OPTION [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SELF\_MATCHING\_OPTION # Variable: SELF\_MATCHING\_OPTION > `const` **SELF\_MATCHING\_OPTION**: `object` Defined in: packages/sdk/src/trade.ts:859 OrderBook SelfMatchingOption — what happens when your incoming taker order crosses your OWN resting order: 0 cancels the rest of the taker, 1 cancels the whole maker. Every placement and amend verb takes it, and every one of them encodes 0 when you omit it. That default is the SDK's own choice: the pool reads the value out of the order request and has no default to fall back on. ## Type Declaration ### CANCEL\_TAKER > `readonly` **CANCEL\_TAKER**: `0` = `0` 0 — cancel the remaining taker quantity, leave the maker resting. ### CANCEL\_MAKER > `readonly` **CANCEL\_MAKER**: `1` = `1` 1 — cancel the full maker order, let the taker continue. --- # /docs/typescript/api/index/variables/SOMNIA_HIDEKI_TESTNET_ADDRESSES [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_HIDEKI\_TESTNET\_ADDRESSES # Variable: SOMNIA\_HIDEKI\_TESTNET\_ADDRESSES > `const` **SOMNIA\_HIDEKI\_TESTNET\_ADDRESSES**: [`SomniaMarketsAddresses`](../interfaces/SomniaMarketsAddresses.md) Defined in: packages/sdk/src/addresses.ts:68 Hideki testnet (chainId 50383, env `hideki-testnet-development`) protocol addresses, baked in from the deployment manifests at release time — pass as `config.addresses` for a zero-setup start. The live view of every deployed contract is the explorer's /system page. --- # /docs/typescript/api/index/variables/SOMNIA_MAINNET_ADDRESSES [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_MAINNET\_ADDRESSES # Variable: SOMNIA\_MAINNET\_ADDRESSES > `const` **SOMNIA\_MAINNET\_ADDRESSES**: [`SomniaMarketsAddresses`](../interfaces/SomniaMarketsAddresses.md) Defined in: packages/sdk/src/addresses.ts:44 Somnia mainnet (chainId 5031, env `mainnet-production`) protocol addresses, baked in from the deployment manifests at release time — pass as `config.addresses` for a zero-setup start. The live view of every deployed contract is the explorer's /system page. --- # /docs/typescript/api/index/variables/SOMNIA_MAINNET_LEND [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_MAINNET\_LEND # Variable: SOMNIA\_MAINNET\_LEND > `const` **SOMNIA\_MAINNET\_LEND**: [`LendAddresses`](../interfaces/LendAddresses.md) Defined in: packages/sdk/src/lend/client.ts:118 The SomniaLend mainnet deployment (chain 5031), from docs.somnialend.finance/deployed-contracts — set as `config.addresses.lend`. [SOMNIA\_TESTNET\_LEND](SOMNIA_TESTNET_LEND.md) is the testnet sibling. --- # /docs/typescript/api/index/variables/SOMNIA_MAINNET_PRICE_FEED [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_MAINNET\_PRICE\_FEED # Variable: SOMNIA\_MAINNET\_PRICE\_FEED > `const` **SOMNIA\_MAINNET\_PRICE\_FEED**: [`PriceFeedConfig`](../interfaces/PriceFeedConfig.md) Defined in: packages/sdk/src/config.ts:261 The Somnia-mainnet price feed. One endpoint serves every asset. Set it as `priceFeed: SOMNIA_MAINNET_PRICE_FEED`. Reads are pinned to the USDC quote (see [PriceFeedConfig.quote](../interfaces/PriceFeedConfig.md#quote)). This feed indexes the mainnet `PriceFeedScheduler`. Use it with a mainnet client. It is a different deployment from [SOMNIA\_TESTNET\_PRICE\_FEED](SOMNIA_TESTNET_PRICE_FEED.md), not a copy of it. Each feed indexes one chain. The names do not say which chain. To identify a feed, compare a `Feed` row's block number with the block height of each chain. This feed carries fewer symbols than the testnet feed. Code written for the testnet asset list can therefore fail here. Read the feed catalog to learn which bases exist. A base the feed does not carry returns no rows. It does not raise an error. --- # /docs/typescript/api/index/variables/SOMNIA_TESTNET_ADDRESSES [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_TESTNET\_ADDRESSES # Variable: SOMNIA\_TESTNET\_ADDRESSES > `const` **SOMNIA\_TESTNET\_ADDRESSES**: [`SomniaMarketsAddresses`](../interfaces/SomniaMarketsAddresses.md) Defined in: packages/sdk/src/addresses.ts:19 Somnia testnet (chainId 50312, env `testnet-development`) protocol addresses, baked in from the deployment manifests at release time — pass as `config.addresses` for a zero-setup start. The live view of every deployed contract is the explorer's /system page. --- # /docs/typescript/api/index/variables/SOMNIA_TESTNET_LEND [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_TESTNET\_LEND # Variable: SOMNIA\_TESTNET\_LEND > `const` **SOMNIA\_TESTNET\_LEND**: [`LendAddresses`](../interfaces/LendAddresses.md) Defined in: packages/sdk/src/lend/client.ts:134 The SomniaLend Somnia-testnet deployment (chain 50312) — pass to `config.addresses.lend`. Undocumented on docs.somnialend.finance; extracted from the official app's testnet mode (app.somnialend.finance) and verified on-chain (`PoolAddressesProvider.getPool()` matches, the UiPoolDataProvider aggregate decodes, the gateway resolves its wrapped native). --- # /docs/typescript/api/index/variables/SOMNIA_TESTNET_PRICE_FEED [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / SOMNIA\_TESTNET\_PRICE\_FEED # Variable: SOMNIA\_TESTNET\_PRICE\_FEED > `const` **SOMNIA\_TESTNET\_PRICE\_FEED**: [`PriceFeedConfig`](../interfaces/PriceFeedConfig.md) Defined in: packages/sdk/src/config.ts:238 The known Somnia-testnet price feed (dev) — one endpoint serving every asset. Wire it up with `priceFeed: SOMNIA_TESTNET_PRICE_FEED`. Pinned to the USDC quote: the feed also holds now-stale USDT history, and matching both quotes double-counts each base (see [PriceFeedConfig.quote](../interfaces/PriceFeedConfig.md#quote)). This feed indexes the testnet `PriceFeedScheduler`. Use it with a testnet client. A mainnet client reads prices from the other chain if you use this feed. Use [SOMNIA\_MAINNET\_PRICE\_FEED](SOMNIA_MAINNET_PRICE_FEED.md) instead. --- # /docs/typescript/api/index/variables/TIMEFRAMES [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / TIMEFRAMES # Variable: TIMEFRAMES > `const` **TIMEFRAMES**: `Record`\<`string`, `number`\> Defined in: packages/sdk/src/unified/structs.ts:658 Timeframe string → seconds, matching the indexer's candle intervals. --- # /docs/typescript/api/index/variables/ZERO_ADDRESS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / ZERO\_ADDRESS # Variable: ZERO\_ADDRESS > `const` **ZERO\_ADDRESS**: `"0x0000000000000000000000000000000000000000"` = `"0x0000000000000000000000000000000000000000"` Defined in: packages/sdk/src/preflight.ts:49 The all-zero EVM address (exported as `ZERO_ADDRESS`) — the "unset" sentinel the validators test addresses against. --- # /docs/typescript/api/index/variables/binaryMarketTypePlugin [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryMarketTypePlugin # Variable: binaryMarketTypePlugin > `const` **binaryMarketTypePlugin**: [`MarketTypePlugin`](../interfaces/MarketTypePlugin.md)\<[`BinaryVenueParams`](../interfaces/BinaryVenueParams.md)\> Defined in: packages/sdk/src/binary/plugin.ts:51 BINARY_V1 plugin. `encodeVenueFeeParams` / `decodeVenueFeeParams` delegate to the existing operatorReads helpers (the on-chain-backed encoder + the local decoder); `decode` is pure so it needs no client. --- # /docs/typescript/api/index/variables/binaryModuleReadAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryModuleReadAbi # Variable: binaryModuleReadAbi > `const` **binaryModuleReadAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/moduleAbi.ts:82 Read-only BinaryMarketsModule ABI for settlement discovery, pool reuse, and market records. **When to use** Use when keeper or verification code needs the module's chain state without constructing contract signatures by hand. **Gotchas** The `markets` tuple keeps its v1 layout. Read `marketNonce` separately when you need the outcome-token identifier encoding. --- # /docs/typescript/api/index/variables/binaryModuleWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryModuleWriteAbi # Variable: binaryModuleWriteAbi > `const` **binaryModuleWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/moduleAbi.ts:16 BinaryMarketsModule write surface — for keepers/tooling redeeming, minting/merging complete sets, or driving `finalizeMarket`/`releasePool` directly. --- # /docs/typescript/api/index/variables/binaryPoolWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binaryPoolWriteAbi # Variable: binaryPoolWriteAbi > `const` **binaryPoolWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:24 Write ABI for binary order placement, order maintenance, and complete sets. **Gotchas** Binary placement uses `placeBinaryOrder`; the generic `placeOrder` entry reverts on a binary pool. Prices use the YES side even for NO orders. --- # /docs/typescript/api/index/variables/binarySettlementAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / binarySettlementAbi # Variable: binarySettlementAbi > `const` **binarySettlementAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/readsAbi.ts:90 The BinarySettlement redemption singleton — for keepers/tooling reading settlement records or finalizing/redeeming against it directly. --- # /docs/typescript/api/index/variables/contractErrorsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / contractErrorsAbi # Variable: contractErrorsAbi > `const` **contractErrorsAbi**: readonly \[\{ `type`: `"error"`; `name`: `"AccessControlBadConfirmation"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AccessControlUnauthorizedAccount"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; \}, \{ `name`: `"neededRole"`; `type`: `"bytes32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"AccountNotFlat"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdapterNotApproved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AddressEmptyCode"`; `inputs`: readonly \[\{ `name`: `"target"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"AddressIsRegisteredBidder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlBadBankruptcyPrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlCounterpartySameSide"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlFlipNotAllowed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlGasFloorRequiresScanCap"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlRankerInvalidPrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlRankerNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlSelfSettle"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlSessionWindowNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AdlZeroNotional"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AllocatorAlreadyInitialised"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AllocatorNotAtZeroIndex"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AllocatorZeroFree"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyArmed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyClaimed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyFinalized"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyInitialised"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyLinked"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadyRetired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AlreadySubscribed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"AmendOldOrderGone"`; `inputs`: readonly \[\{ `name`: `"oldOrderId"`; `type`: `"uint128"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"AmendReplacementRejected"`; `inputs`: readonly \[\{ `name`: `"requestIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"reason"`; `type`: `"uint8"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ArrayLengthMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BackingMismatch"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"uint256"`; \}, \{ `name`: `"received"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"BackingOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BaseTokenAlreadyHasPool"`; `inputs`: readonly \[\{ `name`: `"baseToken"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"BatchGasGapNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BatchLiquidationDisabled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BatchTooLarge"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderAddressReserved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderAlreadyRegistered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderCannotBeIsolated"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderNotAContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderNotRegistered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BidderQuoteInProgress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BinaryClobFactoryNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BlockInPast"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BooksNotEmpty"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BothFeedsUnavailable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BoundaryNotAligned"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BoundaryNotFuture"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BudgetExhausted"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BuilderAddressReserved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BuilderCodesNotSupported"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BuilderFeeExceedsApproval"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BuilderFeeExceedsCap"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"BuilderNotApproved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CallerInManualVaultMode"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"CallerIsChild"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CallerIsMain"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CampaignInactive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CannotLinkSelf"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CannotStoreZeroOrder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CaptureStepsExhausted"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CaptureTooEarly"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ChainStillTriggerable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ChargeableExceedsDeficit"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ChargeableExceedsLosses"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CircuitBandExceedsInitialMargin"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CircuitBreakerTriggered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CloseAlreadyCaptured"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CloseNotCaptured"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CloseOutMarginExceedsBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CollateralMismatch"`; `inputs`: readonly \[\{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"CollateralNotWNative"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CollateralTokenMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ContextTooLong"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"CreditRecipientInDebt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"DeadlineExpired"`; `inputs`: readonly \[\{ `name`: `"deadline"`; `type`: `"uint64"`; \}, \{ `name`: `"currentTs"`; `type`: `"uint64"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"DelistEscrowActive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"DryRunDifference"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"DuplicateTier"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"DynamicIMFParametersDeprecated"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EMANotInitialized"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EmptyBatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EmptyCallData"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EmptyFilter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EmptyOrderBatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"EmptySelectors"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ERC1967InvalidImplementation"`; `inputs`: readonly \[\{ `name`: `"implementation"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC1967NonPayable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InsufficientAllowance"`; `inputs`: readonly \[\{ `name`: `"spender"`; `type`: `"address"`; \}, \{ `name`: `"allowance"`; `type`: `"uint256"`; \}, \{ `name`: `"needed"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InsufficientBalance"`; `inputs`: readonly \[\{ `name`: `"sender"`; `type`: `"address"`; \}, \{ `name`: `"balance"`; `type`: `"uint256"`; \}, \{ `name`: `"needed"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InvalidApprover"`; `inputs`: readonly \[\{ `name`: `"approver"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InvalidReceiver"`; `inputs`: readonly \[\{ `name`: `"receiver"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InvalidSender"`; `inputs`: readonly \[\{ `name`: `"sender"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ERC20InvalidSpender"`; `inputs`: readonly \[\{ `name`: `"spender"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"EthRefundFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ExceedsBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ExceedsWithdrawableBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ExcessiveInput"`; `inputs`: readonly \[\{ `name`: `"spent"`; `type`: `"uint256"`; \}, \{ `name`: `"maxAllowed"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ExpiredOrderMustBeCancelled"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"FailedCall"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FailedDeployment"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FaucetCapExceeded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FeedsDiverged"`; `inputs`: readonly \[\{ `name`: `"primaryPrice"`; `type`: `"uint256"`; \}, \{ `name`: `"secondaryPrice"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"FeeParamsTooLong"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FeeRecipientNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FeeRecipientRequired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FeeTooHigh"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FillOrKillNotFillable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FillPriceOutsideBand"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FillPriceOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FinalTokenMismatch"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"address"`; \}, \{ `name`: `"actual"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"FirstRollAlreadyArmed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FreshMarketRequired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FundedPrincipalOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FundingCapExceedsMarginBand"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"FundingRecipientInDebt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"GasLimitExceeded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"GasLimitZero"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"HandlerZeroAddress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ImmediateOrCancelNoFill"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InconsistentMinQuantityAndLotSize"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"IncorrectDryRun"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"IncorrectOrder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"IncorrectSender"`; `inputs`: readonly \[\{ `name`: `"sender"`; `type`: `"address"`; \}, \{ `name`: `"expected"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"IndexOutOfBounds"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InputEqualsOutput"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientActivationBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientBacking"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientBalance"`; `inputs`: readonly \[\{ `name`: `"balance"`; `type`: `"uint256"`; \}, \{ `name`: `"needed"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientCollateral"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientCreateValue"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientCredit"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientGasForBatch"`; `inputs`: readonly \[\{ `name`: `"gasAvailable"`; `type`: `"uint256"`; \}, \{ `name`: `"gasRequired"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientGasForPayout"`; `inputs`: readonly \[\{ `name`: `"gasLeft"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientLegInput"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"available"`; `type`: `"uint256"`; \}, \{ `name`: `"required"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientMargin"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientMarginAfterWithdrawal"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientMarginAtCreation"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientMarginForOrder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientOperatorDeposit"`; `inputs`: readonly \[\{ `name`: `"operatorId"`; `type`: `"uint32"`; \}, \{ `name`: `"required"`; `type`: `"uint256"`; \}, \{ `name`: `"available"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientOutput"`; `inputs`: readonly \[\{ `name`: `"received"`; `type`: `"uint256"`; \}, \{ `name`: `"minRequired"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientPermission"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientSomiPayment"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsufficientVaultBalance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsuranceFundCandidateHasDebt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsuranceFundCandidateHasPositions"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsuranceFundCannotTrade"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsuranceFundFeeRecipientConflict"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InsuranceFundNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAdapter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAddress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAdlRankerContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAdlRankerOrdering"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAmount"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidAsset"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidBaseToken"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidBidderAddress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidBuilder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidCircuitBreakerParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidConfig"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidCreator"`; `inputs`: readonly \[\{ `name`: `"creator"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidCreditCapBps"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidCreditGranterContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidDepositOrWithdrawal"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidDeviationBps"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidDynamicIMFParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidFeeRecipient"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidFundingCapDivergenceMargin"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidFundingParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidFundingPayer"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidGasBufferBps"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidGasParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidInitialization"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidInsuranceFundContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidIntervalSeconds"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLegQuantity"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLeverage"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLimitPrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLinkedWalletRegistry"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLinkedWalletRegistryContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLiquidationEngineContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLiquidationFeeRecipient"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidLotSize"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMarginBank"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMarginParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMarketExpiry"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMarketIndex"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMaxChildren"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMaxFeePerGas"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMaxLegs"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMidpointEmaParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMinQuantity"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMinStopDistance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidMsgValue"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"uint256"`; \}, \{ `name`: `"actual"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOperator"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOperatorPermissionsRegistry"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOrderOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOrderPair"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOutcomeIndex"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOutcomeToken"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidParameter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPaymasterData"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPayoutVector"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPerpPool"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPerpPoolFactory"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPerpPoolFactoryContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPolicy"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPool"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPremiumImpactNotional"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidPrice"`; `inputs`: readonly \[\{ `name`: `"price"`; `type`: `"uint256"`; \}, \{ `name`: `"tickSize"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidQuantity"`; `inputs`: readonly \[\{ `name`: `"quantity"`; `type`: `"uint256"`; \}, \{ `name`: `"constraint"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidReceiver"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidRegistry"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSeriesConfig"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSettlement"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSettlementParameters"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSettlementTime"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSettlementWindow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSlippage"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSlippageTolerance"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSomiPaymentPerOrder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSpotPool"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidSpotPoolRegistry"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTakerSide"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTickSize"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTier"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTokenAddress"`; `inputs`: readonly \[\{ `name`: `"token"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTradingWindow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidTriggerPrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidUnlinkGuard"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidVenueFeeParams"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidVenueSignature"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"InvalidVenueVoidPolicy"`; `inputs`: readonly \[\{ `name`: `"policy"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"InvalidVoidPolicy"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"IsolatedMarketBlocked"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"IsolatedSpansMultipleMarkets"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"KickoffOutOfRange"`; `inputs`: readonly \[\{ `name`: `"seriesId"`; `type`: `"uint32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"LegFillFailed"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"LegInputOverflow"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"runningInputAmount"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"LegPlacementRejected"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"reason"`; `type`: `"bytes"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"LegPlacementRevertedWithoutReason"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"LengthMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LimitPriceIncompatibleWithTrigger"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LinkedListCorrupted"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LinkedListEmptyKey"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LinkedListNodeAlreadyExists"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LinkedWalletFundingDisabled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LiquidationEngineNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"LiquidationFeeRecipientCannotBeInsuranceFund"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MainFundedAccountCannotBeCredited"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MainnetDeploymentForbidden"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarginBankMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarginBankNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketAlreadyAdded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketDeployFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketExpiryInPast"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketNotEmpty"`; `inputs`: readonly \[\{ `name`: `"activeAccounts"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"MarketNotFinalizedYet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketNotSettled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketNotSettled"`; `inputs`: readonly \[\{ `name`: `"marketId"`; `type`: `"bytes32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"MarketRestricted"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketSettled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarketTypeMismatch"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"bytes4"`; \}, \{ `name`: `"actual"`; `type`: `"bytes4"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"MarketTypeReserved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MarkPriceUnavailable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MaxChildrenReached"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MaxPositionSizeExceeded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MaxTiersAboveCeiling"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MaxTiersBelowActive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MetadataAlreadySet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"MigrationSubsNotArmed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ModuleTypeMismatch"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"bytes4"`; \}, \{ `name`: `"actual"`; `type`: `"bytes4"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"MustBeSentFromZeroAddress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeAmountMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeInputNotSupportedInAutoPullMode"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeIntermediateUnsupported"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"NativePayoutFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeRefundExceedsInput"`; `inputs`: readonly \[\{ `name`: `"refund"`; `type`: `"uint256"`; \}, \{ `name`: `"forwarded"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"NativeRefundFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeTokenTransferFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeTransferFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NativeWithdrawFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoActiveSubscription"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoBadDebt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoCreditToReclaim"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoFundedPrincipal"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoOpenPosition"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoPendingQuestion"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoPositionToFlatten"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoPrecompile"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoProposalPending"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoReducingPositionAtCreation"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoSettlementScheduled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NoSponsorSigner"`; `inputs`: readonly \[\{ `name`: `"operatorId"`; `type`: `"uint32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"NoStateChange"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotALinkedChild"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotArmed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotASideHolder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotASpotPool"`; `inputs`: readonly \[\{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"NotAuthorizedAdapter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotEntryPoint"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotExpired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotFinalized"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NothingOwed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NothingToAdopt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NothingToClaim"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NothingToReturn"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotIdPool"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotInitializing"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotLinked"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotLiquidatable"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotModule"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotOperatorOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotOperatorOwner"`; `inputs`: readonly \[\{ `name`: `"operatorId"`; `type`: `"uint32"`; \}, \{ `name`: `"caller"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"NotOracle"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotQuiesced"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotReactivity"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotReceiver"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotRegistrar"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"NotSettlement"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyAdmin"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyAgentPlatform"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyApprovedContracts"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyCreditGranter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyFundingPayer"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyLiquidationEngine"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyMarginBank"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyPerpPool"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyPrecompile"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlyReactivityPrecompile"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OnlySelf"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OpeningOrderRequiresQuantity"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OpenInterestCapExceeded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OperatorDisabled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OperatorIdReserved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OperatorNotActive"`; `inputs`: readonly \[\{ `name`: `"operatorId"`; `type`: `"uint32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"OracleNotAContract"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OracleNotAnswered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OracleNotInitialized"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OraclePriceStale"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderAlreadyExpired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderAlreadyLinked"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderDoesNotExist"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderExpiryBeyondMarket"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderIdMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OrderInfoIdMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OutcomeCountMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OutcomeTokenNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OutcomeTransferFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"OwnableInvalidOwner"`; `inputs`: readonly \[\{ `name`: `"owner"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"OwnableUnauthorizedAccount"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"OwnerMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PendingOwnerOnly"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PermitTokenMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerpPoolAlreadyRegistered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerpPoolHasActivePositions"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerpPoolNotFromFactory"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerpPoolNotRegistered"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerpPoolWrongMarginBank"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PerUserOrderIndexInconsistency"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PlacementRevertedWithoutReason"`; `inputs`: readonly \[\{ `name`: `"isBid"`; `type`: `"bool"`; \}, \{ `name`: `"quoteIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"PlacementRevertedWithoutReason"`; `inputs`: readonly \[\{ `name`: `"isBid"`; `type`: `"bool"`; \}, \{ `name`: `"userData"`; `type`: `"uint64"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"PokeTooSoon"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PoolAlreadyReleased"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PoolBooksNotEmpty"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PoolCreatorUnknown"`; `inputs`: readonly \[\{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"PoolIndexOutOfBounds"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PoolNotApproved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PoolNotRegistered"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"PoolStateUnchanged"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PositionBelowMinQuantity"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PostOnlyWouldCross"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PredecessorAlreadyAdopted"`; `inputs`: readonly \[\{ `name`: `"prior"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"PriceNotAlignedToTickSize"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PriceOutOfBounds"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PriceOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PriceTooLarge"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PrimaryEqualsSecondary"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"PriorFundingPayerOutstanding"`; `inputs`: readonly \[\{ `name`: `"outstandingPayer"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"QuantityBelowMinimum"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"QuantityBelowMinimum"`; `inputs`: readonly \[\{ `name`: `"quantity"`; `type`: `"uint256"`; \}, \{ `name`: `"minimum"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"QuantityNotAlignedToLotSize"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"QuestionNotFinal"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"QueueEmpty"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RankerNotLinkAware"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RecoveryAmountInvalid"`; `inputs`: readonly \[\{ `name`: `"amount"`; `type`: `"uint256"`; \}, \{ `name`: `"balance"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RecoveryDestinationZero"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RecoveryRateLimited"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RecoveryTokenIsNative"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RedeemAuthExpired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RedeemNonceUsed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RedeemSignatureInvalid"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ReduceOnlyBudgetExceeded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ReentrancyGuardReentrantCall"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RefundFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RegistryNotApprovedByOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RegistryRequiredForGroupMode"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RenounceDisabled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ReviveTooSoon"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RouteEmpty"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderCodesNotSupportedOnPool"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderFeeExceedsPoolCap"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}, \{ `name`: `"builderFeeBpsTimes1k"`; `type`: `"uint96"`; \}, \{ `name`: `"maxBuilderFeeBpsTimes1k"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderFeeWithoutBuilder"`; `inputs`: readonly \[\{ `name`: `"builderFeeBpsTimes1k"`; `type`: `"uint96"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderIsPool"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderIsRouter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RouterBuilderNotApproved"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}, \{ `name`: `"builderFeeBpsTimes1k"`; `type`: `"uint96"`; \}, \{ `name`: `"approved"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterInvalidLegPrice"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"priceLimit"`; `type`: `"uint256"`; \}, \{ `name`: `"tickSize"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterMarketQuoteInvalidPriceLimit"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"providedPriceLimit"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterNotApprovedAsOperator"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"pool"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterQuantityBelowMinimum"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"quantity"`; `type`: `"uint256"`; \}, \{ `name`: `"minQuantity"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterQuantityNotLotAligned"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"quantity"`; `type`: `"uint256"`; \}, \{ `name`: `"lotSize"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouterQuoteInputZero"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RouterQuoteOutputZero"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"RouteTokenMismatch"`; `inputs`: readonly \[\{ `name`: `"legIndex"`; `type`: `"uint256"`; \}, \{ `name`: `"expected"`; `type`: `"address"`; \}, \{ `name`: `"actualBase"`; `type`: `"address"`; \}, \{ `name`: `"actualQuote"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"RouteTooLong"`; `inputs`: readonly \[\{ `name`: `"maxLegs"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SafeCastOverflowedIntDowncast"`; `inputs`: readonly \[\{ `name`: `"bits"`; `type`: `"uint8"`; \}, \{ `name`: `"value"`; `type`: `"int256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SafeCastOverflowedUintDowncast"`; `inputs`: readonly \[\{ `name`: `"bits"`; `type`: `"uint8"`; \}, \{ `name`: `"value"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SafeERC20FailedOperation"`; `inputs`: readonly \[\{ `name`: `"token"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SelfMatchCancelTaker"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SeriesAlreadyLive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SeriesIdOutOfRange"`; `inputs`: readonly \[\{ `name`: `"seriesId"`; `type`: `"uint32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SeriesNotStalled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementAlreadyScheduled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementAlreadySet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementNotReady"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementParametersNotConfigured"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SettlementWindowOpen"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SideHolderIndexOutOfBounds"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SimulatedFeedRevert"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"StaleMarketId"`; `inputs`: readonly \[\{ `name`: `"marketId"`; `type`: `"bytes32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"StalePrice"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SubscriptionAlreadyActive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SubscriptionStillActive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"SymbolIndexOutOfRange"`; `inputs`: readonly \[\{ `name`: `"symbolIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SymbolLengthUnsupported"`; `inputs`: readonly \[\{ `name`: `"length"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SymbolMismatch"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"string"`; \}, \{ `name`: `"actual"`; `type`: `"string"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SymbolNotInitialized"`; `inputs`: readonly \[\{ `name`: `"symbolIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"SymbolStalePrice"`; `inputs`: readonly \[\{ `name`: `"symbolIndex"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"TakeoverPriceOutOfRange"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TakeoverPriceOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TakerFillWouldMintBadDebt"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TierBalanceInsufficient"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TimestampInPast"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TokenZero"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TooManyMarkets"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TooManyMarketsForQuestion"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TooManyRestingOrders"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TradingNotActive"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TransferRecipientReserved"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TransferSourceAndDestinationSame"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"TriggerTooCloseToEma"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"Unauthorized"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnderpaidScheduleFee"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnderpaidSchedulingCost"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnexpectedFillPair"`; `inputs`: readonly \[\{ `name`: `"takerKind"`; `type`: `"uint8"`; \}, \{ `name`: `"makerKind"`; `type`: `"uint8"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnexpectedNativeDeposit"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownFire"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownMarket"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownMarketType"`; `inputs`: readonly \[\{ `name`: `"marketType"`; `type`: `"bytes4"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnknownOperator"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownOracleQuestion"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownReader"`; `inputs`: readonly \[\{ `name`: `"reader"`; `type`: `"address"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnknownSeries"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnknownSeriesSelector"`; `inputs`: readonly \[\{ `name`: `"selector"`; `type`: `"bytes4"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnknownSymbol"`; `inputs`: readonly \[\{ `name`: `"symbol"`; `type`: `"string"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnknownVenue"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnlinkBlockedByGuard"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnsponsoredSelector"`; `inputs`: readonly \[\{ `name`: `"selector"`; `type`: `"bytes4"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UnsubscribeFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UnsupportedFeeParamsVersion"`; `inputs`: readonly \[\{ `name`: `"version"`; `type`: `"uint8"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"UseBinaryPlacement"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UseDepositNative"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UseFundNative"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UUPSUnauthorizedCallContext"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"UUPSUnsupportedProxiableUUID"`; `inputs`: readonly \[\{ `name`: `"slot"`; `type`: `"bytes32"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"VenueAuthExpired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueCreationDisabled"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueFeeAboveHardCap"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueIdRequired"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueMismatch"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueNonceUsed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenuePolicyDenied"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VenueSignerUnset"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VoucherAccountCannotBeMainFunded"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VoucherAccountLeverageLocked"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VoucherLeverageCapNotSet"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VoucherMarketNotAllowed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"VwapOverflow"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WithdrawalBelowCreditFloor"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WithdrawalBelowFundedPrincipal"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WithdrawalExceedsDeposit"`; `inputs`: readonly \[\{ `name`: `"operatorId"`; `type`: `"uint32"`; \}, \{ `name`: `"requested"`; `type`: `"uint256"`; \}, \{ `name`: `"available"`; `type`: `"uint256"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"WithdrawalFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WithdrawFailed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WrongEmitter"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WrongEvent"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WrongReserveAttached"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"WrongStatus"`; `inputs`: readonly \[\{ `name`: `"expected"`; `type`: `"uint8"`; \}, \{ `name`: `"actual"`; `type`: `"uint8"`; \}\]; \}, \{ `type`: `"error"`; `name`: `"ZeroAddress"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroAgentOracle"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroAmount"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroCollateralFillsAllowed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroDeposit"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroEntryPoint"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroImpl"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroModule"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroOrder"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroOrderIndex"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroOwner"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroPrimary"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroPriority"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroQuoteFillsAllowed"`; `inputs`: readonly \[\]; \}, \{ `type`: `"error"`; `name`: `"ZeroReader"`; `inputs`: readonly \[\]; \}\] Defined in: packages/sdk/src/contractErrorsAbi.ts:20 Custom-error ABI entries for every protocol contract — the revert-decoding table. --- # /docs/typescript/api/index/variables/erc20VaultWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / erc20VaultWriteAbi # Variable: erc20VaultWriteAbi > `const` **erc20VaultWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:235 --- # /docs/typescript/api/index/variables/erc20WriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / erc20WriteAbi # Variable: erc20WriteAbi > `const` **erc20WriteAbi**: readonly \[\{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:9 --- # /docs/typescript/api/index/variables/erc6909Abi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / erc6909Abi # Variable: erc6909Abi > `const` **erc6909Abi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/readsAbi.ts:149 The protocol-wide ERC-6909 outcome-token singleton — for keepers/tooling reading outcome balances or wiring operator approvals/transfers directly. --- # /docs/typescript/api/index/variables/lendDebtTokenAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / lendDebtTokenAbi # Variable: lendDebtTokenAbi > `const` **lendDebtTokenAbi**: readonly \[\{ \}, \{ \}\] Defined in: packages/sdk/src/lend/lendAbi.ts:71 Aave variable-debt-token credit delegation — `borrowNative` routes the borrow through the gateway, so the user must first delegate borrowing power on the WSOMI variable debt token to it (`approveDelegation`); `borrowAllowance` reads the remaining delegated headroom. --- # /docs/typescript/api/index/variables/lendGatewayAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / lendGatewayAbi # Variable: lendGatewayAbi > `const` **lendGatewayAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/lend/lendAbi.ts:55 WrappedTokenGatewayV3 — wraps/unwraps native SOMI around the WSOMI reserve so users lend/borrow the native token without touching WSOMI themselves. The v3.0 gateway takes the Pool address as its first argument on every call. --- # /docs/typescript/api/index/variables/lendPoolAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / lendPoolAbi # Variable: lendPoolAbi > `const` **lendPoolAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/lend/lendAbi.ts:17 SomniaLend Pool (Aave v3 `IPool` subset) — the user actions the SDK sends (supply / withdraw / borrow / repay and the collateral toggle) plus the account-aggregate and per-reserve reads backing the lend client's `getAccount`. --- # /docs/typescript/api/index/variables/lendUiPoolDataProviderAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / lendUiPoolDataProviderAbi # Variable: lendUiPoolDataProviderAbi > `const` **lendUiPoolDataProviderAbi**: `Abi` Defined in: packages/sdk/src/lend/lendAbi.ts:46 UiPoolDataProviderV3 — Aave's aggregated read: the whole market and a user's every position in one eth_call each (see the signature const above for the verified v3.0 tuple shape; typed as plain `Abi` deliberately). --- # /docs/typescript/api/index/variables/liquidationEngineEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / liquidationEngineEventsAbi # Variable: liquidationEngineEventsAbi > `const` **liquidationEngineEventsAbi**: readonly \[\{ `type`: `"event"`; `name`: `"AccountLiquidated"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"positionsProcessed"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"stageReached"`; `type`: `"uint8"`; `indexed`: `false`; \}, \{ `name`: `"marginStatusBefore"`; `type`: `"uint8"`; `indexed`: `false`; \}, \{ `name`: `"marginStatusAfter"`; `type`: `"uint8"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"PositionLiquidated"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"sizeDelta"`; `type`: `"int128"`; `indexed`: `false`; \}, \{ `name`: `"markPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"PositionSkippedBelowMinQuantity"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"size"`; `type`: `"int128"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"PositionTakenOver"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"bidder"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"size"`; `type`: `"int128"`; `indexed`: `false`; \}, \{ `name`: `"takeoverPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"LiquidationFeeCharged"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"tier"`; `type`: `"uint256"`; `indexed`: `true`; \}, \{ `name`: `"fillNotional"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"LiquidationKeeperRewardPaid"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"keeper"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"LiquidationThrottled"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"blockVolume"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"volumeCap"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"ResidualBadDebt"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"residual"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"ResidualBackedByOpenPnl"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"residual"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"equity"`; `type`: `"int256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"CoverageDeclinedByEquityCap"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"declined"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"tiers"`; `type`: `"uint256[]"`; `indexed`: `false`; \}, \{ `name`: `"losses"`; `type`: `"uint256[]"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"AdlCapacityShortfall"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"residualSize"`; `type`: `"uint128"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"AdlPriceCapacityExhausted"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"residual"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"AdlSessionDiscarded"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"absorbed"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"reason"`; `type`: `"uint8"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}\] Defined in: packages/sdk/src/eventsAbi.ts:502 LiquidationEngine events — the liquidation waterfall. Also a singleton, and the waterfall is SPLIT with MarginBank: the engine emits the stages and their costs, while the settlement legs (`AutoDeleveraged`, `CloseOutMarginSettled`, `BadDebtAbsorbed`, `PositionTransferred`) land on `marginBankEventsAbi` above. A consumer that wants the whole story needs both ABIs. Account-level events carry NO pool: `AccountLiquidated` covers every position the stage walked, and the residual/ADL-shortfall events describe the account's hole. Only the per-position events are pool-scoped, which is why a per-pool liquidation filter is lossy. Owner-parameter `*Updated` events, bidder registration, and the scan-progress checkpoints (`AdlScanCheckpointed`, `AdlNoBadDebtToSocialize`) are out: they are keeper mechanics, not account outcomes. Generated from `indexer/abis/LiquidationEngine.json` and pinned by topic0 in `test/perpEventsAbi.test.ts`. --- # /docs/typescript/api/index/variables/marginBankEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marginBankEventsAbi # Variable: marginBankEventsAbi > `const` **marginBankEventsAbi**: readonly \[\{ `type`: `"event"`; `name`: `"PositionUpdated"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"newSize"`; `type`: `"int128"`; `indexed`: `false`; \}, \{ `name`: `"avgEntryPrice"`; `type`: `"uint128"`; `indexed`: `false`; \}, \{ `name`: `"realizedPnl"`; `type`: `"int256"`; `indexed`: `false`; \}, \{ `name`: `"entryFundingIndex"`; `type`: `"int256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"FundingSettled"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"payment"`; `type`: `"int256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"Deposited"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"DepositedFor"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"Withdrawn"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"CollateralLocked"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"CollateralUnlocked"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"FeeCharged"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"insurancePortion"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"RebatePaid"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"AutoDeleveraged"`; `inputs`: readonly \[\{ `name`: `"counterparty"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"bankrupt"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"sizeReduced"`; `type`: `"int128"`; `indexed`: `false`; \}, \{ `name`: `"bankruptcyPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"CloseOutMarginSettled"`; `inputs`: readonly \[\{ `name`: `"from"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"to"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"BadDebtAbsorbed"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"badDebt"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"covered"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"absorbedBy"`; `type`: `"address"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"PositionTransferred"`; `inputs`: readonly \[\{ `name`: `"from"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"to"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"size"`; `type`: `"int128"`; `indexed`: `false`; \}, \{ `name`: `"collateralTransferred"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"LiquidationOrderPanicked"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"panicCode"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"MainFundedChild"`; `inputs`: readonly \[\{ `name`: `"child"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"payer"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"outstandingPrincipal"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"IsolatedModeSet"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"enabled"`; `type`: `"bool"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"MaxLeverageSet"`; `inputs`: readonly \[\{ `name`: `"account"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"leverageX"`; `type`: `"uint16"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"BuilderFeeCharged"`; `inputs`: readonly \[\{ `name`: `"payer"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"builder"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"perpPool"`; `type`: `"address"`; `indexed`: `true`; \}, \{ `name`: `"amount"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}\] Defined in: packages/sdk/src/eventsAbi.ts:479 The published MarginBank event ABI — every fragment, in one const. --- # /docs/typescript/api/index/variables/marginBankWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / marginBankWriteAbi # Variable: marginBankWriteAbi > `const` **marginBankWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:175 --- # /docs/typescript/api/index/variables/operatorRegistryWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / operatorRegistryWriteAbi # Variable: operatorRegistryWriteAbi > `const` **operatorRegistryWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:396 --- # /docs/typescript/api/index/variables/oracleHubAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / oracleHubAbi # Variable: oracleHubAbi > `const` **oracleHubAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/machineryAbi.ts:33 OracleHub function ABI (writes + point-status views) — mirrors `smart-contracts/src/adapters/OracleHub.sol` exactly. Backs the `OracleHubAdmin` writes and the standalone oracleHub.ts reads. --- # /docs/typescript/api/index/variables/oracleHubEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / oracleHubEventsAbi # Variable: oracleHubEventsAbi > `const` **oracleHubEventsAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/machineryAbi.ts:104 OracleHub event ABI — decoded from `scheduleQuestion` receipts (`QuestionScheduled` vs `QuestionReused`) and by keepers reconciling the §8e exact-metering invariants. Indexed-ness mirrors OracleHub.sol. --- # /docs/typescript/api/index/variables/orderBookBatchWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / orderBookBatchWriteAbi # Variable: orderBookBatchWriteAbi > `const` **orderBookBatchWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:136 --- # /docs/typescript/api/index/variables/orderBookEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / orderBookEventsAbi # Variable: orderBookEventsAbi > `const` **orderBookEventsAbi**: readonly \[\{ `type`: `"event"`; `name`: `"OrderPlaced"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}, \{ `name`: `"placedOrder"`; `type`: `"tuple"`; `indexed`: `false`; `components`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; \}, \{ `name`: `"isBid"`; `type`: `"bool"`; \}, \{ `name`: `"owner"`; `type`: `"address"`; \}, \{ `name`: `"userData"`; `type`: `"uint64"`; \}, \{ `name`: `"price"`; `type`: `"uint256"`; \}, \{ `name`: `"fullQuantity"`; `type`: `"uint256"`; \}, \{ `name`: `"quantityRemaining"`; `type`: `"uint256"`; \}, \{ `name`: `"expireTimestampNs"`; `type`: `"uint64"`; \}\]; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderRested"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderCancelled"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderExpired"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderReduced"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}, \{ `name`: `"newQuantity"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderFilled"`; `inputs`: readonly \[\{ `name`: `"takerOrderId"`; `type`: `"uint128"`; `indexed`: `true`; \}, \{ `name`: `"makerOrderId"`; `type`: `"uint128"`; `indexed`: `true`; \}, \{ `name`: `"quantityFilled"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"takerRemainingQuantity"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"makerRemainingQuantity"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"fillPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderCancelledSelfMatch"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"MakerOrderCancelledExceedsPosition"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OrderCancelledPreFill"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}\] Defined in: packages/sdk/src/eventsAbi.ts:29 Order lifecycle events shared by SpotPool + BinaryPool (the OrderBook base). --- # /docs/typescript/api/index/variables/perpPoolEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpPoolEventsAbi # Variable: perpPoolEventsAbi > `const` **perpPoolEventsAbi**: readonly \[\{ `type`: `"event"`; `name`: `"FundingUpdated"`; `inputs`: readonly \[\{ `name`: `"fundingRate"`; `type`: `"int256"`; `indexed`: `false`; \}, \{ `name`: `"cumulativeFundingPerUnit"`; `type`: `"int256"`; `indexed`: `false`; \}, \{ `name`: `"indexPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}, \{ `name`: `"intervalsSettled"`; `type`: `"uint64"`; `indexed`: `false`; \}, \{ `name`: `"markPrice"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"OpenInterestUpdated"`; `inputs`: readonly \[\{ `name`: `"openInterest"`; `type`: `"uint256"`; `indexed`: `false`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"MakerOrderCancelledNegativeEquity"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}, \{ `type`: `"event"`; `name`: `"MakerOrderCancelledStaleMark"`; `inputs`: readonly \[\{ `name`: `"orderId"`; `type`: `"uint128"`; `indexed`: `true`; \}\]; `anonymous`: `false`; \}\] Defined in: packages/sdk/src/eventsAbi.ts:164 PerpPool-only events the live tail materializes (funding + open interest). Signatures verified against the DEPLOYED implementation's runtime bytecode, not against a source tree — the claim they previously carried ("mirror IPerpPool exactly, deployed testnet implementation") was false for both events here, and being false in a comment is how it survived: a wrong arity is a different topic0, so `watchEvent` filtered on something no pool ever emitted and the live funding tail silently never fired. `mise run verify:abis` in the indexer package is what now checks this class of claim mechanically. --- # /docs/typescript/api/index/variables/perpPoolWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / perpPoolWriteAbi # Variable: perpPoolWriteAbi > `const` **perpPoolWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:158 Write ABI for perpetual order placement, cancellation, and funding updates. **Gotchas** Perpetual placement is not payable. Margin comes from MarginBank rather than per-order escrow. --- # /docs/typescript/api/index/variables/spotPoolOperatorRegistryReadAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / spotPoolOperatorRegistryReadAbi # Variable: spotPoolOperatorRegistryReadAbi > `const` **spotPoolOperatorRegistryReadAbi**: readonly \[\{ \}\] Defined in: packages/sdk/src/readsAbi.ts:168 --- # /docs/typescript/api/index/variables/spotPoolWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / spotPoolWriteAbi # Variable: spotPoolWriteAbi > `const` **spotPoolWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:89 Write ABI for single spot order placement, cancellation, and amendment. **Gotchas** `placeOrder` is payable because native-base sells can carry value. The singular amend has a different revert surface from batch amendment. --- # /docs/typescript/api/index/variables/spotStopRegistryEventsAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / spotStopRegistryEventsAbi # Variable: spotStopRegistryEventsAbi > `const` **spotStopRegistryEventsAbi**: readonly \[\{ \}, \{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:277 --- # /docs/typescript/api/index/variables/spotStopRegistryWriteAbi [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [index](../README.md) / spotStopRegistryWriteAbi # Variable: spotStopRegistryWriteAbi > `const` **spotStopRegistryWriteAbi**: readonly \[\{ \}, \{ \}, \{ \}\] Defined in: packages/sdk/src/tradeAbi.ts:253 --- # /docs/typescript/api/native [**@somnia-chain/markets-sdk**](../README.md) *** [@somnia-chain/markets-sdk](../README.md) / native # native ## native RPC - [NativeRpcRequester](interfaces/NativeRpcRequester.md) - [SomniaNative](interfaces/SomniaNative.md) - [createNative](functions/createNative.md) - [isMethodNotFound](functions/isMethodNotFound.md) - [isUnauthorized](functions/isUnauthorized.md) - [SomniaMempoolStatus](variables/SomniaMempoolStatus.md) - [SomniaMempoolStatus](type-aliases/SomniaMempoolStatus.md) - [SomniaRpcError](interfaces/SomniaRpcError.md) - [getSomniaRpcError](functions/getSomniaRpcError.md) - [SomniaTransactionReceipt](type-aliases/SomniaTransactionReceipt.md) - [sessionPrivateKey](functions/sessionPrivateKey.md) - [sessionAddress](functions/sessionAddress.md) - [SomniaBlockTag](type-aliases/SomniaBlockTag.md) - [SomniaBlockParam](type-aliases/SomniaBlockParam.md) - [SomniaBlockResources](interfaces/SomniaBlockResources.md) - [SomniaConsensusBlock](interfaces/SomniaConsensusBlock.md) - [SomniaExecutionBlock](interfaces/SomniaExecutionBlock.md) - [SomniaBlock](interfaces/SomniaBlock.md) - [SomniaChainStatistics](interfaces/SomniaChainStatistics.md) - [SomniaReactivitySubscription](interfaces/SomniaReactivitySubscription.md) - [SomniaNodePublicKeys](interfaces/SomniaNodePublicKeys.md) - [SessionTransactionRequest](interfaces/SessionTransactionRequest.md) - [RpcSomniaBlock](interfaces/RpcSomniaBlock.md) - [RpcSomniaChainStatistics](interfaces/RpcSomniaChainStatistics.md) - [RpcSomniaReactivitySubscription](interfaces/RpcSomniaReactivitySubscription.md) - [RpcSomniaNodePublicKeys](interfaces/RpcSomniaNodePublicKeys.md) --- # /docs/typescript/api/native/functions/createNative [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / createNative # Function: createNative() > **createNative**(`client`): [`SomniaNative`](../interfaces/SomniaNative.md) Defined in: packages/sdk/src/native/client.ts:235 Wrap any JSON-RPC client in the Somnia-native API. **Details** - `client`: Anything with an EIP-1193 `request` method. - Returns: The [SomniaNative](../interfaces/SomniaNative.md) surface. **Example** (Reading a native block) ```ts import { createPublicClient, http } from "viem"; import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; import { createNative } from "@somnia-chain/markets-sdk/native"; const client = createPublicClient({ chain: somniaShannon, transport: http() }); const native = createNative(client); const block = await native.getBlock("latest"); console.log(block?.consensusBlock.proposerAddress, block?.executionBlock.executionGasUsed); ``` Works with the markets client too — `createNative(exchange.client.publicClient)` — and with a plain injected provider, since all it needs is `.request`. ## Parameters ### client [`NativeRpcRequester`](../interfaces/NativeRpcRequester.md) ## Returns [`SomniaNative`](../interfaces/SomniaNative.md) --- # /docs/typescript/api/native/functions/getSomniaRpcError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / getSomniaRpcError # Function: getSomniaRpcError() > **getSomniaRpcError**(`error`): [`SomniaRpcError`](../interfaces/SomniaRpcError.md) \| `null` Defined in: packages/sdk/src/native/errors.ts:144 Recover the node's own JSON-RPC error from whatever a client threw. Use it instead of `error.message` whenever the message will be logged or shown: a viem `-32000` reads "Missing or invalid parameters." while the node said "account does not exist". **Details** - `error`: Whatever was thrown. - Returns: The node's error, or `null` if this wasn't a JSON-RPC error at all. **Example** (Reading a native RPC error) ```ts import { getSomniaRpcError } from "@somnia-chain/markets-sdk/native"; try { await native.sendSessionTransaction({ seed, gas: 21_000n, to, value }); } catch (error) { const rpc = getSomniaRpcError(error); console.error(rpc?.message ?? (error as Error).message); // "account does not exist" } ``` Walks the `cause` chain and returns the **innermost** `{ code, message }` pair, which is the node's, since each wrapper layer re-describes it. Falls back to a viem `details` string when the raw object is not reachable. ## Parameters ### error `unknown` ## Returns [`SomniaRpcError`](../interfaces/SomniaRpcError.md) \| `null` --- # /docs/typescript/api/native/functions/isMethodNotFound [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / isMethodNotFound # Function: isMethodNotFound() > **isMethodNotFound**(`error`): `boolean` Defined in: packages/sdk/src/native/client.ts:375 True when an error means "this node doesn't have that method". These endpoints are node-version dependent, and a stock geth/anvil has none of them — so a UI that offers native features should degrade rather than break. Mirrors the same check the SDK's write path uses for `eth_sendRawTransactionSync`. **Details** - `error`: Whatever was thrown. **Example** (Handling an unsupported method) ```ts import { createNative, isMethodNotFound } from "@somnia-chain/markets-sdk/native"; const stats = await native.getStatistics("earliest", "latest").catch((e) => { if (isMethodNotFound(e)) return null; // not a Somnia node — hide the panel throw e; }); ``` ## Parameters ### error `unknown` ## Returns `boolean` --- # /docs/typescript/api/native/functions/isUnauthorized [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / isUnauthorized # Function: isUnauthorized() > **isUnauthorized**(`error`): `boolean` Defined in: packages/sdk/src/native/client.ts:402 True when an error means "that method is operator-only on this node" — the `{ code: -1, message: "unauthorized" }` a public endpoint returns for the protected methods. Matches on the **message**, not the code, and that is deliberate: `-1` is the node's default error code, shared by at least `invalid range`, `could not load statistics` and `Block does not exist` (all confirmed live). Keying on the code would report a bad block range as an authorization failure. **Details** - `error`: Whatever was thrown. ## Parameters ### error `unknown` ## Returns `boolean` --- # /docs/typescript/api/native/functions/sessionAddress [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / sessionAddress # Function: sessionAddress() > **sessionAddress**(`seed`): `` `0x${string}` `` Defined in: packages/sdk/src/native/session.ts:115 The address a session seed controls — computed locally, no RPC. Identical to what `somnia_getSessionAddress` returns for the same seed, and cheaper: use it to display or pre-fund a session account before any network call. `client.getSessionAddress(seed)` asks the node the same question if you want the round-trip as confirmation. **Details** - `seed`: 32-byte session seed. - Returns: The checksummed address of the derived account. **Gotchas** - Throws If the seed is not 32 bytes of hex. **Example** (Deriving a session address) ```ts import { sessionAddress } from "@somnia-chain/markets-sdk/native"; const seed = "0x1111111111111111111111111111111111111111111111111111111111111111"; sessionAddress(seed); // "0xD56D8c05Aa8dA0f3Afd676Aec94014e89aF3cc51" — fund this ``` ## Parameters ### seed `` `0x${string}` `` ## Returns `` `0x${string}` `` --- # /docs/typescript/api/native/functions/sessionPrivateKey [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / sessionPrivateKey # Function: sessionPrivateKey() > **sessionPrivateKey**(`seed`): `` `0x${string}` `` Defined in: packages/sdk/src/native/session.ts:76 Derive a session's **private key** from its seed, exactly as the node does. ``` for i = 0, 1, 2, …: candidate = keccak256(seed ‖ uint64_le(i)) if 0 < candidate < secp256k1_n: return candidate ``` The loop exists only for completeness: a 256-bit keccak output falls outside `[1, n-1]` with probability under 2^-128, so `i = 0` returns in every case anyone will ever observe. (Because `i = 0` encodes to eight zero bytes, its endianness is unobservable; the node documents little-endian and that is what this implements, so a hypothetical `i > 0` would still agree.) This exists to make one thing unmissable: **whoever holds the seed holds this key**, and can move the session account's funds without touching the node. Guard a seed exactly as you would guard the key it produces. **Details** - `seed`: 32-byte session seed. - Returns: The derived secp256k1 private key. **Gotchas** - Throws If the seed is not 32 bytes of hex. **Example** (Signing with a session key) ```ts import { sessionPrivateKey } from "@somnia-chain/markets-sdk/native"; import { privateKeyToAccount } from "viem/accounts"; // Sign locally instead of letting the node sign for you. const account = privateKeyToAccount(sessionPrivateKey(seed)); ``` ## Parameters ### seed `` `0x${string}` `` ## Returns `` `0x${string}` `` --- # /docs/typescript/api/native/interfaces/NativeRpcRequester [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / NativeRpcRequester # Interface: NativeRpcRequester Defined in: packages/sdk/src/native/client.ts:88 Anything that can make a JSON-RPC request — which every viem client is, and so is an injected EIP-1193 provider (`window.ethereum`) or a wagmi connector. Typed structurally so this module never needs a viem client of its own: whatever you already have, hand it over. ## Methods ### request() > **request**(`args`, `options?`): `Promise`\<`unknown`\> Defined in: packages/sdk/src/native/client.ts:95 Make a JSON-RPC request. The second argument is viem's per-request options — only `retryCount` is used, and only to stop a value-bearing session send from being retried (see `sendSessionTransaction`). A provider that ignores it is fine; the parameter is optional. #### Parameters ##### args ###### method `string` ###### params? `unknown` ##### options? ###### retryCount? `number` #### Returns `Promise`\<`unknown`\> --- # /docs/typescript/api/native/interfaces/RpcSomniaBlock [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / RpcSomniaBlock # Interface: RpcSomniaBlock Defined in: packages/sdk/src/native/types.ts:244 Raw `somnia_getBlockByHash` / `somnia_getBlockByNumber` payload. ## Properties ### consensus\_block > **consensus\_block**: `object` Defined in: packages/sdk/src/native/types.ts:245 #### block\_number > **block\_number**: `` `0x${string}` `` #### timestamp > **timestamp**: `` `0x${string}` `` #### data\_chain\_blocks > **data\_chain\_blocks**: `` `0x${string}` ``[] #### delayed\_ledger\_block\_number > **delayed\_ledger\_block\_number**: `` `0x${string}` `` #### delayed\_ledger\_block\_hash > **delayed\_ledger\_block\_hash**: `` `0x${string}` `` #### parent\_consensus\_block\_hash > **parent\_consensus\_block\_hash**: `` `0x${string}` `` #### proposer\_address > **proposer\_address**: `` `0x${string}` `` #### block\_resources > **block\_resources**: `object` ##### block\_resources.validation\_gas > **validation\_gas**: `` `0x${string}` `` ##### block\_resources.compressed\_bytes > **compressed\_bytes**: `` `0x${string}` `` ##### block\_resources.uncompressed\_bytes > **uncompressed\_bytes**: `` `0x${string}` `` #### consensus\_block\_hash > **consensus\_block\_hash**: `` `0x${string}` `` *** ### execution\_block > **execution\_block**: `object` Defined in: packages/sdk/src/native/types.ts:256 #### transaction\_ids\_hash > **transaction\_ids\_hash**: `` `0x${string}` `` #### receipts\_hash > **receipts\_hash**: `` `0x${string}` `` #### execution\_gas\_limit > **execution\_gas\_limit**: `` `0x${string}` `` #### execution\_gas\_used > **execution\_gas\_used**: `` `0x${string}` `` #### execution\_state\_snapshot > **execution\_state\_snapshot**: `` `0x${string}` `` #### state\_snapshot\_block\_number > **state\_snapshot\_block\_number**: `` `0x${string}` `` #### operation\_sequence\_hash > **operation\_sequence\_hash**: `` `0x${string}` `` *** ### parent\_ledger\_block\_hash > **parent\_ledger\_block\_hash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:265 *** ### ledger\_block\_hash > **ledger\_block\_hash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:266 --- # /docs/typescript/api/native/interfaces/RpcSomniaChainStatistics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / RpcSomniaChainStatistics # Interface: RpcSomniaChainStatistics Defined in: packages/sdk/src/native/types.ts:274 Raw `somnia_getStatistics` payload — camelCase on the wire, unlike the blocks. ## Properties ### numSuccessfulTransactions > **numSuccessfulTransactions**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:275 *** ### numRevertedTransactions > **numRevertedTransactions**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:276 *** ### numContractsAdded > **numContractsAdded**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:277 *** ### numAccountsAdded > **numAccountsAdded**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:278 *** ### numNewUsedEoaAccounts > **numNewUsedEoaAccounts**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:279 *** ### numNativeTransferTransactions > **numNativeTransferTransactions**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:280 *** ### numGasUnitsSpent > **numGasUnitsSpent**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:281 *** ### gasFeeSpent > **gasFeeSpent**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:282 --- # /docs/typescript/api/native/interfaces/RpcSomniaNodePublicKeys [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / RpcSomniaNodePublicKeys # Interface: RpcSomniaNodePublicKeys Defined in: packages/sdk/src/native/types.ts:309 Raw `somnia_nodePublicKeys` payload. ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:310 *** ### ecdsa\_public\_key > **ecdsa\_public\_key**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:311 *** ### bls\_public\_key > **bls\_public\_key**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:312 *** ### bls\_proof\_of\_possession > **bls\_proof\_of\_possession**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:313 *** ### proof\_of\_address > **proof\_of\_address**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:314 --- # /docs/typescript/api/native/interfaces/RpcSomniaReactivitySubscription [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / RpcSomniaReactivitySubscription # Interface: RpcSomniaReactivitySubscription Defined in: packages/sdk/src/native/types.ts:290 Raw `somnia_reactivityGetSubscriptionInfo` element. ## Properties ### id > **id**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:291 *** ### topics > **topics**: `` `0x${string}` ``[] Defined in: packages/sdk/src/native/types.ts:292 *** ### origin > **origin**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:293 *** ### caller > **caller**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:294 *** ### emitter > **emitter**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:295 *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:296 *** ### handler\_contract\_address > **handler\_contract\_address**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:297 *** ### handler\_function\_selector > **handler\_function\_selector**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:298 *** ### gas\_limit > **gas\_limit**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:299 *** ### priority\_fee\_per\_gas > **priority\_fee\_per\_gas**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:300 *** ### max\_fee\_per\_gas > **max\_fee\_per\_gas**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:301 --- # /docs/typescript/api/native/interfaces/SessionTransactionRequest [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SessionTransactionRequest # Interface: SessionTransactionRequest Defined in: packages/sdk/src/native/types.ts:222 A transaction to submit through a **session** — the node derives the key from `seed`, assigns the nonce, signs, submits, retries, and returns the receipt. ⚠️ `seed` is a **secret with the authority of a private key**: anyone who knows it controls the derived account (the derivation is public — see [sessionAddress](../functions/sessionAddress.md)). Treat it exactly as you would a key. ## Properties ### seed > **seed**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:224 32-byte seed identifying the session, and therefore the sending account. *** ### gas > **gas**: `bigint` Defined in: packages/sdk/src/native/types.ts:226 Execution gas limit. Required — the node does not estimate it. *** ### to? > `optional` **to?**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:228 Recipient. **Omit to deploy a contract** (`data` is then the init code). *** ### value? > `optional` **value?**: `bigint` Defined in: packages/sdk/src/native/types.ts:230 Native value to send, in wei. Defaults to 0. *** ### data? > `optional` **data?**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:232 Calldata, or contract init code when `to` is omitted. Defaults to empty. --- # /docs/typescript/api/native/interfaces/SomniaBlock [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaBlock # Interface: SomniaBlock Defined in: packages/sdk/src/native/types.ts:112 A Somnia **ledger** block — the native block structure, which is not the same thing as the Ethereum-compatible block `eth_getBlockByNumber` returns. It pairs the consensus block (ordering, proposer, timing) with the execution block (what running the transactions produced), so it exposes detail the eth surface has no field for: the data-chain blocks committed, the state snapshot, the proposer. ## Properties ### consensusBlock > **consensusBlock**: [`SomniaConsensusBlock`](SomniaConsensusBlock.md) Defined in: packages/sdk/src/native/types.ts:114 Consensus half: ordering, timing, proposer. *** ### executionBlock > **executionBlock**: [`SomniaExecutionBlock`](SomniaExecutionBlock.md) Defined in: packages/sdk/src/native/types.ts:116 Execution half: gas, receipts hash, state snapshot. *** ### parentLedgerBlockHash > **parentLedgerBlockHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:118 Parent ledger block hash. *** ### ledgerBlockHash > **ledgerBlockHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:120 This block's ledger hash — what `getSomniaBlockByHash` takes. --- # /docs/typescript/api/native/interfaces/SomniaBlockResources [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaBlockResources # Interface: SomniaBlockResources Defined in: packages/sdk/src/native/types.ts:45 Resources a consensus block consumed, as the node reports them. ## Properties ### validationGas > **validationGas**: `bigint` Defined in: packages/sdk/src/native/types.ts:47 Gas spent validating the block's transactions. *** ### compressedBytes > **compressedBytes**: `bigint` Defined in: packages/sdk/src/native/types.ts:49 Compressed size of the block's data, in bytes. *** ### uncompressedBytes > **uncompressedBytes**: `bigint` Defined in: packages/sdk/src/native/types.ts:51 Uncompressed size of the block's data, in bytes. --- # /docs/typescript/api/native/interfaces/SomniaChainStatistics [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaChainStatistics # Interface: SomniaChainStatistics Defined in: packages/sdk/src/native/types.ts:130 Aggregate activity over a block range. Every field is a count except the last. ## Properties ### successfulTransactions > **successfulTransactions**: `bigint` Defined in: packages/sdk/src/native/types.ts:132 Transactions that executed successfully. *** ### revertedTransactions > **revertedTransactions**: `bigint` Defined in: packages/sdk/src/native/types.ts:134 Transactions that reverted. *** ### contractsAdded > **contractsAdded**: `bigint` Defined in: packages/sdk/src/native/types.ts:136 Contracts deployed. *** ### accountsAdded > **accountsAdded**: `bigint` Defined in: packages/sdk/src/native/types.ts:138 Accounts created. *** ### newUsedEoaAccounts > **newUsedEoaAccounts**: `bigint` Defined in: packages/sdk/src/native/types.ts:140 EOAs used for the first time. *** ### nativeTransferTransactions > **nativeTransferTransactions**: `bigint` Defined in: packages/sdk/src/native/types.ts:142 Plain native-value transfers. *** ### gasUnitsSpent > **gasUnitsSpent**: `bigint` Defined in: packages/sdk/src/native/types.ts:144 Total gas units spent. *** ### gasFeeSpent > **gasFeeSpent**: `bigint` Defined in: packages/sdk/src/native/types.ts:146 Total fees paid, in wei. --- # /docs/typescript/api/native/interfaces/SomniaConsensusBlock [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaConsensusBlock # Interface: SomniaConsensusBlock Defined in: packages/sdk/src/native/types.ts:60 The consensus half of a Somnia ledger block: ordering, timing, and which data-chain blocks it commits. ## Properties ### blockNumber > **blockNumber**: `bigint` Defined in: packages/sdk/src/native/types.ts:62 Ledger block number. *** ### timestamp > **timestamp**: `bigint` Defined in: packages/sdk/src/native/types.ts:64 Block time in unix **milliseconds** (not seconds — Somnia blocks are ~100ms). *** ### dataChainBlocks > **dataChainBlocks**: `` `0x${string}` ``[] Defined in: packages/sdk/src/native/types.ts:66 Hashes of the data-chain blocks this consensus block commits. *** ### delayedLedgerBlockNumber > **delayedLedgerBlockNumber**: `bigint` Defined in: packages/sdk/src/native/types.ts:68 The delayed ledger block this one references. *** ### delayedLedgerBlockHash > **delayedLedgerBlockHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:70 Hash of that delayed ledger block. *** ### parentConsensusBlockHash > **parentConsensusBlockHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:72 Parent consensus block hash. *** ### proposerAddress > **proposerAddress**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:74 Validator that proposed the block. *** ### blockResources > **blockResources**: [`SomniaBlockResources`](SomniaBlockResources.md) Defined in: packages/sdk/src/native/types.ts:76 What the block cost to validate + carry. *** ### consensusBlockHash > **consensusBlockHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:78 This block's own consensus hash. --- # /docs/typescript/api/native/interfaces/SomniaExecutionBlock [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaExecutionBlock # Interface: SomniaExecutionBlock Defined in: packages/sdk/src/native/types.ts:86 The execution half of a ledger block: what running its transactions produced. ## Properties ### transactionIdsHash > **transactionIdsHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:88 Hash over the executed transaction ids. *** ### receiptsHash > **receiptsHash**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:90 Hash over the produced receipts. *** ### executionGasLimit > **executionGasLimit**: `bigint` Defined in: packages/sdk/src/native/types.ts:92 Gas limit for execution. *** ### executionGasUsed > **executionGasUsed**: `bigint` Defined in: packages/sdk/src/native/types.ts:94 Gas actually used. *** ### executionStateSnapshot > **executionStateSnapshot**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:96 State snapshot this execution built on. *** ### stateSnapshotBlockNumber > **stateSnapshotBlockNumber**: `bigint` Defined in: packages/sdk/src/native/types.ts:98 Block number of that snapshot. *** ### operationSequenceHash > **operationSequenceHash**: `bigint` Defined in: packages/sdk/src/native/types.ts:100 Rolling hash of the operation sequence. --- # /docs/typescript/api/native/interfaces/SomniaNative [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaNative # Interface: SomniaNative Defined in: packages/sdk/src/native/client.ts:107 The Somnia-native RPC surface — the twelve methods in the public JSON-RPC reference. Build one with [createNative](../functions/createNative.md). Reads throw on failure and return `null` only where the node genuinely means "no such thing" — a missing block, an unknown subscription. ## Methods ### isReady() > **isReady**(`opts?`): `Promise`\<`boolean`\> Defined in: packages/sdk/src/native/client.ts:115 Is the node ready to serve? `false` while it is still syncing. **Details** - `opts`: `withErrorCode: true` calls `somnia_isReadyWithErrorCode` instead, which **throws** on a not-ready node (`Is not ready`, JSON-RPC internal error) rather than returning `false` — that variant exists so a health check can key on the error. It never returns `false`. #### Parameters ##### opts? ###### withErrorCode? `boolean` #### Returns `Promise`\<`boolean`\> *** ### getBlock() > **getBlock**(`block?`): `Promise`\<[`SomniaBlock`](SomniaBlock.md) \| `null`\> Defined in: packages/sdk/src/native/client.ts:125 A Somnia **ledger** block — richer than the Ethereum-compatible block, with the proposer, the committed data-chain blocks and the execution state snapshot. Takes a tag (`"latest"`, `"earliest"`, `"pending"`, `"safe"`, `"finalized"`), a block number, **or** a 32-byte ledger block hash — dispatching to `somnia_getBlockByHash` for the last of those. #### Parameters ##### block? `` `0x${string}` `` \| [`SomniaBlockParam`](../type-aliases/SomniaBlockParam.md) #### Returns `Promise`\<[`SomniaBlock`](SomniaBlock.md) \| `null`\> *** ### getStatistics() > **getStatistics**(`from`, `to`): `Promise`\<[`SomniaChainStatistics`](SomniaChainStatistics.md)\> Defined in: packages/sdk/src/native/client.ts:128 Aggregate activity between two blocks, inclusive. #### Parameters ##### from [`SomniaBlockParam`](../type-aliases/SomniaBlockParam.md) ##### to [`SomniaBlockParam`](../type-aliases/SomniaBlockParam.md) #### Returns `Promise`\<[`SomniaChainStatistics`](SomniaChainStatistics.md)\> *** ### listPrivilegedReceipts() > **listPrivilegedReceipts**(`block?`): `Promise`\<`TransactionReceipt`[]\> Defined in: packages/sdk/src/native/client.ts:136 Receipts for the **privileged** (protocol-issued) transactions in a block — the ones no user submitted, e.g. reactivity callbacks. Usually empty. Takes a tag, a number, or a 32-byte block hash, like [getBlock](#getblock). #### Parameters ##### block? `` `0x${string}` `` \| [`SomniaBlockParam`](../type-aliases/SomniaBlockParam.md) #### Returns `Promise`\<`TransactionReceipt`[]\> *** ### listReactivitySubscriptionIds() > **listReactivitySubscriptionIds**(`owner`): `Promise`\<`bigint`[]\> Defined in: packages/sdk/src/native/client.ts:139 Ids of every reactivity subscription owned by an address. #### Parameters ##### owner `` `0x${string}` `` #### Returns `Promise`\<`bigint`[]\> *** ### getReactivitySubscription() > **getReactivitySubscription**(`id`): `Promise`\<[`SomniaReactivitySubscription`](SomniaReactivitySubscription.md) \| `null`\> Defined in: packages/sdk/src/native/client.ts:142 One reactivity subscription, or `null` when no subscription has that id. #### Parameters ##### id `number` \| `bigint` #### Returns `Promise`\<[`SomniaReactivitySubscription`](SomniaReactivitySubscription.md) \| `null`\> *** ### listReactivitySubscriptions() > **listReactivitySubscriptions**(`ids`): `Promise`\<[`SomniaReactivitySubscription`](SomniaReactivitySubscription.md)[]\> Defined in: packages/sdk/src/native/client.ts:145 Several reactivity subscriptions in one round-trip. Unknown ids are omitted. #### Parameters ##### ids readonly (`number` \| `bigint`)[] #### Returns `Promise`\<[`SomniaReactivitySubscription`](SomniaReactivitySubscription.md)[]\> *** ### getNodePublicKeys() > **getNodePublicKeys**(): `Promise`\<[`SomniaNodePublicKeys`](SomniaNodePublicKeys.md)\> Defined in: packages/sdk/src/native/client.ts:148 The serving node's identity keys for the current epoch. #### Returns `Promise`\<[`SomniaNodePublicKeys`](SomniaNodePublicKeys.md)\> *** ### getSessionAddress() > **getSessionAddress**(`seed`): `Promise`\<`` `0x${string}` ``\> Defined in: packages/sdk/src/native/client.ts:162 The address a session seed controls, **as the node computes it**. [sessionAddress](../functions/sessionAddress.md) computes the same value locally with no round-trip; this is the way to confirm the node agrees. Note the node creates its in-memory sender for the seed as a side effect. **Gotchas** - Throws `RpcError` when the node or the transport rejects the call. The seed is never in it. `cause` is the node's own `{ code, message, data? }` when the node answered (read it with [getSomniaRpcError](../functions/getSomniaRpcError.md)), or the transport's `{ name, message, status? }` with the request text blanked when it did not. #### Parameters ##### seed `` `0x${string}` `` #### Returns `Promise`\<`` `0x${string}` ``\> *** ### sendSessionTransaction() > **sendSessionTransaction**(`tx`): `Promise`\<[`SomniaTransactionReceipt`](../type-aliases/SomniaTransactionReceipt.md)\> Defined in: packages/sdk/src/native/client.ts:191 Submit a transaction through a session and **wait for its receipt**. The node derives the key from the seed, assigns the nonce, signs, submits and retries transient failures — so this one call replaces sign + send + poll. It does not return until the transaction has executed, which can take a while under retry; give the underlying transport a generous timeout. Before using it, know four things: - **The seed is a private key.** Anyone with it controls the account. - **Pre-fund the account** ([sessionAddress](../functions/sessionAddress.md)) or the transaction cannot pay gas. - **The nonce space is shared** with `eth_sendRawTransaction` from the same address. Sending both ways at once corrupts the sequence. - The session lives in the serving node's memory, so it is not shared between nodes and is rebuilt from the seed after a restart. Sent with retries disabled: a retry would be a second transfer, not a second attempt at the same one. The receipt carries `executionTimeMicros` when the node reports it: the node-side time from request to answer, in microseconds. **Gotchas** - Throws If the node returns no receipt. - Throws `RpcError` when the node or the transport rejects the transaction (mempool errors arrive as JSON-RPC `-32000`; a node-side timeout as `timeout`). The seed is never in it. `cause` is the node's own `{ code, message, data? }` when the node answered (read it with [getSomniaRpcError](../functions/getSomniaRpcError.md)), or the transport's `{ name, message, status? }` with the request text blanked when it did not. #### Parameters ##### tx [`SessionTransactionRequest`](SessionTransactionRequest.md) #### Returns `Promise`\<[`SomniaTransactionReceipt`](../type-aliases/SomniaTransactionReceipt.md)\> *** ### request() > **request**\<`T`\>(`method`, `params?`): `Promise`\<`T`\> Defined in: packages/sdk/src/native/client.ts:205 Call any `somnia_*` method directly — the escape hatch for an endpoint this module doesn't wrap: an operator-only one, one a newer node has added, or one the public reference omits. Params go through untouched, so hex-encode quantities yourself. ⚠️ Off the documented surface you are on your own, and not every undocumented endpoint is merely unstable — `somnia_getStorageDatabaseEntries` will make a node dump unbounded data for a large enough key list, and has taken a public testnet down. Know what a method does before reaching for it here. #### Type Parameters ##### T `T` = `unknown` #### Parameters ##### method `string` ##### params? `unknown`[] #### Returns `Promise`\<`T`\> --- # /docs/typescript/api/native/interfaces/SomniaNodePublicKeys [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaNodePublicKeys # Interface: SomniaNodePublicKeys Defined in: packages/sdk/src/native/types.ts:197 The serving node's identity keys for the current epoch — the node's `EpochNodePublicKeys`, all five fields. The two proofs are what bind the keys together: without them the address and the BLS key are just three unrelated values, which is why the node publishes them alongside and why they are not dropped here. ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:199 The node's address. *** ### ecdsaPublicKey > **ecdsaPublicKey**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:201 Its secp256k1 public key (compressed). *** ### blsPublicKey > **blsPublicKey**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:203 Its BLS public key. *** ### blsProofOfPossession > **blsProofOfPossession**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:205 BLS proof of possession — proves the node holds the BLS private key. *** ### proofOfAddress > **proofOfAddress**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:207 Proof binding the BLS key to [SomniaNodePublicKeys.address](#address). --- # /docs/typescript/api/native/interfaces/SomniaReactivitySubscription [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaReactivitySubscription # Interface: SomniaReactivitySubscription Defined in: packages/sdk/src/native/types.ts:160 A registered Solidity reactivity subscription, as the node stores it. The same subscriptions the reactivity precompile manages — see `@somnia-chain/markets-sdk/reactivity` for creating them. This read is the way to enumerate what already exists without decoding events. ## Properties ### id > **id**: `bigint` Defined in: packages/sdk/src/native/types.ts:162 Subscription id. *** ### topics > **topics**: \[`` `0x${string}` ``, `` `0x${string}` ``, `` `0x${string}` ``, `` `0x${string}` ``\] Defined in: packages/sdk/src/native/types.ts:164 The four topic filters; `bytes32(0)` is a wildcard / unused slot. *** ### origin > **origin**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:166 `tx.origin` filter; zero address is a wildcard. *** ### caller > **caller**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:168 Reserved by the protocol — currently always the zero address. *** ### emitter > **emitter**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:170 Emitting-contract filter; zero address is a wildcard. *** ### owner > **owner**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:172 Who owns the subscription, and whose balance funds its callbacks. *** ### handlerContractAddress > **handlerContractAddress**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:174 Handler contract the validator calls. *** ### handlerFunctionSelector > **handlerFunctionSelector**: `` `0x${string}` `` Defined in: packages/sdk/src/native/types.ts:176 Handler entrypoint (`0x53edf33d` for the default `onEvent`). *** ### gasLimit > **gasLimit**: `bigint` Defined in: packages/sdk/src/native/types.ts:178 Gas provisioned per callback. *** ### priorityFeePerGas > **priorityFeePerGas**: `bigint` Defined in: packages/sdk/src/native/types.ts:180 Tip per gas for the callback, in wei. *** ### maxFeePerGas > **maxFeePerGas**: `bigint` Defined in: packages/sdk/src/native/types.ts:182 Fee ceiling per gas for the callback, in wei. --- # /docs/typescript/api/native/interfaces/SomniaRpcError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaRpcError # Interface: SomniaRpcError Defined in: packages/sdk/src/native/errors.ts:97 The JSON-RPC error the node actually sent, recovered from a client's wrapper. ## Properties ### code > **code**: `number` Defined in: packages/sdk/src/native/errors.ts:99 JSON-RPC code — `-32000` for a mempool rejection, `-32601` unknown method, `-1` the node default. *** ### message > **message**: `string` Defined in: packages/sdk/src/native/errors.ts:101 The node's own message, e.g. `"account does not exist"` — not the client's paraphrase. *** ### data > **data**: `` `0x${string}` `` \| `null` Defined in: packages/sdk/src/native/errors.ts:103 The `data` field verbatim, or `null` when absent. *** ### mempoolStatus > **mempoolStatus**: [`SomniaMempoolStatus`](../type-aliases/SomniaMempoolStatus.md) \| `null` Defined in: packages/sdk/src/native/errors.ts:108 `data` decoded, when it is a single mempool status byte. `null` when `data` is absent, is not one byte, or is not a known code — a newer node may add one. --- # /docs/typescript/api/native/type-aliases/SomniaBlockParam [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaBlockParam # Type Alias: SomniaBlockParam > **SomniaBlockParam** = [`SomniaBlockTag`](SomniaBlockTag.md) \| `bigint` \| `number` Defined in: packages/sdk/src/native/types.ts:36 Where to read from: a tag, or an exact block number. Note the node rejects a JSON *number* (`-32602 invalid parameters`) — pass a `bigint`/`number` here and this module hex-encodes it for you. --- # /docs/typescript/api/native/type-aliases/SomniaBlockTag [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaBlockTag # Type Alias: SomniaBlockTag > **SomniaBlockTag** = `"latest"` \| `"earliest"` \| `"pending"` \| `"safe"` \| `"finalized"` Defined in: packages/sdk/src/native/types.ts:26 A block identifier the node accepts: a tag, or an exact block number. --- # /docs/typescript/api/native/type-aliases/SomniaMempoolStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaMempoolStatus # Type Alias: SomniaMempoolStatus > **SomniaMempoolStatus** = *typeof* [`SomniaMempoolStatus`](../variables/SomniaMempoolStatus.md)\[keyof *typeof* [`SomniaMempoolStatus`](../variables/SomniaMempoolStatus.md)\] Defined in: packages/sdk/src/native/errors.ts:52 One of the [SomniaMempoolStatus](../variables/SomniaMempoolStatus.md) codes. --- # /docs/typescript/api/native/type-aliases/SomniaTransactionReceipt [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaTransactionReceipt # Type Alias: SomniaTransactionReceipt > **SomniaTransactionReceipt** = `TransactionReceipt` & `object` Defined in: packages/sdk/src/native/receipt.ts:26 A receipt from a Somnia send that returns it in the same call, with the node's timing decoded. **Details** `executionTimeMicros` is the time in microseconds from the node receiving the request to its answer: mempool, finality and execution inside Somnia. It is absent when the node does not report it (an older node, or a receipt read back with `eth_getTransactionReceipt`). ## Type Declaration ### executionTimeMicros? > `optional` **executionTimeMicros?**: `number` Node-side end-to-end time in microseconds. Absent when the node does not report it. --- # /docs/typescript/api/native/variables/SomniaMempoolStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [native](../README.md) / SomniaMempoolStatus # Variable: SomniaMempoolStatus > `const` **SomniaMempoolStatus**: `object` Defined in: packages/sdk/src/native/errors.ts:52 The node's mempool verdict, as the `data` byte of a `-32000` error carries it. Worth branching on rather than matching error strings: `nonceTooSmall` is retryable with a bumped nonce, `insufficientBalance` needs funding, and `accountDoesNotExist` means the *sender* has never been seen — a different fix from either. **Example** (Branching on mempool status) ```ts import { SomniaMempoolStatus, getSomniaRpcError } from "@somnia-chain/markets-sdk/native"; const rpc = getSomniaRpcError(error); if (rpc?.mempoolStatus === SomniaMempoolStatus.nonceTooSmall) { // stale nonce count — re-read it and retry } ``` ## Type Declaration ### success > `readonly` **success**: `0` = `0` Accepted. Never seen on an error. ### hasInFlightTransactions > `readonly` **hasInFlightTransactions**: `1` = `1` The sender already has transactions in flight. ### accountDoesNotExist > `readonly` **accountDoesNotExist**: `2` = `2` The SENDER has never existed on chain — fund it before it can transact. ### insufficientBalance > `readonly` **insufficientBalance**: `3` = `3` The sender cannot cover `value` plus the gas ceiling. ### nonceTooSmall > `readonly` **nonceTooSmall**: `4` = `4` Nonce below the account's next — including when `eth_getTransactionCount` lags. ### nonceTooLarge > `readonly` **nonceTooLarge**: `5` = `5` Nonce beyond what the mempool will queue. ### nonceNotCloseEnough > `readonly` **nonceNotCloseEnough**: `6` = `6` Nonce too far ahead of the account's next to hold. ### accountAlreadyLinked > `readonly` **accountAlreadyLinked**: `7` = `7` The account is already linked. ### invalidTransaction > `readonly` **invalidTransaction**: `8` = `8` Malformed, or below the intrinsic gas cost. ### invalidSignature > `readonly` **invalidSignature**: `9` = `9` Signature did not recover to the sender. ### accountNotLinked > `readonly` **accountNotLinked**: `10` = `10` The account is not linked. ### mempoolFull > `readonly` **mempoolFull**: `11` = `11` No room; retry later. ### gasPriceBelowBaseFee > `readonly` **gasPriceBelowBaseFee**: `12` = `12` `maxFeePerGas` under the block's base fee. ### gasPriceBelowDynamicFee > `readonly` **gasPriceBelowDynamicFee**: `13` = `13` `maxFeePerGas` under the dynamic fee the node currently requires. ### tooMuchValueInFlight > `readonly` **tooMuchValueInFlight**: `14` = `14` The sender's in-flight value exceeds what the mempool allows at once. --- # /docs/typescript/api/react [**@somnia-chain/markets-sdk**](../README.md) *** [@somnia-chain/markets-sdk](../README.md) / react # react ## funding ### FundingRateSeries Re-exports [FundingRateSeries](../index/type-aliases/FundingRateSeries.md) *** ### FundingSeriesBucket Re-exports [FundingSeriesBucket](../index/type-aliases/FundingSeriesBucket.md) ## Other ### PoolSeedStatus Re-exports [PoolSeedStatus](../index/interfaces/PoolSeedStatus.md) ## React - [HookChainOptions](interfaces/HookChainOptions.md) - [SomniaMarketsProvider](functions/SomniaMarketsProvider.md) - [useSomniaMarketsClient](functions/useSomniaMarketsClient.md) - [useWatchMarketResult](functions/useWatchMarketResult.md) - [useWatchUserResult](functions/useWatchUserResult.md) - [useWatchPriceResult](functions/useWatchPriceResult.md) - [useWatchMarket](functions/useWatchMarket.md) - [useWatchUser](functions/useWatchUser.md) - [useLiveStatus](functions/useLiveStatus.md) - [usePoolSeedStatus](functions/usePoolSeedStatus.md) - [useIsTailing](functions/useIsTailing.md) - [useLiveFills](functions/useLiveFills.md) - [useLiveUserFills](functions/useLiveUserFills.md) - [useLiveMarketByPool](functions/useLiveMarketByPool.md) - [useLiveMarketByAddress](functions/useLiveMarketByAddress.md) - [useLiveUserOrders](functions/useLiveUserOrders.md) - [useLiveBinaryOrderBook](functions/useLiveBinaryOrderBook.md) - [useLiveBinaryOrderBookByMarket](functions/useLiveBinaryOrderBookByMarket.md) - [useLiveSpotOrderBook](functions/useLiveSpotOrderBook.md) - [IndexerQueryState](interfaces/IndexerQueryState.md) - [useIndexerQuery](functions/useIndexerQuery.md) - [usePortfolio](functions/usePortfolio.md) - [useMarkets](functions/useMarkets.md) - [useCandles](functions/useCandles.md) - [useLiveFundingUpdates](functions/useLiveFundingUpdates.md) - [UseWatchPerpMarketsOptions](interfaces/UseWatchPerpMarketsOptions.md) - [UseLiveLiquidationsOptions](interfaces/UseLiveLiquidationsOptions.md) - [UseLiveFundingPaymentsOptions](interfaces/UseLiveFundingPaymentsOptions.md) - [useWatchPerpMarkets](functions/useWatchPerpMarkets.md) - [useWatchPerpMarketsResult](functions/useWatchPerpMarketsResult.md) - [useLiveLiquidations](functions/useLiveLiquidations.md) - [useLiveFundingPayments](functions/useLiveFundingPayments.md) - [useFundingRateSeries](functions/useFundingRateSeries.md) - [useMarketFees](functions/useMarketFees.md) - [useOperators](functions/useOperators.md) - [useMarketCreators](functions/useMarketCreators.md) - [useOracleAdapters](functions/useOracleAdapters.md) - [useLiveMarkets](functions/useLiveMarkets.md) - [useWatchPrice](functions/useWatchPrice.md) - [useLivePrice](functions/useLivePrice.md) - [useLivePriceFeedInfo](functions/useLivePriceFeedInfo.md) - [useLivePriceTicks](functions/useLivePriceTicks.md) - [useLendReserves](functions/useLendReserves.md) - [useLendAccount](functions/useLendAccount.md) --- # /docs/typescript/api/react/functions/SomniaMarketsProvider [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / SomniaMarketsProvider # Function: SomniaMarketsProvider() > **SomniaMarketsProvider**(`__namedParameters`): `ReactNode` Defined in: packages/sdk/src/hooks.ts:89 Provide the SDK's engine tier to the hooks below. Build one exchange (`new SomniaMarkets(...)`) near the root of your app and pass it as `exchange` — every hook then accepts a `chainId` filter to read any chain the exchange spans. Passing `client` (one engine) is the single-chain form and keeps working unchanged. ## Parameters ### \_\_namedParameters #### client? [`SomniaMarketsClient`](../../index/interfaces/SomniaMarketsClient.md) One engine. Every hook reads it, and a `chainId` filter must name its chain. #### exchange? [`SomniaMarkets`](../../index/classes/SomniaMarkets.md) A (possibly multi-chain) exchange. Hooks read its primary engine unless filtered. #### chainSeedPools? readonly `object`[] Binary pools to seed from chain. Requires `addresses.binaryModule` on each selected chain's client. Fixed for this provider mount; remount to change it. #### children `ReactNode` ## Returns `ReactNode` --- # /docs/typescript/api/react/functions/useCandles [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useCandles # Function: useCandles() > **useCandles**(`pool`, `intervalSeconds`, `opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Candle`](../../index/type-aliases/Candle.md)[]\> Defined in: packages/sdk/src/hooks.ts:729 OHLCV candles for one pool + interval (indexer read), oldest first. ## Parameters ### pool `string` \| `undefined` ### intervalSeconds `number` ### opts? #### limit? `number` #### from? `number` #### to? `number` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Candle`](../../index/type-aliases/Candle.md)[]\> --- # /docs/typescript/api/react/functions/useFundingRateSeries [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useFundingRateSeries # Function: useFundingRateSeries() > **useFundingRateSeries**(`pool`, `intervalSeconds`, `window`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`FundingRateSeries`](../../index/type-aliases/FundingRateSeries.md)\<[`FundingRateCandle`](../../index/type-aliases/FundingRateCandle.md)\>\> Defined in: packages/sdk/src/hooks.ts:984 A pool's funding-rate rollups over `[from, to)` at one resolution (3600 | 14400 | 86400), densified onto the grid and oldest-first. The read for a funding chart. Poll plus nudge: the rollups are re-read when the live tail observes a settlement on this pool, so the tip advances at settlement time rather than on the next poll tick. Callers should not re-implement that — the whole point of this hook. The nudge waits for the indexer. A settlement arrives on the tail as soon as its block is confirmed, which is before the indexer has processed that block. So the hook reads `getSyncStatus` about once a second until the indexer's `latestProcessedBlock` reaches the settlement's block, then re-reads the rollups once. The wait is bounded at 4 seconds in total. At the bound the hook re-reads the rollups anyway, which is a best effort and is never worse than an immediate re-read. The wait stops on unmount and on a pool change, and it makes no request after that. It survives a `from`/`to` window roll: the roll issues its own read, but that read can still be pre-settlement, so the wait continues and then re-reads the ROLLED window. A `getSyncStatus` failure stops the wait and appears as `catchUpError`; the hook never treats a failed watermark read as coverage. A caller-cancelled wait leaves `catchUpError` unset. THE CALLER OWNS THE CLOCK. `from`/`to` are required and must be stable across renders: a `Date.now()` read inside this hook would change the query deps on every render and refetch forever. Snap your window to the grid (`Math.floor(now / interval) * interval`) and it will be stable between buckets. Reading the result: - `avgFundingRate8h` is already per-8h. Convert with the helpers in `funding.ts` (`fundingRate1h`, `annualizedFundingRate`) — never by hand in a component. - `coverage` is a 1e18-scaled ratio in [0, 1]. A bucket at rate 0 with LOW coverage is a pause, not a measured zero — hatch it. `filled: true` marks a slot with no row at all; both cases are `coverage: "0"`, and only `filled` separates them. - Cumulative funding is exact and needs none of that reasoning: `realizedFundingPerBase(first.cumulativeFundingStart, last.cumulativeFundingEnd)` telescopes across gaps, because the index is flat over uncovered time. Watch acquisition failures use the configured debug/console warning channel. Use useWatchMarketResult for typed acquisition error UI. History query failures remain in `state.error`. ## Parameters ### pool `string` \| `undefined` ### intervalSeconds `number` ### window #### from `number` #### to `number` #### limit? `number` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`FundingRateSeries`](../../index/type-aliases/FundingRateSeries.md)\<[`FundingRateCandle`](../../index/type-aliases/FundingRateCandle.md)\>\> ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useIndexerQuery [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useIndexerQuery # Function: useIndexerQuery() > **useIndexerQuery**\<`T`\>(`fn`, `deps`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<`T`\> Defined in: packages/sdk/src/hooks.ts:648 Run an async indexer read against the context client, re-running when `deps` change. Errors are captured (not thrown) so a failed indexer read renders as `error`, not a crash. A superseded request (deps changed, `refetch`, unmount) is aborted via the `signal` handed to `fn`, and its response is discarded either way. Client reads take no per-request signal (cancellation is client-scoped, via `ClientConfig.signal`), so the signal matters when `fn` does its own fetching — pass it to anything that accepts one. **Example** (Running a custom indexer query) ```ts const { data: markets } = useIndexerQuery((c) => c.listBinaryMarkets({ limit: 20 }), []); ``` ## Type Parameters ### T `T` ## Parameters ### fn (`client`, `signal`) => `Promise`\<`T`\> ### deps readonly `unknown`[] ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<`T`\> --- # /docs/typescript/api/react/functions/useIsTailing [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useIsTailing # Function: useIsTailing() > **useIsTailing**(`options?`): `boolean` Defined in: packages/sdk/src/hooks.ts:392 True when at least one watch is live (vs idle / hydrating / reconnecting). ## Parameters ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns `boolean` --- # /docs/typescript/api/react/functions/useLendAccount [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLendAccount # Function: useLendAccount() > **useLendAccount**(`account`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`LendAccount`](../../index/interfaces/LendAccount.md) \| `undefined`\> Defined in: packages/sdk/src/hooks.ts:1321 A SomniaLend account's health factor + positions (chain read). Re-runs when `account` changes; `undefined` account resolves to `undefined` data. ## Parameters ### account `` `0x${string}` `` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`LendAccount`](../../index/interfaces/LendAccount.md) \| `undefined`\> --- # /docs/typescript/api/react/functions/useLendReserves [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLendReserves # Function: useLendReserves() > **useLendReserves**(`options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`LendReserve`](../../index/interfaces/LendReserve.md)[]\> Defined in: packages/sdk/src/hooks.ts:1311 Every SomniaLend reserve — rates, caps, prices (chain read via the UiPoolDataProvider aggregate). Errors (surfaced on `error`) when the client's `config.addresses.lend` is unset. ## Parameters ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`LendReserve`](../../index/interfaces/LendReserve.md)[]\> --- # /docs/typescript/api/react/functions/useLiveBinaryOrderBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveBinaryOrderBook # Function: useLiveBinaryOrderBook() > **useLiveBinaryOrderBook**(`pool`, `depth?`, `options?`): [`BinaryOrderBook`](../../index/interfaces/BinaryOrderBook.md) Defined in: packages/sdk/src/hooks.ts:519 The locally-materialized resting book of a binary pool (4-sided), updating the moment an order event lands — no round-trips, no refetch interval. Watches the pool while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. The owner supplies `blockNumber` as an applied-event watermark. Heads alone do not advance it. Expiry remains a wall-clock projection. ## Parameters ### pool `string` \| `undefined` ### depth? `number` = `10` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`BinaryOrderBook`](../../index/interfaces/BinaryOrderBook.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveBinaryOrderBookByMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveBinaryOrderBookByMarket # Function: useLiveBinaryOrderBookByMarket() > **useLiveBinaryOrderBookByMarket**(`marketId`, `depth?`, `options?`): [`BinaryOrderBook`](../../index/interfaces/BinaryOrderBook.md) Defined in: packages/sdk/src/hooks.ts:550 The locally-materialized resting book of a binary MARKET, resolved by its `marketId` (4-sided) — mirrors [useLiveBinaryOrderBook](useLiveBinaryOrderBook.md) but keyed on the market rather than the pool. Because a BinaryPool is recycled across markets, this returns an EMPTY book once the given market is no longer the pool's current binding, so a stale page never shows the successor market's orders. Watches the market's pool while mounted (once the market is known to the live store). Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. The owner supplies `blockNumber` as an applied-event watermark. Heads alone do not advance it. Expiry remains a wall-clock projection. ## Parameters ### marketId `string` \| `undefined` ### depth? `number` = `10` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`BinaryOrderBook`](../../index/interfaces/BinaryOrderBook.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveFills [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveFills # Function: useLiveFills() > **useLiveFills**(`pool`, `limit?`, `options?`): [`LiveFill`](../../index/interfaces/LiveFill.md)[] Defined in: packages/sdk/src/hooks.ts:408 Live trade tape for one pool. Watches the pool while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `undefined` ### limit? `number` = `40` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`LiveFill`](../../index/interfaces/LiveFill.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveFundingPayments [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveFundingPayments # Function: useLiveFundingPayments() > **useLiveFundingPayments**(`opts?`): [`FundingPayment`](../../index/type-aliases/FundingPayment.md)[] Defined in: packages/sdk/src/hooks.ts:905 Per-account funding settlements the live tail has seen, NEWEST FIRST. Holds the perp-plane watch while mounted. Distinct from [useLiveFundingUpdates](useLiveFundingUpdates.md), which is the per-pool RATE series: this is what each account actually paid or received, and `amount` is signed with **positive meaning the account paid**. Pass `chainId` to read another chain the provider spans. Acquires the plane itself, with no MarginBank hint — mount [useWatchPerpMarkets](useWatchPerpMarkets.md) above it on a deployment whose indexer has no perp market row to read the bank from. Background acquisition failures use the configured debug/console warning channel. Use [useWatchPerpMarketsResult](useWatchPerpMarketsResult.md) for inline error UI — without it a failed plane and a venue with no settlements render identically. ## Parameters ### opts? [`UseLiveFundingPaymentsOptions`](../interfaces/UseLiveFundingPaymentsOptions.md) ## Returns [`FundingPayment`](../../index/type-aliases/FundingPayment.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveFundingUpdates [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveFundingUpdates # Function: useLiveFundingUpdates() > **useLiveFundingUpdates**(`pool`, `limit?`, `options?`): [`LiveFundingUpdate`](../../index/interfaces/LiveFundingUpdate.md)[] Defined in: packages/sdk/src/hooks.ts:759 Funding settlements for one pool seen by the live tail, OLDEST FIRST (chart order, matching `SomniaMarketsClient.getLiveFundingUpdates`) — not newest first like [useLiveFills](useLiveFills.md). Watches the pool while mounted. These are the tail's counterpart to the indexed `FundingRateUpdate` series and carry only what `FundingUpdated` puts on the wire — no `intervalsAccrued`, no covered span. For a chart, prefer [useFundingRateSeries](useFundingRateSeries.md), which uses these purely as a nudge. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `undefined` ### limit? `number` = `50` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`LiveFundingUpdate`](../../index/interfaces/LiveFundingUpdate.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveLiquidations [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveLiquidations # Function: useLiveLiquidations() > **useLiveLiquidations**(`opts?`): [`LiquidationEvent`](../../index/type-aliases/LiquidationEvent.md)[] Defined in: packages/sdk/src/hooks.ts:874 Liquidation waterfall legs the live tail has seen, NEWEST FIRST. Holds the perp-plane watch while mounted. Rows are the same [LiquidationEvent](../../index/type-aliases/LiquidationEvent.md) the indexed `getLiquidations` serves, so a live feed and a paged history render through one component. One liquidation is SEVERAL rows sharing a `txHash` — read `kind` to tell the stages apart, and read the field TSDoc before aggregating: `badDebt` and `deficit` are levels that double-count when summed. A `pool` filter drops the account-level legs, which name no pool. Pass `account` for one wallet's whole story. Pass `chainId` to read another chain the provider spans. Acquires the plane itself, with no MarginBank hint — mount [useWatchPerpMarkets](useWatchPerpMarkets.md) above it on a deployment whose indexer has no perp market row to read the bank from. Background acquisition failures use the configured debug/console warning channel. Use [useWatchPerpMarketsResult](useWatchPerpMarketsResult.md) for inline error UI — without it a failed plane and a venue with no liquidations render identically. ## Parameters ### opts? [`UseLiveLiquidationsOptions`](../interfaces/UseLiveLiquidationsOptions.md) ## Returns [`LiquidationEvent`](../../index/type-aliases/LiquidationEvent.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveMarketByAddress [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveMarketByAddress # Function: useLiveMarketByAddress() > **useLiveMarketByAddress**(`addr`, `options?`): [`BinaryMarket`](../../index/type-aliases/BinaryMarket.md) \| `null` Defined in: packages/sdk/src/hooks.ts:470 One binary market by its BinaryMarket contract address. NOTE: watches are pool-keyed, so this hook does not open one — it reads whatever a pool-keyed hook (or explicit watchMarket) on the same page has hydrated. ## Parameters ### addr `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`BinaryMarket`](../../index/type-aliases/BinaryMarket.md) \| `null` --- # /docs/typescript/api/react/functions/useLiveMarketByPool [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveMarketByPool # Function: useLiveMarketByPool() > **useLiveMarketByPool**(`pool`, `options?`): [`Market`](../../index/type-aliases/Market.md) \| `null` Defined in: packages/sdk/src/hooks.ts:453 One market by pool address (either kind). Watches the pool while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`Market`](../../index/type-aliases/Market.md) \| `null` ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveMarkets [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveMarkets # Function: useLiveMarkets() > **useLiveMarkets**(`options?`): [`Market`](../../index/type-aliases/Market.md)[] Defined in: packages/sdk/src/hooks.ts:1184 Every market the live store knows (spot + perp + binary), from the live tail — synchronous, memoized. Pair with [useWatchMarket](useWatchMarket.md)/`watchMarkets` to keep it populated; unlike [useMarkets](useMarkets.md) this is the zero-round-trip store view, not an indexer fetch. ## Parameters ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`Market`](../../index/type-aliases/Market.md)[] --- # /docs/typescript/api/react/functions/useLivePrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLivePrice # Function: useLivePrice() > **useLivePrice**(`asset`, `options?`): [`LivePrice`](../../index/interfaces/LivePrice.md) \| `null` Defined in: packages/sdk/src/hooks.ts:1236 The live current price of one asset, updating the moment a new tick is pushed — no round-trips, no refetch interval. Watches the feed while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### asset `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`LivePrice`](../../index/interfaces/LivePrice.md) \| `null` ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLivePriceFeedInfo [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLivePriceFeedInfo # Function: useLivePriceFeedInfo() > **useLivePriceFeedInfo**(`asset`, `options?`): [`PriceFeedInfo`](../../index/interfaces/PriceFeedInfo.md) \| `null` Defined in: packages/sdk/src/hooks.ts:1262 The live feed metadata of one asset — pair symbol, quote, decimals, and the freshness fields (`updatedAtMs` / `sourceUpdatedAtMs` / `resynced`). Watches the feed while mounted. Note this does NOT re-render as a price ages: a stalled feed pushes nothing, so the store never notifies. Callers rendering an age must drive their own timer (see [PriceFeedInfo.updatedAtMs](../../index/interfaces/PriceFeedInfo.md#updatedatms)). Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### asset `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`PriceFeedInfo`](../../index/interfaces/PriceFeedInfo.md) \| `null` ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLivePriceTicks [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLivePriceTicks # Function: useLivePriceTicks() > **useLivePriceTicks**(`asset`, `limit?`, `options?`): [`PricePoint`](../../index/interfaces/PricePoint.md)[] Defined in: packages/sdk/src/hooks.ts:1286 The live tick tape of one asset, newest first. Watches the feed while mounted. The array keeps its reference until this asset receives new ticks, and every reader of the same asset and limit shares it. It is frozen: copy it before you sort or reverse it. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### asset `string` \| `undefined` ### limit? `number` = `100` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`PricePoint`](../../index/interfaces/PricePoint.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveSpotOrderBook [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveSpotOrderBook # Function: useLiveSpotOrderBook() > **useLiveSpotOrderBook**(`pool`, `depth?`, `options?`): [`SpotOrderBook`](../../index/interfaces/SpotOrderBook.md) Defined in: packages/sdk/src/hooks.ts:581 The locally-materialized resting book of a spot pool, updating the moment an order event lands — no round-trips, no refetch interval. Watches the pool while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. The owner supplies the same per-scope `blockNumber` as its native live read. It is absent until hydration supplies provenance. ## Parameters ### pool `string` \| `undefined` ### depth? `number` = `12` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`SpotOrderBook`](../../index/interfaces/SpotOrderBook.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveStatus # Function: useLiveStatus() > **useLiveStatus**(`options?`): [`TailStatus`](../../index/interfaces/TailStatus.md) Defined in: packages/sdk/src/hooks.ts:363 The live tail's status snapshot (mode, blocks, event counter) — drive a connection banner off it, or use [useIsTailing](useIsTailing.md) for the common boolean. ## Parameters ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`TailStatus`](../../index/interfaces/TailStatus.md) --- # /docs/typescript/api/react/functions/useLiveUserFills [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveUserFills # Function: useLiveUserFills() > **useLiveUserFills**(`pool`, `user`, `limit?`, `options?`): [`LiveFill`](../../index/interfaces/LiveFill.md)[] Defined in: packages/sdk/src/hooks.ts:429 Fills `user` participated in. Watches `pool` while mounted when given; with `pool === null` it reads across whatever markets other hooks are watching (pair with useWatchUser for history). Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `null` ### user `string` \| `undefined` ### limit? `number` = `50` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`LiveFill`](../../index/interfaces/LiveFill.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useLiveUserOrders [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useLiveUserOrders # Function: useLiveUserOrders() > **useLiveUserOrders**(`pool`, `user`, `limit?`, `options?`): [`LiveOrder`](../../index/interfaces/LiveOrder.md)[] Defined in: packages/sdk/src/hooks.ts:488 `user`'s orders on one pool. Watches the pool while mounted. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `undefined` ### user `string` \| `undefined` ### limit? `number` = `100` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`LiveOrder`](../../index/interfaces/LiveOrder.md)[] ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useMarketCreators [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useMarketCreators # Function: useMarketCreators() > **useMarketCreators**(`opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedMarketCreator`](../../index/type-aliases/IndexedMarketCreator.md)[]\> Defined in: packages/sdk/src/hooks.ts:1146 MarketCreator directory (indexer read) — the operator machinery list. Pass `owner`/`operatorId`/`venueId` to filter, page with `limit`/`offset`. Each row carries its nested `series`. ## Parameters ### opts? [`MarketCreatorFilter`](../../index/type-aliases/MarketCreatorFilter.md) & `object` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedMarketCreator`](../../index/type-aliases/IndexedMarketCreator.md)[]\> --- # /docs/typescript/api/react/functions/useMarketFees [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useMarketFees # Function: useMarketFees() > **useMarketFees**(`marketId`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`MarketFees`](../../index/type-aliases/MarketFees.md) \| `null` \| `undefined`\> Defined in: packages/sdk/src/hooks.ts:1112 A market's frozen fee config + running total (indexer read), or null. ## Parameters ### marketId `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`MarketFees`](../../index/type-aliases/MarketFees.md) \| `null` \| `undefined`\> --- # /docs/typescript/api/react/functions/useMarkets [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useMarkets # Function: useMarkets() > **useMarkets**(`opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Market`](../../index/type-aliases/Market.md)[]\> Defined in: packages/sdk/src/hooks.ts:713 Markets, newest first (indexer read). Pass `marketType` to narrow. ## Parameters ### opts? #### marketType? [`MarketType`](../../index/type-aliases/MarketType.md) #### limit? `number` #### offset? `number` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Market`](../../index/type-aliases/Market.md)[]\> --- # /docs/typescript/api/react/functions/useOperators [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useOperators # Function: useOperators() > **useOperators**(`opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedOperator`](../../index/type-aliases/IndexedOperator.md)[]\> Defined in: packages/sdk/src/hooks.ts:1128 Operator directory (indexer read). Pass `owner`/`enabled` to filter, page with `limit`/`offset`. ## Parameters ### opts? [`OperatorFilter`](../../index/type-aliases/OperatorFilter.md) & `object` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedOperator`](../../index/type-aliases/IndexedOperator.md)[]\> --- # /docs/typescript/api/react/functions/useOracleAdapters [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useOracleAdapters # Function: useOracleAdapters() > **useOracleAdapters**(`opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedOracleAdapter`](../../index/type-aliases/IndexedOracleAdapter.md)[]\> Defined in: packages/sdk/src/hooks.ts:1163 Oracle-adapter directory (indexer read). Pass `owner`/`approved` to filter, page with `limit`/`offset`. ## Parameters ### opts? #### owner? `string` #### approved? `boolean` #### limit? `number` #### offset? `number` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`IndexedOracleAdapter`](../../index/type-aliases/IndexedOracleAdapter.md)[]\> --- # /docs/typescript/api/react/functions/usePoolSeedStatus [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / usePoolSeedStatus # Function: usePoolSeedStatus() > **usePoolSeedStatus**(`pool`, `options?`): [`PoolSeedStatus`](../../index/interfaces/PoolSeedStatus.md) \| `null` Defined in: packages/sdk/src/hooks.ts:378 The seed provenance for one watched pool, or `null` before that pool has seeded. A chain-seeded binary book can be available while `fillsLoaded` remains false: the chain seed does not load indexer fill history. Use the provider's `chainSeedPools` policy to select binary pools; that policy requires `addresses.binaryModule` on the selected chain's client. ## Parameters ### pool `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`PoolSeedStatus`](../../index/interfaces/PoolSeedStatus.md) \| `null` ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/usePortfolio [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / usePortfolio # Function: usePortfolio() > **usePortfolio**(`account`, `opts?`, `options?`): [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Portfolio`](../../index/type-aliases/Portfolio.md) \| `undefined`\> Defined in: packages/sdk/src/hooks.ts:696 A wallet's binary portfolio (indexer read). Re-runs when `account`/`opts` change. ## Parameters ### account `string` \| `undefined` ### opts? [`PortfolioOptions`](../../index/type-aliases/PortfolioOptions.md) ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`IndexerQueryState`](../interfaces/IndexerQueryState.md)\<[`Portfolio`](../../index/type-aliases/Portfolio.md) \| `undefined`\> --- # /docs/typescript/api/react/functions/useSomniaMarketsClient [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useSomniaMarketsClient # Function: useSomniaMarketsClient() > **useSomniaMarketsClient**(`chainId?`): [`SomniaMarketsClient`](../../index/interfaces/SomniaMarketsClient.md) Defined in: packages/sdk/src/hooks.ts:183 The SomniaMarketsClient from the nearest provider — the primary chain's engine, or the engine of `chainId` when given. Throws if there isn't a provider, or if the provider does not span `chainId`. ## Parameters ### chainId? `number` ## Returns [`SomniaMarketsClient`](../../index/interfaces/SomniaMarketsClient.md) ## Throws No SomniaMarketsProvider is present in the component tree. --- # /docs/typescript/api/react/functions/useWatchMarket [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchMarket # Function: useWatchMarket() > **useWatchMarket**(`pool`, `options?`): [`WatchStatus`](../../index/type-aliases/WatchStatus.md) Defined in: packages/sdk/src/hooks.ts:332 Watch one market while mounted (ref-counted; shared with the data hooks) and report its watch state — render loading UI off `"hydrating"`. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### pool `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`WatchStatus`](../../index/type-aliases/WatchStatus.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchMarketResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchMarketResult # Function: useWatchMarketResult() > **useWatchMarketResult**(`pool`, `options?`): [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) Defined in: packages/sdk/src/hooks.ts:288 Acquire a market watch and return typed acquisition failure for inline rendering. Later lifecycle remains available through the owner's getWatchStatus and useLiveStatus. Releases late handles and ignores errors after owner/key changes or unmount. ## Parameters ### pool `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchPerpMarkets [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchPerpMarkets # Function: useWatchPerpMarkets() > **useWatchPerpMarkets**(`opts?`): [`WatchStatus`](../../index/type-aliases/WatchStatus.md) Defined in: packages/sdk/src/hooks.ts:822 Hold the perp-PLANE watch while mounted and report its state. One watch for the whole venue, so mounting this in several components is one subscription and one snapshot — the refcount is what makes a liquidation feed and a funding-settlement feed on the same page cost one of each. MOUNT THIS ABOVE [useLiveLiquidations](useLiveLiquidations.md) / [useLiveFundingPayments](useLiveFundingPayments.md) when the deployment needs `opts.marginBank`. Those two acquire the plane themselves, with no hint to give — which is enough everywhere the indexer has a perp market row, and is exactly the case the hint does not cover. Background acquisition failures use the configured debug/console warning channel. Use [useWatchPerpMarketsResult](useWatchPerpMarketsResult.md) for inline error UI. ## Parameters ### opts? [`UseWatchPerpMarketsOptions`](../interfaces/UseWatchPerpMarketsOptions.md) ## Returns [`WatchStatus`](../../index/type-aliases/WatchStatus.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchPerpMarketsResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchPerpMarketsResult # Function: useWatchPerpMarketsResult() > **useWatchPerpMarketsResult**(`opts?`): [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) Defined in: packages/sdk/src/hooks.ts:844 Acquire the perp-plane watch and return its typed acquisition failure for inline rendering — the sibling of [useWatchPerpMarkets](useWatchPerpMarkets.md), which only warns. Worth preferring here: a plane that failed to start and a venue where nothing has been liquidated both render as an empty feed, and only this tells them apart. ## Parameters ### opts? [`UseWatchPerpMarketsOptions`](../interfaces/UseWatchPerpMarketsOptions.md) ## Returns [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchPrice [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchPrice # Function: useWatchPrice() > **useWatchPrice**(`asset`, `options?`): [`PriceFeedStatus`](../../index/type-aliases/PriceFeedStatus.md) Defined in: packages/sdk/src/hooks.ts:1215 Watch one asset's price feed (e.g. `"BTC"`, `"ETH"`) while mounted (ref-counted; shared with the price data hooks) and report its watch state. Render off the returned state. `"error"` means the server rejected this asset's subscription: the price hooks keep returning their last values, which have stopped updating. See [PriceFeedStatus](../../index/type-aliases/PriceFeedStatus.md). Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### asset `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`PriceFeedStatus`](../../index/type-aliases/PriceFeedStatus.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchPriceResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchPriceResult # Function: useWatchPriceResult() > **useWatchPriceResult**(`asset`, `options?`): [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) Defined in: packages/sdk/src/hooks.ts:310 Acquire an asset's price watch and expose typed failure without an error boundary. getPriceStatus retains legacy setup state. The concrete owner's getPriceHealth distinguishes confirmed delivery. ## Parameters ### asset `string` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchUser [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchUser # Function: useWatchUser() > **useWatchUser**(`user`, `options?`): `void` Defined in: packages/sdk/src/hooks.ts:352 Hydrate + hold `user`'s order/fill history while mounted, so the user-scoped live reads have depth predating the market watches. Background acquisition failures use the configured debug/console warning channel. Use the corresponding useWatchMarketResult/useWatchUserResult/useWatchPriceResult hook for inline error UI. ## Parameters ### user `string` \| `null` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns `void` ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/functions/useWatchUserResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / useWatchUserResult # Function: useWatchUserResult() > **useWatchUserResult**(`user`, `options?`): [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) Defined in: packages/sdk/src/hooks.ts:297 Acquire user history and expose typed failure without an error boundary. ## Parameters ### user `string` \| `null` \| `undefined` ### options? [`HookChainOptions`](../interfaces/HookChainOptions.md) = `{}` ## Returns [`WatchAcquisitionResult`](../type-aliases/WatchAcquisitionResult.md) ## Throws No Markets provider is mounted. --- # /docs/typescript/api/react/interfaces/HookChainOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / HookChainOptions # Interface: HookChainOptions Defined in: packages/sdk/src/hooks.ts:75 Chain filter every data hook accepts as its trailing options. Omit it to read the PRIMARY chain (the exchange's first binding); pass `chainId` to read another configured chain's engine. The four perp-plane hooks (`useWatchPerpMarkets`, `useWatchPerpMarketsResult`, `useLiveLiquidations`, `useLiveFundingPayments`) take `chainId` as a field of their one options object instead. ## Extended by - [`UseWatchPerpMarketsOptions`](UseWatchPerpMarketsOptions.md) - [`UseLiveLiquidationsOptions`](UseLiveLiquidationsOptions.md) - [`UseLiveFundingPaymentsOptions`](UseLiveFundingPaymentsOptions.md) ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/hooks.ts:77 Numeric chain id whose engine answers this hook. Defaults to the primary chain. --- # /docs/typescript/api/react/interfaces/IndexerQueryState [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / IndexerQueryState # Interface: IndexerQueryState\ Defined in: packages/sdk/src/hooks.ts:606 The state one [useIndexerQuery](../functions/useIndexerQuery.md) exposes. ## Type Parameters ### T `T` ## Properties ### data > **data**: `T` \| `undefined` Defined in: packages/sdk/src/hooks.ts:611 Latest successful result — `undefined` until the first response lands; the previous value is kept while a refetch is in flight or after it fails. *** ### loading > **loading**: `boolean` Defined in: packages/sdk/src/hooks.ts:613 True while a request is in flight (initial load and refetches alike). *** ### error > **error**: `Error` \| `null` Defined in: packages/sdk/src/hooks.ts:615 The most recent request's failure, or null. Cleared when a new request starts. *** ### refetch > **refetch**: () => `void` Defined in: packages/sdk/src/hooks.ts:617 Re-run the query imperatively (e.g. a manual refresh button). #### Returns `void` *** ### catchUpError? > `optional` **catchUpError?**: [`InvalidInputError`](../../index/classes/InvalidInputError.md) \| [`IndexerError`](../../index/classes/IndexerError.md) Defined in: packages/sdk/src/hooks.ts:628 Failure of a hook-owned wait for the indexer to catch up, when the hook runs one. Only [useFundingRateSeries](../functions/useFundingRateSeries.md) sets it today, and its wait reads `getSyncStatus` — so the reachable failures are exactly that member's union (`SomniaMarketsClientGetSyncStatusError`): `IndexerError` when the metadata request fails, `InvalidInputError` when a query variable is invalid. It stays `undefined` when no wait ran, when the wait succeeded, and when the caller cancelled the wait by unmounting or by changing the pool. It is separate from `error`, which belongs to the series query itself. --- # /docs/typescript/api/react/interfaces/UseLiveFundingPaymentsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveFundingPaymentsOptions # Interface: UseLiveFundingPaymentsOptions Defined in: packages/sdk/src/hooks.ts:798 Options for [useLiveFundingPayments](../functions/useLiveFundingPayments.md): the live-store filters plus the chain filter. ## Extends - [`ListLiveFundingPaymentsOptions`](../../index/interfaces/ListLiveFundingPaymentsOptions.md).[`HookChainOptions`](HookChainOptions.md) ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/hooks.ts:77 Numeric chain id whose engine answers this hook. Defaults to the primary chain. #### Inherited from [`HookChainOptions`](HookChainOptions.md).[`chainId`](HookChainOptions.md#chainid) *** ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/liveTail.ts:351 Keep only settlements on this perp pool. #### Inherited from [`ListLiveFundingPaymentsOptions`](../../index/interfaces/ListLiveFundingPaymentsOptions.md).[`pool`](../../index/interfaces/ListLiveFundingPaymentsOptions.md#pool) *** ### account? > `optional` **account?**: `string` Defined in: packages/sdk/src/liveTail.ts:353 Keep only settlements for this account. #### Inherited from [`ListLiveFundingPaymentsOptions`](../../index/interfaces/ListLiveFundingPaymentsOptions.md).[`account`](../../index/interfaces/ListLiveFundingPaymentsOptions.md#account) *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/liveTail.ts:355 Newest-first cap. Default 50. #### Inherited from [`ListLiveFundingPaymentsOptions`](../../index/interfaces/ListLiveFundingPaymentsOptions.md).[`limit`](../../index/interfaces/ListLiveFundingPaymentsOptions.md#limit) --- # /docs/typescript/api/react/interfaces/UseLiveLiquidationsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveLiquidationsOptions # Interface: UseLiveLiquidationsOptions Defined in: packages/sdk/src/hooks.ts:791 Options for [useLiveLiquidations](../functions/useLiveLiquidations.md): the live-store filters plus the chain filter. ## Extends - [`ListLiveLiquidationsOptions`](../../index/interfaces/ListLiveLiquidationsOptions.md).[`HookChainOptions`](HookChainOptions.md) ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/hooks.ts:77 Numeric chain id whose engine answers this hook. Defaults to the primary chain. #### Inherited from [`HookChainOptions`](HookChainOptions.md).[`chainId`](HookChainOptions.md#chainid) *** ### pool? > `optional` **pool?**: `string` Defined in: packages/sdk/src/liveTail.ts:337 Keep only legs on this perp pool. DROPS the account-level legs (`AccountLiquidated`, `ResidualBadDebt`, ...), which carry no pool — filter by `account` for the whole story of one liquidation. #### Inherited from [`ListLiveLiquidationsOptions`](../../index/interfaces/ListLiveLiquidationsOptions.md).[`pool`](../../index/interfaces/ListLiveLiquidationsOptions.md#pool) *** ### account? > `optional` **account?**: `string` Defined in: packages/sdk/src/liveTail.ts:339 Keep only legs keyed on this account (the liquidated side, never the counterparty). #### Inherited from [`ListLiveLiquidationsOptions`](../../index/interfaces/ListLiveLiquidationsOptions.md).[`account`](../../index/interfaces/ListLiveLiquidationsOptions.md#account) *** ### limit? > `optional` **limit?**: `number` Defined in: packages/sdk/src/liveTail.ts:341 Newest-first cap. Default 50. #### Inherited from [`ListLiveLiquidationsOptions`](../../index/interfaces/ListLiveLiquidationsOptions.md).[`limit`](../../index/interfaces/ListLiveLiquidationsOptions.md#limit) --- # /docs/typescript/api/react/interfaces/UseWatchPerpMarketsOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchPerpMarketsOptions # Interface: UseWatchPerpMarketsOptions Defined in: packages/sdk/src/hooks.ts:781 Options for [useWatchPerpMarkets](../functions/useWatchPerpMarkets.md) and [useWatchPerpMarketsResult](../functions/useWatchPerpMarketsResult.md). ## Extends - [`WatchPerpMarketsOptions`](../../index/interfaces/WatchPerpMarketsOptions.md).[`HookChainOptions`](HookChainOptions.md) ## Properties ### chainId? > `optional` **chainId?**: `number` Defined in: packages/sdk/src/hooks.ts:77 Numeric chain id whose engine answers this hook. Defaults to the primary chain. #### Inherited from [`HookChainOptions`](HookChainOptions.md).[`chainId`](HookChainOptions.md#chainid) *** ### enabled? > `optional` **enabled?**: `boolean` Defined in: packages/sdk/src/hooks.ts:783 Hold the watch while mounted. Default `true`; `false` releases it without unmounting. *** ### marginBank? > `optional` **marginBank?**: `string` Defined in: packages/sdk/src/liveTail.ts:323 The MarginBank to read the plane's wiring from, normally UNNECESSARY: the address comes from an indexed perp market row, and `MarginBank.getSystemConfig()` reports the LiquidationEngine from there. Pass it for the one case that cannot cover — an indexer with no perp rows at all, where there is nothing to ask. It fills in wiring the plane LACKS, and only that: it is used when the indexer names no bank, including on a scope a read hook hydrated moments earlier with no hint to give. It never overrides a bank the indexer DID name — the hydrated rows are that bank's plane, so streaming another one would splice two venues into one feed — and it never switches a plane that is already streaming. #### Inherited from [`WatchPerpMarketsOptions`](../../index/interfaces/WatchPerpMarketsOptions.md).[`marginBank`](../../index/interfaces/WatchPerpMarketsOptions.md#marginbank) --- # /docs/typescript/api/react/type-aliases/UseFundingRateSeriesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseFundingRateSeriesError # Type Alias: UseFundingRateSeriesError > **UseFundingRateSeriesError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1341 Render failures for useFundingRateSeries; history query errors remain in the returned state. --- # /docs/typescript/api/react/type-aliases/UseLiveBinaryOrderBookByMarketError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveBinaryOrderBookByMarketError # Type Alias: UseLiveBinaryOrderBookByMarketError > **UseLiveBinaryOrderBookByMarketError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1347 Render failures for useLiveBinaryOrderBookByMarket. --- # /docs/typescript/api/react/type-aliases/UseLiveBinaryOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveBinaryOrderBookError # Type Alias: UseLiveBinaryOrderBookError > **UseLiveBinaryOrderBookError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1349 Render failures for useLiveBinaryOrderBook. --- # /docs/typescript/api/react/type-aliases/UseLiveFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveFillsError # Type Alias: UseLiveFillsError > **UseLiveFillsError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1357 Render failures for useLiveFills. --- # /docs/typescript/api/react/type-aliases/UseLiveFundingPaymentsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveFundingPaymentsError # Type Alias: UseLiveFundingPaymentsError > **UseLiveFundingPaymentsError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1369 Render failures for useLiveFundingPayments. --- # /docs/typescript/api/react/type-aliases/UseLiveFundingUpdatesError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveFundingUpdatesError # Type Alias: UseLiveFundingUpdatesError > **UseLiveFundingUpdatesError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1343 Render failures for useLiveFundingUpdates. --- # /docs/typescript/api/react/type-aliases/UseLiveLiquidationsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveLiquidationsError # Type Alias: UseLiveLiquidationsError > **UseLiveLiquidationsError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1367 Render failures for useLiveLiquidations. --- # /docs/typescript/api/react/type-aliases/UseLiveMarketByPoolError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveMarketByPoolError # Type Alias: UseLiveMarketByPoolError > **UseLiveMarketByPoolError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1353 Render failures for useLiveMarketByPool. --- # /docs/typescript/api/react/type-aliases/UseLivePriceError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLivePriceError # Type Alias: UseLivePriceError > **UseLivePriceError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1337 Render failures for useLivePrice. --- # /docs/typescript/api/react/type-aliases/UseLivePriceFeedInfoError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLivePriceFeedInfoError # Type Alias: UseLivePriceFeedInfoError > **UseLivePriceFeedInfoError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1335 Render failures for useLivePriceFeedInfo. --- # /docs/typescript/api/react/type-aliases/UseLivePriceTicksError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLivePriceTicksError # Type Alias: UseLivePriceTicksError > **UseLivePriceTicksError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1333 Render failures for useLivePriceTicks. --- # /docs/typescript/api/react/type-aliases/UseLiveSpotOrderBookError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveSpotOrderBookError # Type Alias: UseLiveSpotOrderBookError > **UseLiveSpotOrderBookError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1345 Render failures for useLiveSpotOrderBook. --- # /docs/typescript/api/react/type-aliases/UseLiveUserFillsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveUserFillsError # Type Alias: UseLiveUserFillsError > **UseLiveUserFillsError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1355 Render failures for useLiveUserFills. --- # /docs/typescript/api/react/type-aliases/UseLiveUserOrdersError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseLiveUserOrdersError # Type Alias: UseLiveUserOrdersError > **UseLiveUserOrdersError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1351 Render failures for useLiveUserOrders. --- # /docs/typescript/api/react/type-aliases/UseSomniaMarketsClientError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseSomniaMarketsClientError # Type Alias: UseSomniaMarketsClientError > **UseSomniaMarketsClientError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1371 Render failures for useSomniaMarketsClient. --- # /docs/typescript/api/react/type-aliases/UseWatchMarketError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchMarketError # Type Alias: UseWatchMarketError > **UseWatchMarketError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1361 Render failures for useWatchMarket. --- # /docs/typescript/api/react/type-aliases/UseWatchMarketResultError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchMarketResultError # Type Alias: UseWatchMarketResultError > **UseWatchMarketResultError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:316 Provider lookup failure for the additive market acquisition hook. --- # /docs/typescript/api/react/type-aliases/UseWatchPerpMarketsError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchPerpMarketsError # Type Alias: UseWatchPerpMarketsError > **UseWatchPerpMarketsError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1363 Render failures for useWatchPerpMarkets. --- # /docs/typescript/api/react/type-aliases/UseWatchPerpMarketsResultError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchPerpMarketsResultError # Type Alias: UseWatchPerpMarketsResultError > **UseWatchPerpMarketsResultError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1365 Provider lookup failure for the additive perp-plane acquisition hook. --- # /docs/typescript/api/react/type-aliases/UseWatchPriceError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchPriceError # Type Alias: UseWatchPriceError > **UseWatchPriceError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1339 Render failures for useWatchPrice. --- # /docs/typescript/api/react/type-aliases/UseWatchPriceResultError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchPriceResultError # Type Alias: UseWatchPriceResultError > **UseWatchPriceResultError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:320 Provider lookup failure for the additive price acquisition hook. --- # /docs/typescript/api/react/type-aliases/UseWatchUserError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchUserError # Type Alias: UseWatchUserError > **UseWatchUserError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:1359 Render failures for useWatchUser. --- # /docs/typescript/api/react/type-aliases/UseWatchUserResultError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / UseWatchUserResultError # Type Alias: UseWatchUserResultError > **UseWatchUserResultError** = [`InvalidInputError`](../../index/classes/InvalidInputError.md) Defined in: packages/sdk/src/hooks.ts:318 Provider lookup failure for the additive user acquisition hook. --- # /docs/typescript/api/react/type-aliases/WatchAcquisitionError [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / WatchAcquisitionError # Type Alias: WatchAcquisitionError > **WatchAcquisitionError** = [`IndexerError`](../../index/classes/IndexerError.md) \| [`RpcError`](../../index/classes/RpcError.md) \| [`NotConfiguredError`](../../index/classes/NotConfiguredError.md) \| [`ContractRevertError`](../../index/classes/ContractRevertError.md) \| [`InvalidInputError`](../../index/classes/InvalidInputError.md) \| [`InvariantError`](../../index/classes/InvariantError.md) Defined in: packages/sdk/src/hooks.ts:196 A component-visible watch acquisition failure. Cancellation from a superseded effect is ignored. --- # /docs/typescript/api/react/type-aliases/WatchAcquisitionResult [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [react](../README.md) / WatchAcquisitionResult # Type Alias: WatchAcquisitionResult > **WatchAcquisitionResult** = \{ `status`: `"unwatched"` \| `"acquiring"` \| `"acquired"`; `error`: `null`; \} \| \{ `status`: `"error"`; `error`: [`WatchAcquisitionError`](WatchAcquisitionError.md); \} Defined in: packages/sdk/src/hooks.ts:204 Acquisition progress is separate from later transport health. --- # /docs/typescript/api/reactivity [**@somnia-chain/markets-sdk**](../README.md) *** [@somnia-chain/markets-sdk](../README.md) / reactivity # reactivity ## reactivity ### isLocalPrecompileUnavailable Re-exports [isLocalPrecompileUnavailable](../index/functions/isLocalPrecompileUnavailable.md) --- # /docs/typescript/api/reactivity/functions/createReactivity [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / createReactivity # Function: createReactivity() > **createReactivity**(`client`, `opts?`): `SDK` Defined in: packages/sdk/src/reactivity/index.ts:209 Build a reactivity client on the markets client's own WebSocket — the socket is already open and already pointed at the right node, and `watch` needs a WebSocket transport. **Details** - `client`: The engine whose public client to use: `exchange.client` on a single-chain exchange, `exchange.engineFor(chainId)` on a multi-chain one. - `opts`: Optional wallet client for the write methods. - Returns: An upstream `SDK` instance — the full reactivity surface. **Gotchas** - Upstream sends every write on the wallet's chain. When `opts.wallet.chain` is set and is not the engine's chain, this throws before anything is sent. - When `opts.wallet.chain` is unset, the chain is not checked. viem then sends on the wallet's current network, which the SDK cannot read synchronously. **Example** (Watching a contract event) ```ts import { SomniaMarkets } from "@somnia-chain/markets-sdk"; import { createReactivity, unwrap } from "@somnia-chain/markets-sdk/reactivity"; import { somniaShannon } from "@somnia-chain/markets-sdk/chains"; const exchange = new SomniaMarkets({ chain: somniaShannon, wsRpcUrl, indexerUrl }); const reactivity = createReactivity(exchange.client); // Every Transfer on the collateral token, with the sender's new balance read // at the very same block — one notification, no follow-up call. const watch = unwrap( await reactivity.watch({ eventContractSources: [collateral], topicOverrides: [transferTopic], ethCalls: [{ to: collateral, data: balanceOfCalldata }], onData: (n: ReactivityNotification) => console.log(n.result.simulationResults), }), ); await watch.unsubscribe(); ``` ## Parameters ### client `Pick`\<[`SomniaMarketsClient`](../../index/interfaces/SomniaMarketsClient.md), `"getViemClient"` \| `"config"`\> ### opts? [`CreateReactivityOptions`](../interfaces/CreateReactivityOptions.md) = `{}` ## Returns `SDK` ## Throws If `opts.wallet.chain` is set and is not the engine's chain. `chainIds` holds the engine's chain, then the wallet's. --- # /docs/typescript/api/reactivity/functions/unwrap [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / unwrap # Function: unwrap() > **unwrap**\<`T`\>(`result`): `T` Defined in: packages/sdk/src/reactivity/index.ts:257 Turn an upstream result into a value or a throw. Every `@somnia-chain/reactivity` method resolves to `T | Error` rather than throwing — a shape a caller can forget to check, then treat a failure as a transaction hash. This SDK's contract is that failures throw (CONVENTIONS.md), so wrap upstream calls in `unwrap` to get that back. **Details** - `result`: Whatever an upstream reactivity method resolved to. - Returns: `result`, narrowed to exclude `Error`. **Gotchas** - Throws The `Error` upstream returned, unchanged. **Example** (Unwrapping an upstream result) ```ts import { unwrap } from "@somnia-chain/markets-sdk/reactivity"; // Throws on a rejected subscription instead of returning an Error object. const hash = unwrap( await reactivity.subscribe({ handlerContractAddress, filter: { emitter }, options }), ); ``` ## Type Parameters ### T `T` ## Parameters ### result `Error` \| `T` ## Returns `T` --- # /docs/typescript/api/reactivity/interfaces/CreateReactivityOptions [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / CreateReactivityOptions # Interface: CreateReactivityOptions Defined in: packages/sdk/src/reactivity/index.ts:152 Optional extras for [createReactivity](../functions/createReactivity.md). ## Properties ### wallet? > `optional` **wallet?**: `object` Defined in: packages/sdk/src/reactivity/index.ts:159 Wallet client that signs the subscription writes; its account becomes the subscription OWNER and funds every callback. Omit for read-only / `watch`-only use. Its `chain` must be the engine's chain. A wallet with no `chain` is not checked: it sends on its current network. --- # /docs/typescript/api/reactivity/interfaces/ReactivityEvent [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / ReactivityEvent # Interface: ReactivityEvent Defined in: packages/sdk/src/reactivity/index.ts:113 One matched log plus the results of the subscription's `ethCalls`, both read at the same block — the thing a `somnia_watch` subscription exists to deliver. Typed here because upstream types `onData` as `(data: any) => void`, so a caller gets no help at all; and because upstream's own `SubscriptionCallback` describes neither the envelope nor `address`. The shape below is what a live Shannon node actually sends (see test/reactivity.e2e.test.ts, which asserts it against the real chain). ## Properties ### address > **address**: `` `0x${string}` `` Defined in: packages/sdk/src/reactivity/index.ts:115 Contract that emitted the log. *** ### topics > **topics**: `` `0x${string}` ``[] Defined in: packages/sdk/src/reactivity/index.ts:117 Topics of the matched log, topic0 first. *** ### data > **data**: `` `0x${string}` `` Defined in: packages/sdk/src/reactivity/index.ts:119 ABI-encoded non-indexed data of the matched log. *** ### simulationResults > **simulationResults**: `` `0x${string}` ``[] Defined in: packages/sdk/src/reactivity/index.ts:121 Raw return data of each `ethCall`, in the order subscribed. --- # /docs/typescript/api/reactivity/interfaces/ReactivityNotification [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / ReactivityNotification # Interface: ReactivityNotification Defined in: packages/sdk/src/reactivity/index.ts:140 What `watch`'s `onData` is actually called with. NOTE the nesting: viem's WebSocket transport unwraps the JSON-RPC envelope before handing it over, so the payload is at **`notification.result`** — not `notification.params.result`, which upstream's README and type docs still describe (verified against a live node). **Example** (Reading a notification) ```ts onData: (n: ReactivityNotification) => console.log(n.result.simulationResults) ``` ## Properties ### subscription > **subscription**: `string` Defined in: packages/sdk/src/reactivity/index.ts:142 The node's subscription id this notification belongs to. *** ### result > **result**: [`ReactivityEvent`](ReactivityEvent.md) Defined in: packages/sdk/src/reactivity/index.ts:144 The matched log + its atomic call results. --- # /docs/typescript/api/reactivity/variables/DEFAULT_SUBSCRIPTION_OPTIONS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / DEFAULT\_SUBSCRIPTION\_OPTIONS # Variable: DEFAULT\_SUBSCRIPTION\_OPTIONS > `const` **DEFAULT\_SUBSCRIPTION\_OPTIONS**: `object` Defined in: packages/sdk/src/reactivity/index.ts:95 Callback gas/fee options for a subscription that doesn't care: no tip, a 20 gwei ceiling, 10M gas per callback. These are the protocol's own defaults (`SomniaExtensions.DEFAULT_*`), spelled out here because upstream's published build ships `defaultSubscriptionOptions` at runtime but leaves it out of its type declarations — a test pins these values against upstream's. The precompile's own rules on these: `gasLimit` must be in `(0, 200_000_000]`, and a non-zero `maxFeePerGas` must sit at least 6 gwei above `priorityFeePerGas` (pass `0` to skip that check). ## Type Declaration ### priorityFeePerGas > `readonly` **priorityFeePerGas**: `0n` = `0n` ### maxFeePerGas > `readonly` **maxFeePerGas**: `20000000000n` = `20_000_000_000n` ### gasLimit > `readonly` **gasLimit**: `10000000n` = `10_000_000n` --- # /docs/typescript/api/reactivity/variables/SOMNIA_REACTIVITY_PRECOMPILE_ADDRESS [**@somnia-chain/markets-sdk**](../../README.md) *** [@somnia-chain/markets-sdk](../../README.md) / [reactivity](../README.md) / SOMNIA\_REACTIVITY\_PRECOMPILE\_ADDRESS # Variable: SOMNIA\_REACTIVITY\_PRECOMPILE\_ADDRESS > `const` **SOMNIA\_REACTIVITY\_PRECOMPILE\_ADDRESS**: `Address` = `"0x0000000000000000000000000000000000000100"` Defined in: packages/sdk/src/reactivity/index.ts:80 The Somnia reactivity precompile — a privileged contract at the fixed address `0x…0100` on every Somnia network. Filter on it as the `emitter` to catch the precompile's own system ticks (`Schedule` / `BlockTick` / `EpochTick`). It has NO bytecode, so `eth_getCode` returns `0x` for it — presence cannot be probed that way. Use [isLocalPrecompileUnavailable](../../index/functions/isLocalPrecompileUnavailable.md) on the chain id instead.