> ## 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.41

# Monaco Protocol SDK v1.0.41

This release adds a client-assigned `clientOrderId` correlation handle across order placement, replacement, and every order read and WebSocket event; gives order-attached take-profit / stop-loss legs their own sizing so they no longer freeze at the entry order's quantity; adds a new authenticated `account` WebSocket channel streaming a margin account's live health; and emits a `movements` ledger entry for on-chain deposits and withdrawals so that channel lines up with `balances`. It also fixes — and corrects the 1.0.40 migration guidance for — funding an isolated risk bucket, which was silently ratcheting a sole open position's stored margin. One thing to act on: if you followed the 1.0.40 note and used `transferCollateralToRiskBucket` to *increase a position's* margin, that is not what it does — see the fix below.

## Added

### `clientOrderId` — a correlation handle on order placement

`placeLimitOrder`, `placeMarketOrder`, `replaceOrder`, `batchCreate` and `batchReplace` (`@0xmonaco/core`; `POST /api/v1/orders`, `PUT /api/v1/orders/{orderId}`, `POST /api/v1/orders/batch-create` and `.../batch-replace`; gRPC `CreateOrderRequest`, `ReplaceOrderRequest`, `BatchCreateOrderItem`, `BatchReplaceOrderItem`; the `place_limit_order` / `place_market_order` / `replace_order` MCP tools) now accept an optional `clientOrderId` — a label you choose that Monaco stores and echoes back. It is up to 64 characters from `A-Za-z0-9._:-`; surrounding whitespace is trimmed and a blank string is treated as absent. A longer value, or one containing any other character, is rejected with HTTP `400` / gRPC `INVALID_ARGUMENT`; on batch-create the rejection is per item with `error.code` `INVALID_CLIENT_ORDER_ID`, while batch-replace validates every item up front and rejects the whole request.

The handle is echoed on order detail and order list responses (`clientOrderId`, absent when the order carried none) and on every `orders` WebSocket event — placed, taker fill, maker fill, cancelled, rejected and expired. A maker fill carries the resting order's own handle, so a filled quote identifies itself without a follow-up read, and a submit whose HTTP response was lost can be resolved from the stream alone.

It is a **correlation handle, not an idempotency key**: Monaco does not de-duplicate on it and does not enforce uniqueness, so sending the same value twice places two orders. It does not make a lost-response retry safe — reconcile against the order list first, matching on `clientOrderId`, and resubmit only if nothing landed. A replacement is a new order with a new id: it carries its own `clientOrderId` and inherits nothing from the original, the same way `postOnly` already behaves. Orders placed before this release report no `clientOrderId`.

<Warning>
  **Corrections since this release.** Three statements above have been superseded. The original wording is left in place; each correction is listed here:

  * *"does not enforce uniqueness"* — [v1.0.42](/releases/v1.0.42) added a uniqueness guard, but only among your **resting** orders. An order that never rests takes no handle.
  * *"reconcile against the order list"* — the order list is served asynchronously from a replica and can omit an order that did land, and an order rejected *before* acceptance is never written to it at all. Reconcile on the order WebSocket stream (`sdk.ws.userOrders`) instead. See [Client Order IDs](/developers/trade#client-order-ids).
  * *"on every `orders` WebSocket event — placed, taker fill, maker fill, cancelled, rejected and expired"* — accurate for one class of rejection only. An order rejected *after* acceptance — a `LIMIT` with `IOC`/`FOK` that cannot fill, or a `MARKET` order whose apparent liquidity is invalidated by maker-risk revalidation — returns `2xx` with `matchResult.status` `REJECTED` and does emit `OrderRejected`. A create rejected *before* acceptance — malformed, post-only would cross, handle conflict, or a plain `MARKET` submit with no liquidity, rejected during pricing — fails the request, emits nothing, and is never written to order history either (an order rejected *after* acceptance is persisted with status `REJECTED`). And the retained claim above that a lost response "can be resolved from the stream alone" is retracted: a matching event is positive proof the order landed, but the stream is not replayable and its fan-out is non-persistent, so silence is never evidence it did not — absent a matching event the outcome is unresolved.
</Warning>

### Order-attached take-profit / stop-loss legs size independently

The `takeProfit` / `stopLoss` legs attached to an order at placement (`ParentTpSlLeg`; `placeLimitOrder` / `placeMarketOrder` / `batchCreate` in `@0xmonaco/core`, the matching REST and gRPC order requests) gain `quantity` and `closePosition`, the same sizing contract the position-attached `TpSlLeg` already carries. Previously an order-attached leg had no way to express its own size and was frozen at the parent order's quantity, so a position that later grew past it kept a stop covering only part of what was held while still reading as attached. Omit both fields (or set `closePosition: true`) to resolve the full live position size at trigger time, or name a `quantity` for a deliberate partial that never resizes; the two are mutually exclusive, and `quantity` is required when `closePosition` is `false`.

### `account` WebSocket channel — live margin-account health

A new authenticated channel — subscribe with `account` — carries a margin account's health: equity, collateral, free collateral, margin ratio, and maintenance requirement (all decimal strings), plus the margin account id and update timestamp, under an `account_update` event. The channel routing and the `AccountEvent` type in `@0xmonaco/types` ship in this release so integrators can build against the contract, but **the server-side producer that emits these frames is gated off by default and not yet enabled in the deployed environments** — subscribing succeeds and the wire shape is stable, but no frames arrive yet. When the producer is enabled its lag policy is *conflate* (a slow subscriber is fast-forwarded to the latest state) and it republishes an unchanged frame as a keepalive after a bounded quiet interval, so treat repeats as keepalives and each frame as a terminal-state snapshot per margin account, not an additive delta. There is no `sdk.ws` helper, so subscribe over the raw WebSocket protocol with a `Subscribe` frame naming the `account` channel; the raw wire is **snake\_case** (`event_type`, `user_id`, `margin_account_id`, `free_collateral`, `margin_ratio`, `maintenance_requirement`, `updated_at`) while the `AccountEvent` type is the camelCased ergonomic shape nothing converts to on this channel. See the [WebSocket reference](/reference/websockets#account) for the exact wire frame.

### `movements` frames for on-chain deposits and withdrawals

On-chain deposits and withdrawals now emit a `user_movement` frame on the `movements` channel, co-ordered with their `balance_update` on the `balances` channel. Every deposit/withdrawal balance change now has a matching `movements` ledger entry — transaction type `deposit` or `withdrawal`, carrying the amount, token, symbol, and balance snapshot — so the two streams line up; previously a deposit or withdrawal produced a `balances` frame with no corresponding `movements` entry. The `UserMovement` wire shape is unchanged (`transactionType` is a free-form lowercase string); these are additional transaction types on the existing channel.

## Fixed

### Funding an isolated risk bucket no longer ratchets a sole position's margin

Funding an isolated risk bucket through `transferCollateralToRiskBucket()` (`@0xmonaco/core`; the `transfer_collateral_to_risk_bucket` MCP tool; REST `POST /api/v1/margin/risk-buckets/collateral/transfer-in`; gRPC `TransferCollateralToRiskBucket`) no longer credits the bucket's sole open position's stored margin. It now always allocates reusable bucket collateral, as documented. Previously, when the bucket held exactly one open position, every transfer was silently treated as Adjust Margin, so routine bucket funding permanently ratcheted the position's initial margin and collateral requirement instead of leaving the collateral redeployable.

**This corrects the 1.0.40 migration note**, which presented `transferCollateralToRiskBucket` as the `addPositionMargin` replacement. It is not: it funds reusable bucket collateral. To explicitly increase a sole open position's stored margin, use the pair-scoped legacy transfer `transferCollateralToMarginAccount(parentMarginAccountId, { asset, amount, tradingPairId })` (`@0xmonaco/core`; REST `POST /api/v1/margin/accounts/{marginAccountId}/collateral/transfer-in` with `tradingPairId`; gRPC `TransferCollateralToMarginAccount`). There is no MCP tool for this — the pair-scoped transfer is deliberately not exposed — so an assistant increases a position's stored margin through the REST endpoint or `@0xmonaco/core`.

## Upgrade

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

The MCP server ships at `1.0.41` too; it runs via `npx -y @0xmonaco/mcp-server`, so restarting your assistant picks up the new version, the `clientOrderId` option on the order tools, and the corrected `transfer_collateral_to_risk_bucket` behavior.

Nothing in this release is breaking. The one thing worth acting on: if you followed the 1.0.40 migration and used `transferCollateralToRiskBucket` to *add margin to a position*, switch to `transferCollateralToMarginAccount(parentMarginAccountId, { asset, amount, tradingPairId })` — the risk-bucket transfer funds reusable collateral and no longer ratchets a sole position's stored margin.


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