pmxt-core 2.0.11 → 2.1.1
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.
- package/dist/BaseExchange.d.ts +4 -2
- package/dist/BaseExchange.js +2 -2
- package/dist/exchanges/kalshi/fetchEvents.js +6 -2
- package/dist/exchanges/kalshi/fetchMarkets.js +21 -10
- package/dist/exchanges/limitless/fetchEvents.js +4 -1
- package/dist/exchanges/limitless/fetchMarkets.js +7 -3
- package/dist/exchanges/polymarket/fetchEvents.js +33 -18
- package/dist/exchanges/polymarket/fetchMarkets.js +51 -23
- package/dist/exchanges/polymarket/utils.d.ts +6 -0
- package/dist/exchanges/polymarket/utils.js +42 -1
- package/package.json +3 -3
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface MarketFilterParams {
|
|
|
4
4
|
limit?: number;
|
|
5
5
|
offset?: number;
|
|
6
6
|
sort?: 'volume' | 'liquidity' | 'newest';
|
|
7
|
+
status?: 'active' | 'closed' | 'all';
|
|
7
8
|
searchIn?: 'title' | 'description' | 'both';
|
|
8
9
|
query?: string;
|
|
9
10
|
slug?: string;
|
|
@@ -16,6 +17,7 @@ export interface EventFetchParams {
|
|
|
16
17
|
query?: string;
|
|
17
18
|
limit?: number;
|
|
18
19
|
offset?: number;
|
|
20
|
+
status?: 'active' | 'closed' | 'all';
|
|
19
21
|
searchIn?: 'title' | 'description' | 'both';
|
|
20
22
|
}
|
|
21
23
|
export interface HistoryFilterParams {
|
|
@@ -113,14 +115,14 @@ export declare abstract class PredictionMarketExchange {
|
|
|
113
115
|
* @returns Array of unified markets
|
|
114
116
|
*
|
|
115
117
|
* @example-ts Fetch markets
|
|
116
|
-
* const markets = await exchange.fetchMarkets({ query: 'Trump', limit:
|
|
118
|
+
* const markets = await exchange.fetchMarkets({ query: 'Trump', limit: 10000 });
|
|
117
119
|
* console.log(markets[0].title);
|
|
118
120
|
*
|
|
119
121
|
* @example-ts Get market by slug
|
|
120
122
|
* const markets = await exchange.fetchMarkets({ slug: 'will-trump-win' });
|
|
121
123
|
*
|
|
122
124
|
* @example-python Fetch markets
|
|
123
|
-
* markets = exchange.fetch_markets(query='Trump', limit=
|
|
125
|
+
* markets = exchange.fetch_markets(query='Trump', limit=10000)
|
|
124
126
|
* print(markets[0].title)
|
|
125
127
|
*
|
|
126
128
|
* @example-python Get market by slug
|
package/dist/BaseExchange.js
CHANGED
|
@@ -23,14 +23,14 @@ class PredictionMarketExchange {
|
|
|
23
23
|
* @returns Array of unified markets
|
|
24
24
|
*
|
|
25
25
|
* @example-ts Fetch markets
|
|
26
|
-
* const markets = await exchange.fetchMarkets({ query: 'Trump', limit:
|
|
26
|
+
* const markets = await exchange.fetchMarkets({ query: 'Trump', limit: 10000 });
|
|
27
27
|
* console.log(markets[0].title);
|
|
28
28
|
*
|
|
29
29
|
* @example-ts Get market by slug
|
|
30
30
|
* const markets = await exchange.fetchMarkets({ slug: 'will-trump-win' });
|
|
31
31
|
*
|
|
32
32
|
* @example-python Fetch markets
|
|
33
|
-
* markets = exchange.fetch_markets(query='Trump', limit=
|
|
33
|
+
* markets = exchange.fetch_markets(query='Trump', limit=10000)
|
|
34
34
|
* print(markets[0].title)
|
|
35
35
|
*
|
|
36
36
|
* @example-python Get market by slug
|
|
@@ -9,10 +9,14 @@ const utils_1 = require("./utils");
|
|
|
9
9
|
const errors_1 = require("./errors");
|
|
10
10
|
async function fetchEvents(params) {
|
|
11
11
|
try {
|
|
12
|
+
const status = params?.status || 'active';
|
|
13
|
+
let apiStatus = 'open';
|
|
14
|
+
if (status === 'closed')
|
|
15
|
+
apiStatus = 'closed';
|
|
12
16
|
const queryParams = {
|
|
13
17
|
limit: 200, // Reasonable batch for search
|
|
14
18
|
with_nested_markets: true,
|
|
15
|
-
status:
|
|
19
|
+
status: apiStatus
|
|
16
20
|
};
|
|
17
21
|
const response = await axios_1.default.get(utils_1.KALSHI_API_URL, { params: queryParams });
|
|
18
22
|
const events = response.data.events || [];
|
|
@@ -43,7 +47,7 @@ async function fetchEvents(params) {
|
|
|
43
47
|
};
|
|
44
48
|
return unifiedEvent;
|
|
45
49
|
});
|
|
46
|
-
const limit = params?.limit ||
|
|
50
|
+
const limit = params?.limit || 10000;
|
|
47
51
|
return unifiedEvents.slice(0, limit);
|
|
48
52
|
}
|
|
49
53
|
catch (error) {
|
|
@@ -8,7 +8,7 @@ exports.fetchMarkets = fetchMarkets;
|
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const utils_1 = require("./utils");
|
|
10
10
|
const errors_1 = require("./errors");
|
|
11
|
-
async function fetchActiveEvents(targetMarketCount) {
|
|
11
|
+
async function fetchActiveEvents(targetMarketCount, status = 'open') {
|
|
12
12
|
let allEvents = [];
|
|
13
13
|
let totalMarketCount = 0;
|
|
14
14
|
let cursor = null;
|
|
@@ -23,7 +23,7 @@ async function fetchActiveEvents(targetMarketCount) {
|
|
|
23
23
|
const queryParams = {
|
|
24
24
|
limit: BATCH_SIZE,
|
|
25
25
|
with_nested_markets: true,
|
|
26
|
-
status:
|
|
26
|
+
status: status // Filter by status (default 'open')
|
|
27
27
|
};
|
|
28
28
|
if (cursor)
|
|
29
29
|
queryParams.cursor = cursor;
|
|
@@ -138,7 +138,7 @@ async function fetchMarketsBySlug(eventTicker) {
|
|
|
138
138
|
}
|
|
139
139
|
async function searchMarkets(query, params) {
|
|
140
140
|
// We must fetch ALL markets to search them locally since we don't have server-side search
|
|
141
|
-
const searchLimit =
|
|
141
|
+
const searchLimit = 10000;
|
|
142
142
|
const markets = await fetchMarketsDefault({ ...params, limit: searchLimit });
|
|
143
143
|
const lowerQuery = query.toLowerCase();
|
|
144
144
|
const searchIn = params?.searchIn || 'title'; // Default to title-only search
|
|
@@ -151,18 +151,28 @@ async function searchMarkets(query, params) {
|
|
|
151
151
|
return descMatch;
|
|
152
152
|
return titleMatch || descMatch; // 'both'
|
|
153
153
|
});
|
|
154
|
-
const limit = params?.limit ||
|
|
154
|
+
const limit = params?.limit || 10000;
|
|
155
155
|
return filtered.slice(0, limit);
|
|
156
156
|
}
|
|
157
157
|
async function fetchMarketsDefault(params) {
|
|
158
|
-
const limit = params?.limit ||
|
|
158
|
+
const limit = params?.limit || 10000;
|
|
159
159
|
const offset = params?.offset || 0;
|
|
160
160
|
const now = Date.now();
|
|
161
|
+
const status = params?.status || 'active'; // Default to 'active'
|
|
162
|
+
// Map 'active' -> 'open', 'closed' -> 'closed'
|
|
163
|
+
// Kalshi statuses: 'open', 'closed', 'settled'
|
|
164
|
+
let apiStatus = 'open';
|
|
165
|
+
if (status === 'closed')
|
|
166
|
+
apiStatus = 'closed';
|
|
167
|
+
else if (status === 'all')
|
|
168
|
+
apiStatus = 'open'; // Fallback for all? Or loop? For now default to open.
|
|
161
169
|
try {
|
|
162
170
|
let events;
|
|
163
171
|
let seriesMap;
|
|
164
172
|
// Check if we have valid cached data
|
|
165
|
-
|
|
173
|
+
// Only use global cache for the default 'active'/'open' case
|
|
174
|
+
const useCache = (status === 'active' || !params?.status);
|
|
175
|
+
if (useCache && cachedEvents && cachedSeriesMap && (now - lastCacheTime < CACHE_TTL)) {
|
|
166
176
|
events = cachedEvents;
|
|
167
177
|
seriesMap = cachedSeriesMap;
|
|
168
178
|
}
|
|
@@ -173,16 +183,17 @@ async function fetchMarketsDefault(params) {
|
|
|
173
183
|
const isSorted = params?.sort && (params.sort === 'volume' || params.sort === 'liquidity');
|
|
174
184
|
const fetchLimit = isSorted ? 1000 : limit;
|
|
175
185
|
const [allEvents, fetchedSeriesMap] = await Promise.all([
|
|
176
|
-
fetchActiveEvents(fetchLimit),
|
|
186
|
+
fetchActiveEvents(fetchLimit, apiStatus),
|
|
177
187
|
fetchSeriesMap()
|
|
178
188
|
]);
|
|
179
189
|
events = allEvents;
|
|
180
190
|
seriesMap = fetchedSeriesMap;
|
|
181
191
|
events = allEvents;
|
|
182
192
|
seriesMap = fetchedSeriesMap;
|
|
183
|
-
// Cache the dataset ONLY if
|
|
184
|
-
//
|
|
185
|
-
|
|
193
|
+
// Cache the dataset ONLY if:
|
|
194
|
+
// 1. We fetched a comprehensive set (>= 1000)
|
|
195
|
+
// 2. It's the standard 'open' status query
|
|
196
|
+
if (fetchLimit >= 1000 && useCache) {
|
|
186
197
|
cachedEvents = allEvents;
|
|
187
198
|
cachedSeriesMap = fetchedSeriesMap;
|
|
188
199
|
lastCacheTime = now;
|
|
@@ -8,11 +8,14 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
8
8
|
const utils_1 = require("./utils");
|
|
9
9
|
const errors_1 = require("./errors");
|
|
10
10
|
async function fetchEvents(params) {
|
|
11
|
+
if (params?.status === 'closed') {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
11
14
|
try {
|
|
12
15
|
const response = await axios_1.default.get(`${utils_1.LIMITLESS_API_URL}/markets/search`, {
|
|
13
16
|
params: {
|
|
14
17
|
query: params.query,
|
|
15
|
-
limit: params?.limit ||
|
|
18
|
+
limit: params?.limit || 10000
|
|
16
19
|
}
|
|
17
20
|
});
|
|
18
21
|
const markets = response.data?.markets || [];
|
|
@@ -9,6 +9,10 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
9
9
|
const utils_1 = require("./utils");
|
|
10
10
|
const errors_1 = require("./errors");
|
|
11
11
|
async function fetchMarkets(params, apiKey) {
|
|
12
|
+
// Limitless API currently only supports fetching active markets for lists
|
|
13
|
+
if (params?.status === 'closed') {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
12
16
|
try {
|
|
13
17
|
// Create HTTP client (no auth needed for market data)
|
|
14
18
|
const httpClient = new sdk_1.HttpClient({
|
|
@@ -43,7 +47,7 @@ async function searchMarkets(marketFetcher, query, params) {
|
|
|
43
47
|
const response = await axios_1.default.get(`${utils_1.LIMITLESS_API_URL}/markets/search`, {
|
|
44
48
|
params: {
|
|
45
49
|
query: query,
|
|
46
|
-
limit: params?.limit ||
|
|
50
|
+
limit: params?.limit || 10000,
|
|
47
51
|
page: params?.page || 1,
|
|
48
52
|
similarityThreshold: params?.similarityThreshold || 0.5
|
|
49
53
|
}
|
|
@@ -67,10 +71,10 @@ async function searchMarkets(marketFetcher, query, params) {
|
|
|
67
71
|
}
|
|
68
72
|
return allMarkets
|
|
69
73
|
.filter((m) => m !== null && m.outcomes.length > 0)
|
|
70
|
-
.slice(0, params?.limit ||
|
|
74
|
+
.slice(0, params?.limit || 10000);
|
|
71
75
|
}
|
|
72
76
|
async function fetchMarketsDefault(marketFetcher, params) {
|
|
73
|
-
const limit = params?.limit ||
|
|
77
|
+
const limit = params?.limit || 10000;
|
|
74
78
|
const offset = params?.offset || 0;
|
|
75
79
|
// Map sort parameter to SDK's sortBy
|
|
76
80
|
let sortBy = 'lp_rewards';
|
|
@@ -4,30 +4,47 @@ exports.fetchEvents = fetchEvents;
|
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
const errors_1 = require("./errors");
|
|
6
6
|
async function fetchEvents(params) {
|
|
7
|
-
const searchLimit = 100000; // Fetch all events for comprehensive search
|
|
8
7
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
8
|
+
if (!params.query) {
|
|
9
|
+
// If no query is provided, we can't use the search endpoint effectively.
|
|
10
|
+
// However, the BaseExchange interface enforces query presence for fetchEvents.
|
|
11
|
+
// Just in case, we return empty or throw.
|
|
12
|
+
throw new Error("Query is required for Polymarket event search");
|
|
13
|
+
}
|
|
14
|
+
const limit = params.limit || 10000;
|
|
15
|
+
const status = params.status || 'active';
|
|
16
|
+
const queryParams = {
|
|
17
|
+
q: params.query,
|
|
18
|
+
limit_per_type: 50, // Fetch 50 per page for better efficiency
|
|
19
|
+
events_status: status === 'all' ? undefined : status,
|
|
20
|
+
sort: 'volume',
|
|
21
|
+
ascending: false
|
|
22
|
+
};
|
|
23
|
+
// If specific status requested
|
|
24
|
+
if (status === 'active') {
|
|
25
|
+
queryParams.events_status = 'active';
|
|
26
|
+
}
|
|
27
|
+
else if (status === 'closed') {
|
|
28
|
+
queryParams.events_status = 'closed';
|
|
29
|
+
}
|
|
30
|
+
// Use parallel pagination to fetch all matching events
|
|
31
|
+
const events = await (0, utils_1.paginateSearchParallel)(utils_1.GAMMA_SEARCH_URL, queryParams, limit * 10);
|
|
32
|
+
// Client-side filtering to ensure title matches (API does fuzzy search)
|
|
33
|
+
const lowerQuery = params.query.toLowerCase();
|
|
34
|
+
const searchIn = params.searchIn || 'title';
|
|
35
|
+
const filteredEvents = events.filter((event) => {
|
|
19
36
|
const titleMatch = (event.title || '').toLowerCase().includes(lowerQuery);
|
|
20
37
|
const descMatch = (event.description || '').toLowerCase().includes(lowerQuery);
|
|
21
38
|
if (searchIn === 'title')
|
|
22
39
|
return titleMatch;
|
|
23
40
|
if (searchIn === 'description')
|
|
24
41
|
return descMatch;
|
|
25
|
-
return titleMatch || descMatch;
|
|
42
|
+
return titleMatch || descMatch; // 'both'
|
|
26
43
|
});
|
|
27
|
-
// Map to UnifiedEvent
|
|
28
|
-
const unifiedEvents =
|
|
44
|
+
// Map events to UnifiedEvent
|
|
45
|
+
const unifiedEvents = filteredEvents.map((event) => {
|
|
29
46
|
const markets = [];
|
|
30
|
-
if (event.markets) {
|
|
47
|
+
if (event.markets && Array.isArray(event.markets)) {
|
|
31
48
|
for (const market of event.markets) {
|
|
32
49
|
const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market, { useQuestionAsCandidateFallback: true });
|
|
33
50
|
if (unifiedMarket) {
|
|
@@ -48,9 +65,7 @@ async function fetchEvents(params) {
|
|
|
48
65
|
};
|
|
49
66
|
return unifiedEvent;
|
|
50
67
|
});
|
|
51
|
-
|
|
52
|
-
const limit = params?.limit || 20;
|
|
53
|
-
return unifiedEvents.slice(0, limit);
|
|
68
|
+
return unifiedEvents;
|
|
54
69
|
}
|
|
55
70
|
catch (error) {
|
|
56
71
|
throw errors_1.polymarketErrorMapper.mapError(error);
|
|
@@ -45,38 +45,66 @@ async function fetchMarketsBySlug(slug) {
|
|
|
45
45
|
return unifiedMarkets;
|
|
46
46
|
}
|
|
47
47
|
async function searchMarkets(query, params) {
|
|
48
|
-
const
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
const limit = params?.limit || 10000;
|
|
49
|
+
// Use parallel pagination to fetch all matching events
|
|
50
|
+
// Each event can contain multiple markets, so we need a larger pool
|
|
51
|
+
const queryParams = {
|
|
52
|
+
q: query,
|
|
53
|
+
limit_per_type: 50, // Fetch 50 events per page
|
|
54
|
+
events_status: params?.status === 'all' ? undefined : (params?.status || 'active'),
|
|
55
|
+
sort: 'volume',
|
|
56
|
+
ascending: false
|
|
57
|
+
};
|
|
58
|
+
// Fetch events with parallel pagination
|
|
59
|
+
const events = await (0, utils_1.paginateSearchParallel)(utils_1.GAMMA_SEARCH_URL, queryParams, limit * 5);
|
|
60
|
+
const unifiedMarkets = [];
|
|
55
61
|
const lowerQuery = query.toLowerCase();
|
|
56
|
-
const searchIn = params?.searchIn || 'title';
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
const searchIn = params?.searchIn || 'title';
|
|
63
|
+
// Flatten events into markets
|
|
64
|
+
for (const event of events) {
|
|
65
|
+
if (!event.markets)
|
|
66
|
+
continue;
|
|
67
|
+
for (const market of event.markets) {
|
|
68
|
+
const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market, { useQuestionAsCandidateFallback: true });
|
|
69
|
+
if (!unifiedMarket)
|
|
70
|
+
continue;
|
|
71
|
+
// Apply client-side filtering on market title
|
|
72
|
+
const titleMatch = (unifiedMarket.title || '').toLowerCase().includes(lowerQuery);
|
|
73
|
+
const descMatch = (unifiedMarket.description || '').toLowerCase().includes(lowerQuery);
|
|
74
|
+
let matches = false;
|
|
75
|
+
if (searchIn === 'title')
|
|
76
|
+
matches = titleMatch;
|
|
77
|
+
else if (searchIn === 'description')
|
|
78
|
+
matches = descMatch;
|
|
79
|
+
else
|
|
80
|
+
matches = titleMatch || descMatch;
|
|
81
|
+
if (matches) {
|
|
82
|
+
unifiedMarkets.push(unifiedMarket);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return unifiedMarkets.slice(0, limit);
|
|
69
87
|
}
|
|
70
88
|
async function fetchMarketsDefault(params) {
|
|
71
|
-
const limit = params?.limit ||
|
|
89
|
+
const limit = params?.limit || 10000; // Higher default for better coverage
|
|
72
90
|
const offset = params?.offset || 0;
|
|
73
91
|
// Map generic sort params to Polymarket Gamma API params
|
|
74
92
|
let queryParams = {
|
|
75
|
-
active: 'true',
|
|
76
|
-
closed: 'false',
|
|
77
93
|
limit: limit,
|
|
78
94
|
offset: offset,
|
|
79
95
|
};
|
|
96
|
+
const status = params?.status || 'active';
|
|
97
|
+
if (status === 'active') {
|
|
98
|
+
queryParams.active = 'true';
|
|
99
|
+
queryParams.closed = 'false';
|
|
100
|
+
}
|
|
101
|
+
else if (status === 'closed') {
|
|
102
|
+
queryParams.active = 'false';
|
|
103
|
+
queryParams.closed = 'true';
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// 'all' - don't filter by status
|
|
107
|
+
}
|
|
80
108
|
// Gamma API uses 'order' and 'ascending' for sorting
|
|
81
109
|
if (params?.sort === 'volume') {
|
|
82
110
|
queryParams.order = 'volume';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnifiedMarket, CandleInterval } from '../../types';
|
|
2
2
|
export declare const GAMMA_API_URL = "https://gamma-api.polymarket.com/events";
|
|
3
|
+
export declare const GAMMA_SEARCH_URL = "https://gamma-api.polymarket.com/public-search";
|
|
3
4
|
export declare const CLOB_API_URL = "https://clob.polymarket.com";
|
|
4
5
|
export declare const DATA_API_URL = "https://data-api.polymarket.com";
|
|
5
6
|
export declare function mapMarketToUnified(event: any, market: any, options?: {
|
|
@@ -11,3 +12,8 @@ export declare function mapIntervalToFidelity(interval: CandleInterval): number;
|
|
|
11
12
|
* Polymarket Gamma API has a hard limit of 500 results per request.
|
|
12
13
|
*/
|
|
13
14
|
export declare function paginateParallel(url: string, params: any, maxResults?: number): Promise<any[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Fetch all results from Gamma public-search API using parallel pagination.
|
|
17
|
+
* Uses 'page' parameter instead of 'offset'.
|
|
18
|
+
*/
|
|
19
|
+
export declare function paginateSearchParallel(url: string, params: any, maxResults?: number): Promise<any[]>;
|
|
@@ -33,12 +33,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.DATA_API_URL = exports.CLOB_API_URL = exports.GAMMA_API_URL = void 0;
|
|
36
|
+
exports.DATA_API_URL = exports.CLOB_API_URL = exports.GAMMA_SEARCH_URL = exports.GAMMA_API_URL = void 0;
|
|
37
37
|
exports.mapMarketToUnified = mapMarketToUnified;
|
|
38
38
|
exports.mapIntervalToFidelity = mapIntervalToFidelity;
|
|
39
39
|
exports.paginateParallel = paginateParallel;
|
|
40
|
+
exports.paginateSearchParallel = paginateSearchParallel;
|
|
40
41
|
const market_utils_1 = require("../../utils/market-utils");
|
|
41
42
|
exports.GAMMA_API_URL = 'https://gamma-api.polymarket.com/events';
|
|
43
|
+
exports.GAMMA_SEARCH_URL = 'https://gamma-api.polymarket.com/public-search';
|
|
42
44
|
exports.CLOB_API_URL = 'https://clob.polymarket.com';
|
|
43
45
|
exports.DATA_API_URL = 'https://data-api.polymarket.com';
|
|
44
46
|
function mapMarketToUnified(event, market, options = {}) {
|
|
@@ -171,3 +173,42 @@ async function paginateParallel(url, params, maxResults = 10000) {
|
|
|
171
173
|
}));
|
|
172
174
|
return [firstPage, ...remainingPages].flat();
|
|
173
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Fetch all results from Gamma public-search API using parallel pagination.
|
|
178
|
+
* Uses 'page' parameter instead of 'offset'.
|
|
179
|
+
*/
|
|
180
|
+
async function paginateSearchParallel(url, params, maxResults = 10000) {
|
|
181
|
+
const axios = (await Promise.resolve().then(() => __importStar(require('axios')))).default;
|
|
182
|
+
// 1. Fetch the first page to check pagination info
|
|
183
|
+
const firstPageResponse = await axios.get(url, {
|
|
184
|
+
params: { ...params, page: 1 }
|
|
185
|
+
});
|
|
186
|
+
const data = firstPageResponse.data;
|
|
187
|
+
const firstPageEvents = data.events || [];
|
|
188
|
+
const pagination = data.pagination;
|
|
189
|
+
// If no more pages, return what we have
|
|
190
|
+
if (!pagination?.hasMore || firstPageEvents.length === 0) {
|
|
191
|
+
return firstPageEvents;
|
|
192
|
+
}
|
|
193
|
+
// 2. Calculate how many pages to fetch based on totalResults and limit_per_type
|
|
194
|
+
const limitPerType = params.limit_per_type || 20;
|
|
195
|
+
const totalResults = Math.min(pagination.totalResults || 0, maxResults);
|
|
196
|
+
const totalPages = Math.ceil(totalResults / limitPerType);
|
|
197
|
+
// Fetch remaining pages in parallel
|
|
198
|
+
const pageNumbers = [];
|
|
199
|
+
for (let i = 2; i <= totalPages; i++) {
|
|
200
|
+
pageNumbers.push(i);
|
|
201
|
+
}
|
|
202
|
+
const remainingPages = await Promise.all(pageNumbers.map(async (pageNum) => {
|
|
203
|
+
try {
|
|
204
|
+
const res = await axios.get(url, {
|
|
205
|
+
params: { ...params, page: pageNum }
|
|
206
|
+
});
|
|
207
|
+
return res.data?.events || [];
|
|
208
|
+
}
|
|
209
|
+
catch (e) {
|
|
210
|
+
return []; // Swallow individual page errors to be robust
|
|
211
|
+
}
|
|
212
|
+
}));
|
|
213
|
+
return [firstPageEvents, ...remainingPages].flat();
|
|
214
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
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.
|
|
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.
|
|
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.1.1,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.1.1,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"
|