@0xmonaco/core 1.0.75 → 1.0.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,10 +62,9 @@ export declare class BuildercodesAPIImpl extends BaseAPI implements Buildercodes
62
62
  /**
63
63
  * Claim accrued BuilderCodes payout balance into a trading balance.
64
64
  *
65
- * Throws 403 when the caller is refused — either BuilderCodes is not
66
- * enabled, or the session is a delegated agent. Delegated sessions are
67
- * refused before the feature flag is read, so a 403 there is permanent for
68
- * that session type rather than a rollout state.
65
+ * Throws 403 when the session is a delegated agent — permanent for that
66
+ * session type rather than a rollout state. No program switch gates the
67
+ * claim, so a balance already credited stays claimable.
69
68
  *
70
69
  * Throws 409 when the payout balance is insufficient for the requested
71
70
  * amount (including when the caller has never accrued a share).
@@ -140,12 +140,12 @@ export class BuildercodesAPIImpl extends BaseAPI {
140
140
  validate(ListBuildercodePayoutsParamsSchema, params);
141
141
  }
142
142
  const searchParams = new URLSearchParams();
143
- if (params?.page !== undefined) {
144
- searchParams.append("page", params.page.toString());
145
- }
146
143
  if (params?.pageSize !== undefined) {
147
144
  searchParams.append("pageSize", params.pageSize.toString());
148
145
  }
146
+ if (params?.pageToken !== undefined) {
147
+ searchParams.append("pageToken", params.pageToken);
148
+ }
149
149
  if (params?.kind !== undefined) {
150
150
  searchParams.append("kind", params.kind);
151
151
  }
@@ -175,10 +175,9 @@ export class BuildercodesAPIImpl extends BaseAPI {
175
175
  /**
176
176
  * Claim accrued BuilderCodes payout balance into a trading balance.
177
177
  *
178
- * Throws 403 when the caller is refused — either BuilderCodes is not
179
- * enabled, or the session is a delegated agent. Delegated sessions are
180
- * refused before the feature flag is read, so a 403 there is permanent for
181
- * that session type rather than a rollout state.
178
+ * Throws 403 when the session is a delegated agent — permanent for that
179
+ * session type rather than a rollout state. No program switch gates the
180
+ * claim, so a balance already credited stays claimable.
182
181
  *
183
182
  * Throws 409 when the payout balance is insufficient for the requested
184
183
  * amount (including when the caller has never accrued a share).
@@ -1,12 +1,14 @@
1
+ import { ListManagedMarketAssignmentsSchema, validate } from "@0xmonaco/types";
1
2
  import { BaseAPI } from "../base";
2
3
  /** Managed quote intents use the existing wallet session and never move funding. */
3
4
  export class ManagedMarketsAPIImpl extends BaseAPI {
4
5
  async listAssignments(request = {}) {
6
+ validate(ListManagedMarketAssignmentsSchema, request);
5
7
  const query = new URLSearchParams();
6
- if (request.page !== undefined)
7
- query.set("page", String(request.page));
8
8
  if (request.pageSize !== undefined)
9
9
  query.set("pageSize", String(request.pageSize));
10
+ if (request.pageToken !== undefined)
11
+ query.set("pageToken", request.pageToken);
10
12
  return this.makeAuthenticatedRequest(`/api/v1/managed-markets/assignments${query.size ? `?${query}` : ""}`);
11
13
  }
12
14
  async claimLease(launchId, request) {
@@ -47,8 +47,8 @@ export declare const perpRoutes: {
47
47
  readonly initiate: () => string;
48
48
  readonly byIndex: (withdrawalIndex: number) => string;
49
49
  readonly list: (params?: {
50
- page?: number;
51
50
  pageSize?: number;
51
+ pageToken?: string;
52
52
  }) => string;
53
53
  };
54
54
  readonly market: {
@@ -26,23 +26,54 @@ export declare function parseRawTradeEvent(raw: RawTradeEvent): TradeEvent;
26
26
  * Options for fetching trades
27
27
  */
28
28
  export interface GetTradesOptions {
29
- /** Page number (starts from 1, default: 1) */
30
- page?: number;
31
- /** Maximum number of records to return (default: 25, max: 100) */
29
+ /** Maximum number of records to return (default: 25, max: 1000) */
32
30
  pageSize?: number;
31
+ /**
32
+ * Cursor from a previous response's `nextPageToken`. Omit (or pass "") to
33
+ * start at the most recent trade.
34
+ */
35
+ pageToken?: string;
36
+ }
37
+ /**
38
+ * One page of a pair's trade feed.
39
+ *
40
+ * `nextPageToken` is empty exactly when the walk is finished — the server
41
+ * over-fetches one row to prove it — so a caller can stop on the empty token
42
+ * without a confirming extra request.
43
+ */
44
+ export interface GetTradesPage {
45
+ /** Trades in this page, newest first. */
46
+ trades: TradeEvent[];
47
+ /** Cursor to pass as `pageToken` for the next page; "" when exhausted. */
48
+ nextPageToken: string;
33
49
  }
34
50
  /**
35
51
  * Trades API for fetching historical trade data
36
52
  */
37
53
  export declare class TradesAPIImpl extends BaseAPI {
38
54
  /**
39
- * Get historical trades for a trading pair
55
+ * Get one page of historical trades for a trading pair.
56
+ *
57
+ * Cursor paged (0XM-2821): the page number was removed because `trades` is
58
+ * appended to continuously, so an offset silently repeated the newest trades
59
+ * as fills landed mid-walk. Start with no `pageToken` and follow
60
+ * `nextPageToken` until it comes back empty.
40
61
  *
41
62
  * @param tradingPairId - The trading pair UUID
42
- * @param options - Pagination options
43
- * @returns Array of TradeEvent records sorted by executedAt descending (newest first)
63
+ * @param options - Cursor pagination options
64
+ * @returns One page of TradeEvent records sorted by executedAt descending (newest first), plus the next cursor
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * let pageToken: string | undefined;
69
+ * do {
70
+ * const page = await sdk.trades.getTrades(pairId, { pageSize: 100, pageToken });
71
+ * handle(page.trades);
72
+ * pageToken = page.nextPageToken || undefined;
73
+ * } while (pageToken);
74
+ * ```
44
75
  */
45
- getTrades(tradingPairId: string, options?: GetTradesOptions): Promise<TradeEvent[]>;
76
+ getTrades(tradingPairId: string, options?: GetTradesOptions): Promise<GetTradesPage>;
46
77
  /**
47
78
  * Get a single trade by its UUID.
48
79
  *
@@ -1,3 +1,4 @@
1
+ import { GetTradesSchema, validate } from "@0xmonaco/types";
1
2
  import { BaseAPI } from "../base";
2
3
  import { perpRoutes } from "../perp";
3
4
  /**
@@ -22,23 +23,49 @@ export function parseRawTradeEvent(raw) {
22
23
  */
23
24
  export class TradesAPIImpl extends BaseAPI {
24
25
  /**
25
- * Get historical trades for a trading pair
26
+ * Get one page of historical trades for a trading pair.
27
+ *
28
+ * Cursor paged (0XM-2821): the page number was removed because `trades` is
29
+ * appended to continuously, so an offset silently repeated the newest trades
30
+ * as fills landed mid-walk. Start with no `pageToken` and follow
31
+ * `nextPageToken` until it comes back empty.
26
32
  *
27
33
  * @param tradingPairId - The trading pair UUID
28
- * @param options - Pagination options
29
- * @returns Array of TradeEvent records sorted by executedAt descending (newest first)
34
+ * @param options - Cursor pagination options
35
+ * @returns One page of TradeEvent records sorted by executedAt descending (newest first), plus the next cursor
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * let pageToken: string | undefined;
40
+ * do {
41
+ * const page = await sdk.trades.getTrades(pairId, { pageSize: 100, pageToken });
42
+ * handle(page.trades);
43
+ * pageToken = page.nextPageToken || undefined;
44
+ * } while (pageToken);
45
+ * ```
30
46
  */
31
47
  async getTrades(tradingPairId, options = {}) {
32
- const { page = 1 } = options;
33
- // Ensure pageSize is a positive number between 1 and 100, defaulting to 25
34
- const pageSize = options.pageSize != null && options.pageSize > 0 ? Math.min(options.pageSize, 100) : 25;
48
+ validate(GetTradesSchema, options);
35
49
  const params = new URLSearchParams();
36
- if (page > 1) {
37
- params.set("page", String(page));
50
+ // Only send what the caller set: the server owns the 25 default, so
51
+ // restating it here would pin the SDK to a value the API can move.
52
+ if (options.pageSize != null) {
53
+ params.set("pageSize", String(options.pageSize));
54
+ }
55
+ if (options.pageToken != null && options.pageToken !== "") {
56
+ params.set("pageToken", options.pageToken);
38
57
  }
39
- params.set("pageSize", String(pageSize));
40
- const response = await this.makePublicRequest(`/api/v1/trades/${encodeURIComponent(tradingPairId)}?${params.toString()}`);
41
- return response.trades.map(parseRawTradeEvent);
58
+ const query = params.toString();
59
+ const response = await this.makePublicRequest(`/api/v1/trades/${encodeURIComponent(tradingPairId)}${query === "" ? "" : `?${query}`}`);
60
+ return {
61
+ // `?? []` because an empty page omits `trades` entirely; without it the
62
+ // last page of a walk would throw instead of ending it.
63
+ trades: (response.trades ?? []).map(parseRawTradeEvent),
64
+ // Absent rather than "" on a wire that omits empty strings: either way the
65
+ // walk is finished, and a caller testing `nextPageToken || undefined`
66
+ // must not see `undefined` become a truthy string.
67
+ nextPageToken: response.nextPageToken ?? "",
68
+ };
42
69
  }
43
70
  /**
44
71
  * Get a single trade by its UUID.
@@ -399,6 +399,7 @@ function parseMarketStatsData(raw) {
399
399
  bestAskPrice: readOptionalString(data, "bestAskPrice"),
400
400
  openInterest: readOptionalString(data, "openInterest"),
401
401
  openInterestLimit: readOptionalString(data, "openInterestLimit"),
402
+ openInterestHeadroom: readOptionalString(data, "openInterestHeadroom"),
402
403
  lastTradePrice: readOptionalString(data, "lastTradePrice"),
403
404
  dailyBaseTokenVolume: readOptionalString(data, "dailyBaseTokenVolume"),
404
405
  dailyQuoteTokenVolume: readOptionalString(data, "dailyQuoteTokenVolume"),
@@ -413,6 +414,11 @@ function parseMarketStatsData(raw) {
413
414
  baseInterestRate: readOptionalString(data, "baseInterestRate"),
414
415
  fundingClampSmall: readOptionalString(data, "fundingClampSmall"),
415
416
  fundingClampBig: readOptionalString(data, "fundingClampBig"),
417
+ // Lenient like the summary's marketStatus: an unrecognized value passes
418
+ // through rather than dropping the frame.
419
+ marketStatus: readOptionalString(data, "marketStatus"),
420
+ fundingIntervalSeconds: readOptionalNumber(data, "fundingIntervalSeconds"),
421
+ lastFundingTime: readOptionalNumber(data, "lastFundingTime"),
416
422
  };
417
423
  }
418
424
  function parseMarketStatsEvent(rawData) {
@@ -448,6 +454,10 @@ function parseMarketStatsSummary(raw) {
448
454
  // marketStatus stays lenient (read as string, not a strict enum) so an
449
455
  // unrecognized status value never drops an otherwise-valid summary row.
450
456
  marketStatus: readString(data, "marketStatus"),
457
+ indexPrice: readOptionalString(data, "indexPrice"),
458
+ fundingRate: readOptionalString(data, "fundingRate"),
459
+ premium: readOptionalString(data, "premium"),
460
+ openInterestNotional: readOptionalString(data, "openInterestNotional"),
451
461
  };
452
462
  }
453
463
  function parseMarketStatsAllEvent(rawData) {
@@ -490,6 +500,17 @@ function parseInstrumentEventData(raw) {
490
500
  // non-string value still throws.
491
501
  baseIconUrl: readOptionalString(data, "baseIconUrl") ?? null,
492
502
  quoteIconUrl: readOptionalString(data, "quoteIconUrl") ?? null,
503
+ // Asset identity and minLeverage: a server that predates them omits the
504
+ // keys, so absent reads as `undefined` and never as a made-up `0` or `""`.
505
+ baseAssetId: readOptionalString(data, "baseAssetId"),
506
+ quoteAssetId: readOptionalString(data, "quoteAssetId"),
507
+ baseToken: readOptionalString(data, "baseToken"),
508
+ quoteToken: readOptionalString(data, "quoteToken"),
509
+ baseAssetName: readOptionalString(data, "baseAssetName"),
510
+ quoteAssetName: readOptionalString(data, "quoteAssetName"),
511
+ baseDecimals: readOptionalNumber(data, "baseDecimals"),
512
+ quoteDecimals: readOptionalNumber(data, "quoteDecimals"),
513
+ minLeverage: readOptionalString(data, "minLeverage"),
493
514
  maxLeverage: readOptionalString(data, "maxLeverage"),
494
515
  initialMarginRate: readOptionalString(data, "initialMarginRate"),
495
516
  maintenanceMarginRate: readOptionalString(data, "maintenanceMarginRate"),
@@ -1700,8 +1721,9 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1700
1721
  * markets, or pass one to filter. Every frame carries the market's FULL
1701
1722
  * current config as a terminal-state snapshot (never an additive delta);
1702
1723
  * `changedFields` names what the mutation touched. A subscribe-time snapshot
1703
- * of the current active-pair list arrives before the live diffs; a
1704
- * subscriber joining a channel this client already holds is replayed the
1724
+ * of every listed market arrives before the live diffs, inactive markets
1725
+ * included and flagged `isActive: false` (filter on `isActive` for the
1726
+ * tradable set); a subscriber joining a channel this client already holds is replayed the
1705
1727
  * current baseline from a local cache instead (the server snapshots only
1706
1728
  * genuinely new wire subscriptions). Detected broadcast lag closes the connection
1707
1729
  * with 1013; a new wire subscription provides a fresh baseline.
@@ -1744,8 +1766,8 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1744
1766
  }
1745
1767
  },
1746
1768
  // The subscribe-time baseline arrives as one Snapshot frame whose data is
1747
- // a flat InstrumentEventData[] (a `listing` per active market, no
1748
- // per-item envelope).
1769
+ // a flat InstrumentEventData[] (a `listing` per market, inactive ones
1770
+ // flagged `isActive: false`, no per-item envelope).
1749
1771
  //
1750
1772
  // Where it goes depends on whether the caller opted in. With
1751
1773
  // `onSnapshot`, the rows are handed over as one array and the event
@@ -1757,7 +1779,7 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1757
1779
  // asked would be a silent behaviour break.
1758
1780
  //
1759
1781
  // Either way the local cache is replaced wholesale rather than upserted,
1760
- // so markets absent from the snapshot (delisted while disconnected) do
1782
+ // so markets absent from the snapshot (no longer listed) do
1761
1783
  // not linger.
1762
1784
  snapshotFrameHandler("instrument", parseInstrumentEventData, (items) => {
1763
1785
  const events = items.map((item) => ({ tradingPairId: item.tradingPairId, data: item }));
@@ -1801,18 +1823,13 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
1801
1823
  // follows the same delivery contract: one array to `onSnapshot`
1802
1824
  // when opted in, per-market events otherwise.
1803
1825
  //
1804
- // The two forms carry deliberately different sets. The ARRAY is
1805
- // filtered to active markets, because that is what a real snapshot
1806
- // is — the server enumerates active pairs, while this cache also
1807
- // holds the delistings it has seen live — and a consumer replaces
1808
- // its market set from the array, so a delisted row there would
1809
- // resurrect a market that is gone. The per-market EVENTS are not
1810
- // filtered: a delisting is a legitimate event, it is what tells a
1811
- // legacy subscriber the market went inactive, and dropping it would
1812
- // change a caller that never opted into any of this.
1826
+ // Both forms carry the cache's full set, delistings it has seen live
1827
+ // included, because that is what a real snapshot is: the server
1828
+ // enumerates inactive markets too, each flagged `isActive: false`.
1829
+ // A consumer wanting the tradable set filters on `isActive`.
1813
1830
  if (onSnapshot) {
1814
1831
  try {
1815
- onSnapshot(replay.filter((event) => event.data.isActive).map((event) => event.data));
1832
+ onSnapshot(replay.map((event) => event.data));
1816
1833
  }
1817
1834
  catch (err) {
1818
1835
  console.error("WebSocket: Error processing instrument baseline replay", err);
@@ -1,3 +1,4 @@
1
+ import { ListPendingWithdrawalsSchema, validate } from "@0xmonaco/types";
1
2
  import { BaseAPI } from "../base";
2
3
  import { perpRoutes } from "../perp";
3
4
  /**
@@ -30,6 +31,7 @@ export class WithdrawalsAPIImpl extends BaseAPI {
30
31
  async listPendingWithdrawals(params) {
31
32
  // The gateway serves camelCase (the REST wire format), which matches the
32
33
  // public surface, so the response is returned directly with no remapping.
33
- return this.makeAuthenticatedRequest(perpRoutes.withdrawals.list({ page: params?.page, pageSize: params?.pageSize }));
34
+ validate(ListPendingWithdrawalsSchema, params ?? {});
35
+ return this.makeAuthenticatedRequest(perpRoutes.withdrawals.list({ pageSize: params?.pageSize, pageToken: params?.pageToken }));
34
36
  }
35
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmonaco/core",
3
- "version": "1.0.75",
3
+ "version": "1.0.77",
4
4
  "type": "module",
5
5
  "homepage": "https://docs.0xmonaco.com/sdk/typescript",
6
6
  "main": "./dist/index.js",
@@ -19,8 +19,8 @@
19
19
  "viem": "^2.45.2"
20
20
  },
21
21
  "dependencies": {
22
- "@0xmonaco/contracts": "1.0.75",
23
- "@0xmonaco/types": "1.0.75",
22
+ "@0xmonaco/contracts": "1.0.77",
23
+ "@0xmonaco/types": "1.0.77",
24
24
  "@noble/curves": "^1.9.1",
25
25
  "@noble/hashes": "^2.4.0",
26
26
  "http-status-codes": "^2.3.0"