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

# Monaco Protocol SDK v1.0.69

This release rolls up the consumer-facing changes shipped since v1.0.67. `sdk.ws.conditionalOrders()` now receives **exactly one versioned update per transition**, TWAP children get **`orders` frames tagged with their `parentOrderId`** and the resting orders they fill get their maker fills, trade fees report the **total fee paid** split into `monacoFee` + `builderFee`, and BuilderCodes payouts name their **payout stream**. Closed positions no longer count a partial-close fee twice, and a position closed over many fills reports its lifetime figures. A risk bucket entering liquidation has its resting orders cancelled at once, a first-use automatically funded `SELL` limit order is no longer refused for want of margin it does not need, the faucet quota is scoped to each wallet and application, and public whitelist submissions are closed. **Action items:** if you consume `conditional_order_update`, handle the new `position_closed`, `reparented` and `expired` reasons and merge by `version`; if you read `fee` from user trades or `orders` fill frames, it now includes the builder fee — read `monacoFee` for Monaco's share; if you call `sdk.whitelist.submit`, it now fails with `403`; and if you use the Rust gRPC SDK, `ListBuildercodePayoutsRequest` no longer derives `Copy`.

## Changed

### One versioned conditional-order update per transition

`sdk.ws.conditionalOrders()` receives exactly one `conditional_order_update` for every conditional-order transition, including OCO sibling cancels (`oco_cancelled`), cancels when the position closes (`position_closed`) or the entry order ends (`parent_cancelled`), activation of a pending leg (`activated`), failed and expired triggers (`expired`), and legs carried onto a replaced entry order (`reparented`). `ConditionalOrderEventReason` gains `position_closed`, `reparented` and `expired`. Every live update carries `version`, the revision of the row it describes — the same value REST and the subscribe-time snapshot return — so merge state from any of the three with `incoming.version >= local.version` when both carry one; a versioned row supersedes an unversioned one. The triggered update carries state `TRIGGERED` with `triggeredOrderId` and `triggeredAt`. Created and cancelled updates are sent once the change is durable, slightly later than before. See [WebSockets](/sdk/typescript/websockets).

### Trade fees report the total fee paid

`sdk.profile.getUserTrades()` (`GET /api/v1/accounts/trades`; gRPC `AccountsService.GetUserTrades`, and `TradesService.ListUserTrades`) returns `UserTrade.fee` as the total fee the user paid on the trade: for a taker, Monaco's taker fee plus the frontend's builder fee (`applicationTakerFee`); for a maker, the maker fee (negative for a rebate). Previously a taker's `fee` left out the builder fee. Two optional components sit beside it, so `fee = monacoFee + builderFee`: `monacoFee` (Monaco's share) and `builderFee` (always `"0"` for a maker, because builder fees are charged to takers only). The accounts `UserTrade` also gains `monacoFeeRaw` and `builderFeeRaw`.

`orders` fill frames (`OrderFilled`, `OrderPartiallyFilled`, `OrderMatched`) carry `fee` as the total fee for the fills they cover and add `monacoFee` / `monacoFeeRaw` and `builderFee` / `builderFeeRaw` (wire `monaco_fee`, `monaco_fee_raw`, `builder_fee`, `builder_fee_raw`). A taker frame's `fee` now includes the builder fee and matches the order echo's `totalTakerFees`; a maker frame's `builderFee` is `"0"`. The components are optional because a server older than them omits them, and `orders` snapshot rows carry no fee fields. No value changes today: every application charges a 0 bps builder fee, so `builderFee` is `"0"` and `fee` equals `monacoFee` on every trade.

### BuilderCodes payouts carry their payout stream

Every `BuildercodePayout` row from `sdk.buildercodes.listPayouts()` (`GET /api/v1/buildercodes/payouts`; gRPC `BuildercodeRewardsService.ListBuildercodePayouts`) gains `kind`: `REVENUE_SHARE` (the frontend's share of Monaco's fee) or `BUILDER_FEE` (the frontend's own builder fee, paid by the taker). Both credit the same claimable balance; every credit today is `REVENUE_SHARE`, because the builder fee a taker pays is not yet credited to the payout bucket. `listPayouts({ kind })` filters to one stream — the SDK rejects any other value before a request is sent, and the server returns `400` (`INVALID_ARGUMENT` on gRPC) for one — and `total` / `totalPages` then count that stream only; with no filter the listing is unchanged. `sdk.buildercodes.getPayoutSummary()` (`GET /api/v1/buildercodes/payouts/summary`; gRPC `GetBuildercodePayoutSummary`) keeps `byToken` as before, summed across both streams, and adds `byTokenAndKind`: one row per token and stream with `token`, `kind`, `totalAmount` (RAW), `payoutCount` and `lastCreditedAt`, and a token's rows add up to its `byToken` total. `@0xmonaco/types` adds `BuildercodePayoutKind` and `BuildercodePayoutTokenKindTotal` with their schemas; `BuildercodePayout.kind` and `GetBuildercodePayoutSummaryResponse.byTokenAndKind` are optional because an older server omits them. In the Rust gRPC SDK, `ListBuildercodePayoutsRequest` no longer derives `Copy` because it now holds a `String` — clone it where code relied on implicit copies. See [BuilderCodes](/sdk/typescript/buildercodes).

### Public whitelist submissions are closed

`sdk.whitelist.submit` (`POST /api/v1/whitelist`; gRPC `WhitelistService.SubmitWhitelist`) rejects every decoded request with `403` `FORBIDDEN` (`PERMISSION_DENIED` on gRPC): `"Public whitelist applications are closed."` The request fields are unchanged for client compatibility, and the legacy success response stays in the generated types but is no longer returned. Existing applicant records and administrative approvals are preserved, and a submission reads or writes no applicant data.

### Faucet quota is per wallet and application

The faucet's daily limit applies to each wallet on each application it signs in to, rather than to the wallet across all applications. `sdk.faucet.mint` (`POST /api/v1/faucet/mint`; gRPC `FaucetService.MintTokens`) enforces it per wallet and application, and `sdk.faucet.getInfo` (`GET /api/v1/faucet/info`; gRPC `FaucetService.GetFaucetInfo`) counts and lists only the calling application's requests. No wire shape changes. See [Faucet](/developers/faucet).

## Added

### `orders` frames for TWAP children and the makers they fill

A child order a TWAP parent places is an ordinary order on the `orders` channel: a taker slice sends `OrderPlaced`, its taker fill and, when the price band stops it short, an `OrderCancelled` for the remainder; a passive child sends `OrderPlaced` when it rests, a maker fill each time it trades, and `OrderCancelled` when it leaves the book (`terminalReason` `REPLACED` on a reprice or deadline sweep, `USER_REQUESTED` when the parent is cancelled or ends). Each resting order a TWAP slice fills receives its maker fill as it would from any other taker. Previously none of these frames were sent. Every TWAP-child frame and `orders` snapshot row carries `parentOrderId`, the same id `getOrder` returns; it is absent for any other order. `CommonOrderEventData` and `OrderSnapshotItem` gain optional `parentOrderId`, and the REST `Order` type now declares it. A resting order that a TWAP slice cancels — for self-trade prevention, or because it failed its risk re-check during the match — receives no `OrderCancelled` frame, so read its terminal state from REST. See [WebSockets](/reference/websockets).

## Fixed

### Resting orders are cancelled when a risk bucket enters liquidation

When a risk bucket breaches maintenance margin and enters `PendingLiquidation`, every one of its resting orders is cancelled, starting in the entry that records the transition — up to 150 there, with any remainder in consecutive entries sequenced immediately after it and nothing interleaved — whether the breach came from an oracle mark, a funding settlement, an auto-deleveraging haircut or a fill — and each sends an `OrderCancelled` frame with `terminalReason` `LIQUIDATION`. Previously those orders stayed on the book until the liquidation itself reached the bucket, and in that window another bucket's liquidation could fill them as makers and deepen the breach. See [Liquidations](/trading-mechanics/liquidations).

### First-use automatically funded sells are sized from their limit

An automatically funded `LIMIT` order on a new risk bucket is sized from its submitted limit price. When a `SELL` executes above that limit, admission tops the bucket up from the parent margin account, bounded by the parent's capacity, instead of leaving it short of initial margin. Previously the sizing read the public best bid, which could include the wallet's own orders that self-trade prevention would cancel, so otherwise affordable orders were refused. This applies to `ISOLATED` and `CROSS` risk buckets, and order-risk previews use the same admission path. Explicit `riskBucketCollateral` stays fee-capped, and unused fee funding is still returned only on `ISOLATED` buckets. See [Trade](/developers/trade).

### Closed positions no longer count a partial-close fee twice

`GET /api/v1/positions` and `GET /api/v1/positions/{position_id}` (gRPC `PositionsService.ListPositions`, `GetPosition`) no longer count a partial-close fee twice. With complete fee history, optional `cumFees` is the position's whole-life fee total — opening and reducing fees, application fees, liquidation fees and signed rebates — and a closed position's `netRealizedPnl` and `realizedRoe` deduct it once. Existing historical attribution errors are not repaired, and a closed position whose fee history is no longer retained keeps its closing-execution `netRealizedPnl` and `realizedRoe`. `feesPaid` remains closing-only and `exitPrice` remains the execution VWAP across all closes. No ledger charges change. See [Positions](/sdk/typescript/positions).

### Positions closed over many fills report lifetime figures

A closed position is served from its reducing executions whenever those executions reconcile against its stored `realizedPnl` to within one raw quote unit (0.000001). The check used to compare them exactly, so ordinary rounding noise pushed healthy positions onto the stored fallback. Affected positions now populate `exitPrice`, `netRealizedPnl`, `realizedRoe`, `fundingPaid` and `feesPaid` where they came back null, and `size` and `isolatedMargin` carry the lifetime closed quantity and allocated margin basis rather than the pre-close remainder. `realizedPnl` is unchanged. Because this is a read-path change, already-closed positions report the corrected values immediately.

## Upgrade

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

Existing TypeScript calls are source-compatible — method signatures are unchanged, and every new response field is optional. The Rust gRPC SDK has one source break: `ListBuildercodePayoutsRequest` no longer derives `Copy`, so code that reuses a moved request must `clone()` it. Four behaviours differ: `ConditionalOrderEventReason` has three more values, so an exhaustive `switch` needs cases for them; `fee` on user trades and `orders` fill frames includes the builder fee; `sdk.whitelist.submit` always fails with `403`; and the faucet quota is counted per application.
