pmxt-core 2.19.6 → 2.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/BaseExchange.d.ts +69 -30
  2. package/dist/BaseExchange.js +124 -82
  3. package/dist/exchanges/baozi/index.d.ts +2 -0
  4. package/dist/exchanges/baozi/index.js +2 -0
  5. package/dist/exchanges/baozi/price.d.ts +3 -0
  6. package/dist/exchanges/baozi/price.js +16 -0
  7. package/dist/exchanges/baozi/price.test.d.ts +1 -0
  8. package/dist/exchanges/baozi/price.test.js +33 -0
  9. package/dist/exchanges/baozi/utils.js +5 -9
  10. package/dist/exchanges/kalshi/api.d.ts +1 -1
  11. package/dist/exchanges/kalshi/api.js +1 -1
  12. package/dist/exchanges/kalshi/fetchOHLCV.js +5 -4
  13. package/dist/exchanges/kalshi/fetchOrderBook.js +21 -21
  14. package/dist/exchanges/kalshi/fetchTrades.js +2 -1
  15. package/dist/exchanges/kalshi/index.d.ts +3 -1
  16. package/dist/exchanges/kalshi/index.js +19 -16
  17. package/dist/exchanges/kalshi/price.d.ts +3 -0
  18. package/dist/exchanges/kalshi/price.js +14 -0
  19. package/dist/exchanges/kalshi/price.test.d.ts +1 -0
  20. package/dist/exchanges/kalshi/price.test.js +24 -0
  21. package/dist/exchanges/kalshi/utils.js +5 -4
  22. package/dist/exchanges/limitless/api.d.ts +1 -1
  23. package/dist/exchanges/limitless/api.js +1 -1
  24. package/dist/exchanges/limitless/index.d.ts +58 -19
  25. package/dist/exchanges/limitless/index.js +169 -101
  26. package/dist/exchanges/limitless/websocket.d.ts +10 -3
  27. package/dist/exchanges/limitless/websocket.js +71 -52
  28. package/dist/exchanges/myriad/api.d.ts +1 -1
  29. package/dist/exchanges/myriad/api.js +1 -1
  30. package/dist/exchanges/myriad/index.d.ts +3 -1
  31. package/dist/exchanges/myriad/index.js +7 -4
  32. package/dist/exchanges/myriad/price.d.ts +1 -0
  33. package/dist/exchanges/myriad/price.js +7 -0
  34. package/dist/exchanges/myriad/price.test.d.ts +1 -0
  35. package/dist/exchanges/myriad/price.test.js +17 -0
  36. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  37. package/dist/exchanges/polymarket/api-clob.js +1 -1
  38. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  39. package/dist/exchanges/polymarket/api-data.js +1 -1
  40. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  41. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  42. package/dist/exchanges/polymarket/index.d.ts +28 -15
  43. package/dist/exchanges/polymarket/index.js +217 -137
  44. package/dist/exchanges/polymarket/websocket.d.ts +11 -4
  45. package/dist/exchanges/polymarket/websocket.js +58 -36
  46. package/dist/exchanges/probable/api.d.ts +1 -1
  47. package/dist/exchanges/probable/api.js +1 -1
  48. package/dist/exchanges/probable/index.d.ts +2 -0
  49. package/dist/exchanges/probable/index.js +2 -0
  50. package/dist/subscriber/base.d.ts +82 -0
  51. package/dist/subscriber/base.js +2 -0
  52. package/dist/subscriber/external/goldsky.d.ts +96 -0
  53. package/dist/subscriber/external/goldsky.js +412 -0
  54. package/dist/subscriber/watcher.d.ts +85 -0
  55. package/dist/subscriber/watcher.js +178 -0
  56. package/dist/types.d.ts +5 -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
@@ -1,21 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LimitlessExchange = void 0;
3
+ exports.LimitlessExchange = exports.buildLimitlessBalanceActivity = exports.LIMITLESS_DEFAULT_SUBSCRIPTION = void 0;
4
+ const sdk_1 = require("@limitless-exchange/sdk");
5
+ const ethers_1 = require("ethers");
4
6
  const BaseExchange_1 = require("../../BaseExchange");
5
- const fetchMarkets_1 = require("./fetchMarkets");
7
+ const errors_1 = require("../../errors");
8
+ const goldsky_1 = require("../../subscriber/external/goldsky");
9
+ Object.defineProperty(exports, "buildLimitlessBalanceActivity", { enumerable: true, get: function () { return goldsky_1.buildLimitlessBalanceActivity; } });
10
+ Object.defineProperty(exports, "LIMITLESS_DEFAULT_SUBSCRIPTION", { enumerable: true, get: function () { return goldsky_1.LIMITLESS_DEFAULT_SUBSCRIPTION; } });
11
+ const openapi_1 = require("../../utils/openapi");
12
+ const api_1 = require("./api");
13
+ const auth_1 = require("./auth");
14
+ const client_1 = require("./client");
15
+ const errors_2 = require("./errors");
6
16
  const fetchEvents_1 = require("./fetchEvents");
17
+ const fetchMarkets_1 = require("./fetchMarkets");
7
18
  const fetchOHLCV_1 = require("./fetchOHLCV");
8
19
  const fetchOrderBook_1 = require("./fetchOrderBook");
9
20
  const fetchTrades_1 = require("./fetchTrades");
10
- const auth_1 = require("./auth");
11
- const client_1 = require("./client");
12
21
  const websocket_1 = require("./websocket");
13
- const errors_1 = require("./errors");
14
- const errors_2 = require("../../errors");
15
- const sdk_1 = require("@limitless-exchange/sdk");
16
- const ethers_1 = require("ethers");
17
- const openapi_1 = require("../../utils/openapi");
18
- const api_1 = require("./api");
19
22
  class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
20
23
  has = {
21
24
  fetchMarkets: true,
@@ -29,6 +32,8 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
29
32
  fetchOpenOrders: true,
30
33
  fetchPositions: true,
31
34
  fetchBalance: true,
35
+ watchAddress: true,
36
+ unwatchAddress: true,
32
37
  watchOrderBook: true,
33
38
  watchTrades: true,
34
39
  fetchMyTrades: true,
@@ -40,6 +45,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
40
45
  auth;
41
46
  client;
42
47
  wsConfig;
48
+ ws;
43
49
  constructor(options) {
44
50
  // Support both old signature (credentials only) and new signature (options object)
45
51
  let credentials;
@@ -85,22 +91,8 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
85
91
  return 'Limitless';
86
92
  }
87
93
  // ----------------------------------------------------------------------------
88
- // Implicit API Error Mapping
89
- // ----------------------------------------------------------------------------
90
- mapImplicitApiError(error) {
91
- throw errors_1.limitlessErrorMapper.mapError(error);
92
- }
93
- // ----------------------------------------------------------------------------
94
94
  // Implementation methods for CCXT-style API
95
95
  // ----------------------------------------------------------------------------
96
- async fetchMarketsImpl(params) {
97
- // Pass API key if available for authenticated requests
98
- const apiKey = this.auth?.getApiKey();
99
- return (0, fetchMarkets_1.fetchMarkets)(params, apiKey, this.callApi.bind(this));
100
- }
101
- async fetchEventsImpl(params) {
102
- return (0, fetchEvents_1.fetchEvents)(params, this.callApi.bind(this), this.http);
103
- }
104
96
  async fetchOHLCV(id, params) {
105
97
  return (0, fetchOHLCV_1.fetchOHLCV)(id, params, this.callApi.bind(this));
106
98
  }
@@ -115,26 +107,6 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
115
107
  }
116
108
  return (0, fetchTrades_1.fetchTrades)(id, params, this.http);
117
109
  }
118
- // ----------------------------------------------------------------------------
119
- // Trading Methods
120
- // ----------------------------------------------------------------------------
121
- ensureClient() {
122
- if (!this.client) {
123
- throw new Error('Trading operations require authentication. ' +
124
- 'Initialize LimitlessExchange with credentials: new LimitlessExchange({ privateKey: "0x...", apiKey: "lmts_..." })');
125
- }
126
- return this.client;
127
- }
128
- /**
129
- * Ensure authentication is initialized before trading operations.
130
- */
131
- ensureAuth() {
132
- if (!this.auth) {
133
- throw new errors_2.AuthenticationError('Trading operations require authentication. ' +
134
- 'Initialize LimitlessExchange with credentials: new LimitlessExchange({ privateKey: "0x...", apiKey: "lmts_..." })', 'Limitless');
135
- }
136
- return this.auth;
137
- }
138
110
  async createOrder(params) {
139
111
  const client = this.ensureClient();
140
112
  try {
@@ -172,9 +144,12 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
172
144
  };
173
145
  }
174
146
  catch (error) {
175
- throw errors_1.limitlessErrorMapper.mapError(error);
147
+ throw errors_2.limitlessErrorMapper.mapError(error);
176
148
  }
177
149
  }
150
+ // ----------------------------------------------------------------------------
151
+ // Trading Methods
152
+ // ----------------------------------------------------------------------------
178
153
  async cancelOrder(orderId) {
179
154
  const client = this.ensureClient();
180
155
  try {
@@ -193,7 +168,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
193
168
  };
194
169
  }
195
170
  catch (error) {
196
- throw errors_1.limitlessErrorMapper.mapError(error);
171
+ throw errors_2.limitlessErrorMapper.mapError(error);
197
172
  }
198
173
  }
199
174
  async fetchOrder(orderId) {
@@ -228,7 +203,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
228
203
  }));
229
204
  }
230
205
  catch (error) {
231
- throw errors_1.limitlessErrorMapper.mapError(error);
206
+ throw errors_2.limitlessErrorMapper.mapError(error);
232
207
  }
233
208
  }
234
209
  async fetchMyTrades(params) {
@@ -248,7 +223,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
248
223
  }));
249
224
  }
250
225
  catch (error) {
251
- throw errors_1.limitlessErrorMapper.mapError(error);
226
+ throw errors_2.limitlessErrorMapper.mapError(error);
252
227
  }
253
228
  }
254
229
  async fetchClosedOrders(params) {
@@ -293,10 +268,10 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
293
268
  timestamp: o.createdAt ? new Date(o.createdAt).getTime() : Date.now(),
294
269
  }));
295
270
  }
296
- async fetchPositions() {
297
- const auth = this.ensureAuth();
298
- const address = auth.getAddress();
299
- const result = await this.callApi('PublicPortfolioController_getPositions', { account: address });
271
+ async fetchPositions(address) {
272
+ // Public endpoint — no auth needed when an address is explicitly supplied.
273
+ const account = address ?? this.ensureAuth().getAddress();
274
+ const result = await this.callApi('PublicPortfolioController_getPositions', { account });
300
275
  const data = result?.data || result || [];
301
276
  return data.map((p) => ({
302
277
  marketId: p.market?.slug || p.conditionId,
@@ -309,61 +284,25 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
309
284
  realizedPnL: parseFloat(p.realizedPnl || '0'),
310
285
  }));
311
286
  }
312
- async fetchBalance() {
313
- const auth = this.ensureAuth();
287
+ async fetchBalance(address) {
314
288
  try {
315
- // Query USDC balance directly from the blockchain
316
- // Base chain RPC (not Polygon)
317
- const provider = new ethers_1.providers.JsonRpcProvider('https://mainnet.base.org');
318
- const address = auth.getAddress();
319
- // Get USDC contract address for Base
320
- const usdcAddress = (0, sdk_1.getContractAddress)('USDC');
321
- // USDC ERC20 ABI (balanceOf only)
322
- const usdcContract = new ethers_1.Contract(usdcAddress, ['function balanceOf(address) view returns (uint256)'], provider);
323
- // Query balance
324
- const rawBalance = await usdcContract.balanceOf(address);
325
- // USDC has 6 decimals
326
- const USDC_DECIMALS = 6;
327
- const total = parseFloat(rawBalance.toString()) / Math.pow(10, USDC_DECIMALS);
328
- return [
329
- {
330
- currency: 'USDC',
331
- total: total,
332
- available: total, // On-chain balance is all available
333
- locked: 0,
334
- },
335
- ];
289
+ // When an external address is provided use on-chain RPC only — no auth required.
290
+ const targetAddress = address ?? this.ensureAuth().getAddress();
291
+ return await this.getAddressOnChainBalance(targetAddress);
336
292
  }
337
293
  catch (error) {
338
- throw errors_1.limitlessErrorMapper.mapError(error);
339
- }
340
- }
341
- // ----------------------------------------------------------------------------
342
- // WebSocket Methods
343
- // ----------------------------------------------------------------------------
344
- ws;
345
- /**
346
- * Initialize WebSocket with API key if available.
347
- */
348
- initWebSocket() {
349
- if (!this.ws) {
350
- const wsConfig = {
351
- ...this.wsConfig,
352
- apiKey: this.auth?.getApiKey(),
353
- };
354
- this.ws = new websocket_1.LimitlessWebSocket(this.callApi.bind(this), wsConfig);
294
+ throw errors_2.limitlessErrorMapper.mapError(error);
355
295
  }
356
- return this.ws;
357
296
  }
358
297
  async watchOrderBook(id, limit) {
359
- const ws = this.initWebSocket();
298
+ const ws = this.ensureWs();
360
299
  // Return the snapshot immediately (this allows the script to proceed)
361
300
  // Future versions could implement a more sophisticated queueing system
362
301
  return ws.watchOrderBook(id);
363
302
  }
364
- async watchTrades(id, since, limit) {
365
- const ws = this.initWebSocket();
366
- return ws.watchTrades(id);
303
+ async watchTrades(id, address, since, limit) {
304
+ const ws = this.ensureWs();
305
+ return ws.watchTrades(id, address);
367
306
  }
368
307
  /**
369
308
  * Watch AMM price updates for a market address (Limitless only).
@@ -381,7 +320,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
381
320
  * exchange.watch_prices(market_address, callback=lambda data: print('Price update:', data))
382
321
  */
383
322
  async watchPrices(marketAddress, callback) {
384
- const ws = this.initWebSocket();
323
+ const ws = this.ensureWs();
385
324
  return ws.watchPrices(marketAddress, callback);
386
325
  }
387
326
  /**
@@ -400,9 +339,12 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
400
339
  */
401
340
  async watchUserPositions(callback) {
402
341
  this.ensureAuth(); // Ensure API key is available
403
- const ws = this.initWebSocket();
342
+ const ws = this.ensureWs();
404
343
  return ws.watchUserPositions(callback);
405
344
  }
345
+ // ----------------------------------------------------------------------------
346
+ // WebSocket Methods
347
+ // ----------------------------------------------------------------------------
406
348
  /**
407
349
  * Watch user transactions in real-time (Limitless only).
408
350
  * Requires API key authentication.
@@ -419,14 +361,140 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
419
361
  */
420
362
  async watchUserTransactions(callback) {
421
363
  this.ensureAuth(); // Ensure API key is available
422
- const ws = this.initWebSocket();
364
+ const ws = this.ensureWs();
423
365
  return ws.watchUserTransactions(callback);
424
366
  }
367
+ /**
368
+ * Stream activity (positions, balances) for any public Base-chain wallet address.
369
+ *
370
+ * Uses polling of the Limitless public portfolio API (positions) and on-chain Base
371
+ * RPC calls (USDC balance). No credentials are required.
372
+ *
373
+ * Note: Limitless does not expose a public per-address trades endpoint, so the
374
+ * `'trades'` type returns an empty array when watching a public address.
375
+ *
376
+ * Follows the CCXT Pro streaming pattern: the first call returns the initial snapshot
377
+ * immediately; subsequent calls block until a change is detected.
378
+ *
379
+ * @param address - Any public Base-chain wallet address
380
+ * @param types - Activity types to watch (default: all)
381
+ *
382
+ * @example-ts
383
+ * while (true) {
384
+ * const activity = await exchange.watchAddress('0xabc...', ['positions', 'balances']);
385
+ * console.log(activity.positions, activity.balances);
386
+ * }
387
+ */
388
+ async watchAddress(address, types = ['trades', 'positions', 'balances']) {
389
+ return this.ensureWs().watchAddress(address, types);
390
+ }
391
+ /**
392
+ * Stop watching an address and release polling resources.
393
+ * Any pending `watchAddress` promises for that address will be rejected.
394
+ */
395
+ async unwatchAddress(address) {
396
+ return this.ensureWs().unwatchAddress(address);
397
+ }
425
398
  async close() {
426
399
  if (this.ws) {
427
- this.ws.close();
400
+ await this.ws.close();
428
401
  this.ws = undefined;
429
402
  }
430
403
  }
404
+ mapImplicitApiError(error) {
405
+ throw errors_2.limitlessErrorMapper.mapError(error);
406
+ }
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
+ }
418
+ async getAddressOnChainBalance(targetAddress) {
419
+ // Query USDC balance directly from Base chain
420
+ const provider = new ethers_1.providers.JsonRpcProvider('https://mainnet.base.org');
421
+ // Get USDC contract address for Base
422
+ const usdcAddress = (0, sdk_1.getContractAddress)('USDC');
423
+ // USDC ERC20 ABI (balanceOf only)
424
+ const usdcContract = new ethers_1.Contract(usdcAddress, ['function balanceOf(address) view returns (uint256)'], provider);
425
+ const rawBalance = await usdcContract.balanceOf(targetAddress);
426
+ const USDC_DECIMALS = 6;
427
+ const total = parseFloat(rawBalance.toString()) / Math.pow(10, USDC_DECIMALS);
428
+ return [{
429
+ currency: 'USDC',
430
+ total,
431
+ available: total, // On-chain balance is all available
432
+ locked: 0,
433
+ }];
434
+ }
435
+ ensureClient() {
436
+ if (!this.client) {
437
+ throw new Error('Trading operations require authentication. ' +
438
+ 'Initialize LimitlessExchange with credentials: new LimitlessExchange({ privateKey: "0x...", apiKey: "lmts_..." })');
439
+ }
440
+ return this.client;
441
+ }
442
+ /**
443
+ * Ensure authentication is initialized before trading operations.
444
+ */
445
+ ensureAuth() {
446
+ if (!this.auth) {
447
+ throw new errors_1.AuthenticationError('Trading operations require authentication. ' +
448
+ 'Initialize LimitlessExchange with credentials: new LimitlessExchange({ privateKey: "0x...", apiKey: "lmts_..." })', 'Limitless');
449
+ }
450
+ return this.auth;
451
+ }
452
+ /**
453
+ * Initialize WebSocket with API key if available.
454
+ */
455
+ ensureWs() {
456
+ if (!this.ws) {
457
+ const wsConfig = {
458
+ ...this.wsConfig,
459
+ apiKey: this.auth?.getApiKey(),
460
+ };
461
+ this.ws = new websocket_1.LimitlessWebSocket(this.callApi.bind(this), wsConfig);
462
+ }
463
+ return this.ws;
464
+ }
465
+ /**
466
+ * Fetch a composite activity snapshot for a Base-chain address from the Limitless
467
+ * public portfolio API and Base RPC. Used internally by the BaseSubscriber polling loop.
468
+ */
469
+ async fetchWatchedAddressActivity(params) {
470
+ const address = params.address;
471
+ const types = params.types;
472
+ const result = { address, timestamp: Date.now() };
473
+ const fetches = [];
474
+ // Limitless has no public per-address trades endpoint; return empty.
475
+ if (types.includes('trades')) {
476
+ result.trades = [];
477
+ }
478
+ if (types.includes('positions')) {
479
+ fetches.push(this.fetchPositions(address)
480
+ .then((positions) => {
481
+ result.positions = positions;
482
+ })
483
+ .catch(() => {
484
+ result.positions = [];
485
+ }));
486
+ }
487
+ if (types.includes('balances')) {
488
+ fetches.push(this.getAddressOnChainBalance(address)
489
+ .then((balances) => {
490
+ result.balances = balances;
491
+ })
492
+ .catch(() => {
493
+ result.balances = [];
494
+ }));
495
+ }
496
+ await Promise.all(fetches);
497
+ return result;
498
+ }
431
499
  }
432
500
  exports.LimitlessExchange = LimitlessExchange;
@@ -1,4 +1,6 @@
1
- import { WebSocketClient, WebSocketConfig, ILogger } from '@limitless-exchange/sdk';
1
+ import { ILogger, WebSocketClient, WebSocketConfig } from '@limitless-exchange/sdk';
2
+ import { SubscribedAddressSnapshot, SubscriptionOption } from "../../subscriber/base";
3
+ import { WatcherConfig } from "../../subscriber/watcher";
2
4
  import { OrderBook, Trade } from '../../types';
3
5
  export interface LimitlessWebSocketConfig extends Partial<WebSocketConfig> {
4
6
  apiKey?: string;
@@ -7,6 +9,8 @@ export interface LimitlessWebSocketConfig extends Partial<WebSocketConfig> {
7
9
  logger?: ILogger;
8
10
  autoReconnect?: boolean;
9
11
  reconnectDelay?: number;
12
+ /** Watcher subscription configurations */
13
+ watcherConfig?: WatcherConfig;
10
14
  }
11
15
  /**
12
16
  * Limitless WebSocket implementation using the official SDK.
@@ -18,6 +22,7 @@ export interface LimitlessWebSocketConfig extends Partial<WebSocketConfig> {
18
22
  */
19
23
  export declare class LimitlessWebSocket {
20
24
  private client;
25
+ private readonly watcher;
21
26
  private config;
22
27
  private callApi;
23
28
  private orderbookCallbacks;
@@ -26,7 +31,6 @@ export declare class LimitlessWebSocket {
26
31
  private orderbookBuffers;
27
32
  private lastOrderbookTimestamps;
28
33
  constructor(callApi: (operationId: string, params?: Record<string, any>) => Promise<any>, config?: LimitlessWebSocketConfig);
29
- private setupEventHandlers;
30
34
  /**
31
35
  * Watch orderbook updates for a CLOB market.
32
36
  *
@@ -58,11 +62,13 @@ export declare class LimitlessWebSocket {
58
62
  /**
59
63
  * Legacy method - watch trades (not directly supported, falls back to orderbook)
60
64
  */
61
- watchTrades(marketSlug: string): Promise<Trade[]>;
65
+ watchTrades(marketSlug: string, address?: string): Promise<Trade[]>;
62
66
  /**
63
67
  * Unsubscribe from a market.
64
68
  */
65
69
  unsubscribe(marketSlugOrAddress: string): Promise<void>;
70
+ watchAddress(address: string, types: SubscriptionOption[]): Promise<SubscribedAddressSnapshot>;
71
+ unwatchAddress(address: string): Promise<void>;
66
72
  /**
67
73
  * Close the WebSocket connection.
68
74
  */
@@ -75,6 +81,7 @@ export declare class LimitlessWebSocket {
75
81
  * Get the underlying SDK WebSocket client for advanced usage.
76
82
  */
77
83
  getClient(): WebSocketClient;
84
+ private setupEventHandlers;
78
85
  private transformOrderbookData;
79
86
  private getEmptyOrderbook;
80
87
  }
@@ -2,12 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LimitlessWebSocket = void 0;
4
4
  const sdk_1 = require("@limitless-exchange/sdk");
5
+ const goldsky_1 = require("../../subscriber/external/goldsky");
6
+ const watcher_1 = require("../../subscriber/watcher");
5
7
  const fetchOrderBook_1 = require("./fetchOrderBook");
6
8
  // Limitless uses USDC with 6 decimals
7
9
  const USDC_DECIMALS = 6;
8
10
  const USDC_SCALE = Math.pow(10, USDC_DECIMALS);
9
11
  /**
10
- * Convert raw orderbook size from smallest unit to human-readable USDC amount.
12
+ * Convert raw orderbook size from the smallest unit to human-readable USDC amount.
11
13
  */
12
14
  function convertSize(rawSize) {
13
15
  return rawSize / USDC_SCALE;
@@ -22,6 +24,7 @@ function convertSize(rawSize) {
22
24
  */
23
25
  class LimitlessWebSocket {
24
26
  client;
27
+ watcher;
25
28
  config;
26
29
  callApi;
27
30
  orderbookCallbacks = new Map();
@@ -42,55 +45,14 @@ class LimitlessWebSocket {
42
45
  this.client = new sdk_1.WebSocketClient(wsConfig, config.logger);
43
46
  // Set up event handlers
44
47
  this.setupEventHandlers();
45
- }
46
- setupEventHandlers() {
47
- // Handle orderbook updates
48
- this.client.on('orderbookUpdate', (data) => {
49
- const { marketSlug, orderbook } = data;
50
- const pmxtOrderbook = this.transformOrderbookData(orderbook);
51
- // Update timestamp for this market
52
- this.lastOrderbookTimestamps.set(marketSlug, Date.now());
53
- // Execute callback if registered
54
- const callback = this.orderbookCallbacks.get(marketSlug);
55
- if (callback) {
56
- callback(pmxtOrderbook);
57
- }
58
- // Handle resolvers and buffers
59
- const resolvers = this.orderbookResolvers.get(marketSlug) || [];
60
- if (resolvers.length > 0) {
61
- // If someone is waiting, give it to them immediately
62
- const resolver = resolvers.shift();
63
- resolver.resolve(pmxtOrderbook);
64
- }
65
- else {
66
- // Otherwise, buffer it for the next call
67
- if (!this.orderbookBuffers.has(marketSlug)) {
68
- this.orderbookBuffers.set(marketSlug, []);
69
- }
70
- const buffer = this.orderbookBuffers.get(marketSlug);
71
- buffer.push(pmxtOrderbook);
72
- // Keep buffer size reasonable
73
- if (buffer.length > 100)
74
- buffer.shift();
75
- }
48
+ const watcherConfig = this.config.watcherConfig;
49
+ const subscriber = new goldsky_1.GoldSkySubscriber({
50
+ ...watcherConfig,
51
+ buildSubscription: goldsky_1.LIMITLESS_DEFAULT_SUBSCRIPTION,
76
52
  });
77
- // Handle AMM price updates
78
- this.client.on('newPriceData', (data) => {
79
- const { marketAddress } = data;
80
- const callback = this.priceCallbacks.get(marketAddress);
81
- if (callback) {
82
- callback(data);
83
- }
84
- });
85
- // Handle connection events
86
- this.client.on('connect', () => {
87
- console.log('[LimitlessWS] Connected to WebSocket');
88
- });
89
- this.client.on('disconnect', (reason) => {
90
- console.log(`[LimitlessWS] Disconnected from WebSocket: ${reason}`);
91
- });
92
- this.client.on('error', (error) => {
93
- console.error('[LimitlessWS] WebSocket error:', error);
53
+ this.watcher = new watcher_1.AddressWatcher((address, types) => this.callApi("fetchWatchedAddressActivity", { address, types }), {
54
+ subscriber,
55
+ buildActivity: goldsky_1.buildLimitlessBalanceActivity,
94
56
  });
95
57
  }
96
58
  /**
@@ -202,7 +164,7 @@ class LimitlessWebSocket {
202
164
  if (!this.client.isConnected()) {
203
165
  await this.client.connect();
204
166
  }
205
- await this.client.subscribe('orders'); // SDK uses 'orders' channel for user positional updates too?
167
+ await this.client.subscribe('orders'); // SDK uses 'orders' channel for user positional updates too?
206
168
  // Actually, the channel type has 'subscribe_positions'. Let's check.
207
169
  // Wait, I saw 'orders' in SubscriptionChannel.
208
170
  // Let's use 'orders' as it's common for user data.
@@ -227,7 +189,7 @@ class LimitlessWebSocket {
227
189
  /**
228
190
  * Legacy method - watch trades (not directly supported, falls back to orderbook)
229
191
  */
230
- async watchTrades(marketSlug) {
192
+ async watchTrades(marketSlug, address) {
231
193
  console.warn('[LimitlessWS] watchTrades is not directly supported. ' +
232
194
  'Use watchOrderBook() for real-time orderbook updates or fetchOHLCV() for historical data.');
233
195
  return [];
@@ -246,13 +208,20 @@ class LimitlessWebSocket {
246
208
  marketAddresses: [marketSlugOrAddress],
247
209
  });
248
210
  }
211
+ async watchAddress(address, types) {
212
+ return this.watcher.watch(address, types);
213
+ }
214
+ async unwatchAddress(address) {
215
+ return this.watcher.unwatch(address);
216
+ }
249
217
  /**
250
218
  * Close the WebSocket connection.
251
219
  */
252
220
  async close() {
253
221
  this.orderbookCallbacks.clear();
254
222
  this.priceCallbacks.clear();
255
- this.client.disconnect();
223
+ await this.client.disconnect();
224
+ this.watcher.close();
256
225
  }
257
226
  /**
258
227
  * Check if connected.
@@ -266,6 +235,56 @@ class LimitlessWebSocket {
266
235
  getClient() {
267
236
  return this.client;
268
237
  }
238
+ setupEventHandlers() {
239
+ // Handle orderbook updates
240
+ this.client.on('orderbookUpdate', (data) => {
241
+ const { marketSlug, orderbook } = data;
242
+ const pmxtOrderbook = this.transformOrderbookData(orderbook);
243
+ // Update timestamp for this market
244
+ this.lastOrderbookTimestamps.set(marketSlug, Date.now());
245
+ // Execute callback if registered
246
+ const callback = this.orderbookCallbacks.get(marketSlug);
247
+ if (callback) {
248
+ callback(pmxtOrderbook);
249
+ }
250
+ // Handle resolvers and buffers
251
+ const resolvers = this.orderbookResolvers.get(marketSlug) || [];
252
+ if (resolvers.length > 0) {
253
+ // If someone is waiting, give it to them immediately
254
+ const resolver = resolvers.shift();
255
+ resolver.resolve(pmxtOrderbook);
256
+ }
257
+ else {
258
+ // Otherwise, buffer it for the next call
259
+ if (!this.orderbookBuffers.has(marketSlug)) {
260
+ this.orderbookBuffers.set(marketSlug, []);
261
+ }
262
+ const buffer = this.orderbookBuffers.get(marketSlug);
263
+ buffer.push(pmxtOrderbook);
264
+ // Keep buffer size reasonable
265
+ if (buffer.length > 100)
266
+ buffer.shift();
267
+ }
268
+ });
269
+ // Handle AMM price updates
270
+ this.client.on('newPriceData', (data) => {
271
+ const { marketAddress } = data;
272
+ const callback = this.priceCallbacks.get(marketAddress);
273
+ if (callback) {
274
+ callback(data);
275
+ }
276
+ });
277
+ // Handle connection events
278
+ this.client.on('connect', () => {
279
+ console.log('[LimitlessWS] Connected to WebSocket');
280
+ });
281
+ this.client.on('disconnect', (reason) => {
282
+ console.log(`[LimitlessWS] Disconnected from WebSocket: ${reason}`);
283
+ });
284
+ this.client.on('error', (error) => {
285
+ console.error('[LimitlessWS] WebSocket error:', error);
286
+ });
287
+ }
269
288
  transformOrderbookData(orderbook) {
270
289
  // Convert sizes from smallest unit to human-readable USDC amounts
271
290
  const bids = (orderbook.bids || []).map((level) => ({
@@ -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-06T09:16:55.607Z
3
+ * Generated at: 2026-03-14T16:40:09.282Z
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-06T09:16:55.607Z
6
+ * Generated at: 2026-03-14T16:40:09.282Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.myriadApiSpec = {
@@ -13,6 +13,8 @@ export declare class MyriadExchange extends PredictionMarketExchange {
13
13
  fetchOpenOrders: "emulated";
14
14
  fetchPositions: true;
15
15
  fetchBalance: "emulated";
16
+ watchAddress: false;
17
+ unwatchAddress: false;
16
18
  watchOrderBook: "emulated";
17
19
  watchTrades: "emulated";
18
20
  fetchMyTrades: true;
@@ -42,6 +44,6 @@ export declare class MyriadExchange extends PredictionMarketExchange {
42
44
  fetchPositions(): Promise<Position[]>;
43
45
  fetchBalance(): Promise<Balance[]>;
44
46
  watchOrderBook(id: string, _limit?: number): Promise<OrderBook>;
45
- watchTrades(id: string, _since?: number, _limit?: number): Promise<Trade[]>;
47
+ watchTrades(id: string, address?: string, _since?: number, _limit?: number): Promise<Trade[]>;
46
48
  close(): Promise<void>;
47
49
  }