pmxt-core 2.20.1 → 2.20.2
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/exchanges/baozi/fetcher.d.ts +40 -0
- package/dist/exchanges/baozi/fetcher.js +155 -0
- package/dist/exchanges/baozi/index.d.ts +2 -0
- package/dist/exchanges/baozi/index.js +60 -131
- package/dist/exchanges/baozi/normalizer.d.ts +14 -0
- package/dist/exchanges/baozi/normalizer.js +208 -0
- package/dist/exchanges/interfaces.d.ts +28 -0
- package/dist/exchanges/interfaces.js +2 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/kalshi/fetcher.d.ts +126 -0
- package/dist/exchanges/kalshi/fetcher.js +313 -0
- package/dist/exchanges/kalshi/index.d.ts +6 -6
- package/dist/exchanges/kalshi/index.js +119 -202
- package/dist/exchanges/kalshi/normalizer.d.ts +25 -0
- package/dist/exchanges/kalshi/normalizer.js +294 -0
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/limitless/fetcher.d.ts +81 -0
- package/dist/exchanges/limitless/fetcher.js +238 -0
- package/dist/exchanges/limitless/index.d.ts +6 -9
- package/dist/exchanges/limitless/index.js +81 -79
- package/dist/exchanges/limitless/normalizer.d.ts +14 -0
- package/dist/exchanges/limitless/normalizer.js +117 -0
- package/dist/exchanges/limitless/websocket.d.ts +3 -0
- package/dist/exchanges/limitless/websocket.js +5 -4
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/myriad/fetcher.d.ts +73 -0
- package/dist/exchanges/myriad/fetcher.js +217 -0
- package/dist/exchanges/myriad/index.d.ts +2 -0
- package/dist/exchanges/myriad/index.js +40 -97
- package/dist/exchanges/myriad/normalizer.d.ts +14 -0
- package/dist/exchanges/myriad/normalizer.js +167 -0
- package/dist/exchanges/myriad/websocket.d.ts +3 -1
- package/dist/exchanges/myriad/websocket.js +4 -3
- package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
- package/dist/exchanges/polymarket/api-clob.js +1 -1
- package/dist/exchanges/polymarket/api-data.d.ts +1 -1
- package/dist/exchanges/polymarket/api-data.js +1 -1
- package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
- package/dist/exchanges/polymarket/api-gamma.js +1 -1
- package/dist/exchanges/polymarket/fetcher.d.ts +99 -0
- package/dist/exchanges/polymarket/fetcher.js +335 -0
- package/dist/exchanges/polymarket/index.d.ts +2 -0
- package/dist/exchanges/polymarket/index.js +80 -66
- package/dist/exchanges/polymarket/normalizer.d.ts +18 -0
- package/dist/exchanges/polymarket/normalizer.js +126 -0
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/fetcher.d.ts +106 -0
- package/dist/exchanges/probable/fetcher.js +357 -0
- package/dist/exchanges/probable/index.d.ts +3 -1
- package/dist/exchanges/probable/index.js +73 -105
- package/dist/exchanges/probable/normalizer.d.ts +14 -0
- package/dist/exchanges/probable/normalizer.js +109 -0
- package/package.json +3 -3
- package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
- package/dist/exchanges/baozi/fetchEvents.js +0 -39
- package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
- package/dist/exchanges/baozi/fetchMarkets.js +0 -160
- package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
- package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
- package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
- package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
- package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
- package/dist/exchanges/baozi/fetchTrades.js +0 -10
- package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
- package/dist/exchanges/kalshi/fetchEvents.js +0 -196
- package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
- package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
- package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
- package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
- package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
- package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
- package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
- package/dist/exchanges/kalshi/fetchTrades.js +0 -33
- package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
- package/dist/exchanges/limitless/fetchEvents.js +0 -173
- package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
- package/dist/exchanges/limitless/fetchMarkets.js +0 -152
- package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
- package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
- package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
- package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
- package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
- package/dist/exchanges/limitless/fetchTrades.js +0 -27
- package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
- package/dist/exchanges/myriad/fetchEvents.js +0 -48
- package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/myriad/fetchMarkets.js +0 -102
- package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
- package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
- package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
- package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
- package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
- package/dist/exchanges/polymarket/fetchEvents.js +0 -135
- package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
- package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
- package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
- package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
- package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
- package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
- package/dist/exchanges/polymarket/fetchTrades.js +0 -43
- package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
- package/dist/exchanges/probable/fetchEvents.js +0 -151
- package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/probable/fetchMarkets.js +0 -239
- package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
- package/dist/exchanges/probable/fetchTrades.js +0 -40
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProbableFetcher = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
class ProbableFetcher {
|
|
7
|
+
ctx;
|
|
8
|
+
constructor(ctx) {
|
|
9
|
+
this.ctx = ctx;
|
|
10
|
+
}
|
|
11
|
+
// -----------------------------------------------------------------------
|
|
12
|
+
// Markets
|
|
13
|
+
// -----------------------------------------------------------------------
|
|
14
|
+
async fetchRawMarkets(params) {
|
|
15
|
+
try {
|
|
16
|
+
if (params?.marketId) {
|
|
17
|
+
return this.fetchRawMarketByIdOrSlug(params.marketId);
|
|
18
|
+
}
|
|
19
|
+
if (params?.slug) {
|
|
20
|
+
return this.fetchRawMarketByIdOrSlug(params.slug);
|
|
21
|
+
}
|
|
22
|
+
if (params?.outcomeId) {
|
|
23
|
+
return this.fetchRawMarketsList(params);
|
|
24
|
+
}
|
|
25
|
+
if (params?.eventId) {
|
|
26
|
+
return this.fetchRawMarketsList(params);
|
|
27
|
+
}
|
|
28
|
+
if (params?.query) {
|
|
29
|
+
return this.fetchRawMarketsViaSearch(params.query, params);
|
|
30
|
+
}
|
|
31
|
+
return this.fetchRawMarketsList(params);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw errors_1.probableErrorMapper.mapError(error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// -----------------------------------------------------------------------
|
|
38
|
+
// Events
|
|
39
|
+
// -----------------------------------------------------------------------
|
|
40
|
+
async fetchRawEvents(params) {
|
|
41
|
+
try {
|
|
42
|
+
if (params.eventId) {
|
|
43
|
+
const event = await this.fetchRawEventById(params.eventId);
|
|
44
|
+
return event ? [event] : [];
|
|
45
|
+
}
|
|
46
|
+
if (params.slug) {
|
|
47
|
+
const event = await this.fetchRawEventBySlug(params.slug);
|
|
48
|
+
return event ? [event] : [];
|
|
49
|
+
}
|
|
50
|
+
if (params.query) {
|
|
51
|
+
return this.fetchRawEventsViaSearch(params);
|
|
52
|
+
}
|
|
53
|
+
return this.fetchRawEventsList(params);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
throw errors_1.probableErrorMapper.mapError(error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async fetchRawEventById(id) {
|
|
60
|
+
try {
|
|
61
|
+
const numericId = Number(id);
|
|
62
|
+
if (isNaN(numericId))
|
|
63
|
+
return null;
|
|
64
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.EVENTS_PATH}${numericId}`);
|
|
65
|
+
return response.data || null;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (isNotFoundError(error))
|
|
69
|
+
return null;
|
|
70
|
+
throw errors_1.probableErrorMapper.mapError(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async fetchRawEventBySlug(slug) {
|
|
74
|
+
try {
|
|
75
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.EVENTS_PATH}slug/${slug}`);
|
|
76
|
+
return response.data || null;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (isNotFoundError(error))
|
|
80
|
+
return null;
|
|
81
|
+
throw errors_1.probableErrorMapper.mapError(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// -----------------------------------------------------------------------
|
|
85
|
+
// Order Book
|
|
86
|
+
// -----------------------------------------------------------------------
|
|
87
|
+
async fetchRawOrderBook(id) {
|
|
88
|
+
const data = await this.ctx.callApi('getPublicApiV1Book', { token_id: id });
|
|
89
|
+
return data;
|
|
90
|
+
}
|
|
91
|
+
// -----------------------------------------------------------------------
|
|
92
|
+
// OHLCV
|
|
93
|
+
// -----------------------------------------------------------------------
|
|
94
|
+
async fetchRawOHLCV(id, params) {
|
|
95
|
+
const INTERVAL_MAP = {
|
|
96
|
+
'1m': '1m',
|
|
97
|
+
'5m': '1m',
|
|
98
|
+
'15m': '1m',
|
|
99
|
+
'1h': '1h',
|
|
100
|
+
'6h': '6h',
|
|
101
|
+
'1d': '1d',
|
|
102
|
+
};
|
|
103
|
+
const queryParams = {
|
|
104
|
+
market: id,
|
|
105
|
+
interval: INTERVAL_MAP[params.resolution] || '1h',
|
|
106
|
+
};
|
|
107
|
+
if (params.start)
|
|
108
|
+
queryParams.startTs = Math.floor(params.start.getTime() / 1000);
|
|
109
|
+
if (params.end)
|
|
110
|
+
queryParams.endTs = Math.floor(params.end.getTime() / 1000);
|
|
111
|
+
const data = await this.ctx.callApi('getPublicApiV1PricesHistory', queryParams);
|
|
112
|
+
return data?.history || data || [];
|
|
113
|
+
}
|
|
114
|
+
// -----------------------------------------------------------------------
|
|
115
|
+
// Trades
|
|
116
|
+
// -----------------------------------------------------------------------
|
|
117
|
+
async fetchRawTrades(id, params) {
|
|
118
|
+
const queryParams = { tokenId: id };
|
|
119
|
+
if (params.limit)
|
|
120
|
+
queryParams.limit = params.limit;
|
|
121
|
+
// Uses CLOB client via callApi -- the SDK class will pass the CLOB
|
|
122
|
+
// client's getTrades through callApi or directly. For now, this goes
|
|
123
|
+
// through the implicit API.
|
|
124
|
+
const data = await this.ctx.callApi('getPublicApiV1Trades', queryParams);
|
|
125
|
+
const trades = Array.isArray(data) ? data : (data?.data || []);
|
|
126
|
+
return trades;
|
|
127
|
+
}
|
|
128
|
+
async fetchRawMyTrades(params, walletAddress) {
|
|
129
|
+
const queryParams = { user: walletAddress };
|
|
130
|
+
if (params?.limit)
|
|
131
|
+
queryParams.limit = params.limit;
|
|
132
|
+
const data = await this.ctx.callApi('getPublicApiV1Trades', queryParams);
|
|
133
|
+
const trades = Array.isArray(data) ? data : (data?.data || []);
|
|
134
|
+
return trades;
|
|
135
|
+
}
|
|
136
|
+
// -----------------------------------------------------------------------
|
|
137
|
+
// Positions & Balance
|
|
138
|
+
// -----------------------------------------------------------------------
|
|
139
|
+
async fetchRawPositions(walletAddress) {
|
|
140
|
+
const result = await this.ctx.callApi('getPublicApiV1PositionCurrent', { user: walletAddress, limit: 500 });
|
|
141
|
+
return Array.isArray(result) ? result : (result?.data || []);
|
|
142
|
+
}
|
|
143
|
+
// -----------------------------------------------------------------------
|
|
144
|
+
// Midpoint (price enrichment)
|
|
145
|
+
// -----------------------------------------------------------------------
|
|
146
|
+
async fetchRawMidpoint(tokenId) {
|
|
147
|
+
return this.ctx.callApi('getPublicApiV1Midpoint', { token_id: tokenId });
|
|
148
|
+
}
|
|
149
|
+
async fetchRawSearch(queryParams) {
|
|
150
|
+
return this.ctx.callApi('getPublicApiV1PublicSearch', queryParams);
|
|
151
|
+
}
|
|
152
|
+
// -----------------------------------------------------------------------
|
|
153
|
+
// Private helpers
|
|
154
|
+
// -----------------------------------------------------------------------
|
|
155
|
+
async fetchRawMarketByIdOrSlug(slug) {
|
|
156
|
+
let cleanSlug = slug;
|
|
157
|
+
let marketIdFromQuery = null;
|
|
158
|
+
if (slug.includes('?')) {
|
|
159
|
+
try {
|
|
160
|
+
const urlParts = slug.split('?');
|
|
161
|
+
cleanSlug = urlParts[0];
|
|
162
|
+
const query = urlParts[1];
|
|
163
|
+
const searchParams = new URLSearchParams(query);
|
|
164
|
+
marketIdFromQuery = searchParams.get('market');
|
|
165
|
+
if (marketIdFromQuery) {
|
|
166
|
+
const result = await this.fetchRawMarketByIdOrSlug(marketIdFromQuery);
|
|
167
|
+
if (result.length > 0)
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Fall back to original slug if parsing fails
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const numericId = Number(cleanSlug);
|
|
176
|
+
if (!isNaN(numericId) && String(numericId) === cleanSlug) {
|
|
177
|
+
try {
|
|
178
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.MARKETS_PATH}${numericId}`);
|
|
179
|
+
return response.data ? [response.data] : [];
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (isMarketNotFoundError(error)) {
|
|
183
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.MARKETS_PATH}`, {
|
|
184
|
+
params: { page: 1, limit: 100, active: true },
|
|
185
|
+
});
|
|
186
|
+
const markets = response.data?.markets || [];
|
|
187
|
+
return markets.filter(m => String(m.id) === cleanSlug);
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return this.fetchRawMarketsViaSearch(cleanSlug, { slug: cleanSlug });
|
|
193
|
+
}
|
|
194
|
+
async fetchRawMarketsList(params) {
|
|
195
|
+
const limit = params?.limit || 20;
|
|
196
|
+
const page = params?.offset ? Math.floor(params.offset / limit) + 1 : 1;
|
|
197
|
+
const queryParams = { page, limit };
|
|
198
|
+
if (params?.status) {
|
|
199
|
+
switch (params.status) {
|
|
200
|
+
case 'active':
|
|
201
|
+
queryParams.active = true;
|
|
202
|
+
break;
|
|
203
|
+
case 'inactive':
|
|
204
|
+
case 'closed':
|
|
205
|
+
queryParams.closed = true;
|
|
206
|
+
break;
|
|
207
|
+
case 'all':
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
queryParams.active = true;
|
|
213
|
+
}
|
|
214
|
+
if (params?.eventId) {
|
|
215
|
+
queryParams.event_id = params.eventId;
|
|
216
|
+
}
|
|
217
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.MARKETS_PATH}`, { params: queryParams });
|
|
218
|
+
return response.data?.markets || [];
|
|
219
|
+
}
|
|
220
|
+
async fetchRawMarketsViaSearch(query, params) {
|
|
221
|
+
const limit = params?.limit || 20;
|
|
222
|
+
const page = params?.offset ? Math.floor(params.offset / limit) + 1 : 1;
|
|
223
|
+
let searchQuery = query;
|
|
224
|
+
if (query.includes('-')) {
|
|
225
|
+
const tokens = query.split('-');
|
|
226
|
+
searchQuery = tokens.slice(0, 3).join(' ');
|
|
227
|
+
}
|
|
228
|
+
const queryParams = { q: searchQuery, page, limit };
|
|
229
|
+
if (params?.status) {
|
|
230
|
+
switch (params.status) {
|
|
231
|
+
case 'inactive':
|
|
232
|
+
case 'closed':
|
|
233
|
+
queryParams.events_status = 'closed';
|
|
234
|
+
queryParams.keep_closed_markets = 1;
|
|
235
|
+
break;
|
|
236
|
+
case 'all':
|
|
237
|
+
queryParams.events_status = 'all';
|
|
238
|
+
queryParams.keep_closed_markets = 1;
|
|
239
|
+
break;
|
|
240
|
+
case 'active':
|
|
241
|
+
default:
|
|
242
|
+
queryParams.events_status = 'active';
|
|
243
|
+
queryParams.keep_closed_markets = 0;
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else if (params?.slug) {
|
|
248
|
+
queryParams.events_status = 'all';
|
|
249
|
+
queryParams.keep_closed_markets = 1;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
queryParams.events_status = 'active';
|
|
253
|
+
queryParams.keep_closed_markets = 0;
|
|
254
|
+
}
|
|
255
|
+
if (params?.sort) {
|
|
256
|
+
switch (params.sort) {
|
|
257
|
+
case 'volume':
|
|
258
|
+
queryParams.sort = 'volume';
|
|
259
|
+
break;
|
|
260
|
+
case 'newest':
|
|
261
|
+
queryParams.sort = 'created_at';
|
|
262
|
+
queryParams.ascending = false;
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const searchData = await this.ctx.callApi('getPublicApiV1PublicSearch', queryParams);
|
|
267
|
+
const events = searchData?.events || [];
|
|
268
|
+
const rawMarkets = [];
|
|
269
|
+
for (const event of events) {
|
|
270
|
+
if (event.markets && Array.isArray(event.markets)) {
|
|
271
|
+
for (const market of event.markets) {
|
|
272
|
+
rawMarkets.push({ ...market, _parentEvent: event });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return rawMarkets;
|
|
277
|
+
}
|
|
278
|
+
async fetchRawEventsList(params) {
|
|
279
|
+
const limit = params.limit || 20;
|
|
280
|
+
const page = params.offset ? Math.floor(params.offset / limit) + 1 : 1;
|
|
281
|
+
const queryParams = { page, limit };
|
|
282
|
+
if (params.status) {
|
|
283
|
+
switch (params.status) {
|
|
284
|
+
case 'active':
|
|
285
|
+
queryParams.status = 'active';
|
|
286
|
+
break;
|
|
287
|
+
case 'inactive':
|
|
288
|
+
case 'closed':
|
|
289
|
+
queryParams.status = 'closed';
|
|
290
|
+
break;
|
|
291
|
+
case 'all':
|
|
292
|
+
queryParams.status = 'all';
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
queryParams.status = 'active';
|
|
298
|
+
}
|
|
299
|
+
queryParams.sort = 'volume';
|
|
300
|
+
queryParams.ascending = false;
|
|
301
|
+
const response = await this.ctx.http.get(`${utils_1.BASE_URL}${utils_1.EVENTS_PATH}`, { params: queryParams });
|
|
302
|
+
const data = response.data;
|
|
303
|
+
// API returns either a raw array or { events: [...] }
|
|
304
|
+
return Array.isArray(data) ? data : (data?.events || []);
|
|
305
|
+
}
|
|
306
|
+
async fetchRawEventsViaSearch(params) {
|
|
307
|
+
const limit = params.limit || 20;
|
|
308
|
+
const page = params.offset ? Math.floor(params.offset / limit) + 1 : 1;
|
|
309
|
+
const queryParams = {
|
|
310
|
+
q: params.query,
|
|
311
|
+
page,
|
|
312
|
+
limit,
|
|
313
|
+
events_status: mapStatus(params.status),
|
|
314
|
+
keep_closed_markets: params.status === 'all' || params.status === 'inactive' || params.status === 'closed' ? 1 : 0,
|
|
315
|
+
};
|
|
316
|
+
const searchData = await this.ctx.callApi('getPublicApiV1PublicSearch', queryParams);
|
|
317
|
+
return searchData?.events || [];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
exports.ProbableFetcher = ProbableFetcher;
|
|
321
|
+
// ---------------------------------------------------------------------------
|
|
322
|
+
// Helpers
|
|
323
|
+
// ---------------------------------------------------------------------------
|
|
324
|
+
function isNotFoundError(error) {
|
|
325
|
+
const status = error.response?.status;
|
|
326
|
+
if (status === 404 || status === 400)
|
|
327
|
+
return true;
|
|
328
|
+
if (status === 500) {
|
|
329
|
+
const data = error.response?.data;
|
|
330
|
+
const msg = typeof data === 'string' ? data : (data?.detail || data?.message || '');
|
|
331
|
+
return /not found/i.test(String(msg));
|
|
332
|
+
}
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
function isMarketNotFoundError(error) {
|
|
336
|
+
const status = error.response?.status;
|
|
337
|
+
if (status === 404 || status === 400)
|
|
338
|
+
return true;
|
|
339
|
+
if (status === 500) {
|
|
340
|
+
const data = error.response?.data;
|
|
341
|
+
const msg = typeof data === 'string' ? data : (data?.detail || data?.message || '');
|
|
342
|
+
return /not found|failed to retrieve/i.test(String(msg));
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
function mapStatus(status) {
|
|
347
|
+
switch (status) {
|
|
348
|
+
case 'inactive':
|
|
349
|
+
case 'closed':
|
|
350
|
+
return 'closed';
|
|
351
|
+
case 'all':
|
|
352
|
+
return 'all';
|
|
353
|
+
case 'active':
|
|
354
|
+
default:
|
|
355
|
+
return 'active';
|
|
356
|
+
}
|
|
357
|
+
}
|
|
@@ -27,6 +27,8 @@ export declare class ProbableExchange extends PredictionMarketExchange {
|
|
|
27
27
|
private auth?;
|
|
28
28
|
private ws?;
|
|
29
29
|
private wsConfig?;
|
|
30
|
+
private readonly fetcher;
|
|
31
|
+
private readonly normalizer;
|
|
30
32
|
constructor(credentials?: ExchangeCredentials, wsConfig?: ProbableWebSocketConfig);
|
|
31
33
|
get name(): string;
|
|
32
34
|
protected mapImplicitApiError(error: any): any;
|
|
@@ -74,6 +76,7 @@ export declare class ProbableExchange extends PredictionMarketExchange {
|
|
|
74
76
|
fetchOrderBook(id: string): Promise<OrderBook>;
|
|
75
77
|
fetchOHLCV(id: string, params: OHLCVParams): Promise<PriceCandle[]>;
|
|
76
78
|
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
79
|
+
fetchTrades(id: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
|
|
77
80
|
createOrder(params: CreateOrderParams): Promise<Order>;
|
|
78
81
|
/**
|
|
79
82
|
* Cancel an order.
|
|
@@ -89,7 +92,6 @@ export declare class ProbableExchange extends PredictionMarketExchange {
|
|
|
89
92
|
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
90
93
|
fetchPositions(): Promise<Position[]>;
|
|
91
94
|
fetchBalance(): Promise<Balance[]>;
|
|
92
|
-
fetchTrades(id: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
|
|
93
95
|
watchOrderBook(id: string, limit?: number): Promise<OrderBook>;
|
|
94
96
|
close(): Promise<void>;
|
|
95
97
|
}
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ProbableExchange = void 0;
|
|
4
4
|
const BaseExchange_1 = require("../../BaseExchange");
|
|
5
|
-
const fetchMarkets_1 = require("./fetchMarkets");
|
|
6
|
-
const fetchEvents_1 = require("./fetchEvents");
|
|
7
|
-
const fetchTrades_1 = require("./fetchTrades");
|
|
8
5
|
const auth_1 = require("./auth");
|
|
9
6
|
const websocket_1 = require("./websocket");
|
|
10
7
|
const errors_1 = require("./errors");
|
|
@@ -13,25 +10,9 @@ const clob_1 = require("@prob/clob");
|
|
|
13
10
|
const openapi_1 = require("../../utils/openapi");
|
|
14
11
|
const api_1 = require("./api");
|
|
15
12
|
const utils_1 = require("./utils");
|
|
13
|
+
const fetcher_1 = require("./fetcher");
|
|
14
|
+
const normalizer_1 = require("./normalizer");
|
|
16
15
|
const BSC_USDT_ADDRESS = '0x55d398326f99059fF775485246999027B3197955';
|
|
17
|
-
function aggregateCandles(candles, intervalMs) {
|
|
18
|
-
if (candles.length === 0)
|
|
19
|
-
return [];
|
|
20
|
-
const buckets = new Map();
|
|
21
|
-
for (const c of candles) {
|
|
22
|
-
const key = Math.floor(c.timestamp / intervalMs) * intervalMs;
|
|
23
|
-
const existing = buckets.get(key);
|
|
24
|
-
if (!existing) {
|
|
25
|
-
buckets.set(key, { ...c, timestamp: key });
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
existing.high = Math.max(existing.high, c.high);
|
|
29
|
-
existing.low = Math.min(existing.low, c.low);
|
|
30
|
-
existing.close = c.close;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return Array.from(buckets.values()).sort((a, b) => a.timestamp - b.timestamp);
|
|
34
|
-
}
|
|
35
16
|
class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
36
17
|
has = {
|
|
37
18
|
fetchMarkets: true,
|
|
@@ -58,6 +39,8 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
58
39
|
auth;
|
|
59
40
|
ws;
|
|
60
41
|
wsConfig;
|
|
42
|
+
fetcher;
|
|
43
|
+
normalizer;
|
|
61
44
|
constructor(credentials, wsConfig) {
|
|
62
45
|
super(credentials);
|
|
63
46
|
this.rateLimit = 500;
|
|
@@ -67,6 +50,13 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
67
50
|
}
|
|
68
51
|
const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.probableApiSpec, utils_1.BASE_URL);
|
|
69
52
|
this.defineImplicitApi(descriptor);
|
|
53
|
+
const ctx = {
|
|
54
|
+
http: this.http,
|
|
55
|
+
callApi: this.callApi.bind(this),
|
|
56
|
+
getHeaders: () => ({ 'Content-Type': 'application/json' }),
|
|
57
|
+
};
|
|
58
|
+
this.fetcher = new fetcher_1.ProbableFetcher(ctx);
|
|
59
|
+
this.normalizer = new normalizer_1.ProbableNormalizer();
|
|
70
60
|
}
|
|
71
61
|
get name() {
|
|
72
62
|
return 'Probable';
|
|
@@ -82,13 +72,38 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
82
72
|
return this.auth;
|
|
83
73
|
}
|
|
84
74
|
// --------------------------------------------------------------------------
|
|
85
|
-
// Market Data (
|
|
75
|
+
// Market Data (fetcher -> normalizer)
|
|
86
76
|
// --------------------------------------------------------------------------
|
|
87
77
|
async fetchMarketsImpl(params) {
|
|
88
|
-
|
|
78
|
+
const rawMarkets = await this.fetcher.fetchRawMarkets(params);
|
|
79
|
+
const markets = rawMarkets
|
|
80
|
+
.map((raw) => this.normalizer.normalizeMarket(raw))
|
|
81
|
+
.filter((m) => m !== null);
|
|
82
|
+
// Filter by outcomeId client-side if requested
|
|
83
|
+
const filtered = params?.outcomeId
|
|
84
|
+
? markets.filter(m => m.outcomes.some(o => o.outcomeId === params.outcomeId))
|
|
85
|
+
: markets;
|
|
86
|
+
// Slug-based exact matching for search results
|
|
87
|
+
if (params?.slug && rawMarkets.length > 0) {
|
|
88
|
+
const exact = filtered.filter(m => m.marketId === params.slug ||
|
|
89
|
+
m.url.includes(params.slug) ||
|
|
90
|
+
rawMarkets.find(r => this.normalizer.normalizeMarket(r)?.marketId === m.marketId)?._parentEvent?.slug === params.slug);
|
|
91
|
+
if (exact.length > 0) {
|
|
92
|
+
await this.normalizer.enrichMarketsWithPrices(exact, (tokenId) => this.fetcher.fetchRawMidpoint(tokenId));
|
|
93
|
+
return exact;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
await this.normalizer.enrichMarketsWithPrices(filtered, (tokenId) => this.fetcher.fetchRawMidpoint(tokenId));
|
|
97
|
+
return filtered;
|
|
89
98
|
}
|
|
90
99
|
async fetchEventsImpl(params) {
|
|
91
|
-
|
|
100
|
+
const rawEvents = await this.fetcher.fetchRawEvents(params);
|
|
101
|
+
const events = rawEvents
|
|
102
|
+
.map((raw) => this.normalizer.normalizeEvent(raw))
|
|
103
|
+
.filter((e) => e !== null);
|
|
104
|
+
const allMarkets = events.flatMap((e) => e.markets);
|
|
105
|
+
await this.normalizer.enrichMarketsWithPrices(allMarkets, (tokenId) => this.fetcher.fetchRawMidpoint(tokenId));
|
|
106
|
+
return events;
|
|
92
107
|
}
|
|
93
108
|
/**
|
|
94
109
|
* Fetch a single event by its numeric ID (Probable only).
|
|
@@ -110,7 +125,14 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
110
125
|
* print(len(event.markets), 'markets')
|
|
111
126
|
*/
|
|
112
127
|
async getEventById(id) {
|
|
113
|
-
|
|
128
|
+
const raw = await this.fetcher.fetchRawEventById(id);
|
|
129
|
+
if (!raw)
|
|
130
|
+
return null;
|
|
131
|
+
const event = this.normalizer.normalizeEvent(raw);
|
|
132
|
+
if (event) {
|
|
133
|
+
await this.normalizer.enrichMarketsWithPrices(event.markets, (tokenId) => this.fetcher.fetchRawMidpoint(tokenId));
|
|
134
|
+
}
|
|
135
|
+
return event;
|
|
114
136
|
}
|
|
115
137
|
/**
|
|
116
138
|
* Fetch a single event by its URL slug (Probable only).
|
|
@@ -130,80 +152,42 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
130
152
|
* print(event.title)
|
|
131
153
|
*/
|
|
132
154
|
async getEventBySlug(slug) {
|
|
133
|
-
|
|
155
|
+
const raw = await this.fetcher.fetchRawEventBySlug(slug);
|
|
156
|
+
if (!raw)
|
|
157
|
+
return null;
|
|
158
|
+
const event = this.normalizer.normalizeEvent(raw);
|
|
159
|
+
if (event) {
|
|
160
|
+
await this.normalizer.enrichMarketsWithPrices(event.markets, (tokenId) => this.fetcher.fetchRawMidpoint(tokenId));
|
|
161
|
+
}
|
|
162
|
+
return event;
|
|
134
163
|
}
|
|
135
164
|
async fetchOrderBook(id) {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
.map((level) => ({ price: parseFloat(level.price), size: parseFloat(level.size) }))
|
|
139
|
-
.sort((a, b) => b.price - a.price);
|
|
140
|
-
const asks = (data.asks || [])
|
|
141
|
-
.map((level) => ({ price: parseFloat(level.price), size: parseFloat(level.size) }))
|
|
142
|
-
.sort((a, b) => a.price - b.price);
|
|
143
|
-
return {
|
|
144
|
-
bids,
|
|
145
|
-
asks,
|
|
146
|
-
timestamp: data.timestamp ? new Date(data.timestamp).getTime() : Date.now(),
|
|
147
|
-
};
|
|
165
|
+
const raw = await this.fetcher.fetchRawOrderBook(id);
|
|
166
|
+
return this.normalizer.normalizeOrderBook(raw, id);
|
|
148
167
|
}
|
|
149
168
|
async fetchOHLCV(id, params) {
|
|
150
169
|
if (!params.resolution) {
|
|
151
170
|
throw new Error('fetchOHLCV requires a resolution parameter.');
|
|
152
171
|
}
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
'5m': '1m',
|
|
156
|
-
'15m': '1m',
|
|
157
|
-
'1h': '1h',
|
|
158
|
-
'6h': '6h',
|
|
159
|
-
'1d': '1d',
|
|
160
|
-
};
|
|
161
|
-
const queryParams = {
|
|
162
|
-
market: id,
|
|
163
|
-
interval: INTERVAL_MAP[params.resolution] || '1h',
|
|
164
|
-
};
|
|
165
|
-
if (params.start)
|
|
166
|
-
queryParams.startTs = Math.floor(params.start.getTime() / 1000);
|
|
167
|
-
if (params.end)
|
|
168
|
-
queryParams.endTs = Math.floor(params.end.getTime() / 1000);
|
|
169
|
-
const data = await this.callApi('getPublicApiV1PricesHistory', queryParams);
|
|
170
|
-
const points = data?.history || data || [];
|
|
171
|
-
let candles = points
|
|
172
|
-
.map((p) => {
|
|
173
|
-
const price = Number(p.p);
|
|
174
|
-
const ts = Number(p.t) * 1000;
|
|
175
|
-
return { timestamp: ts, open: price, high: price, low: price, close: price, volume: 0 };
|
|
176
|
-
})
|
|
177
|
-
.sort((a, b) => a.timestamp - b.timestamp);
|
|
178
|
-
if (params.resolution === '5m') {
|
|
179
|
-
candles = aggregateCandles(candles, 5 * 60 * 1000);
|
|
180
|
-
}
|
|
181
|
-
else if (params.resolution === '15m') {
|
|
182
|
-
candles = aggregateCandles(candles, 15 * 60 * 1000);
|
|
183
|
-
}
|
|
184
|
-
if (params.limit) {
|
|
185
|
-
candles = candles.slice(-params.limit);
|
|
186
|
-
}
|
|
187
|
-
return candles;
|
|
172
|
+
const rawPoints = await this.fetcher.fetchRawOHLCV(id, params);
|
|
173
|
+
return this.normalizer.normalizeOHLCV(rawPoints, params);
|
|
188
174
|
}
|
|
189
175
|
async fetchMyTrades(params) {
|
|
190
176
|
const auth = this.ensureAuth();
|
|
191
177
|
const address = auth.getAddress();
|
|
192
|
-
const
|
|
193
|
-
|
|
178
|
+
const rawTrades = await this.fetcher.fetchRawMyTrades(params || {}, address);
|
|
179
|
+
return rawTrades.map((raw, i) => this.normalizer.normalizeUserTrade(raw, i));
|
|
180
|
+
}
|
|
181
|
+
async fetchTrades(id, params) {
|
|
182
|
+
const auth = this.ensureAuth();
|
|
183
|
+
const client = auth.getClobClient();
|
|
184
|
+
// Use CLOB client directly for trades (legacy behaviour preserved)
|
|
185
|
+
const queryParams = { tokenId: id };
|
|
186
|
+
if (params.limit)
|
|
194
187
|
queryParams.limit = params.limit;
|
|
195
|
-
const
|
|
196
|
-
const trades = Array.isArray(
|
|
197
|
-
return trades.map((
|
|
198
|
-
id: String(t.tradeId || t.id || t.timestamp),
|
|
199
|
-
timestamp: typeof t.time === 'number'
|
|
200
|
-
? (t.time > 1e12 ? t.time : t.time * 1000)
|
|
201
|
-
: Date.now(),
|
|
202
|
-
price: parseFloat(t.price || '0'),
|
|
203
|
-
amount: parseFloat(t.qty || t.size || t.amount || '0'),
|
|
204
|
-
side: (t.side || '').toLowerCase() === 'buy' ? 'buy' : 'sell',
|
|
205
|
-
orderId: t.orderId,
|
|
206
|
-
}));
|
|
188
|
+
const response = await client.getTrades(queryParams);
|
|
189
|
+
const trades = Array.isArray(response) ? response : response?.data || [];
|
|
190
|
+
return trades.map((raw, i) => this.normalizer.normalizeTrade(raw, i));
|
|
207
191
|
}
|
|
208
192
|
// --------------------------------------------------------------------------
|
|
209
193
|
// Trading Methods
|
|
@@ -236,7 +220,6 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
236
220
|
unsignedOrder.feeRateBps = BigInt(params.fee);
|
|
237
221
|
}
|
|
238
222
|
const response = await client.postOrder(unsignedOrder);
|
|
239
|
-
// postOrder returns PostOrderResponse which can be success or error
|
|
240
223
|
if (response && 'code' in response && response.code !== undefined) {
|
|
241
224
|
throw new Error(response.msg || 'Order placement failed');
|
|
242
225
|
}
|
|
@@ -365,18 +348,8 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
365
348
|
try {
|
|
366
349
|
const auth = this.ensureAuth();
|
|
367
350
|
const address = auth.getAddress();
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
return data.map((p) => ({
|
|
371
|
-
marketId: String(p.conditionId || p.condition_id || ''),
|
|
372
|
-
outcomeId: String(p.asset || p.token_id || ''),
|
|
373
|
-
outcomeLabel: p.outcome || p.title || 'Unknown',
|
|
374
|
-
size: parseFloat(p.size || '0'),
|
|
375
|
-
entryPrice: parseFloat(p.avgPrice || p.avg_price || '0'),
|
|
376
|
-
currentPrice: parseFloat(p.curPrice || p.cur_price || '0'),
|
|
377
|
-
unrealizedPnL: parseFloat(p.cashPnl || p.cash_pnl || '0'),
|
|
378
|
-
realizedPnL: parseFloat(p.realizedPnl || p.realized_pnl || '0'),
|
|
379
|
-
}));
|
|
351
|
+
const rawItems = await this.fetcher.fetchRawPositions(address);
|
|
352
|
+
return rawItems.map((raw) => this.normalizer.normalizePosition(raw));
|
|
380
353
|
}
|
|
381
354
|
catch (error) {
|
|
382
355
|
throw errors_1.probableErrorMapper.mapError(error);
|
|
@@ -428,11 +401,6 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
428
401
|
throw errors_1.probableErrorMapper.mapError(error);
|
|
429
402
|
}
|
|
430
403
|
}
|
|
431
|
-
async fetchTrades(id, params) {
|
|
432
|
-
const auth = this.ensureAuth();
|
|
433
|
-
const client = auth.getClobClient();
|
|
434
|
-
return (0, fetchTrades_1.fetchTrades)(id, params, client, this.http);
|
|
435
|
-
}
|
|
436
404
|
// --------------------------------------------------------------------------
|
|
437
405
|
// WebSocket Streaming (public, no auth needed)
|
|
438
406
|
// --------------------------------------------------------------------------
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OHLCVParams } from '../../BaseExchange';
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Position } from '../../types';
|
|
3
|
+
import { IExchangeNormalizer } from '../interfaces';
|
|
4
|
+
import { ProbableRawMarket, ProbableRawEvent, ProbableRawOrderBook, ProbableRawPricePoint, ProbableRawTrade, ProbableRawPosition } from './fetcher';
|
|
5
|
+
export declare class ProbableNormalizer implements IExchangeNormalizer<ProbableRawMarket, ProbableRawEvent> {
|
|
6
|
+
normalizeMarket(raw: ProbableRawMarket): UnifiedMarket | null;
|
|
7
|
+
normalizeEvent(raw: ProbableRawEvent): UnifiedEvent | null;
|
|
8
|
+
normalizeOrderBook(raw: ProbableRawOrderBook, _id: string): OrderBook;
|
|
9
|
+
normalizeOHLCV(rawPoints: ProbableRawPricePoint[], params: OHLCVParams): PriceCandle[];
|
|
10
|
+
normalizeTrade(raw: ProbableRawTrade, index: number): Trade;
|
|
11
|
+
normalizeUserTrade(raw: ProbableRawTrade, index: number): UserTrade;
|
|
12
|
+
normalizePosition(raw: ProbableRawPosition): Position;
|
|
13
|
+
enrichMarketsWithPrices(markets: UnifiedMarket[], callMidpoint: (tokenId: string) => Promise<any>): Promise<void>;
|
|
14
|
+
}
|