pmxt-core 2.27.4 → 2.27.6

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.
@@ -3,24 +3,37 @@ import { SubscribedAddressSnapshot, SubscriptionOption } from './subscriber/base
3
3
  import { Balance, BuiltOrder, CandleInterval, CreateOrderParams, Order, OrderBook, Position, PriceCandle, Trade, UnifiedEvent, UnifiedMarket, UserTrade } from './types';
4
4
  import { ExecutionPriceResult } from './utils/math';
5
5
  export interface ApiEndpoint {
6
+ /** HTTP verb for the endpoint (e.g. GET, POST). */
6
7
  method: string;
8
+ /** URL path template, relative to the descriptor's baseUrl. */
7
9
  path: string;
10
+ /** Whether this endpoint requires authenticated credentials. */
8
11
  isPrivate?: boolean;
12
+ /** Identifier used to generate the implicit API method name. */
9
13
  operationId?: string;
10
14
  }
11
15
  export interface ApiDescriptor {
16
+ /** Base URL that all endpoint paths are resolved against. */
12
17
  baseUrl: string;
18
+ /** Map of endpoint key to endpoint definition used by the implicit API machinery. */
13
19
  endpoints: Record<string, ApiEndpoint>;
14
20
  }
15
21
  export interface ImplicitApiMethodInfo {
22
+ /** Generated method name exposed on the exchange instance. */
16
23
  name: string;
24
+ /** HTTP verb for the underlying endpoint. */
17
25
  method: string;
26
+ /** URL path template for the underlying endpoint. */
18
27
  path: string;
28
+ /** Whether the underlying endpoint requires authenticated credentials. */
19
29
  isPrivate: boolean;
20
30
  }
21
31
  export interface MarketFilterParams {
32
+ /** Maximum number of results to return */
22
33
  limit?: number;
34
+ /** Pagination offset — number of results to skip */
23
35
  offset?: number;
36
+ /** Sort order for results */
24
37
  sort?: 'volume' | 'liquidity' | 'newest';
25
38
  status?: 'active' | 'inactive' | 'closed' | 'all';
26
39
  searchIn?: 'title' | 'description' | 'both';
@@ -36,10 +49,14 @@ export interface MarketFetchParams extends MarketFilterParams {
36
49
  }
37
50
  export interface EventFetchParams {
38
51
  query?: string;
52
+ /** Maximum number of results to return */
39
53
  limit?: number;
54
+ /** Pagination offset — number of results to skip */
40
55
  offset?: number;
56
+ /** Sort order for results */
41
57
  sort?: 'volume' | 'liquidity' | 'newest';
42
58
  status?: 'active' | 'inactive' | 'closed' | 'all';
59
+ /** Where to search (default: 'title') */
43
60
  searchIn?: 'title' | 'description' | 'both';
44
61
  eventId?: string;
45
62
  slug?: string;
@@ -49,37 +66,53 @@ export interface EventFetchParams {
49
66
  */
50
67
  export interface HistoryFilterParams {
51
68
  resolution?: CandleInterval;
69
+ /** Start of the time range */
52
70
  start?: Date;
71
+ /** End of the time range */
53
72
  end?: Date;
73
+ /** Maximum number of results to return */
54
74
  limit?: number;
55
75
  }
56
76
  export interface OHLCVParams {
57
77
  resolution: CandleInterval;
78
+ /** Start of the time range */
58
79
  start?: Date;
80
+ /** End of the time range */
59
81
  end?: Date;
82
+ /** Maximum number of results to return */
60
83
  limit?: number;
61
84
  }
62
85
  /**
63
86
  * Parameters for fetching trade history. No resolution parameter - trades are discrete events.
64
87
  */
65
88
  export interface TradesParams {
89
+ /** Start of the time range */
66
90
  start?: Date;
91
+ /** End of the time range */
67
92
  end?: Date;
93
+ /** Maximum number of results to return */
68
94
  limit?: number;
69
95
  }
70
96
  export interface MyTradesParams {
71
97
  outcomeId?: string;
72
98
  marketId?: string;
99
+ /** Only return records after this date */
73
100
  since?: Date;
101
+ /** Only return records before this date */
74
102
  until?: Date;
103
+ /** Maximum number of results to return */
75
104
  limit?: number;
76
105
  cursor?: string;
77
106
  }
78
107
  export interface OrderHistoryParams {
79
108
  marketId?: string;
109
+ /** Only return records after this date */
80
110
  since?: Date;
111
+ /** Only return records before this date */
81
112
  until?: Date;
113
+ /** Maximum number of results to return */
82
114
  limit?: number;
115
+ /** Opaque pagination cursor from a previous response */
83
116
  cursor?: string;
84
117
  }
85
118
  export type MarketFilterCriteria = {
@@ -89,14 +122,17 @@ export type MarketFilterCriteria = {
89
122
  min?: number;
90
123
  max?: number;
91
124
  };
125
+ /** Filter by total (lifetime) volume range */
92
126
  volume?: {
93
127
  min?: number;
94
128
  max?: number;
95
129
  };
130
+ /** Filter by current liquidity range */
96
131
  liquidity?: {
97
132
  min?: number;
98
133
  max?: number;
99
134
  };
135
+ /** Filter by open interest range */
100
136
  openInterest?: {
101
137
  min?: number;
102
138
  max?: number;
@@ -123,6 +159,7 @@ export type EventFilterCriteria = {
123
159
  text?: string;
124
160
  searchIn?: ('title' | 'description' | 'category' | 'tags')[];
125
161
  category?: string;
162
+ /** Match events that have any of these tags */
126
163
  tags?: string[];
127
164
  marketCount?: {
128
165
  min?: number;
@@ -136,25 +173,45 @@ export type EventFilterCriteria = {
136
173
  export type EventFilterFunction = (event: UnifiedEvent) => boolean;
137
174
  export type ExchangeCapability = true | false | 'emulated';
138
175
  export interface ExchangeHas {
176
+ /** Whether this exchange supports fetching markets. */
139
177
  fetchMarkets: ExchangeCapability;
178
+ /** Whether this exchange supports fetching events. */
140
179
  fetchEvents: ExchangeCapability;
180
+ /** Whether this exchange supports fetching OHLCV candles. */
141
181
  fetchOHLCV: ExchangeCapability;
182
+ /** Whether this exchange supports fetching the order book. */
142
183
  fetchOrderBook: ExchangeCapability;
184
+ /** Whether this exchange supports fetching public trades. */
143
185
  fetchTrades: ExchangeCapability;
186
+ /** Whether this exchange supports creating orders. */
144
187
  createOrder: ExchangeCapability;
188
+ /** Whether this exchange supports cancelling orders. */
145
189
  cancelOrder: ExchangeCapability;
190
+ /** Whether this exchange supports fetching a single order by id. */
146
191
  fetchOrder: ExchangeCapability;
192
+ /** Whether this exchange supports fetching open orders. */
147
193
  fetchOpenOrders: ExchangeCapability;
194
+ /** Whether this exchange supports fetching account positions. */
148
195
  fetchPositions: ExchangeCapability;
196
+ /** Whether this exchange supports fetching account balances. */
149
197
  fetchBalance: ExchangeCapability;
198
+ /** Whether this exchange supports subscribing to an on-chain address for updates. */
150
199
  watchAddress: ExchangeCapability;
200
+ /** Whether this exchange supports unsubscribing from a watched address. */
151
201
  unwatchAddress: ExchangeCapability;
202
+ /** Whether this exchange supports streaming order book updates. */
152
203
  watchOrderBook: ExchangeCapability;
204
+ /** Whether this exchange supports streaming trade updates. */
153
205
  watchTrades: ExchangeCapability;
206
+ /** Whether this exchange supports fetching the authenticated user's trade history. */
154
207
  fetchMyTrades: ExchangeCapability;
208
+ /** Whether this exchange supports fetching closed orders. */
155
209
  fetchClosedOrders: ExchangeCapability;
210
+ /** Whether this exchange supports fetching all orders (open and closed). */
156
211
  fetchAllOrders: ExchangeCapability;
212
+ /** Whether this exchange supports building a signed order without submitting it. */
157
213
  buildOrder: ExchangeCapability;
214
+ /** Whether this exchange supports submitting a pre-built order. */
158
215
  submitOrder: ExchangeCapability;
159
216
  }
160
217
  /**
@@ -162,7 +219,9 @@ export interface ExchangeHas {
162
219
  */
163
220
  export interface ExchangeCredentials {
164
221
  apiKey?: string;
222
+ /** Standard API secret for HMAC-authenticated exchanges */
165
223
  apiSecret?: string;
224
+ /** Standard API passphrase for HMAC-authenticated exchanges */
166
225
  passphrase?: string;
167
226
  /** Metaculus: `Authorization: Token <apiToken>` for higher rate limits */
168
227
  apiToken?: string;
@@ -180,8 +239,11 @@ export interface ExchangeOptions {
180
239
  }
181
240
  /** Shape returned by fetchMarketsPaginated */
182
241
  export interface PaginatedMarketsResult {
242
+ /** The page of unified markets */
183
243
  data: UnifiedMarket[];
244
+ /** Total number of markets in the snapshot */
184
245
  total: number;
246
+ /** Cursor to pass to the next call, or undefined if this is the last page */
185
247
  nextCursor?: string;
186
248
  }
187
249
  export declare abstract class PredictionMarketExchange {
@@ -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-04-09T14:31:05.346Z
3
+ * Generated at: 2026-04-09T15:36:23.083Z
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-04-09T14:31:05.346Z
6
+ * Generated at: 2026-04-09T15:36:23.083Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.kalshiApiSpec = {
@@ -21,5 +21,8 @@ export declare class KalshiNormalizer implements IExchangeNormalizer<KalshiRawEv
21
21
  }): Balance[];
22
22
  private mapOrderStatus;
23
23
  private deriveEventDescription;
24
+ private deriveOutcomeLabel;
25
+ private cleanLabel;
26
+ private templateRule;
24
27
  }
25
28
  export declare function sortRawEvents(events: any[], sort: string): any[];
@@ -34,10 +34,7 @@ class KalshiNormalizer {
34
34
  else if (market.yes_ask) {
35
35
  price = (0, price_1.fromKalshiCents)(market.yes_ask);
36
36
  }
37
- let candidateName = null;
38
- if (market.subtitle || market.yes_sub_title) {
39
- candidateName = (market.subtitle || market.yes_sub_title);
40
- }
37
+ const candidateName = this.deriveOutcomeLabel(market);
41
38
  let priceChange = 0;
42
39
  if (market.previous_price_dollars !== undefined && market.last_price_dollars !== undefined) {
43
40
  priceChange = market.last_price_dollars - market.previous_price_dollars;
@@ -261,27 +258,64 @@ class KalshiNormalizer {
261
258
  return '';
262
259
  if (texts.length === 1)
263
260
  return texts[0];
264
- let prefix = texts[0];
265
- for (const t of texts) {
266
- while (!t.startsWith(prefix))
267
- prefix = prefix.slice(0, -1);
268
- if (!prefix)
269
- break;
261
+ const templates = new Map();
262
+ for (const market of markets) {
263
+ const rawRule = typeof market?.rules_primary === 'string' ? market.rules_primary : '';
264
+ if (!rawRule)
265
+ continue;
266
+ const candidate = this.deriveOutcomeLabel(market);
267
+ const templated = this.templateRule(rawRule, candidate);
268
+ templates.set(templated, (templates.get(templated) ?? 0) + 1);
270
269
  }
271
- const suffixCandidates = texts.map((t) => t.slice(prefix.length));
272
- let suffix = suffixCandidates[0];
273
- for (const t of suffixCandidates) {
274
- while (!t.endsWith(suffix))
275
- suffix = suffix.slice(1);
276
- if (!suffix)
277
- break;
270
+ // Only consider templates that actually contain the {x} placeholder so
271
+ // that a rule we failed to template (e.g. candidate name missing) can
272
+ // never win the vote and leak a specific name into the event description.
273
+ if (templates.size > 0) {
274
+ let bestTemplate = null;
275
+ let bestCount = 0;
276
+ for (const [template, count] of templates.entries()) {
277
+ if (!template.includes('{x}'))
278
+ continue;
279
+ if (count > bestCount) {
280
+ bestTemplate = template;
281
+ bestCount = count;
282
+ }
283
+ }
284
+ if (bestTemplate)
285
+ return bestTemplate;
278
286
  }
279
- if (prefix.length + suffix.length < 20)
280
- return texts[0];
281
- const variables = texts.map((t) => t.slice(prefix.length, suffix.length ? t.length - suffix.length : undefined));
282
- if (new Set(variables).size === 1)
283
- return texts[0];
284
- return prefix + '{x}' + suffix;
287
+ return texts[0];
288
+ }
289
+ deriveOutcomeLabel(market) {
290
+ const yesSubtitle = this.cleanLabel(market.yes_sub_title);
291
+ if (yesSubtitle)
292
+ return yesSubtitle;
293
+ const subtitle = this.cleanLabel(market.subtitle);
294
+ if (subtitle)
295
+ return subtitle;
296
+ return null;
297
+ }
298
+ cleanLabel(value) {
299
+ if (typeof value !== 'string')
300
+ return null;
301
+ const trimmed = value.trim();
302
+ if (!trimmed)
303
+ return null;
304
+ // Some Kalshi markets use structural subtitles like ":: Democratic".
305
+ if (trimmed.startsWith('::'))
306
+ return null;
307
+ return trimmed;
308
+ }
309
+ templateRule(rule, candidateName) {
310
+ if (!candidateName)
311
+ return rule;
312
+ const escaped = candidateName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
313
+ // Unicode-aware word boundaries so non-ASCII candidate names (Jose,
314
+ // Muller, O'Brien, etc.) still template correctly. JavaScript's \b is
315
+ // ASCII-only and would silently fail on such names.
316
+ const matcher = new RegExp(`(?<![\\p{L}\\p{N}])${escaped}(?![\\p{L}\\p{N}])`, 'gu');
317
+ const replaced = rule.replace(matcher, '{x}');
318
+ return replaced === rule ? rule : replaced;
285
319
  }
286
320
  }
287
321
  exports.KalshiNormalizer = KalshiNormalizer;
@@ -18,11 +18,17 @@ function mapMarketToUnified(event, market) {
18
18
  else if (market.yes_ask) {
19
19
  price = (0, price_1.fromKalshiCents)(market.yes_ask);
20
20
  }
21
- // Extract candidate name
22
- let candidateName = null;
23
- if (market.subtitle || market.yes_sub_title) {
24
- candidateName = market.subtitle || market.yes_sub_title;
25
- }
21
+ // Extract candidate name. Prefer explicit outcome subtitle and ignore
22
+ // structural labels such as ":: Democratic".
23
+ const cleanLabel = (value) => {
24
+ if (typeof value !== "string")
25
+ return null;
26
+ const trimmed = value.trim();
27
+ if (!trimmed || trimmed.startsWith("::"))
28
+ return null;
29
+ return trimmed;
30
+ };
31
+ const candidateName = cleanLabel(market.yes_sub_title) ?? cleanLabel(market.subtitle);
26
32
  // Calculate 24h change
27
33
  let priceChange = 0;
28
34
  if (market.previous_price_dollars !== undefined &&
@@ -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-04-09T14:31:05.395Z
3
+ * Generated at: 2026-04-09T15:36:23.133Z
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-04-09T14:31:05.395Z
6
+ * Generated at: 2026-04-09T15:36:23.133Z
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-04-09T14:31:05.411Z
3
+ * Generated at: 2026-04-09T15:36:23.142Z
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-04-09T14:31:05.411Z
6
+ * Generated at: 2026-04-09T15:36:23.142Z
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-04-09T14:31:05.416Z
3
+ * Generated at: 2026-04-09T15:36:23.147Z
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-04-09T14:31:05.416Z
6
+ * Generated at: 2026-04-09T15:36:23.147Z
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-04-09T14:31:05.354Z
3
+ * Generated at: 2026-04-09T15:36:23.092Z
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-04-09T14:31:05.354Z
6
+ * Generated at: 2026-04-09T15:36:23.092Z
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-04-09T14:31:05.372Z
3
+ * Generated at: 2026-04-09T15:36:23.112Z
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-04-09T14:31:05.372Z
6
+ * Generated at: 2026-04-09T15:36:23.112Z
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-04-09T14:31:05.369Z
3
+ * Generated at: 2026-04-09T15:36:23.107Z
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-04-09T14:31:05.369Z
6
+ * Generated at: 2026-04-09T15:36:23.107Z
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-04-09T14:31:05.402Z
3
+ * Generated at: 2026-04-09T15:36:23.137Z
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-04-09T14:31:05.402Z
6
+ * Generated at: 2026-04-09T15:36:23.137Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.probableApiSpec = {