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.
Files changed (111) hide show
  1. package/dist/exchanges/baozi/fetcher.d.ts +40 -0
  2. package/dist/exchanges/baozi/fetcher.js +155 -0
  3. package/dist/exchanges/baozi/index.d.ts +2 -0
  4. package/dist/exchanges/baozi/index.js +60 -131
  5. package/dist/exchanges/baozi/normalizer.d.ts +14 -0
  6. package/dist/exchanges/baozi/normalizer.js +208 -0
  7. package/dist/exchanges/interfaces.d.ts +28 -0
  8. package/dist/exchanges/interfaces.js +2 -0
  9. package/dist/exchanges/kalshi/api.d.ts +1 -1
  10. package/dist/exchanges/kalshi/api.js +1 -1
  11. package/dist/exchanges/kalshi/fetcher.d.ts +126 -0
  12. package/dist/exchanges/kalshi/fetcher.js +313 -0
  13. package/dist/exchanges/kalshi/index.d.ts +6 -6
  14. package/dist/exchanges/kalshi/index.js +119 -202
  15. package/dist/exchanges/kalshi/normalizer.d.ts +25 -0
  16. package/dist/exchanges/kalshi/normalizer.js +294 -0
  17. package/dist/exchanges/limitless/api.d.ts +1 -1
  18. package/dist/exchanges/limitless/api.js +1 -1
  19. package/dist/exchanges/limitless/fetcher.d.ts +81 -0
  20. package/dist/exchanges/limitless/fetcher.js +238 -0
  21. package/dist/exchanges/limitless/index.d.ts +6 -9
  22. package/dist/exchanges/limitless/index.js +81 -79
  23. package/dist/exchanges/limitless/normalizer.d.ts +14 -0
  24. package/dist/exchanges/limitless/normalizer.js +117 -0
  25. package/dist/exchanges/limitless/websocket.d.ts +3 -0
  26. package/dist/exchanges/limitless/websocket.js +5 -4
  27. package/dist/exchanges/myriad/api.d.ts +1 -1
  28. package/dist/exchanges/myriad/api.js +1 -1
  29. package/dist/exchanges/myriad/fetcher.d.ts +73 -0
  30. package/dist/exchanges/myriad/fetcher.js +217 -0
  31. package/dist/exchanges/myriad/index.d.ts +2 -0
  32. package/dist/exchanges/myriad/index.js +40 -97
  33. package/dist/exchanges/myriad/normalizer.d.ts +14 -0
  34. package/dist/exchanges/myriad/normalizer.js +167 -0
  35. package/dist/exchanges/myriad/websocket.d.ts +3 -1
  36. package/dist/exchanges/myriad/websocket.js +4 -3
  37. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  38. package/dist/exchanges/polymarket/api-clob.js +1 -1
  39. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  40. package/dist/exchanges/polymarket/api-data.js +1 -1
  41. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  42. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  43. package/dist/exchanges/polymarket/fetcher.d.ts +99 -0
  44. package/dist/exchanges/polymarket/fetcher.js +335 -0
  45. package/dist/exchanges/polymarket/index.d.ts +2 -0
  46. package/dist/exchanges/polymarket/index.js +80 -66
  47. package/dist/exchanges/polymarket/normalizer.d.ts +18 -0
  48. package/dist/exchanges/polymarket/normalizer.js +126 -0
  49. package/dist/exchanges/probable/api.d.ts +1 -1
  50. package/dist/exchanges/probable/api.js +1 -1
  51. package/dist/exchanges/probable/fetcher.d.ts +106 -0
  52. package/dist/exchanges/probable/fetcher.js +357 -0
  53. package/dist/exchanges/probable/index.d.ts +3 -1
  54. package/dist/exchanges/probable/index.js +73 -105
  55. package/dist/exchanges/probable/normalizer.d.ts +14 -0
  56. package/dist/exchanges/probable/normalizer.js +109 -0
  57. package/package.json +3 -3
  58. package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
  59. package/dist/exchanges/baozi/fetchEvents.js +0 -39
  60. package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
  61. package/dist/exchanges/baozi/fetchMarkets.js +0 -160
  62. package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
  63. package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
  64. package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
  65. package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
  66. package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
  67. package/dist/exchanges/baozi/fetchTrades.js +0 -10
  68. package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
  69. package/dist/exchanges/kalshi/fetchEvents.js +0 -196
  70. package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
  71. package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
  72. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
  73. package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
  74. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
  75. package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
  76. package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
  77. package/dist/exchanges/kalshi/fetchTrades.js +0 -33
  78. package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
  79. package/dist/exchanges/limitless/fetchEvents.js +0 -173
  80. package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
  81. package/dist/exchanges/limitless/fetchMarkets.js +0 -152
  82. package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
  83. package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
  84. package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
  85. package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
  86. package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
  87. package/dist/exchanges/limitless/fetchTrades.js +0 -27
  88. package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
  89. package/dist/exchanges/myriad/fetchEvents.js +0 -48
  90. package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
  91. package/dist/exchanges/myriad/fetchMarkets.js +0 -102
  92. package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
  93. package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
  94. package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
  95. package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
  96. package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
  97. package/dist/exchanges/polymarket/fetchEvents.js +0 -135
  98. package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
  99. package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
  100. package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
  101. package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
  102. package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
  103. package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
  104. package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
  105. package/dist/exchanges/polymarket/fetchTrades.js +0 -43
  106. package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
  107. package/dist/exchanges/probable/fetchEvents.js +0 -151
  108. package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
  109. package/dist/exchanges/probable/fetchMarkets.js +0 -239
  110. package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
  111. 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 (read-only, no auth needed)
75
+ // Market Data (fetcher -> normalizer)
86
76
  // --------------------------------------------------------------------------
87
77
  async fetchMarketsImpl(params) {
88
- return (0, fetchMarkets_1.fetchMarkets)(params, this.http, (tokenId) => this.callApi('getPublicApiV1Midpoint', { token_id: tokenId }), (queryParams) => this.callApi('getPublicApiV1PublicSearch', queryParams));
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
- return (0, fetchEvents_1.fetchEvents)(params, this.http, (tokenId) => this.callApi('getPublicApiV1Midpoint', { token_id: tokenId }), (queryParams) => this.callApi('getPublicApiV1PublicSearch', queryParams));
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
- return (0, fetchEvents_1.fetchEventById)(id, this.http, (tokenId) => this.callApi('getPublicApiV1Midpoint', { token_id: tokenId }));
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
- return (0, fetchEvents_1.fetchEventBySlug)(slug, this.http, (tokenId) => this.callApi('getPublicApiV1Midpoint', { token_id: tokenId }));
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 data = await this.callApi('getPublicApiV1Book', { token_id: id });
137
- const bids = (data.bids || [])
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 INTERVAL_MAP = {
154
- '1m': '1m',
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 queryParams = { user: address };
193
- if (params?.limit)
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 data = await this.callApi('getPublicApiV1Trades', queryParams);
196
- const trades = Array.isArray(data) ? data : (data.data || []);
197
- return trades.map((t) => ({
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 result = await this.callApi('getPublicApiV1PositionCurrent', { user: address, limit: 500 });
369
- const data = Array.isArray(result) ? result : (result?.data || []);
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
+ }