Skip to main content

Monaco Protocol SDK v1.0.83

The order listing no longer returns a TWAP order’s slices, candles carry open interest, and a position keeps one full-close take-profit and one full-close stop-loss no matter where each was set. An authenticated call the server cannot verify for a moment now answers retryable 503 instead of 401, a replacement re-checks the TP/SL legs it carries, and the first cross order’s risk preview matches what placement charges. Action item: if you read a TWAP’s slices from getPaginatedOrders, iterateOrders or useUserOrders, read them with sdk.trading.listTwapOrderSlices instead.

Breaking

TWAP slices leave the order listing

sdk.trading.getPaginatedOrders and iterateOrders (GET /api/v1/orders; gRPC OrdersService.ListOrders) no longer return a TWAP order’s slices — the child orders that carry parentOrderId — resting or finished, under any filter, and total / totalPages no longer count them. Read them with sdk.trading.listTwapOrderSlices(twapOrderId) (GET /api/v1/orders/twap/{twapOrderId}/slices; gRPC OrdersService.ListTwapOrderSlices). getOrder still returns a slice by id, and sdk.ws.userOrders still delivers every slice frame and orders snapshot row with parentOrderId. Request and response shapes are unchanged; the Rust REST SDK’s list_orders and the Rust gRPC SDK’s OrdersService::list_orders follow the same rule. useUserOrders mirrors the listing: it drops slice rows from the REST page, from the orders subscribe-time snapshot and from live order frames, so a resting slice no longer appears live and then vanishes on the next REST read. See TWAP Orders and useUserOrders.

Added

Open interest on candles

Each Candlestick from sdk.market.getCandlesticks (GET /api/v1/market/pairs/charts/candlestick/{tradingPairId}/{interval}; gRPC MarketService.GetCandles), each sdk.ws.ohlcv snapshot and event, useOHLCV and useMarket.getCandlesticks may carry openInterestBase and openInterestNotional. openInterestBase is one-sided LONG open interest in base-asset units, from the latest sample at or before the candle end. openInterestNotional values that quantity at the price paired with the same sample, not the candle close, in quote-asset units. Both are optional and nullable: null or absent means unavailable, and the quantity can be known while the notional is not. The endpoint stays unauthenticated and takes no new request fields. See OHLCV and Market.

Changed

One full-close take-profit and stop-loss per position

A position keeps at most one active full-close (closePosition) take-profit and one full-close stop-loss, whether the leg came from attachPositionTpSl (POST /api/v1/positions/{positionId}/tp-sl; gRPC PositionsService.AttachPositionTpSl) or from takeProfit / stopLoss on an entry order, and the leg set most recently wins. Attaching a full-close TP/SL to a position now also retires an already-armed full-close leg of the same type that came from an entry order; before, entry-order legs were left armed beside it and the closer one fired first. A leg still pending on an unfilled entry order is left alone. When that order fills, its full-close leg is cancelled instead of armed if the position TP/SL was attached later, and replaces the position’s leg if it was set later. A retired leg emits conditional_order_update with reason: "cancelled" and the failure reason “superseded by a newer full-position TP/SL of the same type”. Fixed-quantity legs, OCO siblings and trailing stops are unchanged. See Trade.

Fixed

  • A busy session check is 503, not 401 — when the server cannot complete an authenticated request’s session check because a database or other dependency is unavailable, REST answers 503 SERVICE_UNAVAILABLE and gRPC UNAVAILABLE, with the message Authentication temporarily unavailable; retry. Before, it answered 401 / UNAUTHENTICATED carrying internal error text, which read as a dead session. Keep the session and retry with backoff. 401 / UNAUTHENTICATED still means the credentials were rejected: a bad signature, a timestamp outside the skew window, or a session that was not found, has expired or been revoked, or whose delegation is inactive. See Error Handling.
  • A replacement re-checks the TP/SL it carries — replaceOrder and batchReplace (PUT /api/v1/orders/{orderId}, POST /api/v1/orders/batch-replace; gRPC OrdersService.ReplaceOrder, OrdersService.BatchReplaceOrders) move an entry order’s pending TP/SL legs onto the replacement, and now judge them as placement would: a fixed trigger left on the wrong side of the replacement’s expected entry is refused with INVALID_ORDER, and the original keeps resting. Before, an edit could move the entry past its own stop, which then fired as soon as the order filled. A replacement that fills on arrival now also arms the moved legs — a fixed TP/SL on any fill, a trailing stop on a full fill — where before they stayed pending and left the position unprotected. See Replace Orders.
  • The first cross order’s risk preview matches placement — simulateRiskBucketOrderRisk with marginMode: "CROSS", simulateParentMarginOrderRisk and simulateOrderRisk preview a first cross order (no active cross risk bucket yet) funded the way placement funds it: the risk bucket is created empty and admission draws what the order needs. Before, the preview modeled the whole unallocated balance behind the position, so equityAfter, freeCollateralAfter and the estimated liquidation price looked far safer than what the placed order got. Response shapes are unchanged; no SDK change is needed.
  • The mainnet preset reaches the production REST API — network: "mainnet" sends REST calls to https://apimonaco.xyz, and so does the MCP server’s default MONACO_NETWORK=mainnet. The previous https://api.monaco.xyz never resolved, so no working client changes behavior. Custom apiUrl overrides are unaffected.

Upgrade

If you grouped a TWAP’s slices by scanning getPaginatedOrders for parentOrderId, call listTwapOrderSlices instead.