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

# V1.0.48

# Monaco Protocol SDK v1.0.48

A small release. Risk-bucket rows across the margin and portfolio surfaces gain `availableOrderCollateral` — the risk engine's own answer to "how much more can this bucket commit to new orders", which is a different figure from `withdrawableCollateral` and deliberately so. React gains `useInstruments`, a typed hook over the public `instrument` channel. And the `conditionalOrders` WebSocket parser stops throwing away whole frames it does not fully recognize, which comes with one type-level breaking change: `ConditionalOrderEventData` now declares what the server can actually send, so an exhaustive `switch` over `timeInForce` or `reason` needs a `default` branch to keep compiling.

## Breaking

### `ConditionalOrderEventData` declares the values the server can really send

Two fields widen. `timeInForce` goes from `"GTC" | "IOC"` to the full `TimeInForce` union: the creation paths validate the narrow pair, but the field mirrors an unconstrained server column that is mapped exhaustively over every variant, so a value written by any other path reaches the wire as-is. And `reason` goes from the `ConditionalOrderEventReason` union to `string`, because the wire field is a free-form server string rather than a closed enum — the subscribe-time snapshot already reuses the same shape with `"snapshot"`.

`ConditionalOrderEventReason` is still exported and still documents the canonical live values (`created`, `activated`, `cancelled`, `parent_cancelled`, `triggered`, `failed`, `oco_cancelled`); it is now a narrowing aid rather than a closed set.

Code that switched exhaustively over `timeInForce` or `reason` needs a `default` branch. More generally, every value union on this interface is now documented as "the set the server can send today", not a runtime guarantee — see the Fixed section for why. See [Conditional Orders Channel](/sdk/typescript/websockets#conditional-orders-channel).

## Added

### `availableOrderCollateral` on risk-bucket rows

Risk-bucket rows returned by `getMarginAccountSummary`, `getParentMarginAccountSummary`, and `listMarginAccounts` (`GET /api/v1/margin/accounts/{margin_account_id}`, `GET /api/v1/margin/parent-margin-account`, `GET /api/v1/margin/accounts`; gRPC `MarginAccountsService`) now carry an optional `availableOrderCollateral`, and so do the `riskBuckets` rows from `sdk.portfolio.getMargin()` (`GET /api/v1/accounts/me/portfolio/margin`; gRPC `AccountsService.GetPortfolioMargin`).

It is the collateral still available to open **new** orders in that bucket: the largest increase in the bucket's worst-case order reserve that the risk engine's admission gate will accept, with automatic top-up from the parent margin account's unallocated capacity already included. It is zero while the account or bucket is frozen for liquidation, and for an isolated bucket whose market is halted — a cross bucket picks its market per order, so a halt cannot be folded into its figure, and a halted pair still refuses orders.

This is the trading-side sibling of `withdrawableCollateral`, and the two differ on purpose: this one credits an unrealized gain in full, because a gain is legitimate initial margin for a new position, while a withdrawal never counts one. It already contains the bucket's live free collateral, so do not add `freeCollateral` or `unrealizedPnl` on top; it can also legitimately differ from the same row's `freeCollateral`, which is a persisted reconstruction that cannot see the engine's worst-case resting-order reserve.

Two things to get right before you build on it. It is **not additive across rows** — every bucket's figure includes the same parent unallocated headroom, so summing them multiply-counts it, and committing collateral in one bucket shrinks its siblings' figures. And it is a **requirement budget, not an order size**: an order is charged the increase it causes in the bucket's worst-case per-pair reserve, so a reducing, reduce-only, or opposite-side order sheltered by a larger resting ladder needs less of it or none at all — and can be admitted even when this field reads zero — while an order crossing a losing position can need more than its own margin plus fees. Divide by a market's initial margin rate for indicative notional capacity; the authoritative per-order answer is still `simulateRiskBucketOrderRisk`.

The field is present only on risk-bucket rows served from a live risk engine snapshot. It is absent — the key is omitted, never null — on parent rows and on persisted-fallback reads, where neither term of the gate is reconstructable, so handle `undefined`. On the portfolio surface it is truncated toward zero at quote decimals, like the `withdrawableCollateral` beside it. See [Margin Accounts](/sdk/typescript/margin-accounts) and [Perps Collateral](/developers/perps-collateral).

### `useInstruments` React hook

`useInstruments(tradingPairId?)` is a typed hook over the public `instrument` WebSocket channel, subscribing through `sdk.ws.instruments()` and unsubscribing on unmount. It applies the subscribe-time snapshot and every subsequent change frame as a terminal-state entry per market. Three `change` kinds are emitted today — `listing`, `delisting`, and `config_change`; `halt` and `unhalt` exist on `InstrumentChangeKind` for a future market-regime producer and are not emitted by the admin trading-pair path.

It returns `instruments` — an `InstrumentEventData[]` ordered by symbol and then by trading pair id, so a spot and a perp market sharing a symbol keep a stable order — plus `instrumentsByPair` keyed by that id, `subscribed`, `error`, and `clearError`. Omit the argument to follow every market. A delisted market stays in the list carrying `isActive: false` rather than disappearing, so a consumer can tell "no longer tradable" from "never seen"; filter on `isActive` for the tradable set.

`subscribed` means "registered", not "receiving" — the client accepts subscriptions while the socket is down and sends them on the next open — and `error` is a bad-usage signal (an empty `tradingPairId` is the reachable case), not a transport one. See [`useInstruments`](/sdk/react/hooks/use-instruments).

## Fixed

### The `conditionalOrders` parser no longer drops whole frames on an unexpected value

An unexpected enum value anywhere in a `conditional_order_update` frame used to throw inside the WebSocket message handler, losing the entire update silently. A `timeInForce` of `FOK` or `GTD`, or any `reason` the server added, was enough to do it.

`orderType`, `timeInForce`, `state`, `side`, `positionSide`, `conditionType`, `triggerSource`, `associationType`, and `reason` are now read leniently and passed through as-is, matching what the position, liquidation, and market-stats parsers already do — a dropped frame is a worse failure than an unhandled value. `event_type` stays strict, so a mis-routed frame is still rejected. Match on these fields with a `default` branch. See [Conditional Orders Channel](/sdk/typescript/websockets#conditional-orders-channel).

## Upgrade

```bash theme={null}
npm install @0xmonaco/core@1.0.48 @0xmonaco/types@1.0.48 @0xmonaco/react@1.0.48 @0xmonaco/contracts@1.0.48
# or bun
bun add @0xmonaco/core@1.0.48 @0xmonaco/types@1.0.48 @0xmonaco/react@1.0.48 @0xmonaco/contracts@1.0.48
```

The MCP server ships at `1.0.48` too; it runs via `npx -y @0xmonaco/mcp-server`, so restarting your assistant picks up the new version. Every SDK bump is a patch release.

One action item, and it is compile-time only: if you switch exhaustively over `ConditionalOrderEventData.timeInForce` or `.reason`, add a `default` branch. Nothing else here is breaking — `availableOrderCollateral` is an optional field, and `useInstruments` is a new export. If you already size orders from `freeCollateral` or `withdrawableCollateral`, read the `availableOrderCollateral` notes above before switching: it answers a different question, it is not additive across buckets, and it is absent on parent rows and fallback reads.


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