pmxt-core 2.0.9 → 2.0.11

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.
@@ -77,18 +77,14 @@ async function fetchMarketsDefault(marketFetcher, params) {
77
77
  if (params?.sort === 'volume') {
78
78
  sortBy = 'high_value';
79
79
  }
80
- // Calculate page number from offset
81
- const page = Math.floor(offset / limit) + 1;
82
80
  try {
83
- // Use SDK's getActiveMarkets method
84
- const response = await marketFetcher.getActiveMarkets({
85
- limit: limit,
86
- page: page,
87
- sortBy: sortBy,
88
- });
89
- const markets = response.data || [];
81
+ // Use pagination utility to handle limits > 25
82
+ // The utility over-fetches to account for markets that get filtered out
83
+ const totalToFetch = limit + offset;
84
+ const rawMarkets = await (0, utils_1.paginateLimitlessMarkets)(marketFetcher, totalToFetch, sortBy);
85
+ // Map and filter markets
90
86
  const unifiedMarkets = [];
91
- for (const market of markets) {
87
+ for (const market of rawMarkets) {
92
88
  const unifiedMarket = (0, utils_1.mapMarketToUnified)(market);
93
89
  // Only include markets that are valid and have outcomes (compliance requirement)
94
90
  if (unifiedMarket && unifiedMarket.outcomes.length > 0) {
@@ -99,7 +95,9 @@ async function fetchMarketsDefault(marketFetcher, params) {
99
95
  if (params?.sort === 'volume') {
100
96
  unifiedMarkets.sort((a, b) => (b.volume ?? 0) - (a.volume ?? 0));
101
97
  }
102
- return unifiedMarkets;
98
+ // Apply offset and limit to the FILTERED results
99
+ const marketsAfterOffset = offset > 0 ? unifiedMarkets.slice(offset) : unifiedMarkets;
100
+ return marketsAfterOffset.slice(0, limit);
103
101
  }
104
102
  catch (error) {
105
103
  throw errors_1.limitlessErrorMapper.mapError(error);
@@ -2,3 +2,12 @@ import { UnifiedMarket, CandleInterval } from '../../types';
2
2
  export declare const LIMITLESS_API_URL = "https://api.limitless.exchange";
3
3
  export declare function mapMarketToUnified(market: any): UnifiedMarket | null;
4
4
  export declare function mapIntervalToFidelity(interval: CandleInterval): number;
5
+ /**
6
+ * Fetch paginated results from Limitless API.
7
+ * The API has a hard limit of 25 items per request, so this function
8
+ * handles automatic pagination when more items are requested.
9
+ *
10
+ * This function fetches all available markets up to a reasonable limit
11
+ * to ensure the caller can filter and still get the requested number.
12
+ */
13
+ export declare function paginateLimitlessMarkets(fetcher: any, requestedLimit: number, sortBy: 'lp_rewards' | 'ending_soon' | 'newest' | 'high_value'): Promise<any[]>;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIMITLESS_API_URL = void 0;
4
4
  exports.mapMarketToUnified = mapMarketToUnified;
5
5
  exports.mapIntervalToFidelity = mapIntervalToFidelity;
6
+ exports.paginateLimitlessMarkets = paginateLimitlessMarkets;
6
7
  const market_utils_1 = require("../../utils/market-utils");
7
8
  exports.LIMITLESS_API_URL = 'https://api.limitless.exchange';
8
9
  function mapMarketToUnified(market) {
@@ -60,3 +61,50 @@ function mapIntervalToFidelity(interval) {
60
61
  };
61
62
  return mapping[interval];
62
63
  }
64
+ /**
65
+ * Fetch paginated results from Limitless API.
66
+ * The API has a hard limit of 25 items per request, so this function
67
+ * handles automatic pagination when more items are requested.
68
+ *
69
+ * This function fetches all available markets up to a reasonable limit
70
+ * to ensure the caller can filter and still get the requested number.
71
+ */
72
+ async function paginateLimitlessMarkets(fetcher, requestedLimit, sortBy) {
73
+ const PAGE_SIZE = 25;
74
+ const targetLimit = requestedLimit || PAGE_SIZE;
75
+ const MAX_PAGES = 20; // Safety limit to prevent infinite loops
76
+ if (targetLimit <= PAGE_SIZE) {
77
+ const response = await fetcher.getActiveMarkets({
78
+ limit: targetLimit,
79
+ page: 1,
80
+ sortBy: sortBy,
81
+ });
82
+ return response.data || [];
83
+ }
84
+ // Fetch more pages than theoretically needed to account for filtering
85
+ // ~33% of markets lack tokens and get filtered out, so we over-fetch
86
+ // by 70% to ensure we get enough valid markets after filtering
87
+ const estimatedPages = Math.ceil(targetLimit / PAGE_SIZE);
88
+ const pagesWithBuffer = Math.min(Math.ceil(estimatedPages * 1.7), MAX_PAGES);
89
+ const pageNumbers = [];
90
+ for (let i = 1; i <= pagesWithBuffer; i++) {
91
+ pageNumbers.push(i);
92
+ }
93
+ const pages = await Promise.all(pageNumbers.map(async (page) => {
94
+ try {
95
+ const response = await fetcher.getActiveMarkets({
96
+ limit: PAGE_SIZE,
97
+ page: page,
98
+ sortBy: sortBy,
99
+ });
100
+ return response.data || [];
101
+ }
102
+ catch (e) {
103
+ return [];
104
+ }
105
+ }));
106
+ const allMarkets = pages.flat();
107
+ // Don't slice here - let the caller handle limiting after filtering
108
+ // This ensures we return enough raw markets for the caller to filter
109
+ return allMarkets;
110
+ }
@@ -3,13 +3,7 @@
3
3
  * Polymarket WebSocket implementation for pmxt.
4
4
  *
5
5
  * NOTICE: This implementation depends on "@nevuamarkets/poly-websockets",
6
- * which is licensed under the AGPL-3.0 License.
7
- *
8
- * While pmxt is licensed under MIT, using these specific WebSocket methods
9
- * may subject your application to the terms of the AGPL-3.0.
10
- *
11
- * If you must avoid AGPL-3.0, do not use the watchOrderBook() or
12
- * watchTrades() methods for Polymarket.
6
+ * which is licensed under the MIT License.
13
7
  */
14
8
  import { OrderBook, Trade } from '../../types';
15
9
  export interface PolymarketWebSocketConfig {
@@ -4,13 +4,7 @@
4
4
  * Polymarket WebSocket implementation for pmxt.
5
5
  *
6
6
  * NOTICE: This implementation depends on "@nevuamarkets/poly-websockets",
7
- * which is licensed under the AGPL-3.0 License.
8
- *
9
- * While pmxt is licensed under MIT, using these specific WebSocket methods
10
- * may subject your application to the terms of the AGPL-3.0.
11
- *
12
- * If you must avoid AGPL-3.0, do not use the watchOrderBook() or
13
- * watchTrades() methods for Polymarket.
7
+ * which is licensed under the MIT License.
14
8
  */
15
9
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
10
  if (k2 === undefined) k2 = k;
@@ -63,7 +57,7 @@ class PolymarketWebSocket {
63
57
  return this.initializationPromise;
64
58
  this.initializationPromise = (async () => {
65
59
  try {
66
- // Dynamic import to handle AGPL dependency optionally
60
+ // Dynamic import to handle optional dependency
67
61
  const poly = await Promise.resolve().then(() => __importStar(require('@nevuamarkets/poly-websockets')));
68
62
  this.manager = new poly.WSSubscriptionManager({
69
63
  onBook: async (events) => {
@@ -92,7 +86,7 @@ class PolymarketWebSocket {
92
86
  catch (e) {
93
87
  const error = e;
94
88
  if (error.message.includes('Cannot find module')) {
95
- throw new Error('Polymarket WebSocket support requires the "@nevuamarkets/poly-websockets" package (AGPL-3.0).\n' +
89
+ throw new Error('Polymarket WebSocket support requires the "@nevuamarkets/poly-websockets" package.\n' +
96
90
  'To use this feature, please install it: npm install @nevuamarkets/poly-websockets');
97
91
  }
98
92
  throw e;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmxt-core",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,8 +29,8 @@
29
29
  "test": "jest -c jest.config.js",
30
30
  "server": "tsx watch src/server/index.ts",
31
31
  "server:prod": "node dist/server/index.js",
32
- "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.0.9,library=urllib3",
33
- "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.0.9,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
32
+ "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.0.11,library=urllib3",
33
+ "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.0.11,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
34
34
  "extract:jsdoc": "node ../scripts/extract-jsdoc.js",
35
35
  "generate:docs": "npm run extract:jsdoc && node ../scripts/generate-api-docs.js",
36
36
  "generate:sdk:all": "npm run generate:sdk:python && npm run generate:sdk:typescript && npm run generate:docs"