pmxt-core 2.20.0 → 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 (113) 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/dist/utils/error-mapper.d.ts +8 -0
  58. package/dist/utils/error-mapper.js +58 -26
  59. package/package.json +3 -3
  60. package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
  61. package/dist/exchanges/baozi/fetchEvents.js +0 -39
  62. package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
  63. package/dist/exchanges/baozi/fetchMarkets.js +0 -160
  64. package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
  65. package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
  66. package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
  67. package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
  68. package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
  69. package/dist/exchanges/baozi/fetchTrades.js +0 -10
  70. package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
  71. package/dist/exchanges/kalshi/fetchEvents.js +0 -196
  72. package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
  73. package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
  74. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
  75. package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
  76. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
  77. package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
  78. package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
  79. package/dist/exchanges/kalshi/fetchTrades.js +0 -33
  80. package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
  81. package/dist/exchanges/limitless/fetchEvents.js +0 -173
  82. package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
  83. package/dist/exchanges/limitless/fetchMarkets.js +0 -152
  84. package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
  85. package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
  86. package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
  87. package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
  88. package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
  89. package/dist/exchanges/limitless/fetchTrades.js +0 -27
  90. package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
  91. package/dist/exchanges/myriad/fetchEvents.js +0 -48
  92. package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
  93. package/dist/exchanges/myriad/fetchMarkets.js +0 -102
  94. package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
  95. package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
  96. package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
  97. package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
  98. package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
  99. package/dist/exchanges/polymarket/fetchEvents.js +0 -135
  100. package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
  101. package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
  102. package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
  103. package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
  104. package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
  105. package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
  106. package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
  107. package/dist/exchanges/polymarket/fetchTrades.js +0 -43
  108. package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
  109. package/dist/exchanges/probable/fetchEvents.js +0 -151
  110. package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
  111. package/dist/exchanges/probable/fetchMarkets.js +0 -239
  112. package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
  113. package/dist/exchanges/probable/fetchTrades.js +0 -40
@@ -13,11 +13,8 @@ const api_1 = require("./api");
13
13
  const auth_1 = require("./auth");
14
14
  const client_1 = require("./client");
15
15
  const errors_2 = require("./errors");
16
- const fetchEvents_1 = require("./fetchEvents");
17
- const fetchMarkets_1 = require("./fetchMarkets");
18
- const fetchOHLCV_1 = require("./fetchOHLCV");
19
- const fetchOrderBook_1 = require("./fetchOrderBook");
20
- const fetchTrades_1 = require("./fetchTrades");
16
+ const fetcher_1 = require("./fetcher");
17
+ const normalizer_1 = require("./normalizer");
21
18
  const websocket_1 = require("./websocket");
22
19
  class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
23
20
  has = {
@@ -46,6 +43,8 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
46
43
  client;
47
44
  wsConfig;
48
45
  ws;
46
+ fetcher;
47
+ normalizer;
49
48
  constructor(options) {
50
49
  // Support both old signature (credentials only) and new signature (options object)
51
50
  let credentials;
@@ -86,27 +85,81 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
86
85
  // Register implicit API for Limitless REST endpoints
87
86
  const apiDescriptor = (0, openapi_1.parseOpenApiSpec)(api_1.limitlessApiSpec);
88
87
  this.defineImplicitApi(apiDescriptor);
88
+ const ctx = {
89
+ http: this.http,
90
+ callApi: this.callApi.bind(this),
91
+ getHeaders: () => this.getHeaders(),
92
+ };
93
+ this.fetcher = new fetcher_1.LimitlessFetcher(ctx, this.http, this.auth?.getApiKey());
94
+ this.normalizer = new normalizer_1.LimitlessNormalizer();
89
95
  }
90
96
  get name() {
91
97
  return 'Limitless';
92
98
  }
93
- // ----------------------------------------------------------------------------
94
- // Implementation methods for CCXT-style API
95
- // ----------------------------------------------------------------------------
99
+ getHeaders() {
100
+ return { 'Content-Type': 'application/json' };
101
+ }
102
+ // ------------------------------------------------------------------------
103
+ // Market Data (fetcher -> normalizer)
104
+ // ------------------------------------------------------------------------
105
+ async fetchMarketsImpl(params) {
106
+ const rawMarkets = await this.fetcher.fetchRawMarkets(params);
107
+ // Handle outcomeId filtering (client-side)
108
+ if (params?.outcomeId) {
109
+ return rawMarkets
110
+ .map((raw) => this.normalizer.normalizeMarket(raw))
111
+ .filter((m) => m !== null && m.outcomes.length > 0)
112
+ .filter(m => m.outcomes.some(o => o.outcomeId === params.outcomeId));
113
+ }
114
+ // Handle search results -- filter and limit
115
+ if (params?.query) {
116
+ return rawMarkets
117
+ .map((raw) => this.normalizer.normalizeMarket(raw))
118
+ .filter((m) => m !== null && m.outcomes.length > 0)
119
+ .slice(0, params?.limit || 250000);
120
+ }
121
+ // Default fetch -- normalize, filter, sort, apply offset/limit
122
+ const unifiedMarkets = rawMarkets
123
+ .map((raw) => this.normalizer.normalizeMarket(raw))
124
+ .filter((m) => m !== null && m.outcomes.length > 0);
125
+ if (params?.sort === 'volume') {
126
+ unifiedMarkets.sort((a, b) => (b.volume ?? 0) - (a.volume ?? 0));
127
+ }
128
+ const offset = params?.offset || 0;
129
+ const limit = params?.limit || 250000;
130
+ const marketsAfterOffset = offset > 0 ? unifiedMarkets.slice(offset) : unifiedMarkets;
131
+ return marketsAfterOffset.slice(0, limit);
132
+ }
133
+ async fetchEventsImpl(params) {
134
+ const rawEvents = await this.fetcher.fetchRawEvents(params);
135
+ return rawEvents
136
+ .map((raw) => this.normalizer.normalizeEvent(raw))
137
+ .filter((e) => e !== null);
138
+ }
96
139
  async fetchOHLCV(id, params) {
97
- return (0, fetchOHLCV_1.fetchOHLCV)(id, params, this.callApi.bind(this));
140
+ const rawPrices = await this.fetcher.fetchRawOHLCV(id, params);
141
+ return this.normalizer.normalizeOHLCV(rawPrices, params);
98
142
  }
99
143
  async fetchOrderBook(id) {
100
- return (0, fetchOrderBook_1.fetchOrderBook)(id, this.callApi.bind(this));
144
+ const rawOrderBook = await this.fetcher.fetchRawOrderBook(id);
145
+ return this.normalizer.normalizeOrderBook(rawOrderBook, id);
101
146
  }
102
147
  async fetchTrades(id, params) {
103
- // Deprecation warning
104
148
  if ('resolution' in params && params.resolution !== undefined) {
105
149
  console.warn('[pmxt] Warning: The "resolution" parameter is deprecated for fetchTrades() and will be ignored. ' +
106
150
  'It will be removed in v3.0.0. Please remove it from your code.');
107
151
  }
108
- return (0, fetchTrades_1.fetchTrades)(id, params, this.http);
152
+ const rawTrades = await this.fetcher.fetchRawTrades(id, params);
153
+ return rawTrades.map((raw, i) => this.normalizer.normalizeTrade(raw, i));
109
154
  }
155
+ async fetchMyTrades(params) {
156
+ const auth = this.ensureAuth();
157
+ const rawTrades = await this.fetcher.fetchRawMyTrades(params || {}, auth.getApiKey());
158
+ return rawTrades.map((raw, i) => this.normalizer.normalizeUserTrade(raw, i));
159
+ }
160
+ // ------------------------------------------------------------------------
161
+ // Trading (kept in SDK class -- uses LimitlessClient)
162
+ // ------------------------------------------------------------------------
110
163
  async createOrder(params) {
111
164
  const client = this.ensureClient();
112
165
  try {
@@ -147,9 +200,6 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
147
200
  throw errors_2.limitlessErrorMapper.mapError(error);
148
201
  }
149
202
  }
150
- // ----------------------------------------------------------------------------
151
- // Trading Methods
152
- // ----------------------------------------------------------------------------
153
203
  async cancelOrder(orderId) {
154
204
  const client = this.ensureClient();
155
205
  try {
@@ -172,18 +222,12 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
172
222
  }
173
223
  }
174
224
  async fetchOrder(orderId) {
175
- // Limitless API does not support fetching a single order by ID directly without the market slug.
176
- // We would need to scan all markets or maintain a local cache.
177
- // For now, we throw specific error.
178
225
  throw new Error('Limitless: fetchOrder(id) is not supported directly. Use fetchOpenOrders(marketSlug).');
179
226
  }
180
227
  async fetchOpenOrders(marketId) {
181
228
  const client = this.ensureClient();
182
229
  try {
183
230
  if (!marketId) {
184
- // We cannot fetch ALL open orders globally efficiently on Limitless (no endpoint).
185
- // We would need to fetch all active markets and query each.
186
- // For this MVP, we return empty or throw. Returning empty to be "compliant" with interface but logging warning.
187
231
  console.warn('Limitless: fetchOpenOrders requires marketId (slug) to be efficient. Returning [].');
188
232
  return [];
189
233
  }
@@ -206,26 +250,6 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
206
250
  throw errors_2.limitlessErrorMapper.mapError(error);
207
251
  }
208
252
  }
209
- async fetchMyTrades(params) {
210
- const auth = this.ensureAuth();
211
- try {
212
- const response = await this.http.get('https://api.limitless.exchange/portfolio/trades', {
213
- headers: { Authorization: `Bearer ${auth.getApiKey()}` },
214
- });
215
- const trades = Array.isArray(response.data) ? response.data : (response.data?.data || []);
216
- return trades.map((t) => ({
217
- id: t.id || String(t.timestamp),
218
- timestamp: t.createdAt ? new Date(t.createdAt).getTime() : (t.timestamp || 0),
219
- price: parseFloat(t.price || '0'),
220
- amount: parseFloat(t.quantity || t.amount || '0'),
221
- side: (t.side || '').toLowerCase() === 'buy' ? 'buy' : 'sell',
222
- orderId: t.orderId,
223
- }));
224
- }
225
- catch (error) {
226
- throw errors_2.limitlessErrorMapper.mapError(error);
227
- }
228
- }
229
253
  async fetchClosedOrders(params) {
230
254
  const client = this.ensureClient();
231
255
  if (!params?.marketId) {
@@ -268,25 +292,18 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
268
292
  timestamp: o.createdAt ? new Date(o.createdAt).getTime() : Date.now(),
269
293
  }));
270
294
  }
295
+ // ------------------------------------------------------------------------
296
+ // Positions & Balance (fetcher -> normalizer)
297
+ // ------------------------------------------------------------------------
271
298
  async fetchPositions(address) {
272
- // Public endpoint no auth needed when an address is explicitly supplied.
299
+ // Public endpoint -- no auth needed when an address is explicitly supplied.
273
300
  const account = address ?? this.ensureAuth().getAddress();
274
- const result = await this.callApi('PublicPortfolioController_getPositions', { account });
275
- const data = result?.data || result || [];
276
- return data.map((p) => ({
277
- marketId: p.market?.slug || p.conditionId,
278
- outcomeId: p.asset,
279
- outcomeLabel: p.outcome || 'Unknown',
280
- size: parseFloat(p.size || '0'),
281
- entryPrice: parseFloat(p.avgPrice || '0'),
282
- currentPrice: parseFloat(p.curPrice || '0'),
283
- unrealizedPnL: parseFloat(p.cashPnl || '0'),
284
- realizedPnL: parseFloat(p.realizedPnl || '0'),
285
- }));
301
+ const rawItems = await this.fetcher.fetchRawPositions(account);
302
+ return rawItems.map((raw) => this.normalizer.normalizePosition(raw));
286
303
  }
287
304
  async fetchBalance(address) {
288
305
  try {
289
- // When an external address is provided use on-chain RPC only no auth required.
306
+ // When an external address is provided use on-chain RPC only -- no auth required.
290
307
  const targetAddress = address ?? this.ensureAuth().getAddress();
291
308
  return await this.getAddressOnChainBalance(targetAddress);
292
309
  }
@@ -294,10 +311,11 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
294
311
  throw errors_2.limitlessErrorMapper.mapError(error);
295
312
  }
296
313
  }
314
+ // ------------------------------------------------------------------------
315
+ // WebSocket
316
+ // ------------------------------------------------------------------------
297
317
  async watchOrderBook(id, limit) {
298
318
  const ws = this.ensureWs();
299
- // Return the snapshot immediately (this allows the script to proceed)
300
- // Future versions could implement a more sophisticated queueing system
301
319
  return ws.watchOrderBook(id);
302
320
  }
303
321
  async watchTrades(id, address, since, limit) {
@@ -338,13 +356,10 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
338
356
  * exchange.watch_user_positions(callback=lambda data: print('Position update:', data))
339
357
  */
340
358
  async watchUserPositions(callback) {
341
- this.ensureAuth(); // Ensure API key is available
359
+ this.ensureAuth();
342
360
  const ws = this.ensureWs();
343
361
  return ws.watchUserPositions(callback);
344
362
  }
345
- // ----------------------------------------------------------------------------
346
- // WebSocket Methods
347
- // ----------------------------------------------------------------------------
348
363
  /**
349
364
  * Watch user transactions in real-time (Limitless only).
350
365
  * Requires API key authentication.
@@ -360,7 +375,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
360
375
  * exchange.watch_user_transactions(callback=lambda data: print('Transaction:', data))
361
376
  */
362
377
  async watchUserTransactions(callback) {
363
- this.ensureAuth(); // Ensure API key is available
378
+ this.ensureAuth();
364
379
  const ws = this.ensureWs();
365
380
  return ws.watchUserTransactions(callback);
366
381
  }
@@ -404,17 +419,9 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
404
419
  mapImplicitApiError(error) {
405
420
  throw errors_2.limitlessErrorMapper.mapError(error);
406
421
  }
407
- // ----------------------------------------------------------------------------
408
- // Implicit API Error Mapping
409
- // ----------------------------------------------------------------------------
410
- async fetchMarketsImpl(params) {
411
- // Pass API key if available for authenticated requests
412
- const apiKey = this.auth?.getApiKey();
413
- return (0, fetchMarkets_1.fetchMarkets)(params, apiKey, this.callApi.bind(this));
414
- }
415
- async fetchEventsImpl(params) {
416
- return (0, fetchEvents_1.fetchEvents)(params, this.callApi.bind(this), this.http);
417
- }
422
+ // ------------------------------------------------------------------------
423
+ // Private helpers
424
+ // ------------------------------------------------------------------------
418
425
  async getAddressOnChainBalance(targetAddress) {
419
426
  // Query USDC balance directly from Base chain
420
427
  const provider = new ethers_1.providers.JsonRpcProvider('https://mainnet.base.org');
@@ -439,9 +446,6 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
439
446
  }
440
447
  return this.client;
441
448
  }
442
- /**
443
- * Ensure authentication is initialized before trading operations.
444
- */
445
449
  ensureAuth() {
446
450
  if (!this.auth) {
447
451
  throw new errors_1.AuthenticationError('Trading operations require authentication. ' +
@@ -449,14 +453,12 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
449
453
  }
450
454
  return this.auth;
451
455
  }
452
- /**
453
- * Initialize WebSocket with API key if available.
454
- */
455
456
  ensureWs() {
456
457
  if (!this.ws) {
457
458
  const wsConfig = {
458
459
  ...this.wsConfig,
459
460
  apiKey: this.auth?.getApiKey(),
461
+ fetchOrderBook: (id) => this.fetchOrderBook(id),
460
462
  };
461
463
  this.ws = new websocket_1.LimitlessWebSocket(this.callApi.bind(this), wsConfig);
462
464
  }
@@ -0,0 +1,14 @@
1
+ import { OHLCVParams } from '../../BaseExchange';
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Position, Balance } from '../../types';
3
+ import { IExchangeNormalizer } from '../interfaces';
4
+ import { LimitlessRawMarket, LimitlessRawEvent, LimitlessRawPricePoint, LimitlessRawOrderBook } from './fetcher';
5
+ export declare class LimitlessNormalizer implements IExchangeNormalizer<LimitlessRawMarket, LimitlessRawEvent> {
6
+ normalizeMarket(raw: LimitlessRawMarket): UnifiedMarket | null;
7
+ normalizeEvent(raw: LimitlessRawEvent): UnifiedEvent | null;
8
+ normalizeOHLCV(rawPrices: LimitlessRawPricePoint[], params: OHLCVParams): PriceCandle[];
9
+ normalizeOrderBook(raw: LimitlessRawOrderBook, _id: string): OrderBook;
10
+ normalizeTrade(_raw: unknown, _index: number): Trade;
11
+ normalizeUserTrade(raw: unknown, _index: number): UserTrade;
12
+ normalizePosition(raw: unknown): Position;
13
+ normalizeBalance(raw: unknown): Balance[];
14
+ }
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LimitlessNormalizer = void 0;
4
+ const utils_1 = require("./utils");
5
+ // Limitless uses USDC with 6 decimals
6
+ const USDC_DECIMALS = 6;
7
+ const USDC_SCALE = Math.pow(10, USDC_DECIMALS);
8
+ function convertSize(rawSize) {
9
+ return rawSize / USDC_SCALE;
10
+ }
11
+ class LimitlessNormalizer {
12
+ normalizeMarket(raw) {
13
+ return (0, utils_1.mapMarketToUnified)(raw);
14
+ }
15
+ normalizeEvent(raw) {
16
+ if (!raw)
17
+ return null;
18
+ let marketsList = [];
19
+ if (raw.markets && Array.isArray(raw.markets)) {
20
+ marketsList = raw.markets
21
+ .map((child) => (0, utils_1.mapMarketToUnified)(child))
22
+ .filter((m) => m !== null);
23
+ }
24
+ else {
25
+ const unifiedMarket = (0, utils_1.mapMarketToUnified)(raw);
26
+ if (unifiedMarket)
27
+ marketsList = [unifiedMarket];
28
+ }
29
+ return {
30
+ id: raw.slug,
31
+ title: raw.title || raw.question || '',
32
+ description: raw.description || '',
33
+ slug: raw.slug,
34
+ markets: marketsList,
35
+ volume24h: marketsList.reduce((sum, m) => sum + m.volume24h, 0),
36
+ volume: marketsList.some(m => m.volume !== undefined)
37
+ ? marketsList.reduce((sum, m) => sum + (m.volume ?? 0), 0)
38
+ : undefined,
39
+ url: `https://limitless.exchange/markets/${raw.slug}`,
40
+ image: raw.logo || `https://limitless.exchange/api/og?slug=${raw.slug}`,
41
+ category: raw.categories?.[0],
42
+ tags: raw.tags || [],
43
+ };
44
+ }
45
+ normalizeOHLCV(rawPrices, params) {
46
+ let candles = rawPrices.map((p) => {
47
+ const price = Number(p.price);
48
+ const ts = Number(p.timestamp);
49
+ return {
50
+ timestamp: ts,
51
+ open: price,
52
+ high: price,
53
+ low: price,
54
+ close: price,
55
+ volume: 0,
56
+ };
57
+ }).sort((a, b) => a.timestamp - b.timestamp);
58
+ if (params.start) {
59
+ candles = candles.filter((c) => c.timestamp >= params.start.getTime());
60
+ }
61
+ if (params.end) {
62
+ candles = candles.filter((c) => c.timestamp <= params.end.getTime());
63
+ }
64
+ if (params.limit) {
65
+ candles = candles.slice(0, params.limit);
66
+ }
67
+ return candles;
68
+ }
69
+ normalizeOrderBook(raw, _id) {
70
+ const bids = (raw.bids || []).map((level) => ({
71
+ price: parseFloat(String(level.price)),
72
+ size: convertSize(parseFloat(String(level.size))),
73
+ })).sort((a, b) => b.price - a.price);
74
+ const asks = (raw.asks || []).map((level) => ({
75
+ price: parseFloat(String(level.price)),
76
+ size: convertSize(parseFloat(String(level.size))),
77
+ })).sort((a, b) => a.price - b.price);
78
+ return {
79
+ bids,
80
+ asks,
81
+ timestamp: raw.timestamp || Date.now(),
82
+ };
83
+ }
84
+ normalizeTrade(_raw, _index) {
85
+ // Limitless does not have a public market trades endpoint
86
+ throw new Error('Limitless normalizeTrade not supported: No public market trades API available.');
87
+ }
88
+ normalizeUserTrade(raw, _index) {
89
+ const t = raw;
90
+ return {
91
+ id: t.id || String(t.timestamp),
92
+ timestamp: t.createdAt ? new Date(t.createdAt).getTime() : (t.timestamp || 0),
93
+ price: parseFloat(t.price || '0'),
94
+ amount: parseFloat(t.quantity || t.amount || '0'),
95
+ side: (t.side || '').toLowerCase() === 'buy' ? 'buy' : 'sell',
96
+ orderId: t.orderId,
97
+ };
98
+ }
99
+ normalizePosition(raw) {
100
+ const p = raw;
101
+ return {
102
+ marketId: p.market?.slug || p.conditionId,
103
+ outcomeId: p.asset,
104
+ outcomeLabel: p.outcome || 'Unknown',
105
+ size: parseFloat(p.size || '0'),
106
+ entryPrice: parseFloat(p.avgPrice || '0'),
107
+ currentPrice: parseFloat(p.curPrice || '0'),
108
+ unrealizedPnL: parseFloat(p.cashPnl || '0'),
109
+ realizedPnL: parseFloat(p.realizedPnl || '0'),
110
+ };
111
+ }
112
+ normalizeBalance(raw) {
113
+ // Not used in the standard flow -- balance comes from on-chain RPC
114
+ return [];
115
+ }
116
+ }
117
+ exports.LimitlessNormalizer = LimitlessNormalizer;
@@ -11,6 +11,8 @@ export interface LimitlessWebSocketConfig extends Partial<WebSocketConfig> {
11
11
  reconnectDelay?: number;
12
12
  /** Watcher subscription configurations */
13
13
  watcherConfig?: WatcherConfig;
14
+ /** Callback to fetch an orderbook snapshot via REST (used as fallback) */
15
+ fetchOrderBook?: (id: string) => Promise<OrderBook>;
14
16
  }
15
17
  /**
16
18
  * Limitless WebSocket implementation using the official SDK.
@@ -25,6 +27,7 @@ export declare class LimitlessWebSocket {
25
27
  private readonly watcher;
26
28
  private config;
27
29
  private callApi;
30
+ private readonly fetchOrderBookSnapshot;
28
31
  private orderbookCallbacks;
29
32
  private priceCallbacks;
30
33
  private orderbookResolvers;
@@ -4,7 +4,6 @@ exports.LimitlessWebSocket = void 0;
4
4
  const sdk_1 = require("@limitless-exchange/sdk");
5
5
  const goldsky_1 = require("../../subscriber/external/goldsky");
6
6
  const watcher_1 = require("../../subscriber/watcher");
7
- const fetchOrderBook_1 = require("./fetchOrderBook");
8
7
  // Limitless uses USDC with 6 decimals
9
8
  const USDC_DECIMALS = 6;
10
9
  const USDC_SCALE = Math.pow(10, USDC_DECIMALS);
@@ -27,6 +26,7 @@ class LimitlessWebSocket {
27
26
  watcher;
28
27
  config;
29
28
  callApi;
29
+ fetchOrderBookSnapshot;
30
30
  orderbookCallbacks = new Map();
31
31
  priceCallbacks = new Map();
32
32
  orderbookResolvers = new Map();
@@ -35,6 +35,7 @@ class LimitlessWebSocket {
35
35
  constructor(callApi, config = {}) {
36
36
  this.callApi = callApi;
37
37
  this.config = config;
38
+ this.fetchOrderBookSnapshot = config.fetchOrderBook ?? (async () => this.getEmptyOrderbook());
38
39
  // Initialize SDK WebSocket client
39
40
  const wsConfig = {
40
41
  url: config.url || 'wss://ws.limitless.exchange',
@@ -86,7 +87,7 @@ class LimitlessWebSocket {
86
87
  if (!this.lastOrderbookTimestamps.has(marketSlug)) {
87
88
  this.lastOrderbookTimestamps.set(marketSlug, Date.now());
88
89
  try {
89
- return await (0, fetchOrderBook_1.fetchOrderBook)(marketSlug, this.callApi);
90
+ return await this.fetchOrderBookSnapshot(marketSlug);
90
91
  }
91
92
  catch (err) {
92
93
  console.warn(`[LimitlessWS] Failed to fetch initial snapshot:`, err);
@@ -103,7 +104,7 @@ class LimitlessWebSocket {
103
104
  if (timeSinceLastUpdate > SNAPSHOT_REFRESH_INTERVAL) {
104
105
  this.lastOrderbookTimestamps.set(marketSlug, Date.now());
105
106
  try {
106
- return await (0, fetchOrderBook_1.fetchOrderBook)(marketSlug, this.callApi);
107
+ return await this.fetchOrderBookSnapshot(marketSlug);
107
108
  }
108
109
  catch (err) {
109
110
  console.warn(`[LimitlessWS] Failed to fetch refresh snapshot:`, err);
@@ -122,7 +123,7 @@ class LimitlessWebSocket {
122
123
  // Timeout: fetch REST snapshot as fallback
123
124
  try {
124
125
  this.lastOrderbookTimestamps.set(marketSlug, Date.now());
125
- const snapshot = await (0, fetchOrderBook_1.fetchOrderBook)(marketSlug, this.callApi);
126
+ const snapshot = await this.fetchOrderBookSnapshot(marketSlug);
126
127
  resolve(snapshot);
127
128
  }
128
129
  catch (err) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
3
- * Generated at: 2026-03-14T16:22:11.436Z
3
+ * Generated at: 2026-03-14T21:28:31.889Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const myriadApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.myriadApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
6
- * Generated at: 2026-03-14T16:22:11.436Z
6
+ * Generated at: 2026-03-14T21:28:31.889Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.myriadApiSpec = {
@@ -0,0 +1,73 @@
1
+ import { MarketFilterParams, EventFetchParams, OHLCVParams, TradesParams, MyTradesParams } from '../../BaseExchange';
2
+ import { IExchangeFetcher, FetcherContext } from '../interfaces';
3
+ export interface MyriadRawMarket {
4
+ id: number;
5
+ networkId: number;
6
+ title?: string;
7
+ description?: string;
8
+ slug?: string;
9
+ imageUrl?: string;
10
+ expiresAt?: string;
11
+ volume24h?: number;
12
+ volume?: number;
13
+ liquidity?: number;
14
+ questionId?: number;
15
+ topics?: string[];
16
+ outcomes?: MyriadRawOutcome[];
17
+ [key: string]: unknown;
18
+ }
19
+ export interface MyriadRawOutcome {
20
+ id: number;
21
+ title?: string;
22
+ price?: number;
23
+ priceChange24h?: number;
24
+ price_charts?: Record<string, {
25
+ timeframe: string;
26
+ prices: {
27
+ value: number;
28
+ timestamp: number;
29
+ }[];
30
+ }>;
31
+ [key: string]: unknown;
32
+ }
33
+ export interface MyriadRawQuestion {
34
+ id: number;
35
+ title?: string;
36
+ markets?: MyriadRawMarket[];
37
+ [key: string]: unknown;
38
+ }
39
+ export interface MyriadRawTradeEvent {
40
+ action?: string;
41
+ blockNumber?: number;
42
+ timestamp?: number;
43
+ value?: number;
44
+ shares?: number;
45
+ outcomeId?: number;
46
+ [key: string]: unknown;
47
+ }
48
+ export interface MyriadRawPortfolioItem {
49
+ networkId: number;
50
+ marketId: number;
51
+ outcomeId: number;
52
+ outcomeTitle?: string;
53
+ shares?: number;
54
+ price?: number;
55
+ profit?: number;
56
+ value?: number;
57
+ [key: string]: unknown;
58
+ }
59
+ export declare class MyriadFetcher implements IExchangeFetcher<MyriadRawMarket, MyriadRawQuestion> {
60
+ private readonly ctx;
61
+ constructor(ctx: FetcherContext);
62
+ fetchRawMarkets(params?: MarketFilterParams): Promise<MyriadRawMarket[]>;
63
+ fetchRawEvents(params: EventFetchParams): Promise<MyriadRawQuestion[]>;
64
+ fetchRawOHLCV(id: string, _params: OHLCVParams): Promise<MyriadRawMarket>;
65
+ fetchRawOrderBook(id: string): Promise<MyriadRawMarket>;
66
+ fetchRawTrades(id: string, params: TradesParams): Promise<MyriadRawTradeEvent[]>;
67
+ fetchRawMyTrades(params: MyTradesParams, walletAddress: string): Promise<MyriadRawTradeEvent[]>;
68
+ fetchRawPositions(walletAddress: string): Promise<MyriadRawPortfolioItem[]>;
69
+ fetchRawBalance(walletAddress: string): Promise<MyriadRawPortfolioItem[]>;
70
+ private fetchRawMarketById;
71
+ private fetchRawMarketBySlug;
72
+ private fetchRawQuestionById;
73
+ }