Skip to main content

Monaco Protocol SDK v1.0.44

This release adds an opt-in asErc20 deposit path for the chain’s wrapped-native asset, so you can deposit it as its ERC20 (approve + depositERC20) instead of the native-coin default introduced in 1.0.43; and a withdrawableCollateral figure on portfolio margin that names the amount that can actually leave a margin account or risk bucket. It also documents a server-side correction to replaceOrder: newOrder.quantity now names the order’s new total quantity, and the replacement inherits the original’s fill history. One thing to act on: if you replace a partially filled order by quantity, pass the new total rather than the remainder — see the change below.

Added

asErc20 deposit option for the wrapped-native asset

sdk.vault.deposit() accepts an options.asErc20 flag (@0xmonaco/core; DepositOptions and DepositSchema in @0xmonaco/types). Since 1.0.43 the chain’s wrapped-native asset (e.g. WSEI) deposits as native coin through the payable depositNative with no ERC20 approval. Passing asErc20: true instead deposits it as its ERC20 through the standard approve + depositERC20 flow — for wallets that hold the wrapped ERC20 itself — and sdk.vault.needsApproval() with the same option reads the real WSEI allowance rather than short-circuiting to false. Every other asset, and a wrapped-native deposit without the flag, is unchanged. options is the fifth argument to deposit() and the third to needsApproval(). The ERC20 path is not auto-approved — deposit() throws a ContractError (code === "CONTRACT_ERROR") whose revertReason is "APPROVAL_REQUIRED" if the allowance is short, so approve first exactly as you would for any ERC20:

withdrawableCollateral on portfolio margin

sdk.portfolio.getMargin() (GET /api/v1/accounts/me/portfolio/margin; gRPC AccountsService.GetPortfolioMargin) adds withdrawableCollateral (decimal string) to both PortfolioMarginTotal and each PortfolioRiskBucket in @0xmonaco/types. It is the largest amount that can actually leave the parent margin account or risk bucket — the bound the engine enforces on transfers-out and withdrawals, and the effective ceiling on funding new isolated / first-use positions (bucket allocation passes the same principal-gated door). Unlike parentAvailableCollateral / freeCollateral (equity figures) it excludes unrealized gains and non-principal balances such as banked realized PnL; on the parent it is min(deposited principal − bucket allocations, freeCollateral − max(unrealizedPnl, 0)), floored at zero. Size transfers, withdrawals, and new isolated positions from withdrawableCollateral; keep freeCollateral as trading-margin headroom for existing cross exposure. The GetAvailableCollateralResponse.marginAvailableCollateral doc was clarified to say the same.

Changed

replaceOrder’s quantity is the order’s new total

sdk.trading.replaceOrder() (PUT /api/v1/orders/{orderId}; gRPC OrdersService.ReplaceOrder) now treats newOrder.quantity as the order’s new total quantity. On a partially filled order the replacement rests total - filled and locks collateral for that remainder only (FIX cancel/replace convention: LeavesQty = OrderQty - CumQty); the total must exceed the filled amount. Previously the value was placed as a fresh order size, so replacing a 96/100-filled order with quantity: "200" rested 200 and locked for all 200 (total exposure 296) — it now rests 104 and reads as 96/200 filled. A replace that omits quantity keeps the order’s total, derived against the live fill state inside the matching step, so a fill landing while the request is in flight can no longer make the replacement rest more than the true remainder; the response’s updatedFields.quantity reports that total (previously a point-in-time remainder snapshot). Unfilled orders are unaffected, and margin reduce-only replacements are exempt (explicit quantities stay close sizes). batchReplace items (BatchReplaceOrderItem.quantity) carry the same total semantics. The replacement also inherits the original’s fill history — filled quantity, VWAP, and realized fee / payment aggregates carry onto the new order’s row, exactly as if the order had been edited in place. The retired original keeps its own terminal row, so summing fill aggregates across a replacement chain’s rows double-counts the carried history; per-order reads and trade-level data are unaffected. Types and wire shape are unchanged — this is a server-side semantics correction, so clients on any SDK version get the new behavior.

Package metadata points at the public docs site

Every published package drops its repository field and sets homepage to the public docs. The previous repository URL referenced a private GitHub repository, so the Repository and Homepage links on the package page returned 404 for anyone outside the org; there is no public source repository to point at, so the field is omitted rather than redirected. The five npm packages (@0xmonaco/core, @0xmonaco/types, @0xmonaco/react, @0xmonaco/contracts, @0xmonaco/mcp-server) point at https://docs.0xmonaco.com/sdk/typescript; the two published Rust crates point at their own reference — monaco-sdk at https://docs.0xmonaco.com/sdk/rust-rest and monaco-grpc-sdk at https://docs.0xmonaco.com/sdk/rust-grpc (their rustdoc landing link follows the same target, and documentation still points at docs.rs). No code, type, or behavior changes — this is why @0xmonaco/react, @0xmonaco/contracts, @0xmonaco/mcp-server, and both Rust crates bump to 1.0.44 with no behavior change.

Upgrade

The MCP server ships at 1.0.44 too; it runs via npx -y @0xmonaco/mcp-server, so restarting your assistant picks up the new version. The API changes are additive and backward-compatible — a new optional withdrawableCollateral response field on portfolio margin and the new opt-in DepositOptions / DepositSchema types — and every SDK bump is a patch release, so the upgrade is drop-in for almost everyone. The one compatibility boundary is behavioral: replaceOrder’s quantity is now the order’s total, so a partially filled replaceOrder that used to pass the remaining quantity now rests the wrong size — and is rejected outright when that value is at or below the amount already filled. Audit those calls before upgrading; everything else is backward-compatible.