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

# Monaco Protocol SDK v1.0.65

This release bounds the page-number item counts on seven more listing reads and fills two WebSocket gaps. `sdk.profile.getUserTrades`, `sdk.positions.listPositions` / `listPositionHistory`, the margin-account movement reads, and `sdk.trading.listConditionalOrders` / `listTwapOrders` now cap the legacy page-number `total` (and `getUserTrades`'s `totalPages`) at each listing's **pagination reach** — exact up to `pageSize` × 10,000 rows and saturating there — so a caller with more history than page-number mode can page through reads the cap instead of driving an unbounded count, and `page` above 10,000 is now rejected. This is the **saturating** shape (no new field, unlike v1.0.64's `totalCapped` on order history): the response schema is unchanged, only the count **values** move, and only for callers above the reach. Of the seven, only `getUserTrades` also offers cursor (`pageToken`) pagination — its SDK default, unchanged and still reporting no totals; the other six are page-number-only (`page` / `pageSize`). On the socket, `sdk.ws.twapOrders` now delivers a subscribe-time snapshot the way the other stateful channels do, and `sdk.ws.instruments` now carries each market's `baseIconUrl` / `quoteIconUrl`. The instrument icons ride the existing frame handler; the TWAP snapshot — like every subscribe-time baseline — arrives through the optional `onSnapshot` callback, so a subscription already passing one receives it with no code change and one that omits it should add an `onSnapshot` handler to opt in.

## Changed

### Page-number listing counts are bounded by their pagination reach

Seven more listing reads now bound the legacy page-number count instead of counting a caller's whole matching history on every page render:

* `sdk.profile.getUserTrades` (`GET /api/v1/accounts/trades`; gRPC `AccountsService.GetUserTrades` and `TradesService.ListUserTrades`)
* `sdk.positions.listPositions` (`GET /api/v1/positions`) and `sdk.positions.listPositionHistory` (`GET /api/v1/positions/history`)
* `sdk.marginAccounts.getMarginAccountMovements` (`GET /api/v1/margin/accounts/{marginAccountId}/movements`) and `sdk.marginAccounts.getParentMarginAccountMovements` (`GET /api/v1/margin/parent-margin-account/movements`)
* `sdk.trading.listConditionalOrders` (`GET /api/v1/orders/conditional`) and `sdk.trading.listTwapOrders` (`GET /api/v1/orders/twap`)

In legacy page-number mode the response `total` is now **exact up to `pageSize` × 10,000 matching rows and saturates there**; `getUserTrades` bounds `totalPages` the same way (exact up to 10,000, the last page page-number mode can reach). A caller with more matching rows than page-number mode can page through reads the capped figure rather than its lifetime total. `page` is capped at 10,000: a larger page is rejected as invalid input (`page must be <= 10000`) instead of fetching rows past the reported last page.

`getUserTrades` is the only one of the seven with a cursor (`pageToken`) mode — its SDK default, unchanged: it still walks full history (hot and archived merged) and reports no totals (`total` / `totalPages` / `page` are `0`), and its page-number totals stay deprecated in favour of that cursor; build "load more" UIs on its `nextPageToken`. The other six are page-number-only — `page` / `pageSize`, no `pageToken` — and `total` is simply the count they report (it is not deprecated). The response **schema does not change** on any of them — every field keeps its type — so there is nothing to adopt. The count **values** change only for a page-number caller above the reach: it now reads the saturated cap where it previously read an exact lifetime count. A page-number loop that stops at `page >= totalPages` keeps terminating; only code that reads `total` as an exact lifetime figure should treat a saturated value as "at least this many".

See [Trade history](/sdk/typescript/trades), [Positions](/sdk/typescript/positions), [Margin accounts](/sdk/typescript/margin-accounts), and [the API reference](/api-reference).

## Fixed

### The `twapOrders` channel delivers a subscribe-time snapshot

`sdk.ws.twapOrders(handler, tradingPairId?, onSnapshot)` now receives a subscribe-time snapshot ahead of the live frames, the way the other stateful channels do: one `TwapOrderEventData` row per owned **non-terminal** (`PENDING` / `ACTIVE`) TWAP parent, optionally scoped to the subscription's trading pair, each row the same shape as a live `twap_order_update` with `reason: "snapshot"`. Previously the server sent no TWAP snapshot, so the `onSnapshot` callback was inert and a baseline needed a REST read. The SDK plumbing was already in place, so the baseline reaches only subscriptions that pass an `onSnapshot` handler: a caller already passing one receives it with no code change, and a caller subscribing as `sdk.ws.twapOrders(handler)` should add an `onSnapshot` handler to opt in. An empty baseline arrives as `onSnapshot([])`; if the read is unavailable the subscription surfaces `SNAPSHOT_UNAVAILABLE` and stays active while live diffs keep flowing.

### The `instruments` channel carries base and quote asset icon URLs

`sdk.ws.instruments(handler, tradingPairId?, onSnapshot)` now surfaces `baseIconUrl` and `quoteIconUrl` (`string | null`) on each parsed `InstrumentEventData`, on both the subscribe-time snapshot and the live frames. The server sends each key present on every market (spot and perp) — an explicit `null` when that asset has no configured icon, never a synthesized URL — and the parser reads it tolerantly, mapping a missing key to `null` so a frame is never dropped for want of it. `InstrumentEventData` gains the two fields as optional (`baseIconUrl?` / `quoteIconUrl?`), so the addition is non-breaking for code that constructs or mocks the shape. A client can now join a position's `tradingPairId` to the instrument row and render both icons without a REST read.

## Upgrade

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

The response schemas are additive-safe — no signature changes to adopt. Two behaviours differ: a page-number caller with more than `pageSize` × 10,000 matching rows on the seven bounded listings now reads a saturated `total` (treat it as "at least this many"), and the `twapOrders` and `instruments` WebSocket channels now deliver data — a TWAP snapshot and asset icon URLs — that clients previously fetched over REST.
