@0xmonaco/core 1.0.28 → 1.0.31

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.
@@ -16,6 +16,7 @@ export * from "./pitpass";
16
16
  export * from "./portfolio";
17
17
  export * from "./positions";
18
18
  export * from "./profile";
19
+ export * from "./pulse";
19
20
  export * from "./sub-accounts";
20
21
  export * from "./trades";
21
22
  export * from "./trading";
package/dist/api/index.js CHANGED
@@ -16,6 +16,7 @@ export * from "./pitpass";
16
16
  export * from "./portfolio";
17
17
  export * from "./positions";
18
18
  export * from "./profile";
19
+ export * from "./pulse";
19
20
  export * from "./sub-accounts";
20
21
  export * from "./trades";
21
22
  export * from "./trading";
@@ -1,4 +1,4 @@
1
- import type { Candlestick, FundingState, GetCandlesticksParams, GetScreenerParams, GetScreenerResponse, GetTradingPairsParams, GetTradingPairsResponse, IndexPrice, Interval, ListFundingHistoryParams, ListFundingHistoryResponse, MarketAPI, MarketMetadata, MarketStats, MarkPrice, OpenInterest, PerpMarketConfig, PerpMarketSummary, TradingMode, TradingPair } from "@0xmonaco/types";
1
+ import type { Candlestick, FundingState, GetCandlesticksParams, GetScreenerParams, GetScreenerResponse, GetTradingPairsParams, GetTradingPairsResponse, IndexPrice, Interval, ListAllFundingHistoryParams, ListAllFundingHistoryResponse, ListFundingHistoryParams, ListFundingHistoryResponse, MarketAPI, MarketMetadata, MarketStats, MarkPrice, OpenInterest, PerpMarketConfig, PerpMarketSummary, TradingMode, TradingPair } from "@0xmonaco/types";
2
2
  import { BaseAPI } from "../base";
3
3
  /**
4
4
  * Market API Implementation
@@ -17,6 +17,7 @@ export declare class MarketAPIImpl extends BaseAPI implements MarketAPI {
17
17
  getIndexPrice(tradingPairId: string): Promise<IndexPrice>;
18
18
  getFundingState(tradingPairId: string): Promise<FundingState>;
19
19
  listFundingHistory(tradingPairId: string, params?: ListFundingHistoryParams): Promise<ListFundingHistoryResponse>;
20
+ listAllFundingHistory(params?: ListAllFundingHistoryParams): Promise<ListAllFundingHistoryResponse>;
20
21
  getOpenInterest(tradingPairId: string): Promise<OpenInterest>;
21
22
  getScreener(params?: GetScreenerParams): Promise<GetScreenerResponse>;
22
23
  getMarketStats(): Promise<MarketStats>;
@@ -100,6 +100,9 @@ export class MarketAPIImpl extends BaseAPI {
100
100
  validate(GetMarketMetadataSchema, { tradingPairId });
101
101
  return await this.makePublicRequest(perpRoutes.market.listFundingHistory(tradingPairId, params));
102
102
  }
103
+ async listAllFundingHistory(params) {
104
+ return await this.makePublicRequest(perpRoutes.market.listAllFundingHistory(params));
105
+ }
103
106
  async getOpenInterest(tradingPairId) {
104
107
  validate(GetMarketMetadataSchema, { tradingPairId });
105
108
  return await this.makePublicRequest(perpRoutes.market.getOpenInterest(tradingPairId));
@@ -67,6 +67,14 @@ export declare const perpRoutes: {
67
67
  endTime?: string;
68
68
  page?: number;
69
69
  pageSize?: number;
70
+ orderBy?: string;
71
+ }) => string;
72
+ readonly listAllFundingHistory: (params?: {
73
+ startTime?: string;
74
+ endTime?: string;
75
+ page?: number;
76
+ pageSize?: number;
77
+ orderBy?: string;
70
78
  }) => string;
71
79
  readonly getOpenInterest: (tradingPairId: string) => string;
72
80
  readonly getScreener: (params?: {
@@ -52,6 +52,7 @@ export const perpRoutes = {
52
52
  getIndexPrice: (tradingPairId) => `${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/index-price`,
53
53
  getFundingState: (tradingPairId) => `${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/funding`,
54
54
  listFundingHistory: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/funding/history`, params),
55
+ listAllFundingHistory: (params) => withQuery(`${API_V1}/market/funding/history`, params),
55
56
  getOpenInterest: (tradingPairId) => `${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/open-interest`,
56
57
  getScreener: (params) => withQuery(`${API_V1}/market/screener`, params),
57
58
  getMarketStats: () => `${API_V1}/market/stats`,
@@ -169,30 +169,65 @@ export declare class ProfileAPIImpl extends BaseAPI implements ProfileAPI {
169
169
  * Fetches the user's executed trades from the /api/v1/accounts/trades endpoint.
170
170
  * Requires a valid access token to be set.
171
171
  *
172
+ * When neither `page` nor `pageToken` is passed, the SDK drives cursor (pageToken)
173
+ * pagination: it starts a cursor walk from the newest row and the response's
174
+ * `nextPageToken` resumes it. Cursor responses carry no exact totals
175
+ * (`total`/`page`/`totalPages` are 0).
176
+ *
172
177
  * @param params - Optional query parameters for pagination and filtering
173
- * @param params.page - Page number (starts from 1, default: 1)
174
- * @param params.pageSize - Number of items per page (default: 20, max: 100)
178
+ * @param params.page - Deprecated: page number for legacy offset pagination (starts
179
+ * from 1). Passing it selects legacy page-number mode, which only sees recent (hot)
180
+ * history and populates `total`/`totalPages`. Use cursor pagination (`pageToken`)
181
+ * instead.
182
+ * @param params.pageSize - Number of items per page (default: 20; max 100
183
+ * in page-number mode, up to 1000 when pageToken is present)
175
184
  * @param params.tradingPairId - Filter by trading pair ID (UUID)
176
- * @param params.pageToken - Pagination cursor (optional): omit for legacy page-number
177
- * pagination; pass `""` to start a cursor walk from the newest row; pass a previous
178
- * response's `nextPageToken` to resume. Any cursor-walk value (`""` or non-empty)
179
- * ignores `page` and covers full trade history (hot and archived rows merged), unlike
180
- * page-number mode.
185
+ * @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
186
+ * the newest row; pass a previous response's `nextPageToken` to resume. Any
187
+ * cursor-walk value (`""` or non-empty) ignores `page` and covers full trade history
188
+ * (hot and archived rows merged), unlike page-number mode. Omitting both `page` and
189
+ * `pageToken` starts a cursor walk (`pageToken=""`).
181
190
  * @returns Promise resolving to paginated trades response
182
191
  * @throws {ValidationError} When the provided params fail client-side validation
183
192
  * @throws {APIError} When the request fails or user is not authenticated
184
193
  *
185
194
  * @example
186
195
  * ```typescript
187
- * // Get first page of trades
188
- * const trades = await profileAPI.getUserTrades();
189
- * console.log(`Total trades: ${trades.total}`);
196
+ * // Walk full trade history with cursor pagination (the default mode)
197
+ * let pageToken: string | undefined;
198
+ * do {
199
+ * const res = await profileAPI.getUserTrades({ pageToken });
200
+ * handle(res.trades);
201
+ * pageToken = res.nextPageToken;
202
+ * } while (pageToken);
190
203
  *
191
204
  * // Filter by trading pair
192
205
  * const pairTrades = await profileAPI.getUserTrades({ tradingPairId: "550e8400-e29b-41d4-a716-446655440000" });
193
206
  * ```
194
207
  */
195
208
  getUserTrades(params?: GetUserTradesParams): Promise<GetUserTradesResponse>;
209
+ /**
210
+ * Walks the user's full trade history with cursor pagination, yielding one
211
+ * trade at a time.
212
+ *
213
+ * Starts a cursor walk (`pageToken: ""`) and follows each response's
214
+ * `nextPageToken` until the server proves exhaustion (a page with zero rows
215
+ * and an empty token). Covers full trade history — hot and archived rows
216
+ * merged — unlike the deprecated page-number mode.
217
+ *
218
+ * @param params - Optional filters and page size; `page`/`pageToken` are
219
+ * managed by the iterator and cannot be passed.
220
+ * @returns Async generator yielding trades newest-first
221
+ * @throws {APIError} When any underlying request fails
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * for await (const trade of profileAPI.iterateUserTrades()) {
226
+ * console.log(trade.tradeId);
227
+ * }
228
+ * ```
229
+ */
230
+ iterateUserTrades(params?: Omit<GetUserTradesParams, "page" | "pageToken">): AsyncGenerator<GetUserTradesResponse["trades"][number], void, undefined>;
196
231
  /**
197
232
  * List the current user's funding payment history with pagination and filters.
198
233
  *
@@ -220,24 +220,37 @@ export class ProfileAPIImpl extends BaseAPI {
220
220
  * Fetches the user's executed trades from the /api/v1/accounts/trades endpoint.
221
221
  * Requires a valid access token to be set.
222
222
  *
223
+ * When neither `page` nor `pageToken` is passed, the SDK drives cursor (pageToken)
224
+ * pagination: it starts a cursor walk from the newest row and the response's
225
+ * `nextPageToken` resumes it. Cursor responses carry no exact totals
226
+ * (`total`/`page`/`totalPages` are 0).
227
+ *
223
228
  * @param params - Optional query parameters for pagination and filtering
224
- * @param params.page - Page number (starts from 1, default: 1)
225
- * @param params.pageSize - Number of items per page (default: 20, max: 100)
229
+ * @param params.page - Deprecated: page number for legacy offset pagination (starts
230
+ * from 1). Passing it selects legacy page-number mode, which only sees recent (hot)
231
+ * history and populates `total`/`totalPages`. Use cursor pagination (`pageToken`)
232
+ * instead.
233
+ * @param params.pageSize - Number of items per page (default: 20; max 100
234
+ * in page-number mode, up to 1000 when pageToken is present)
226
235
  * @param params.tradingPairId - Filter by trading pair ID (UUID)
227
- * @param params.pageToken - Pagination cursor (optional): omit for legacy page-number
228
- * pagination; pass `""` to start a cursor walk from the newest row; pass a previous
229
- * response's `nextPageToken` to resume. Any cursor-walk value (`""` or non-empty)
230
- * ignores `page` and covers full trade history (hot and archived rows merged), unlike
231
- * page-number mode.
236
+ * @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
237
+ * the newest row; pass a previous response's `nextPageToken` to resume. Any
238
+ * cursor-walk value (`""` or non-empty) ignores `page` and covers full trade history
239
+ * (hot and archived rows merged), unlike page-number mode. Omitting both `page` and
240
+ * `pageToken` starts a cursor walk (`pageToken=""`).
232
241
  * @returns Promise resolving to paginated trades response
233
242
  * @throws {ValidationError} When the provided params fail client-side validation
234
243
  * @throws {APIError} When the request fails or user is not authenticated
235
244
  *
236
245
  * @example
237
246
  * ```typescript
238
- * // Get first page of trades
239
- * const trades = await profileAPI.getUserTrades();
240
- * console.log(`Total trades: ${trades.total}`);
247
+ * // Walk full trade history with cursor pagination (the default mode)
248
+ * let pageToken: string | undefined;
249
+ * do {
250
+ * const res = await profileAPI.getUserTrades({ pageToken });
251
+ * handle(res.trades);
252
+ * pageToken = res.nextPageToken;
253
+ * } while (pageToken);
241
254
  *
242
255
  * // Filter by trading pair
243
256
  * const pairTrades = await profileAPI.getUserTrades({ tradingPairId: "550e8400-e29b-41d4-a716-446655440000" });
@@ -247,8 +260,11 @@ export class ProfileAPIImpl extends BaseAPI {
247
260
  if (params) {
248
261
  validate(GetUserTradesSchema, params);
249
262
  }
263
+ // Legacy offset mode only when the caller explicitly asked for a page and
264
+ // no cursor was given; everything else drives cursor (pageToken) mode.
265
+ const legacyOffsetMode = params?.page !== undefined && params?.pageToken === undefined;
250
266
  const searchParams = new URLSearchParams();
251
- if (params?.page !== undefined) {
267
+ if (legacyOffsetMode && params?.page !== undefined) {
252
268
  searchParams.append("page", params.page.toString());
253
269
  }
254
270
  if (params?.pageSize !== undefined) {
@@ -257,13 +273,53 @@ export class ProfileAPIImpl extends BaseAPI {
257
273
  if (params?.tradingPairId !== undefined) {
258
274
  searchParams.append("tradingPairId", params.tradingPairId);
259
275
  }
260
- if (params?.pageToken !== undefined) {
261
- searchParams.append("pageToken", params.pageToken);
276
+ // Cursor mode selects itself by the *presence* of `pageToken` on the wire,
277
+ // even when it is the empty string (the documented way to start a walk),
278
+ // so it must be sent explicitly rather than dropped like a falsy value.
279
+ // When the caller gave neither `page` nor `pageToken`, default to starting
280
+ // a cursor walk (`pageToken=""`).
281
+ if (!legacyOffsetMode) {
282
+ searchParams.append("pageToken", params?.pageToken ?? "");
262
283
  }
263
284
  const queryString = searchParams.toString();
264
285
  const url = queryString ? `/api/v1/accounts/trades?${queryString}` : "/api/v1/accounts/trades";
265
286
  return await this.makeAuthenticatedRequest(url);
266
287
  }
288
+ /**
289
+ * Walks the user's full trade history with cursor pagination, yielding one
290
+ * trade at a time.
291
+ *
292
+ * Starts a cursor walk (`pageToken: ""`) and follows each response's
293
+ * `nextPageToken` until the server proves exhaustion (a page with zero rows
294
+ * and an empty token). Covers full trade history — hot and archived rows
295
+ * merged — unlike the deprecated page-number mode.
296
+ *
297
+ * @param params - Optional filters and page size; `page`/`pageToken` are
298
+ * managed by the iterator and cannot be passed.
299
+ * @returns Async generator yielding trades newest-first
300
+ * @throws {APIError} When any underlying request fails
301
+ *
302
+ * @example
303
+ * ```typescript
304
+ * for await (const trade of profileAPI.iterateUserTrades()) {
305
+ * console.log(trade.tradeId);
306
+ * }
307
+ * ```
308
+ */
309
+ async *iterateUserTrades(params) {
310
+ let pageToken = "";
311
+ // A non-empty token never guarantees further results (AIP-158 "maybe
312
+ // more"): keep following it until a response returns zero rows and an
313
+ // empty token, the sole proof the walk is exhausted.
314
+ for (;;) {
315
+ const response = await this.getUserTrades({ ...params, pageToken });
316
+ yield* response.trades;
317
+ if (!response.nextPageToken) {
318
+ return;
319
+ }
320
+ pageToken = response.nextPageToken;
321
+ }
322
+ }
267
323
  /**
268
324
  * List the current user's funding payment history with pagination and filters.
269
325
  *
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pulse API Implementation
3
+ *
4
+ * Read-only access to the market-pulse news feed: AI-synthesized, per-asset
5
+ * headlines with sentiment tags, served from the backend's hourly-refreshed
6
+ * cache. Public — no authentication required.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const pulse = await sdk.pulse.getPulse();
11
+ * for (const item of pulse.items) {
12
+ * console.log(`[${item.sentiment}] ${item.asset}: ${item.summary}`);
13
+ * }
14
+ * ```
15
+ */
16
+ import type { GetPulseResponse, PulseAPI } from "@0xmonaco/types";
17
+ import { BaseAPI } from "../base";
18
+ export declare class PulseAPIImpl extends BaseAPI implements PulseAPI {
19
+ /**
20
+ * Get the latest market pulse snapshot (public, no auth headers).
21
+ * Returns 503 while the backend cache is cold.
22
+ */
23
+ getPulse(): Promise<GetPulseResponse>;
24
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Pulse API Implementation
3
+ *
4
+ * Read-only access to the market-pulse news feed: AI-synthesized, per-asset
5
+ * headlines with sentiment tags, served from the backend's hourly-refreshed
6
+ * cache. Public — no authentication required.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const pulse = await sdk.pulse.getPulse();
11
+ * for (const item of pulse.items) {
12
+ * console.log(`[${item.sentiment}] ${item.asset}: ${item.summary}`);
13
+ * }
14
+ * ```
15
+ */
16
+ import { BaseAPI } from "../base";
17
+ export class PulseAPIImpl extends BaseAPI {
18
+ /**
19
+ * Get the latest market pulse snapshot (public, no auth headers).
20
+ * Returns 503 while the backend cache is cold.
21
+ */
22
+ async getPulse() {
23
+ return await this.makePublicRequest("/api/v1/pulse", {
24
+ method: "GET",
25
+ });
26
+ }
27
+ }
@@ -0,0 +1 @@
1
+ export { PulseAPIImpl } from "./api";
@@ -0,0 +1 @@
1
+ export { PulseAPIImpl } from "./api";
@@ -260,40 +260,66 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
260
260
  */
261
261
  batchReplace(orders: BatchReplaceOrderParams[]): Promise<BatchReplaceOrdersResponse>;
262
262
  /**
263
- * Gets paginated orders based on query parameters with automatic pagination.
263
+ * Gets orders based on query parameters, cursor-paginated by default.
264
264
  *
265
265
  * Retrieves orders with optional filtering by status, trading pair, and pagination.
266
- * Pagination parameters are always included with sensible defaults for consistent API behavior.
266
+ * When neither `page` nor `pageToken` is passed, the SDK drives cursor (pageToken)
267
+ * pagination: it starts a cursor walk from the newest (or oldest, for
268
+ * `orderBy: "ASC"`) row and the response's `nextPageToken` resumes it. Cursor
269
+ * responses carry no exact totals (`total`/`page`/`totalPages` are 0).
267
270
  *
268
271
  * @param params - Query parameters for filtering orders
269
- * @param params.status - Filter by order status (e.g., "SUBMITTED", "FILLED") (optional)
272
+ * @param params.status - Filter by order status (e.g., "SUBMITTED", "FILLED"), or by
273
+ * any of several statuses at once by passing an array (e.g., ["SUBMITTED", "PARTIALLY_FILLED"]) (optional)
270
274
  * @param params.tradingPairId - Filter by trading pair UUID (optional)
271
- * @param params.page - Page number for pagination (defaults to 1, must be > 0)
272
- * @param params.pageSize - Number of orders per page (defaults to 10, max 100, must be > 0)
273
- * @param params.pageToken - Pagination cursor (optional): omit for legacy page-number
274
- * pagination; pass `""` to start a cursor walk from the newest (or oldest, for
275
- * `orderBy: "ASC"`) row; pass a previous response's `nextPageToken` to resume. Any
276
- * cursor-walk value (`""` or non-empty) ignores `page` and covers full order history
277
- * (hot and archived rows merged), unlike page-number mode.
275
+ * @param params.page - Deprecated: page number for legacy offset pagination (must be > 0).
276
+ * Passing it selects legacy page-number mode, which only sees recent (hot) history and
277
+ * populates `total`/`totalPages`. Use cursor pagination (`pageToken`) instead.
278
+ * @param params.pageSize - Number of orders per page (defaults to 10, must be > 0; max 100
279
+ * in page-number mode, up to 1000 when pageToken is present)
280
+ * @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
281
+ * the newest (or oldest, for `orderBy: "ASC"`) row; pass a previous response's
282
+ * `nextPageToken` to resume. Any cursor-walk value (`""` or non-empty) ignores `page`
283
+ * and covers full order history (hot and archived rows merged), unlike page-number
284
+ * mode. Omitting both `page` and `pageToken` starts a cursor walk (`pageToken=""`).
278
285
  * @returns Promise resolving to GetPaginatedOrdersResponse with orders and pagination info
279
286
  * @throws {APIError} When API communication fails
280
287
  *
281
288
  * @example
282
289
  * ```typescript
283
- * // Get submitted orders for a specific trading pair with custom pagination
284
- * const orders = await tradingAPI.getPaginatedOrders({
285
- * status: "SUBMITTED",
286
- * tradingPairId: "456e7890-e12b-12d3-a456-426614174000",
287
- * page: 1,
288
- * pageSize: 20
289
- * });
290
- * console.log(`Found ${orders.total} orders, showing page ${orders.page}`);
291
- *
292
- * // Get all orders with default pagination (page=1, pageSize=10)
293
- * const allOrders = await tradingAPI.getPaginatedOrders();
290
+ * // Walk full order history with cursor pagination (the default mode)
291
+ * let pageToken: string | undefined;
292
+ * do {
293
+ * const res = await tradingAPI.getPaginatedOrders({ status: "FILLED", pageToken });
294
+ * handle(res.orders);
295
+ * pageToken = res.nextPageToken;
296
+ * } while (pageToken);
294
297
  * ```
295
298
  */
296
299
  getPaginatedOrders(params?: GetPaginatedOrdersParams): Promise<GetPaginatedOrdersResponse>;
300
+ /**
301
+ * Walks the user's full order history with cursor pagination, yielding one
302
+ * order at a time.
303
+ *
304
+ * Starts a cursor walk (`pageToken: ""`) and follows each response's
305
+ * `nextPageToken` until the server proves exhaustion (a page with zero rows
306
+ * and an empty token). Covers full order history — hot and archived rows
307
+ * merged — unlike the deprecated page-number mode.
308
+ *
309
+ * @param params - Optional filters and page size; `page`/`pageToken` are
310
+ * managed by the iterator and cannot be passed.
311
+ * @returns Async generator yielding orders newest-first (or oldest-first for
312
+ * `orderBy: "ASC"`)
313
+ * @throws {APIError} When any underlying request fails
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * for await (const order of tradingAPI.iterateOrders({ status: "FILLED" })) {
318
+ * console.log(order.id);
319
+ * }
320
+ * ```
321
+ */
322
+ iterateOrders(params?: Omit<GetPaginatedOrdersParams, "page" | "pageToken">): AsyncGenerator<GetPaginatedOrdersResponse["orders"][number], void, undefined>;
297
323
  /**
298
324
  * Gets a single order by its ID.
299
325
  *
@@ -409,37 +409,40 @@ export class TradingAPIImpl extends BaseAPI {
409
409
  });
410
410
  }
411
411
  /**
412
- * Gets paginated orders based on query parameters with automatic pagination.
412
+ * Gets orders based on query parameters, cursor-paginated by default.
413
413
  *
414
414
  * Retrieves orders with optional filtering by status, trading pair, and pagination.
415
- * Pagination parameters are always included with sensible defaults for consistent API behavior.
415
+ * When neither `page` nor `pageToken` is passed, the SDK drives cursor (pageToken)
416
+ * pagination: it starts a cursor walk from the newest (or oldest, for
417
+ * `orderBy: "ASC"`) row and the response's `nextPageToken` resumes it. Cursor
418
+ * responses carry no exact totals (`total`/`page`/`totalPages` are 0).
416
419
  *
417
420
  * @param params - Query parameters for filtering orders
418
- * @param params.status - Filter by order status (e.g., "SUBMITTED", "FILLED") (optional)
421
+ * @param params.status - Filter by order status (e.g., "SUBMITTED", "FILLED"), or by
422
+ * any of several statuses at once by passing an array (e.g., ["SUBMITTED", "PARTIALLY_FILLED"]) (optional)
419
423
  * @param params.tradingPairId - Filter by trading pair UUID (optional)
420
- * @param params.page - Page number for pagination (defaults to 1, must be > 0)
421
- * @param params.pageSize - Number of orders per page (defaults to 10, max 100, must be > 0)
422
- * @param params.pageToken - Pagination cursor (optional): omit for legacy page-number
423
- * pagination; pass `""` to start a cursor walk from the newest (or oldest, for
424
- * `orderBy: "ASC"`) row; pass a previous response's `nextPageToken` to resume. Any
425
- * cursor-walk value (`""` or non-empty) ignores `page` and covers full order history
426
- * (hot and archived rows merged), unlike page-number mode.
424
+ * @param params.page - Deprecated: page number for legacy offset pagination (must be > 0).
425
+ * Passing it selects legacy page-number mode, which only sees recent (hot) history and
426
+ * populates `total`/`totalPages`. Use cursor pagination (`pageToken`) instead.
427
+ * @param params.pageSize - Number of orders per page (defaults to 10, must be > 0; max 100
428
+ * in page-number mode, up to 1000 when pageToken is present)
429
+ * @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
430
+ * the newest (or oldest, for `orderBy: "ASC"`) row; pass a previous response's
431
+ * `nextPageToken` to resume. Any cursor-walk value (`""` or non-empty) ignores `page`
432
+ * and covers full order history (hot and archived rows merged), unlike page-number
433
+ * mode. Omitting both `page` and `pageToken` starts a cursor walk (`pageToken=""`).
427
434
  * @returns Promise resolving to GetPaginatedOrdersResponse with orders and pagination info
428
435
  * @throws {APIError} When API communication fails
429
436
  *
430
437
  * @example
431
438
  * ```typescript
432
- * // Get submitted orders for a specific trading pair with custom pagination
433
- * const orders = await tradingAPI.getPaginatedOrders({
434
- * status: "SUBMITTED",
435
- * tradingPairId: "456e7890-e12b-12d3-a456-426614174000",
436
- * page: 1,
437
- * pageSize: 20
438
- * });
439
- * console.log(`Found ${orders.total} orders, showing page ${orders.page}`);
440
- *
441
- * // Get all orders with default pagination (page=1, pageSize=10)
442
- * const allOrders = await tradingAPI.getPaginatedOrders();
439
+ * // Walk full order history with cursor pagination (the default mode)
440
+ * let pageToken: string | undefined;
441
+ * do {
442
+ * const res = await tradingAPI.getPaginatedOrders({ status: "FILLED", pageToken });
443
+ * handle(res.orders);
444
+ * pageToken = res.nextPageToken;
445
+ * } while (pageToken);
443
446
  * ```
444
447
  */
445
448
  async getPaginatedOrders(params) {
@@ -448,16 +451,25 @@ export class TradingAPIImpl extends BaseAPI {
448
451
  validate(GetPaginatedOrdersSchema, params);
449
452
  }
450
453
  // Set pagination defaults with destructuring and validation
451
- const { page = 1, pageSize: requestedPageSize = 10, status, tradingPairId, tradingMode, marginAccountId, pageToken } = params || {};
452
- const validPage = page > 0 ? page : 1;
454
+ const { page, pageSize: requestedPageSize = 10, status, tradingPairId, tradingMode, marginAccountId, pageToken } = params || {};
453
455
  const validPageSize = requestedPageSize > 0 ? requestedPageSize : 10;
454
- const pageSize = Math.min(validPageSize, 100);
456
+ // Legacy offset mode only when the caller explicitly asked for a page and
457
+ // no cursor was given; everything else drives cursor (pageToken) mode.
458
+ const legacyOffsetMode = page !== undefined && pageToken === undefined;
459
+ // Cursor requests may use pages up to 1000 (keyset reads); page-number
460
+ // requests keep the server's 100 cap.
461
+ const pageSize = Math.min(validPageSize, legacyOffsetMode ? 100 : 1000);
455
462
  const searchParams = new URLSearchParams();
456
- // Always include pagination parameters for consistent API behavior
457
- searchParams.append("page", validPage.toString());
463
+ if (legacyOffsetMode) {
464
+ const validPage = page > 0 ? page : 1;
465
+ searchParams.append("page", validPage.toString());
466
+ }
458
467
  searchParams.append("pageSize", pageSize.toString());
459
- if (status) {
460
- searchParams.append("status", status);
468
+ // An array filter is sent as one comma-separated `status` value, which the
469
+ // API reads as "any of these", so several statuses cost a single request.
470
+ const statusFilter = typeof status === "string" ? status : status?.join(",");
471
+ if (statusFilter) {
472
+ searchParams.append("status", statusFilter);
461
473
  }
462
474
  if (tradingPairId) {
463
475
  searchParams.append("tradingPairId", tradingPairId);
@@ -468,18 +480,55 @@ export class TradingAPIImpl extends BaseAPI {
468
480
  if (marginAccountId) {
469
481
  searchParams.append("marginAccountId", marginAccountId);
470
482
  }
471
- // `!== undefined` (not a truthy check): an explicitly-provided empty
472
- // string is the documented way to start a cursor walk (distinct from
473
- // omitting `pageToken` entirely), so it must still be sent rather than
474
- // silently dropped like a falsy value would be.
475
- if (pageToken !== undefined) {
476
- searchParams.append("pageToken", pageToken);
483
+ // Cursor mode selects itself by the *presence* of `pageToken` on the wire,
484
+ // even when it is the empty string (the documented way to start a walk),
485
+ // so it must be sent explicitly rather than dropped like a falsy value.
486
+ // When the caller gave neither `page` nor `pageToken`, default to starting
487
+ // a cursor walk (`pageToken=""`).
488
+ if (!legacyOffsetMode) {
489
+ searchParams.append("pageToken", pageToken ?? "");
477
490
  }
478
491
  const endpoint = `/api/v1/orders?${searchParams.toString()}`;
479
492
  return await this.makeAuthenticatedRequest(endpoint, {
480
493
  method: "GET",
481
494
  });
482
495
  }
496
+ /**
497
+ * Walks the user's full order history with cursor pagination, yielding one
498
+ * order at a time.
499
+ *
500
+ * Starts a cursor walk (`pageToken: ""`) and follows each response's
501
+ * `nextPageToken` until the server proves exhaustion (a page with zero rows
502
+ * and an empty token). Covers full order history — hot and archived rows
503
+ * merged — unlike the deprecated page-number mode.
504
+ *
505
+ * @param params - Optional filters and page size; `page`/`pageToken` are
506
+ * managed by the iterator and cannot be passed.
507
+ * @returns Async generator yielding orders newest-first (or oldest-first for
508
+ * `orderBy: "ASC"`)
509
+ * @throws {APIError} When any underlying request fails
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * for await (const order of tradingAPI.iterateOrders({ status: "FILLED" })) {
514
+ * console.log(order.id);
515
+ * }
516
+ * ```
517
+ */
518
+ async *iterateOrders(params) {
519
+ let pageToken = "";
520
+ // A non-empty token never guarantees further results (AIP-158 "maybe
521
+ // more"): keep following it until a response returns zero rows and an
522
+ // empty token, the sole proof the walk is exhausted.
523
+ for (;;) {
524
+ const response = await this.getPaginatedOrders({ ...params, pageToken });
525
+ yield* response.orders;
526
+ if (!response.nextPageToken) {
527
+ return;
528
+ }
529
+ pageToken = response.nextPageToken;
530
+ }
531
+ }
483
532
  /**
484
533
  * Gets a single order by its ID.
485
534
  *
@@ -30,6 +30,7 @@ export declare const COVERED: {
30
30
  get_market_metadata: string;
31
31
  get_market_stats: string;
32
32
  get_my_fee_tier: string;
33
+ get_pulse: string;
33
34
  get_my_trader_code: string;
34
35
  get_rewards_balance: string;
35
36
  get_trader_code_info: string;
@@ -64,6 +65,7 @@ export declare const COVERED: {
64
65
  get_withdrawal: string;
65
66
  initiate_withdrawal: string;
66
67
  list_pending_withdrawals: string;
68
+ list_all_funding_history: string;
67
69
  list_application_balances: string;
68
70
  list_application_movements: string;
69
71
  list_application_orders: string;
package/dist/coverage.js CHANGED
@@ -30,6 +30,7 @@ export const COVERED = {
30
30
  get_market_metadata: "getMarketMetadata",
31
31
  get_market_stats: "getMarketStats",
32
32
  get_my_fee_tier: "getMyFeeTier",
33
+ get_pulse: "pulse.getPulse",
33
34
  get_my_trader_code: "pitpass.getMyTraderCode",
34
35
  get_rewards_balance: "pitpass.getRewardsBalance",
35
36
  get_trader_code_info: "pitpass.getTraderCodeInfo",
@@ -64,6 +65,7 @@ export const COVERED = {
64
65
  get_withdrawal: "getWithdrawal",
65
66
  initiate_withdrawal: "initiateWithdrawal",
66
67
  list_pending_withdrawals: "listPendingWithdrawals",
68
+ list_all_funding_history: "listAllFundingHistory",
67
69
  list_application_balances: "listApplicationBalances",
68
70
  list_application_movements: "listApplicationMovements",
69
71
  list_application_orders: "listApplicationOrders",
@@ -23,10 +23,10 @@ const DEFAULT_API_URLS = {
23
23
  const DEFAULT_WS_URLS = {
24
24
  local: "ws://localhost:8085/ws",
25
25
  // Dedicated WebSocket ingress (NLB behind Cloudflare). The previous
26
- // ALB path (wss://develop.apimonaco.xyz/ws) keeps working during the
27
- // migration window.
26
+ // ALB paths (wss://develop.apimonaco.xyz/ws, wss://staging.apimonaco.xyz/ws)
27
+ // keep working during the migration window.
28
28
  development: "wss://ws-develop.apimonaco.xyz/ws",
29
- staging: "wss://staging.apimonaco.xyz/ws",
29
+ staging: "wss://ws-staging.apimonaco.xyz/ws",
30
30
  mainnet: "wss://api.monaco.xyz/ws",
31
31
  };
32
32
  /**
package/dist/sdk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApplicationsAPI, AuthAPI, AuthState, DelegatedAgentsAPI, FaucetAPI, FeesAPI, MarginAccountsAPI, MarketAPI, MonacoSDK, Network, PitpassAPI, PortfolioAPI, PositionsAPI, ProfileAPI, SDKConfig, SubAccountsAPI, TradingAPI, VaultAPI, WhitelistAPI, WithdrawalsAPI } from "@0xmonaco/types";
1
+ import type { ApplicationsAPI, AuthAPI, AuthState, DelegatedAgentsAPI, FaucetAPI, FeesAPI, MarginAccountsAPI, MarketAPI, MonacoSDK, Network, PitpassAPI, PortfolioAPI, PositionsAPI, ProfileAPI, PulseAPI, SDKConfig, SubAccountsAPI, TradingAPI, VaultAPI, WhitelistAPI, WithdrawalsAPI } from "@0xmonaco/types";
2
2
  import { type Address, type PublicClient, type TransactionReceipt, type WalletClient } from "viem";
3
3
  import { type MonacoWebSocket, OrderbookAPIImpl, TradesAPIImpl } from "./api";
4
4
  export declare class MonacoSDKImpl implements MonacoSDK {
@@ -18,6 +18,7 @@ export declare class MonacoSDKImpl implements MonacoSDK {
18
18
  faucet: FaucetAPI;
19
19
  whitelist: WhitelistAPI;
20
20
  profile: ProfileAPI;
21
+ pulse: PulseAPI;
21
22
  orderbook: OrderbookAPIImpl;
22
23
  trades: TradesAPIImpl;
23
24
  ws: MonacoWebSocket;
package/dist/sdk.js CHANGED
@@ -12,6 +12,7 @@ import { PitpassAPIImpl } from "./api/pitpass";
12
12
  import { PortfolioAPIImpl } from "./api/portfolio";
13
13
  import { PositionsAPIImpl } from "./api/positions";
14
14
  import { ProfileAPIImpl } from "./api/profile";
15
+ import { PulseAPIImpl } from "./api/pulse";
15
16
  import { SubAccountsAPIImpl } from "./api/sub-accounts";
16
17
  import { TradingAPIImpl } from "./api/trading";
17
18
  import { VaultAPIImpl } from "./api/vault";
@@ -54,6 +55,7 @@ export class MonacoSDKImpl {
54
55
  faucet;
55
56
  whitelist;
56
57
  profile;
58
+ pulse;
57
59
  orderbook;
58
60
  trades;
59
61
  ws;
@@ -82,6 +84,7 @@ export class MonacoSDKImpl {
82
84
  this.subAccounts.setSessionKeypair(credentials);
83
85
  this.faucet.setSessionKeypair(credentials);
84
86
  this.whitelist.setSessionKeypair(credentials);
87
+ this.pulse.setSessionKeypair(credentials);
85
88
  this.profile.setSessionKeypair(credentials);
86
89
  this.orderbook.setSessionKeypair(credentials);
87
90
  this.trades.setSessionKeypair(credentials);
@@ -120,6 +123,7 @@ export class MonacoSDKImpl {
120
123
  this.subAccounts.setServerKey(serverKey);
121
124
  this.faucet.setServerKey(serverKey);
122
125
  this.whitelist.setServerKey(serverKey);
126
+ this.pulse.setServerKey(serverKey);
123
127
  this.profile.setServerKey(serverKey);
124
128
  this.orderbook.setServerKey(serverKey);
125
129
  this.trades.setServerKey(serverKey);
@@ -181,6 +185,7 @@ export class MonacoSDKImpl {
181
185
  this.subAccounts = new SubAccountsAPIImpl(apiUrl);
182
186
  this.faucet = new FaucetAPIImpl(apiUrl);
183
187
  this.whitelist = new WhitelistAPIImpl(apiUrl);
188
+ this.pulse = new PulseAPIImpl(apiUrl);
184
189
  this.auth = new AuthAPIImpl(this.walletClient, this.chain, apiUrl);
185
190
  this.delegatedAgents = new DelegatedAgentsAPIImpl(apiUrl);
186
191
  this.fees = new FeesAPIImpl(apiUrl);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmonaco/core",
3
- "version": "1.0.28",
3
+ "version": "1.0.31",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,8 +23,8 @@
23
23
  "viem": "^2.45.2"
24
24
  },
25
25
  "dependencies": {
26
- "@0xmonaco/contracts": "1.0.28",
27
- "@0xmonaco/types": "1.0.28",
26
+ "@0xmonaco/contracts": "1.0.31",
27
+ "@0xmonaco/types": "1.0.31",
28
28
  "@noble/curves": "^1.9.1",
29
29
  "@noble/hashes": "^1.8.0",
30
30
  "http-status-codes": "^2.3.0"