pmxt-core 2.35.7 → 2.35.9

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,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-27T07:41:03.268Z
6
+ * Generated at: 2026-04-27T12:43:03.895Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.probableApiSpec = {
@@ -1,19 +1,32 @@
1
1
  import { PredictionMarketExchange, type MarketFetchParams, type EventFetchParams } from '../BaseExchange';
2
2
  import type { UnifiedMarket, UnifiedEvent } from '../types';
3
- import type { RouterOptions, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity, FetchMarketMatchesParams, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams } from './types';
3
+ import type { RouterOptions, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity, MatchedMarketPair, MatchedPricePair, FetchMarketMatchesParams, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams, FetchMatchedMarketsParams, FetchMatchedPricesParams } from './types';
4
4
  export declare class Router extends PredictionMarketExchange {
5
5
  private readonly client;
6
6
  constructor(options: RouterOptions);
7
7
  get name(): string;
8
8
  protected fetchMarketsImpl(params?: MarketFetchParams): Promise<UnifiedMarket[]>;
9
9
  protected fetchEventsImpl(params?: EventFetchParams): Promise<UnifiedEvent[]>;
10
- fetchMarketMatches(params: FetchMarketMatchesParams): Promise<MatchResult[]>;
10
+ fetchMarketMatches(params?: FetchMarketMatchesParams): Promise<MatchResult[]>;
11
+ /**
12
+ * Browse mode: fetch all matched market pairs from the catalog.
13
+ * Each result includes sourceMarket (one side) and market (the other).
14
+ */
15
+ private fetchMarketMatchesBrowse;
11
16
  /** @deprecated Use {@link fetchMarketMatches} instead. */
12
17
  fetchMatches(params: FetchMatchesParams): Promise<MatchResult[]>;
13
- fetchEventMatches(params: FetchEventMatchesParams): Promise<EventMatchResult[]>;
18
+ fetchEventMatches(params?: FetchEventMatchesParams): Promise<EventMatchResult[]>;
14
19
  compareMarketPrices(params: FetchMarketMatchesParams): Promise<PriceComparison[]>;
20
+ fetchRelatedMarkets(params: FetchMarketMatchesParams): Promise<PriceComparison[]>;
21
+ /** @deprecated Use {@link fetchRelatedMarkets} instead. */
15
22
  fetchHedges(params: FetchMarketMatchesParams): Promise<PriceComparison[]>;
23
+ /** @deprecated Use {@link fetchMarketMatches} without a marketId instead. */
24
+ fetchMatchedMarkets(params?: FetchMatchedMarketsParams): Promise<MatchedMarketPair[]>;
25
+ /** @deprecated Use {@link fetchMatchedMarkets} instead. */
26
+ fetchMatchedPrices(params?: FetchMatchedPricesParams): Promise<MatchedPricePair[]>;
27
+ /** @deprecated Use {@link fetchMatchedMarkets} instead. */
16
28
  fetchArbitrage(params?: FetchArbitrageParams): Promise<ArbitrageOpportunity[]>;
29
+ private fetchArbitrageInternal;
17
30
  /**
18
31
  * Bulk arbitrage via `GET /v0/arbitrage`. One round-trip.
19
32
  */
@@ -38,10 +38,17 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
38
38
  // -----------------------------------------------------------------------
39
39
  // Cross-exchange market matches
40
40
  // -----------------------------------------------------------------------
41
- async fetchMarketMatches(params) {
41
+ async fetchMarketMatches(params = {}) {
42
42
  if (params.market && !params.marketId) {
43
43
  params = { ...params, marketId: params.market.marketId };
44
44
  }
45
+ // Browse mode: no specific market identifier → return all matches
46
+ // from the catalog, with both sides of each pair.
47
+ const hasIdentifier = params.marketId || params.slug || params.url;
48
+ if (!hasIdentifier) {
49
+ return this.fetchMarketMatchesBrowse(params);
50
+ }
51
+ // Lookup mode: find matches for a specific market.
45
52
  const response = await this.client.getMarketMatches(params);
46
53
  const matches = response.matches ?? [];
47
54
  return matches.map((m) => ({
@@ -53,6 +60,28 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
53
60
  bestAsk: m.market?.bestAsk ?? null,
54
61
  }));
55
62
  }
63
+ /**
64
+ * Browse mode: fetch all matched market pairs from the catalog.
65
+ * Each result includes sourceMarket (one side) and market (the other).
66
+ */
67
+ async fetchMarketMatchesBrowse(params) {
68
+ const bulkParams = {
69
+ minSpread: params.minDifference,
70
+ category: params.category,
71
+ limit: params.limit,
72
+ relations: params.relation ? [params.relation] : undefined,
73
+ };
74
+ const pairs = await this.fetchArbitrageInternal(bulkParams);
75
+ return pairs.map((opp) => ({
76
+ sourceMarket: opp.marketA,
77
+ market: opp.marketB,
78
+ relation: opp.relation ?? 'identity',
79
+ confidence: opp.confidence ?? 0,
80
+ reasoning: opp.reasoning ?? null,
81
+ bestBid: opp.sellPrice ?? null,
82
+ bestAsk: null,
83
+ }));
84
+ }
56
85
  /** @deprecated Use {@link fetchMarketMatches} instead. */
57
86
  async fetchMatches(params) {
58
87
  console.warn('[pmxt] fetchMatches is deprecated, use fetchMarketMatches instead');
@@ -61,7 +90,7 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
61
90
  // -----------------------------------------------------------------------
62
91
  // Cross-exchange event matches
63
92
  // -----------------------------------------------------------------------
64
- async fetchEventMatches(params) {
93
+ async fetchEventMatches(params = {}) {
65
94
  if (params.event && !params.eventId) {
66
95
  params = { ...params, eventId: params.event.id };
67
96
  }
@@ -91,9 +120,9 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
91
120
  }));
92
121
  }
93
122
  // -----------------------------------------------------------------------
94
- // Hedging: subset/superset matches with live prices
123
+ // Related markets: subset/superset matches with live prices
95
124
  // -----------------------------------------------------------------------
96
- async fetchHedges(params) {
125
+ async fetchRelatedMarkets(params) {
97
126
  if (params.market && !params.marketId) {
98
127
  params = { ...params, marketId: params.market.marketId };
99
128
  }
@@ -113,10 +142,51 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
113
142
  venue: m.market.sourceExchange ?? '',
114
143
  }));
115
144
  }
145
+ /** @deprecated Use {@link fetchRelatedMarkets} instead. */
146
+ async fetchHedges(params) {
147
+ console.warn('[pmxt] fetchHedges is deprecated, use fetchRelatedMarkets instead');
148
+ return this.fetchRelatedMarkets(params);
149
+ }
116
150
  // -----------------------------------------------------------------------
117
- // Arbitrage: scan matches for price spreads
151
+ // Matched markets (deprecated use fetchMarketMatches without a
152
+ // marketId for browse mode instead)
118
153
  // -----------------------------------------------------------------------
154
+ /** @deprecated Use {@link fetchMarketMatches} without a marketId instead. */
155
+ async fetchMatchedMarkets(params) {
156
+ // Convert params: minDifference -> minSpread for internal use
157
+ const legacyParams = params
158
+ ? {
159
+ minSpread: params.minDifference,
160
+ category: params.category,
161
+ limit: params.limit,
162
+ relations: params.relations,
163
+ }
164
+ : undefined;
165
+ const legacy = await this.fetchArbitrageInternal(legacyParams);
166
+ return legacy.map((opp) => ({
167
+ marketA: opp.marketA,
168
+ marketB: opp.marketB,
169
+ priceDifference: opp.spread,
170
+ venueA: opp.buyVenue,
171
+ venueB: opp.sellVenue,
172
+ priceA: opp.buyPrice,
173
+ priceB: opp.sellPrice,
174
+ relation: opp.relation,
175
+ confidence: opp.confidence,
176
+ reasoning: opp.reasoning ?? null,
177
+ }));
178
+ }
179
+ /** @deprecated Use {@link fetchMatchedMarkets} instead. */
180
+ async fetchMatchedPrices(params) {
181
+ console.warn('[pmxt] fetchMatchedPrices is deprecated, use fetchMatchedMarkets instead');
182
+ return this.fetchMatchedMarkets(params);
183
+ }
184
+ /** @deprecated Use {@link fetchMatchedMarkets} instead. */
119
185
  async fetchArbitrage(params) {
186
+ console.warn('[pmxt] fetchArbitrage is deprecated, use fetchMatchedPrices instead');
187
+ return this.fetchArbitrageInternal(params);
188
+ }
189
+ async fetchArbitrageInternal(params) {
120
190
  // Try the dedicated bulk endpoint first (single DB query).
121
191
  try {
122
192
  return await this.fetchArbitrageBulk(params);
@@ -102,7 +102,7 @@ describe('Router', () => {
102
102
  expect(result[0].reasoning).toBe('Same market.');
103
103
  });
104
104
  });
105
- describe('fetchHedges', () => {
105
+ describe('fetchRelatedMarkets', () => {
106
106
  it('returns only subset/superset matches with reasoning', async () => {
107
107
  const mockMatches = [
108
108
  {
@@ -125,13 +125,31 @@ describe('Router', () => {
125
125
  },
126
126
  ];
127
127
  clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockMatches });
128
- const result = await router.fetchHedges({ marketId: 'm1' });
128
+ const result = await router.fetchRelatedMarkets({ marketId: 'm1' });
129
129
  expect(result).toHaveLength(2);
130
130
  expect(result[0].relation).toBe('subset');
131
131
  expect(result[0].reasoning).toBe('Narrower market — nomination implies candidacy.');
132
132
  expect(result[1].relation).toBe('superset');
133
133
  });
134
134
  });
135
+ describe('fetchHedges (deprecated)', () => {
136
+ it('delegates to fetchRelatedMarkets and logs deprecation warning', async () => {
137
+ const mockMatches = [
138
+ {
139
+ market: { marketId: 'k2', sourceExchange: 'kalshi', bestBid: 0.40, bestAsk: 0.45 },
140
+ relation: 'subset',
141
+ confidence: 0.8,
142
+ reasoning: 'Narrower market.',
143
+ },
144
+ ];
145
+ clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockMatches });
146
+ const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => { });
147
+ const result = await router.fetchHedges({ marketId: 'm1' });
148
+ expect(warnSpy).toHaveBeenCalledWith('[pmxt] fetchHedges is deprecated, use fetchRelatedMarkets instead');
149
+ expect(result).toHaveLength(1);
150
+ warnSpy.mockRestore();
151
+ });
152
+ });
135
153
  describe('fetchMarkets', () => {
136
154
  it('returns markets from the API', async () => {
137
155
  const mockMarkets = [{ marketId: 'm1', title: 'BTC' }];
@@ -161,6 +179,9 @@ describe('Router', () => {
161
179
  expect(router.has.fetchMatches).toBe(true);
162
180
  expect(router.has.fetchEventMatches).toBe(true);
163
181
  expect(router.has.compareMarketPrices).toBe(true);
182
+ expect(router.has.fetchRelatedMarkets).toBe(true);
183
+ expect(router.has.fetchMatchedMarkets).toBe(true);
184
+ expect(router.has.fetchMatchedPrices).toBe(true);
164
185
  expect(router.has.fetchHedges).toBe(true);
165
186
  expect(router.has.fetchArbitrage).toBe(true);
166
187
  });
@@ -6,6 +6,8 @@ export interface RouterOptions {
6
6
  }
7
7
  export interface MatchResult {
8
8
  market: UnifiedMarket;
9
+ /** The source market this was matched against. Present in browse mode (no marketId), absent in lookup mode. */
10
+ sourceMarket?: UnifiedMarket;
9
11
  relation: MatchRelation;
10
12
  confidence: number;
11
13
  reasoning: string | null;
@@ -39,8 +41,13 @@ export interface ArbitrageOpportunity {
39
41
  confidence?: number;
40
42
  }
41
43
  export interface FetchMarketMatchesParams {
44
+ /** Keyword search across matched market titles. */
45
+ query?: string;
46
+ /** Filter matches by category. */
47
+ category?: string;
42
48
  /** Pass a UnifiedMarket directly instead of marketId/slug/url. */
43
49
  market?: UnifiedMarket;
50
+ /** Lookup a specific market by ID. Omit for browse mode. */
44
51
  marketId?: string;
45
52
  slug?: string;
46
53
  url?: string;
@@ -48,12 +55,21 @@ export interface FetchMarketMatchesParams {
48
55
  minConfidence?: number;
49
56
  limit?: number;
50
57
  includePrices?: boolean;
58
+ /** Minimum price difference between venues. Browse mode only. */
59
+ minDifference?: number;
60
+ /** Sort order. Browse mode only. */
61
+ sort?: 'confidence' | 'volume' | 'priceDifference';
51
62
  }
52
63
  /** @deprecated Use {@link FetchMarketMatchesParams} instead. */
53
64
  export type FetchMatchesParams = FetchMarketMatchesParams;
54
65
  export interface FetchEventMatchesParams {
66
+ /** Keyword search across matched event titles. */
67
+ query?: string;
68
+ /** Filter matches by category. */
69
+ category?: string;
55
70
  /** Pass a UnifiedEvent directly instead of eventId/slug. */
56
71
  event?: UnifiedEvent;
72
+ /** Lookup a specific event by ID. Omit for browse mode. */
57
73
  eventId?: string;
58
74
  slug?: string;
59
75
  relation?: MatchRelation;
@@ -68,6 +84,32 @@ export interface FetchArbitrageParams {
68
84
  /** Comma-separated relation types to include (default: 'identity'). */
69
85
  relations?: MatchRelation[];
70
86
  }
87
+ export interface MatchedMarketPair {
88
+ marketA: UnifiedMarket;
89
+ marketB: UnifiedMarket;
90
+ priceDifference: number;
91
+ venueA: string;
92
+ venueB: string;
93
+ priceA: number;
94
+ priceB: number;
95
+ /** The set-theoretic relation between the two markets (e.g. identity, subset). */
96
+ relation?: MatchRelation;
97
+ /** Match confidence score (0.0 to 1.0). */
98
+ confidence?: number;
99
+ /** Why the two markets were matched. */
100
+ reasoning?: string | null;
101
+ }
102
+ /** @deprecated Use {@link MatchedMarketPair} instead. */
103
+ export type MatchedPricePair = MatchedMarketPair;
104
+ export interface FetchMatchedMarketsParams {
105
+ minDifference?: number;
106
+ category?: string;
107
+ limit?: number;
108
+ /** Comma-separated relation types to include (default: 'identity'). */
109
+ relations?: MatchRelation[];
110
+ }
111
+ /** @deprecated Use {@link FetchMatchedMarketsParams} instead. */
112
+ export type FetchMatchedPricesParams = FetchMatchedMarketsParams;
71
113
  export interface RouterMarketSearchParams {
72
114
  query?: string;
73
115
  sourceExchange?: string;
@@ -374,7 +374,7 @@
374
374
  {
375
375
  "name": "params",
376
376
  "kind": "object",
377
- "optional": false
377
+ "optional": true
378
378
  }
379
379
  ]
380
380
  },
@@ -384,7 +384,7 @@
384
384
  {
385
385
  "name": "params",
386
386
  "kind": "object",
387
- "optional": false
387
+ "optional": true
388
388
  }
389
389
  ]
390
390
  },
@@ -398,6 +398,36 @@
398
398
  }
399
399
  ]
400
400
  },
401
+ "fetchRelatedMarkets": {
402
+ "verb": "get",
403
+ "args": [
404
+ {
405
+ "name": "params",
406
+ "kind": "object",
407
+ "optional": false
408
+ }
409
+ ]
410
+ },
411
+ "fetchMatchedMarkets": {
412
+ "verb": "get",
413
+ "args": [
414
+ {
415
+ "name": "params",
416
+ "kind": "object",
417
+ "optional": true
418
+ }
419
+ ]
420
+ },
421
+ "fetchMatchedPrices": {
422
+ "verb": "get",
423
+ "args": [
424
+ {
425
+ "name": "params",
426
+ "kind": "object",
427
+ "optional": true
428
+ }
429
+ ]
430
+ },
401
431
  "fetchHedges": {
402
432
  "verb": "get",
403
433
  "args": [