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

# Monaco Protocol SDK v1.0.74

This release adds **margin sub-accounts** with per-account PnL and portfolio views, **secured delegated-agent policies** with IP allowlists and bounded expiry, and **referral tree reads** with the full upline. Withdrawable collateral now counts realized PnL, BuilderCodes payouts start crediting builder fees, and every engine write is now rate limited per account. **Action items:** replace `accountState` with `riskBucketState` on margin-account summaries and liquidation events; set an `expiresAt` (or accept the 14-day default) and use only the supported actions when you upsert delegated agents; handle `429` on position closes, copy-trading settings writes, follow stops and reward transfers; treat `AUTO_DELEVERAGING` as a cancel reason.

## Breaking

### `accountState` is replaced by `riskBucketState`

A margin account has no liquidation lifecycle of its own: every position, order and bad-debt record lives in a risk bucket. `MarginAccountSummary.accountState` (`GET /api/v1/margin/accounts`, `GET /api/v1/margin/accounts/{marginAccountId}`, `GET /api/v1/margin/parent-margin-account`; gRPC `MarginAccountsService`) is removed. The new optional `riskBucketState` (`NORMAL`, `PENDING_LIQUIDATION`, `LIQUIDATING`, `BAD_DEBT`, `CLOSED`) is set only on risk-bucket rows and absent on the parent row. The list `state` filter now matches `riskBucketState`, so any filter excludes the parent row.

`sdk.ws.liquidations` events expose `data.riskBucketState` (wire key `risk_bucket_state`) in place of `data.accountState`. See [Margin Accounts](/sdk/typescript/margin-accounts) and [WebSockets](/sdk/typescript/websockets).

## Added

### Margin sub-accounts

A wallet can hold several margin accounts per application, one per sub-account key. The key `default` is the existing parent margin account: it keeps its id and is the only account deposits, withdrawals and wallet transfers touch. Every sub-account holds its own collateral and its own risk buckets.

* `sdk.marginAccounts.createMarginSubAccount({ subaccountKey, label? })` (`POST /api/v1/margin/sub-accounts`; gRPC `MarginAccountsService.CreateSubAccount`) opens a sub-account. Keys are up to 64 letters, digits, `_`, `-`, `.` or `:`; `copy:` keys are reserved and `default` is refused. The default margin account must exist first. Re-creating a closed key re-opens the same account. Open sub-accounts are capped per owner by weighted 14-day volume tier (10 at the first tier, up to 50) or an admin override; copy-trading sub-accounts do not count.
* `sdk.marginAccounts.transferMarginCollateral({ asset, amount, from, to })` (`POST /api/v1/margin/collateral/transfer`; gRPC `MarginAccountsService.TransferCollateral`) moves collateral between the wallet and the default margin account, or from one margin account to another in one atomic step. `from` and `to` are `{ wallet: true }` or `{ marginAccountId }`. Risk-bucket endpoints are refused on this route; fund a risk bucket with `transferCollateralToRiskBucket`.
* `sdk.marginAccounts.closeMarginSubAccount(marginAccountId)` (`POST /api/v1/margin/sub-accounts/{marginAccountId}/close`; gRPC `MarginAccountsService.CloseSubAccount`) closes a flat sub-account in one call: its flat, solvent risk buckets close with it and all of its collateral moves to the default margin account. A risk bucket in liquidation or bad debt refuses the close, and nothing moves.
* `sdk.marginAccounts.getMarginAccountPnl(marginAccountId)` (`GET /api/v1/margin/accounts/{marginAccountId}/pnl`; gRPC `MarginAccountsService.GetMarginAccountPnl`) returns one margin account's own realized and unrealized PnL; an owner's accounts sum to the owner-wide figure.
* `transferCollateralToRiskBucket` and `simulateRiskBucketOrderRisk` take an optional `marginAccountId` naming any of the caller's open sub-accounts, so a sub-account funds and previews its own risk buckets. A copy-trading sub-account's risk buckets belong to its follow and are refused.
* `sdk.portfolio.getMargin({ marginAccountId, includeAccounts })` (`GET /api/v1/accounts/me/portfolio/margin`; gRPC `AccountsService.GetPortfolioMargin`) describes one margin account, and with `includeAccounts` also returns `accounts` (one row per open margin account) and `ownerTotal`. The response names the account it describes in `marginAccountId`.
* `MarginAccountSummary` gains `subaccountKey` and `marginAccountState` (`ACTIVE` or `CLOSED`), and private order events carry `marginAccountId` (wire `margin_account_id`; a maker fill carries the maker's account), so you can route events per sub-account.

Creating and closing a sub-account and account-to-account transfers spend the per-user movement budget. See [Margin Sub-Accounts](/developers/perps-collateral#margin-sub-accounts) and [Margin Accounts](/sdk/typescript/margin-accounts#sub-accounts).

### Secured delegated-agent policies

`sdk.delegatedAgents.upsertDelegatedAgent` (`POST /api/v1/delegated-agents`; gRPC `DelegatedAgentsService.UpsertDelegatedAgent`) policies now scope with AND: an agent listing a margin account (and markets) trades only that account (on those markets); a market-only agent still trades its markets in every account. `expiresAt` defaults to 14 days from now and may be at most 180 days ahead. `allowedActions` accepts `CREATE_ORDER`, `CANCEL_ORDER`, `REPLACE_ORDER`, `READ` and `MANAGE_RISK_BUCKETS` and rejects anything else; a `READ`-only policy is a read-only key. An owner holds at most 10 active, unexpired agents. The new `ipAllowlist` (up to 20 IP addresses or CIDR ranges) restricts where the agent may create its delegated session (`POST /api/v1/delegated-agents/sessions` returns `403` / `PERMISSION_DENIED` from any other address).

`MANAGE_RISK_BUCKETS` lets an agent move a listed margin account's free collateral into that account's own risk buckets through `transferCollateralToRiskBucket` (`POST /api/v1/margin/risk-buckets/collateral/transfer-in`), only into an isolated risk bucket on a listed market when the policy lists markets. Every other collateral route still refuses delegated agents. See [Delegated Agents](/developers/delegated-agents#policy-design).

### Referral tree and full upline

`sdk.pitpass.getMyReferralTree({ parent?, pageSize?, pageToken? })` (`GET /api/v1/pitpass/referrals/me/tree`; gRPC `TraderCodeService.GetMyReferralTree`) reads one level of your own referral tree a page at a time: the wallets a parent referred, each with its level, parent, referral time, referee count and what you earned from it. Omit `parent` for your L1 referees, or pass one of your L1 or L2 referees to expand it; any other wallet is `404` / `NOT_FOUND`. `pageSize` is 1 to 200, default 50. `getMyReferralPosition` also returns `upline`, your referral chain above you (L1, L2, L3) nearest first. React adds `useMyReferralTree`. See [PitPass](/sdk/typescript/pitpass).

### `AUTO_DELEVERAGING` cancel reason

A cancelled order can report the terminal reason `AUTO_DELEVERAGING`: auto-deleveraging fully closed the position your risk bucket held and this reduce-only order on that pair was cancelled with it. You were deleveraged as a counterparty, not liquidated, so it is not reported as `LIQUIDATION`. Code that switches on `terminalReason` should treat unrecognised values as an opaque cause. See [WebSockets](/sdk/typescript/websockets).

## Changed

### Withdrawable collateral counts realized PnL

`withdrawableCollateral` now counts realized PnL on every surface that publishes it: margin-account summaries, `newWithdrawableCollateral` on collateral transfer responses, the margin figure on `GET /api/v1/margin/collateral/available`, and the portfolio margin totals. On the parent margin account the bound is deposits plus settled realized PnL and funding, less risk bucket allocations, and never more than `freeCollateral` less any unrealized gain; a user who deposited 1,000 and realized 500 can now withdraw 1,500, and a settled loss reduces it. A risk bucket's bound is its allocation plus realized PnL, less funding paid, unrealized losses and required margin; it is no longer capped at the allocation, and it is zero while the risk bucket is not `NORMAL`.

A parent margin account is charged at most a risk bucket's allocation: a loss past it is the insurance fund's. A cross risk bucket that goes flat with no resting orders returns its allocation and realized PnL to the parent margin account and stays open, empty. Collateral a risk bucket draws automatically for an order returns to the parent margin account when that order is cancelled or released, less the share its fills used, and a replace to a smaller order returns only the draw it frees; collateral you moved in yourself stays. Transfers into or out of a risk bucket frozen as bad debt are refused. Field types are unchanged. See [Modify Margin](/developers/positions#modify-margin).

### BuilderCodes payouts credit builder fees

`sdk.buildercodes.listPayouts` and `getPayoutSummary` now return `BUILDER_FEE` credits: each positive builder fee charged on an enrolled application's taker fill accrues in full to the application payout wallet's claimable balance, and `appliedBps` reports the charged builder-fee rate. See [BuilderCodes](/developers/buildercodes).

### Every engine write is rate limited

Every authenticated write that sends a command to the matching engine now draws a per-account limit before it reaches the engine. Eight previously unmetered operations can return `429` `RATE_LIMIT_EXCEEDED` with `Retry-After` and `details.retryAfter` (gRPC `RESOURCE_EXHAUSTED` with `RetryInfo`); a `429` applied nothing.

* **Settings writes** share one budget (1 write/s, burst 10, family 4x): the lead trader profile, follow create/edit and the self-trade-prevention default.
* **Follow stops** have their own budget (1 stop/s, burst 20), so closes and edits never delay a stop.
* **Position closes** draw on the order limit's risk-reduction class: `closePosition` one item, `batchCloseAllPositions` one per open position (the first 100 are charged up front; over budget the whole call is refused).
* **Reward transfers** (`sdk.pitpass.transferRewards`, BuilderCodes claims) spend the per-user movement budget shared with withdrawals and collateral transfers.

Position closes and reward transfers follow each environment's enforcement setting. See [Rate Limits](/developers/rate-limits).

### Position frames rank funding and terminal updates

Position WebSocket updates for non-zero funding settlements and terminal closes, liquidations and ADL are ranked with the durable position `version`. Terminal frames keep the historical position size and exact `CLOSED` or `LIQUIDATED` status; detect closure from status, not a zero size. Zero funding payments emit no position frame. See [Positions](/sdk/typescript/positions).

### Liquidation, deleveraging and bad debt

* **Forced closes ignore self-trade prevention.** Liquidation slices can match the account's own resting orders, and an account's other risk buckets' positions can be ADL counterparties; ADL closes positions directly and fills no resting orders, though a position it fully closes has its resting reduce-only orders on that pair cancelled with `AUTO_DELEVERAGING`.
* **ADL is single-price.** ADL starts when the book refuses the position below three quarters of maintenance margin, fills every chunk at the liquidated position's pinned price, and reaches counterparties in two stages by where the fill leaves their account.
* **The insurance fund's role follows the liquidation mode.** In the default Unbounded mode the terminal slice carries no limit and the insurance fund absorbs fills past the pinned price. When the fund is empty, the venue switches to the Zero mode, where anything the book declines at that price goes straight to ADL. It stays there until it is switched back after the fund is replenished.
* **Bad debt drains from the insurance fund.** A risk bucket in bad debt stays frozen with an immutable allocation; the fund credits it as it pays, possibly in parts, and it unfreezes once covered. There is no manual write-off.
* **A risk bucket's loss stops at its allocation**, for cross and isolated alike, and the engine's live account equity never counts an open loss past it (persisted portfolio and fallback summary reads still sum unrealized PnL uncapped).

See [Liquidations](/trading-mechanics/liquidations) and [Auto-Deleveraging](/trading-mechanics/auto-deleveraging).

### Order margin and margin release

* **A margin limit order's initial margin is priced at its limit**, never the average of its fills; a market order uses its pre-trade estimate.
* **Automatic top-up returns only the unused draw.** An order draws only its shortfall from the parent margin account at admission. Cancelling or releasing it returns the part of that draw its fills did not use, and a replace to a smaller order returns only the draw it frees, for cross and isolated risk buckets alike.
* **Margin release is floored at initial margin.** Reducing a position's margin cannot take it below its initial margin requirement.

See [Margin](/trading-mechanics/perps).

## Fixed

### Position reads report index-price outages as unavailable

`listPositions`, `getPosition` and `getPositionRisk` (`GET /api/v1/positions`, `/positions/{positionId}`, `/positions/{positionId}/risk`) return `503` `SERVICE_UNAVAILABLE` / gRPC `UNAVAILABLE` when a transient index-price read fails, so you can retry; other failures stay `500` / `INTERNAL`. See [Positions](/developers/positions#errors-to-handle).

### Funding publication resumes after epoch gaps

Funding publication resumes when old history occupies newer settlement epochs. Epoch numbers may jump; skipped identifiers are not retroactive charges. The funding endpoints' fields are unchanged. See [Funding Rates](/trading-mechanics/funding-rates).

### Copy-position margin errors

`sdk.copyTrading.addFollowPositionMargin` refuses with `400` `COPY_TRADING_REJECTED` when there is no isolated copy position on the pair, the copy position is being liquidated or is in bad debt, or the amount exceeds what the copy account can put in; `409` covers only a stopping or stopped follow. See [Copy Trading](/sdk/typescript/copy-trading).

## Upgrade

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

Rename `accountState` to `riskBucketState` where you read margin-account summaries or liquidation events, and stop expecting a state on the parent row. Review delegated-agent policies for AND scoping and expiry, and retry `429`s after `Retry-After`. Sub-accounts are opt-in; the default margin account and the existing transfer methods are unchanged.


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