pmxt-core 2.51.2 → 2.51.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API_REFERENCE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Prediction Market API Reference
2
2
 
3
- A unified interface for interacting with multiple prediction market exchanges (Kalshi, Polymarket) identically.
3
+ A unified interface for interacting with multiple prediction market exchanges and venues through one interface.
4
4
 
5
5
  ## Installation & Usage
6
6
 
@@ -8,33 +8,22 @@ A unified interface for interacting with multiple prediction market exchanges (K
8
8
  npm install pmxtjs
9
9
  ```
10
10
 
11
- ### Basic Import (CommonJS)
11
+ ### Import Styles
12
12
 
13
13
  ```typescript
14
- import pmxt from 'pmxtjs';
14
+ import { Polymarket, Kalshi } from 'pmxtjs';
15
15
 
16
- const poly = new pmxt.Polymarket();
17
- const kalshi = new pmxt.Kalshi();
16
+ const polymarket = new Polymarket();
17
+ const kalshi = new Kalshi();
18
18
  ```
19
19
 
20
- ### Note for ESM Users
21
-
22
- **pmxt is currently CommonJS-only.** If you're using `"type": "module"` in your `package.json`, you have two options:
23
-
24
- **Option 1: Default import (recommended)**
25
20
  ```typescript
26
21
  import pmxt from 'pmxtjs';
27
- const poly = new pmxt.Polymarket();
28
- ```
29
22
 
30
- **Option 2: Dynamic import**
31
- ```typescript
32
- const pmxt = await import('pmxtjs');
33
- const poly = new pmxt.default.Polymarket();
23
+ const polymarket = new pmxt.Polymarket();
24
+ const kalshi = new pmxt.Kalshi();
34
25
  ```
35
26
 
36
- **Note**: Named exports like `import { Polymarket } from 'pmxtjs'` will **not work** in ESM projects.
37
-
38
27
  ---
39
28
 
40
29
  ## Core Methods
@@ -46,8 +35,8 @@ Get active markets from an exchange. This is the unified method for all market f
46
35
  - `limit`: Number of results (default: 20)
47
36
  - `offset`: Pagination offset
48
37
  - `sort`: 'volume' | 'liquidity' | 'newest'
49
- - `query`: Search text (replaces `searchMarkets`)
50
- - `slug`: Market slug or ticker (replaces `getMarketsBySlug`)
38
+ - `query`: Search text
39
+ - `slug`: Market slug or ticker
51
40
 
52
41
  ```typescript
53
42
  // 1. Fetch recent markets
@@ -56,13 +45,13 @@ const markets = await polymarket.fetchMarkets({
56
45
  sort: 'volume'
57
46
  });
58
47
 
59
- // 2. Search by text (replaces searchMarkets)
48
+ // 2. Search by text
60
49
  const results = await kalshi.fetchMarkets({
61
50
  query: 'Fed rates',
62
51
  limit: 10
63
52
  });
64
53
 
65
- // 3. Fetch by slug/ticker (replaces getMarketsBySlug)
54
+ // 3. Fetch by slug/ticker
66
55
  const market = await polymarket.fetchMarkets({
67
56
  slug: 'who-will-trump-nominate-as-fed-chair'
68
57
  });
@@ -140,7 +129,7 @@ Calculate the volume-weighted average price for a given amount. Returns `0` if t
140
129
 
141
130
  ```typescript
142
131
  const orderBook = await polymarket.fetchOrderBook(outcomeId);
143
- const price = await polymarket.getExecutionPrice(orderBook, 'buy', 100);
132
+ const price = polymarket.getExecutionPrice(orderBook, 'buy', 100);
144
133
  console.log(`Average price for 100 shares: ${price}`);
145
134
  ```
146
135
 
@@ -148,7 +137,7 @@ console.log(`Average price for 100 shares: ${price}`);
148
137
  Calculate detailed execution price information, including partial fills.
149
138
 
150
139
  ```typescript
151
- const detailed = await polymarket.getExecutionPriceDetailed(orderBook, 'buy', 100);
140
+ const detailed = polymarket.getExecutionPriceDetailed(orderBook, 'buy', 100);
152
141
  console.log(`Average Price: ${detailed.price}`);
153
142
  console.log(`Filled Amount: ${detailed.filledAmount}`);
154
143
  console.log(`Fully Filled: ${detailed.fullyFilled}`);
@@ -275,10 +264,10 @@ console.log(`Spread: ${(spread * 100).toFixed(2)}%`);
275
264
 
276
265
  ```typescript
277
266
  try {
278
- const markets = await kalshi.getMarketsBySlug('INVALID-TICKER');
267
+ const market = await kalshi.fetchMarket({ slug: 'INVALID-TICKER' });
268
+ console.log(market.title);
279
269
  } catch (error) {
280
- // Kalshi: "Event not found: INVALID-TICKER"
281
- // Polymarket: Returns empty array []
270
+ // Throws MarketNotFound when no market matches the lookup
282
271
  console.error(error.message);
283
272
  }
284
273
  ```
@@ -310,7 +299,7 @@ import pmxt, {
310
299
 
311
300
  ## Authentication & Trading
312
301
 
313
- Both Polymarket and Kalshi support authenticated trading operations. You must provide credentials when initializing the exchange.
302
+ Authenticated trading is available on venues that expose trading APIs. You must provide the venue-specific credentials when initializing the exchange; the examples below show Polymarket and Kalshi.
314
303
 
315
304
  ### Polymarket Authentication
316
305
 
@@ -39,7 +39,7 @@ function isServerRunning() {
39
39
  // Check if process exists
40
40
  try {
41
41
  process.kill(pid, 0); // Signal 0 checks existence without killing
42
- return { running: true, port };
42
+ return { running: true, pid, port };
43
43
  } catch (err) {
44
44
  // Process doesn't exist, remove stale lock file
45
45
  fs.unlinkSync(LOCK_FILE);
@@ -50,6 +50,26 @@ function isServerRunning() {
50
50
  }
51
51
  }
52
52
 
53
+ /**
54
+ * Remove the lock we just proved unhealthy, without deleting a newer sidecar's
55
+ * lock if another launcher won the race and replaced it first.
56
+ */
57
+ function removeLockFileIfMatches(staleLock) {
58
+ try {
59
+ if (!fs.existsSync(LOCK_FILE)) {
60
+ return false;
61
+ }
62
+ const currentLock = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf-8'));
63
+ if (currentLock.pid === staleLock.pid && currentLock.port === staleLock.port) {
64
+ fs.unlinkSync(LOCK_FILE);
65
+ return true;
66
+ }
67
+ } catch (err) {
68
+ return false;
69
+ }
70
+ return false;
71
+ }
72
+
53
73
  /**
54
74
  * Wait for server to respond to health check
55
75
  */
@@ -196,6 +216,7 @@ async function main() {
196
216
  } catch (err) {
197
217
  // Server process exists but not responding, try to start fresh
198
218
  console.error('Server process exists but not responding, starting fresh...');
219
+ removeLockFileIfMatches(serverStatus);
199
220
  }
200
221
  }
201
222
 
@@ -39,7 +39,7 @@ function isServerRunning() {
39
39
  // Check if process exists
40
40
  try {
41
41
  process.kill(pid, 0); // Signal 0 checks existence without killing
42
- return { running: true, port };
42
+ return { running: true, pid, port };
43
43
  } catch (err) {
44
44
  // Process doesn't exist, remove stale lock file
45
45
  fs.unlinkSync(LOCK_FILE);
@@ -50,6 +50,26 @@ function isServerRunning() {
50
50
  }
51
51
  }
52
52
 
53
+ /**
54
+ * Remove the lock we just proved unhealthy, without deleting a newer sidecar's
55
+ * lock if another launcher won the race and replaced it first.
56
+ */
57
+ function removeLockFileIfMatches(staleLock) {
58
+ try {
59
+ if (!fs.existsSync(LOCK_FILE)) {
60
+ return false;
61
+ }
62
+ const currentLock = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf-8'));
63
+ if (currentLock.pid === staleLock.pid && currentLock.port === staleLock.port) {
64
+ fs.unlinkSync(LOCK_FILE);
65
+ return true;
66
+ }
67
+ } catch (err) {
68
+ return false;
69
+ }
70
+ return false;
71
+ }
72
+
53
73
  /**
54
74
  * Wait for server to respond to health check
55
75
  */
@@ -85,6 +105,44 @@ function waitForHealth(port, timeout = HEALTH_CHECK_TIMEOUT) {
85
105
  });
86
106
  }
87
107
 
108
+ /**
109
+ * Wait for the lock file to appear, then health-check the port it specifies.
110
+ *
111
+ * The sidecar may bind a non-default port when the default is occupied by an
112
+ * orphan. Polling DEFAULT_PORT would be fooled by the orphan, so we wait for
113
+ * the new sidecar to write its lock file and health-check THAT port.
114
+ */
115
+ function waitForLockAndHealth(timeout = HEALTH_CHECK_TIMEOUT) {
116
+ return new Promise((resolve, reject) => {
117
+ const startTime = Date.now();
118
+
119
+ const poll = () => {
120
+ if (Date.now() - startTime > timeout) {
121
+ return reject(new Error('Server health check timeout (lock file never appeared)'));
122
+ }
123
+
124
+ try {
125
+ if (fs.existsSync(LOCK_FILE)) {
126
+ const lockData = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf-8'));
127
+ const port = lockData.port || DEFAULT_PORT;
128
+ // Lock file appeared — now health-check the actual port
129
+ const remaining = timeout - (Date.now() - startTime);
130
+ waitForHealth(port, Math.max(remaining, 1000))
131
+ .then(resolve)
132
+ .catch(reject);
133
+ return;
134
+ }
135
+ } catch (err) {
136
+ // Lock file partially written or unreadable — retry
137
+ }
138
+
139
+ setTimeout(poll, HEALTH_CHECK_INTERVAL);
140
+ };
141
+
142
+ poll();
143
+ });
144
+ }
145
+
88
146
  /**
89
147
  * Start the PMXT server
90
148
  */
@@ -136,8 +194,10 @@ async function startServer() {
136
194
  // Detach from parent process
137
195
  serverProcess.unref();
138
196
 
139
- // Wait for server to be ready
140
- await waitForHealth(DEFAULT_PORT);
197
+ // Wait for the sidecar to write its lock file, then health-check
198
+ // the actual port it bound (which may differ from DEFAULT_PORT if
199
+ // an orphan sidecar is occupying it).
200
+ await waitForLockAndHealth();
141
201
  }
142
202
 
143
203
  /**
@@ -156,6 +216,7 @@ async function main() {
156
216
  } catch (err) {
157
217
  // Server process exists but not responding, try to start fresh
158
218
  console.error('Server process exists but not responding, starting fresh...');
219
+ removeLockFileIfMatches(serverStatus);
159
220
  }
160
221
  }
161
222
 
@@ -627,8 +627,42 @@ export declare abstract class PredictionMarketExchange {
627
627
  * @returns Array of open orders
628
628
  */
629
629
  fetchOpenOrders(marketId?: string): Promise<Order[]>;
630
+ /**
631
+ * Fetch authenticated user trade history.
632
+ *
633
+ * @param params - Optional trade history filters
634
+ * @param params.outcomeId - Filter by outcome token ID
635
+ * @param params.marketId - Filter by market ID or ticker
636
+ * @param params.since - Start timestamp or ISO date
637
+ * @param params.until - End timestamp or ISO date
638
+ * @param params.limit - Maximum number of trades
639
+ * @param params.cursor - Pagination cursor
640
+ * @returns Array of user trades
641
+ */
630
642
  fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
643
+ /**
644
+ * Fetch authenticated closed orders.
645
+ *
646
+ * @param params - Optional order history filters
647
+ * @param params.marketId - Filter by market ID or ticker
648
+ * @param params.since - Start timestamp or ISO date
649
+ * @param params.until - End timestamp or ISO date
650
+ * @param params.limit - Maximum number of orders
651
+ * @param params.cursor - Pagination cursor
652
+ * @returns Array of closed orders
653
+ */
631
654
  fetchClosedOrders(params?: OrderHistoryParams): Promise<Order[]>;
655
+ /**
656
+ * Fetch authenticated order history across open and closed orders.
657
+ *
658
+ * @param params - Optional order history filters
659
+ * @param params.marketId - Filter by market ID or ticker
660
+ * @param params.since - Start timestamp or ISO date
661
+ * @param params.until - End timestamp or ISO date
662
+ * @param params.limit - Maximum number of orders
663
+ * @param params.cursor - Pagination cursor
664
+ * @returns Array of orders
665
+ */
632
666
  fetchAllOrders(params?: OrderHistoryParams): Promise<Order[]>;
633
667
  /**
634
668
  * Fetch current user positions across all markets.
@@ -213,7 +213,13 @@ class PredictionMarketExchange {
213
213
  return limit !== undefined ? filtered.slice(start, start + limit) : filtered.slice(start);
214
214
  }
215
215
  const { limit, offset, ...venueParams } = fetchParams;
216
- const markets = await this.fetchMarketsImpl(Object.keys(venueParams).length > 0 ? venueParams : undefined);
216
+ const hasVenueParams = Object.keys(venueParams).length > 0;
217
+ const shouldForwardSimpleLimit = limit !== undefined && offset === undefined && !hasVenueParams;
218
+ const markets = await this.fetchMarketsImpl(shouldForwardSimpleLimit
219
+ ? { limit }
220
+ : hasVenueParams
221
+ ? venueParams
222
+ : undefined);
217
223
  const start = offset ?? 0;
218
224
  return limit !== undefined ? markets.slice(start, start + limit) : markets.slice(start);
219
225
  }
@@ -357,7 +363,9 @@ class PredictionMarketExchange {
357
363
  return limit !== undefined ? filtered.slice(start, start + limit) : filtered.slice(start);
358
364
  }
359
365
  const { limit, offset, ...venueParams } = fetchParams;
360
- const events = await this.fetchEventsImpl(venueParams);
366
+ const hasVenueParams = Object.keys(venueParams).length > 0;
367
+ const shouldForwardSimpleLimit = limit !== undefined && offset === undefined && !hasVenueParams;
368
+ const events = await this.fetchEventsImpl(shouldForwardSimpleLimit ? { limit } : venueParams);
361
369
  const start = offset ?? 0;
362
370
  return limit !== undefined ? events.slice(start, start + limit) : events.slice(start);
363
371
  }
@@ -607,12 +615,46 @@ class PredictionMarketExchange {
607
615
  async fetchOpenOrders(marketId) {
608
616
  throw new Error("Method fetchOpenOrders not implemented.");
609
617
  }
618
+ /**
619
+ * Fetch authenticated user trade history.
620
+ *
621
+ * @param params - Optional trade history filters
622
+ * @param params.outcomeId - Filter by outcome token ID
623
+ * @param params.marketId - Filter by market ID or ticker
624
+ * @param params.since - Start timestamp or ISO date
625
+ * @param params.until - End timestamp or ISO date
626
+ * @param params.limit - Maximum number of trades
627
+ * @param params.cursor - Pagination cursor
628
+ * @returns Array of user trades
629
+ */
610
630
  async fetchMyTrades(params) {
611
631
  throw new Error("Method fetchMyTrades not implemented.");
612
632
  }
633
+ /**
634
+ * Fetch authenticated closed orders.
635
+ *
636
+ * @param params - Optional order history filters
637
+ * @param params.marketId - Filter by market ID or ticker
638
+ * @param params.since - Start timestamp or ISO date
639
+ * @param params.until - End timestamp or ISO date
640
+ * @param params.limit - Maximum number of orders
641
+ * @param params.cursor - Pagination cursor
642
+ * @returns Array of closed orders
643
+ */
613
644
  async fetchClosedOrders(params) {
614
645
  throw new Error("Method fetchClosedOrders not implemented.");
615
646
  }
647
+ /**
648
+ * Fetch authenticated order history across open and closed orders.
649
+ *
650
+ * @param params - Optional order history filters
651
+ * @param params.marketId - Filter by market ID or ticker
652
+ * @param params.since - Start timestamp or ISO date
653
+ * @param params.until - End timestamp or ISO date
654
+ * @param params.limit - Maximum number of orders
655
+ * @param params.cursor - Pagination cursor
656
+ * @returns Array of orders
657
+ */
616
658
  async fetchAllOrders(params) {
617
659
  throw new Error("Method fetchAllOrders not implemented.");
618
660
  }
@@ -175,7 +175,7 @@ class HyperliquidNormalizer {
175
175
  description: outcome.description,
176
176
  slug: `hl-${outcomeId}`,
177
177
  outcomes,
178
- resolutionDate: expiryDate ?? new Date(0),
178
+ resolutionDate: expiryDate,
179
179
  volume24h: raw.volume24h ?? 0,
180
180
  liquidity: 0,
181
181
  url: buildMarketUrl(outcomeId),
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
3
- * Generated at: 2026-06-23T09:51:53.440Z
3
+ * Generated at: 2026-06-24T09:17:49.567Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const kalshiApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.kalshiApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
6
- * Generated at: 2026-06-23T09:51:53.440Z
6
+ * Generated at: 2026-06-24T09:17:49.567Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.kalshiApiSpec = {
@@ -64,6 +64,19 @@ class KalshiFetcher {
64
64
  return this.fetchAllWithSeriesTicker(params.series);
65
65
  }
66
66
  const status = params?.status || 'active';
67
+ const hasBoundedDefaultRead = status === 'active' &&
68
+ (params.limit !== undefined || params.cursor !== undefined) &&
69
+ !params.query &&
70
+ params.offset === undefined &&
71
+ params.sort === undefined &&
72
+ params.searchIn === undefined &&
73
+ params.category === undefined &&
74
+ params.tags === undefined &&
75
+ params.filter === undefined;
76
+ if (hasBoundedDefaultRead) {
77
+ const page = await this.fetchRawEventPage(params);
78
+ return page.events;
79
+ }
67
80
  if (status === 'all') {
68
81
  const openEvents = await this.fetchAllWithStatus('open');
69
82
  const closedEvents = await this.fetchAllWithStatus('closed');
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
3
- * Generated at: 2026-06-23T09:51:53.479Z
3
+ * Generated at: 2026-06-24T09:17:49.606Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const limitlessApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.limitlessApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
6
- * Generated at: 2026-06-23T09:51:53.479Z
6
+ * Generated at: 2026-06-24T09:17:49.606Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.limitlessApiSpec = {
@@ -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-06-23T09:51:53.491Z
3
+ * Generated at: 2026-06-24T09:17:49.618Z
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-06-23T09:51:53.491Z
6
+ * Generated at: 2026-06-24T09:17:49.618Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.myriadApiSpec = {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
3
- * Generated at: 2026-06-23T09:51:53.496Z
3
+ * Generated at: 2026-06-24T09:17:49.621Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const opinionApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.opinionApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
6
- * Generated at: 2026-06-23T09:51:53.496Z
6
+ * Generated at: 2026-06-24T09:17:49.621Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.opinionApiSpec = {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
3
- * Generated at: 2026-06-23T09:51:53.448Z
3
+ * Generated at: 2026-06-24T09:17:49.575Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const polymarketClobSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.polymarketClobSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
6
- * Generated at: 2026-06-23T09:51:53.448Z
6
+ * Generated at: 2026-06-24T09:17:49.575Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.polymarketClobSpec = {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
3
- * Generated at: 2026-06-23T09:51:53.462Z
3
+ * Generated at: 2026-06-24T09:17:49.588Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const polymarketDataSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.polymarketDataSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
6
- * Generated at: 2026-06-23T09:51:53.462Z
6
+ * Generated at: 2026-06-24T09:17:49.588Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.polymarketDataSpec = {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
3
- * Generated at: 2026-06-23T09:51:53.459Z
3
+ * Generated at: 2026-06-24T09:17:49.586Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const polymarketGammaSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.polymarketGammaSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
6
- * Generated at: 2026-06-23T09:51:53.459Z
6
+ * Generated at: 2026-06-24T09:17:49.586Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.polymarketGammaSpec = {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
3
- * Generated at: 2026-06-23T09:51:53.484Z
3
+ * Generated at: 2026-06-24T09:17:49.613Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const probableApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.probableApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
6
- * Generated at: 2026-06-23T09:51:53.484Z
6
+ * Generated at: 2026-06-24T09:17:49.613Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.probableApiSpec = {
@@ -6,6 +6,7 @@ export interface RainFetcherConfig {
6
6
  subgraphApiKey?: string;
7
7
  rpcUrl?: string;
8
8
  wsRpcUrl?: string;
9
+ sdk?: RainSdk;
9
10
  }
10
11
  export type RainRawMarket = Awaited<ReturnType<RainClient['getPublicMarkets']>>[number];
11
12
  export type RainRawMarketDetails = Awaited<ReturnType<RainClient['getMarketDetails']>>;
@@ -38,7 +39,7 @@ export declare class RainFetcher {
38
39
  status?: string;
39
40
  }): Promise<RainMarketWithDetails[]>;
40
41
  fetchRawMarket(marketId: string): Promise<RainMarketWithDetails | null>;
41
- fetchRawOHLCV(marketId: string, optionIndex: number, interval: string, limit?: number): Promise<RainRawPriceHistory | null>;
42
+ fetchRawOHLCV(marketAddress: string, optionIndex: number, _interval: string, _limit?: number): Promise<RainRawPriceHistory | null>;
42
43
  fetchRawPositions(walletAddress: string): Promise<RainRawPositions>;
43
44
  fetchRawBalance(walletAddress: string, tokenAddresses: string[]): Promise<RainRawBalance>;
44
45
  fetchRawMarketTrades(marketAddress: string, limit?: number): Promise<RainRawMarketTransactions | null>;
@@ -23,7 +23,7 @@ class RainFetcher {
23
23
  }
24
24
  async getClient() {
25
25
  if (!this.client) {
26
- const sdk = await loadSdk();
26
+ const sdk = this.config.sdk ?? await loadSdk();
27
27
  this.client = new sdk.Rain({
28
28
  environment: this.config.environment ?? 'production',
29
29
  rpcUrl: this.config.rpcUrl,
@@ -91,16 +91,15 @@ class RainFetcher {
91
91
  throw errors_1.rainErrorMapper.mapError(error);
92
92
  }
93
93
  }
94
- async fetchRawOHLCV(marketId, optionIndex, interval, limit) {
94
+ async fetchRawOHLCV(marketAddress, optionIndex, _interval, _limit) {
95
95
  if (!this.config.subgraphUrl)
96
96
  return null;
97
97
  try {
98
98
  const client = await this.getClient();
99
99
  return await client.getPriceHistory({
100
- marketId,
101
- optionIndex,
102
- interval: interval,
103
- limit,
100
+ marketAddress: marketAddress,
101
+ interval: _interval,
102
+ option: optionIndex,
104
103
  });
105
104
  }
106
105
  catch (error) {
@@ -96,7 +96,11 @@ class RainExchange extends BaseExchange_1.PredictionMarketExchange {
96
96
  const marketId = parts[1];
97
97
  const choiceIndex = Number(parts[2]);
98
98
  const interval = normalizer_1.RainNormalizer.mapInterval(params.resolution);
99
- const raw = await this.fetcher.fetchRawOHLCV(marketId, choiceIndex, interval, params.limit);
99
+ const market = await this.fetcher.fetchRawMarket(marketId);
100
+ const contractAddress = market?.details?.contractAddress;
101
+ if (!contractAddress)
102
+ return [];
103
+ const raw = await this.fetcher.fetchRawOHLCV(contractAddress, choiceIndex, interval, params.limit);
100
104
  return this.normalizer.normalizeOHLCV(raw, params.limit);
101
105
  }
102
106
  async fetchOrderBook(outcomeId, _limit, _params) {
@@ -40,12 +40,19 @@ class SmarketsFetcher {
40
40
  if (params.eventId) {
41
41
  return this.fetchEnrichedEventById(params.eventId);
42
42
  }
43
+ if (params.limit !== undefined && params.limit <= 0) {
44
+ return [];
45
+ }
43
46
  const stateFilter = this.mapEventStatus(params?.status || 'active');
47
+ const requestedLimit = params.limit === undefined
48
+ ? undefined
49
+ : Math.max(1, Math.floor(params.limit));
44
50
  const rawEvents = await this.fetchPaginatedEvents({
45
51
  state: stateFilter,
46
52
  type_scope: ['single_event'],
47
53
  with_new_type: true,
48
- });
54
+ ...(requestedLimit === undefined ? {} : { limit: Math.min(requestedLimit, BATCH_SIZE) }),
55
+ }, requestedLimit);
49
56
  return this.enrichEvents(rawEvents);
50
57
  }
51
58
  catch (error) {
@@ -153,11 +160,8 @@ class SmarketsFetcher {
153
160
  const contracts = contractsData.contracts || [];
154
161
  if (contracts.length === 0)
155
162
  return [];
156
- // Step 2: Fetch volumes for this market
157
- const volumeData = await this.ctx.callApi('get_volumes_by_market_ids', {
158
- market_ids: [marketId],
159
- });
160
- const volumes = volumeData.volumes || [];
163
+ // Step 2: Fetch optional authenticated volumes for this market.
164
+ const volumes = await this.fetchVolumesByMarketIds([marketId]);
161
165
  // Step 3: We need the event_id. The contracts have market_id but not event_id.
162
166
  // Use the events/markets endpoint by searching for events that contain this market.
163
167
  // The most reliable approach: fetch all active events and find the one that owns
@@ -201,6 +205,8 @@ class SmarketsFetcher {
201
205
  }];
202
206
  }
203
207
  async fetchAllEnrichedEvents(params) {
208
+ if (params?.limit !== undefined && params.limit <= 0)
209
+ return [];
204
210
  const stateFilter = this.mapEventStatus(params?.status || 'active');
205
211
  const limit = params?.limit || 1000;
206
212
  const rawEvents = await this.fetchPaginatedEvents({
@@ -318,6 +324,10 @@ class SmarketsFetcher {
318
324
  async fetchVolumesByMarketIds(marketIds) {
319
325
  if (marketIds.length === 0)
320
326
  return [];
327
+ const headers = this.ctx.getHeaders();
328
+ const hasAuthHeader = Object.entries(headers).some(([key, value]) => key.toLowerCase() === 'authorization' && String(value).trim().length > 0);
329
+ if (!hasAuthHeader)
330
+ return [];
321
331
  const batches = this.batchArray(marketIds, MARKET_ID_BATCH_SIZE);
322
332
  const results = await Promise.all(batches.map(async (batch) => {
323
333
  try {
@@ -1142,6 +1142,7 @@ paths:
1142
1142
  type: array
1143
1143
  items:
1144
1144
  $ref: '#/components/schemas/UserTrade'
1145
+ description: Fetch authenticated user trade history.
1145
1146
  '/api/{exchange}/fetchClosedOrders':
1146
1147
  get:
1147
1148
  summary: Fetch Closed Orders
@@ -1194,6 +1195,7 @@ paths:
1194
1195
  type: array
1195
1196
  items:
1196
1197
  $ref: '#/components/schemas/Order'
1198
+ description: Fetch authenticated closed orders.
1197
1199
  '/api/{exchange}/fetchAllOrders':
1198
1200
  get:
1199
1201
  summary: Fetch All Orders
@@ -1246,6 +1248,7 @@ paths:
1246
1248
  type: array
1247
1249
  items:
1248
1250
  $ref: '#/components/schemas/Order'
1251
+ description: Fetch authenticated order history across open and closed orders.
1249
1252
  '/api/{exchange}/fetchPositions':
1250
1253
  get:
1251
1254
  summary: Fetch Positions
@@ -3639,6 +3642,15 @@ components:
3639
3642
  price:
3640
3643
  type: number
3641
3644
  description: Required for limit orders
3645
+ denom:
3646
+ type: string
3647
+ enum:
3648
+ - usdc
3649
+ - shares
3650
+ description: 'Hosted mode: amount unit.'
3651
+ slippage_pct:
3652
+ type: number
3653
+ description: 'Hosted mode: maximum market-order slippage percentage.'
3642
3654
  fee:
3643
3655
  type: number
3644
3656
  description: 'Optional fee rate (e.g., 1000 for 0.1%)'
@@ -4488,7 +4500,7 @@ x-sdk-constructors:
4488
4500
  type: string
4489
4501
  description: Private key for authentication
4490
4502
  polymarket_us:
4491
- className: PolymarketUs
4503
+ className: PolymarketUS
4492
4504
  params:
4493
4505
  - name: pmxt_api_key
4494
4506
  tsName: pmxtApiKey
@@ -4533,7 +4545,7 @@ x-sdk-constructors:
4533
4545
  type: string
4534
4546
  description: API secret for authentication
4535
4547
  suibets:
4536
- className: Suibets
4548
+ className: SuiBets
4537
4549
  params:
4538
4550
  - name: pmxt_api_key
4539
4551
  tsName: pmxtApiKey
package/dist/types.d.ts CHANGED
@@ -287,6 +287,8 @@ export interface CreateOrderParams {
287
287
  /** Size of the order in contracts/shares. */
288
288
  amount: number;
289
289
  price?: number;
290
+ denom?: 'usdc' | 'shares';
291
+ slippage_pct?: number;
290
292
  fee?: number;
291
293
  tickSize?: number;
292
294
  negRisk?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmxt-core",
3
- "version": "2.51.2",
3
+ "version": "2.51.3",
4
4
  "description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,8 +29,8 @@
29
29
  "test": "jest -c jest.config.js",
30
30
  "server": "tsx watch src/server/index.ts",
31
31
  "server:prod": "node dist/server/index.js",
32
- "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.51.2,library=urllib3",
33
- "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.51.2,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
32
+ "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.51.3,library=urllib3",
33
+ "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.51.3,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
34
34
  "fetch:openapi": "node scripts/fetch-openapi-specs.js",
35
35
  "extract:jsdoc": "node ../scripts/extract-jsdoc.js",
36
36
  "generate:docs": "npm run extract:jsdoc && node ../scripts/generate-api-docs.js",