Skip to main content

Monaco Protocol SDK v0.8.14

This release restructures the idless margin-collateral API into explicit parent margin account and risk bucket endpoints, adds a one-shot batch close for open positions, exposes raw total balances, and introduces the fx asset class for Pyth-backed FX perps.

Removed

Idless “auto margin account” collateral endpoints replaced

The two idless auto margin account shortcuts are removed and replaced by the explicit parent-margin-account / risk-bucket surface below:
  • marginAccounts.transferCollateralToAutoMarginAccount({ asset, amount }) — POST /api/v1/margin/collateral/transfer-in
  • marginAccounts.simulateAutoMarginOrderRisk(request) — POST /api/v1/margin/simulate-order-risk
Both paths now return 404. The id-based methods (transferCollateralToMarginAccount(marginAccountId, …), getMarginAccountSummary(marginAccountId, …), simulateOrderRisk(marginAccountId, …), etc.) are unchanged. Migration:
If you were funding a per-pair (isolated) bucket through the auto shortcut, use the new risk-bucket methods instead — they take an explicit tradingPairId (and optional strategyKey).

Added

Explicit parent-margin-account and risk-bucket collateral API

The idless margin surface is now split along the account model — one parent margin account per user/application, with isolated risk buckets nested underneath it (a bucket is created or reused per tradingPairId + optional strategyKey). No account id is required; the parent is resolved automatically from the caller. All collateral transfers return TransferCollateralResponse (movement_id, margin_account_id, asset, amount, status, new_equity, new_total_collateral_value, new_withdrawable_collateral). The simulate endpoints return SimulateOrderRiskResponse (accepted, reject_reason?, equity_after, initial_margin_required_after, maintenance_margin_required_after, free_collateral_after, estimated_fee?, estimated_liquidation_price?). All endpoints require user auth.

Batch close all open positions

New POST /api/v1/positions/batch-close-all (user auth) submits a MARKET reduce-only close for every open perp position — a one-call “panic close”. It is best-effort and partial: each position closes independently and per-position failures are reported rather than aborting the batch.
Request (BatchCloseAllRequest, all optional): tradingPairId (limit to one pair; otherwise all open positions), slippageToleranceBps (per-close slippage tolerance). Response (BatchCloseAllResponse): total_requested, total_closed (orders accepted — SUCCESS / PARTIAL / PENDING), total_failed, and results[] — each a BatchCloseResult with position_id, optional close_order_id, status, submitted_quantity, and an optional error ({ code, message }). Available across @0xmonaco/core (sdk.positions.batchCloseAllPositions), @0xmonaco/react (usePositions().batchCloseAllPositions), and the batch_close_all_positions MCP tool.

Raw total balance

Balance responses gain total_balance_raw — the total balance (available + locked) as a raw integer string in the token’s smallest unit, alongside the existing normalized total_balance:
  • AccountBalance (GET /api/v1/accounts/balances) and the single-asset balance response (GET /api/v1/accounts/balances/{asset_id}).
  • @0xmonaco/react’s useUserBalances preserves total_balance_raw across WebSocket balance updates, mirroring the existing normalized-total handling.
The field is purely additive — existing available_balance / locked_balance / total_balance (and their _raw counterparts) are unchanged.

fx asset class

Pyth-backed FX perpetual markets add a fourth value to the trading-pair category enum: "fx" (joining "crypto", "equities", "commodities" from v0.8.11). It is accepted as a category filter on getPaginatedTradingPairs / getScreener and returned on TradingPair / ScreenerItem.

Changed

margin_bucket_* fields renamed to risk_bucket_*

Isolated-bucket fields are renamed from margin_bucket_* to risk_bucket_* across orders, positions, and margin responses. The gRPC field numbers are unchanged (binary gRPC clients are unaffected), but the JSON/REST key changes, so REST and TypeScript SDK consumers must update:
  • Order placement — placeLimitOrder / placeMarketOrder options marginBucketId → riskBucketId and marginBucketCollateral → riskBucketCollateral (wire: risk_bucket_id / risk_bucket_collateral). riskBucketId routes the order into an existing isolated bucket; riskBucketCollateral opens a new one.
  • Positions — the Position response field margin_bucket_id → risk_bucket_id (GET /api/v1/positions, GET /api/v1/positions/{position_id}).
  • Margin — risk-bucket summary rows expose risk_bucket_id.

Withdrawals migrated to merkle-proof executeWithdrawal

The withdrawal flow now submits an on-chain merkle-proof executeWithdrawal transaction, replacing the previous server-signed executeSignedWithdrawal path. Because the executable calldata needs the withdrawal’s merkle proof — which only exists once the root is confirmed on-chain — the SDK now polls GET /api/v1/withdrawals/{withdrawal_index} (which returns 404/409 until the proof is ready) before submitting. sdk.vault.withdraw(assetId, amount, autoWait?) and retryWithdrawal(...) keep their call signatures (new arguments are optional), so most call sites need only a version bump — but a v0.8.11 SDK uses the old signed-withdrawal flow (immediate executeSignedWithdrawal, no proof polling), which no longer works against the v0.8.14 backend and vault contract, so frontends must upgrade to the v0.8.14 SDK. On a proof-poll timeout, withdraw() / retryWithdrawal() no longer throw — they resolve to { withdrawalIndex, status: "awaiting_proof" } with nothing submitted on-chain, so the caller keeps the index and can finish the withdrawal later via retryWithdrawal(withdrawalIndex). WithdrawResult.status gains "awaiting_proof" alongside "pending" / "confirmed" / "failed". The default proof-poll timeout is 5 minutes (override with retry.timeoutMs; pass Infinity to wait indefinitely). sdk.vault.withdraw(assetId, amount, autoWait, "margin") can also source an external withdrawal directly from the parent margin account; retry options remain supported as the legacy fourth argument.

Address-shaped return types are now viem Address

Public SDK methods that return addresses now type them as viem’s Address (0x${string}) instead of string, so they flow into viem calls without a cast. SDK.getAccountAddress() returns Address and vault.getVaultAddress() returns Promise<Address>; address fields on returned response/event objects (account / profile / balances, applications config & reporting, market trading-pair contracts, delegated agents, vault balances, withdrawals, and the user balance/movement WebSocket events) are likewise typed as Address. This is a type-only change — no runtime behavior changes, and request/input address params remain string.

Upgrade