pmxt-core 2.33.4 → 2.34.0
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/dist/BaseExchange.d.ts +7 -1
- package/dist/BaseExchange.js +11 -3
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/kalshi/fetcher.d.ts +3 -0
- package/dist/exchanges/kalshi/normalizer.js +5 -5
- package/dist/exchanges/kalshi/utils.js +4 -4
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/opinion/api.d.ts +1 -1
- package/dist/exchanges/opinion/api.js +1 -1
- package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
- package/dist/exchanges/polymarket/api-clob.js +1 -1
- package/dist/exchanges/polymarket/api-data.d.ts +1 -1
- package/dist/exchanges/polymarket/api-data.js +1 -1
- package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
- package/dist/exchanges/polymarket/api-gamma.js +1 -1
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/utils.js +13 -2
- package/dist/router/Router.d.ts +13 -3
- package/dist/router/Router.js +107 -43
- package/dist/router/Router.test.js +23 -4
- package/dist/router/client.d.ts +1 -0
- package/dist/router/client.js +4 -0
- package/dist/router/types.d.ts +13 -1
- package/dist/server/method-verbs.json +10 -0
- package/dist/server/openapi.yaml +145 -4
- package/dist/types.d.ts +4 -0
- package/package.json +3 -3
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { AxiosInstance } from 'axios';
|
|
|
2
2
|
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
|
-
import type { FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity } from './router/types';
|
|
5
|
+
import type { FetchMarketMatchesParams, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity } from './router/types';
|
|
6
6
|
export interface ApiEndpoint {
|
|
7
7
|
/** HTTP verb for the endpoint (e.g. GET, POST). */
|
|
8
8
|
method: string;
|
|
@@ -229,6 +229,8 @@ export interface ExchangeHas {
|
|
|
229
229
|
/** Whether this exchange supports submitting a pre-built order. */
|
|
230
230
|
submitOrder: ExchangeCapability;
|
|
231
231
|
/** Whether this exchange supports fetching cross-venue market matches. */
|
|
232
|
+
fetchMarketMatches: ExchangeCapability;
|
|
233
|
+
/** @deprecated Use {@link fetchMarketMatches} instead. */
|
|
232
234
|
fetchMatches: ExchangeCapability;
|
|
233
235
|
/** Whether this exchange supports fetching cross-venue event matches. */
|
|
234
236
|
fetchEventMatches: ExchangeCapability;
|
|
@@ -576,6 +578,10 @@ export declare abstract class PredictionMarketExchange {
|
|
|
576
578
|
* @param params - Match filter parameters (marketId, relation, minConfidence, etc.)
|
|
577
579
|
* @returns Array of matched markets with relation and confidence
|
|
578
580
|
*/
|
|
581
|
+
fetchMarketMatches(params: FetchMarketMatchesParams): Promise<MatchResult[]>;
|
|
582
|
+
/**
|
|
583
|
+
* @deprecated Use {@link fetchMarketMatches} instead.
|
|
584
|
+
*/
|
|
579
585
|
fetchMatches(params: FetchMatchesParams): Promise<MatchResult[]>;
|
|
580
586
|
/**
|
|
581
587
|
* Find the same or related event on other venues. Given an event on one venue, discover semantically equivalent events across every other venue PMXT ingests — including market-level match details for each child market.
|
package/dist/BaseExchange.js
CHANGED
|
@@ -769,8 +769,15 @@ class PredictionMarketExchange {
|
|
|
769
769
|
* @param params - Match filter parameters (marketId, relation, minConfidence, etc.)
|
|
770
770
|
* @returns Array of matched markets with relation and confidence
|
|
771
771
|
*/
|
|
772
|
+
async fetchMarketMatches(params) {
|
|
773
|
+
throw new Error("Method fetchMarketMatches not implemented.");
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* @deprecated Use {@link fetchMarketMatches} instead.
|
|
777
|
+
*/
|
|
772
778
|
async fetchMatches(params) {
|
|
773
|
-
|
|
779
|
+
console.warn('[pmxt] fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
780
|
+
return this.fetchMarketMatches(params);
|
|
774
781
|
}
|
|
775
782
|
/**
|
|
776
783
|
* Find the same or related event on other venues. Given an event on one venue, discover semantically equivalent events across every other venue PMXT ingests — including market-level match details for each child market.
|
|
@@ -934,7 +941,7 @@ class PredictionMarketExchange {
|
|
|
934
941
|
'watchAddress', 'unwatchAddress', 'watchOrderBook',
|
|
935
942
|
'unwatchOrderBook', 'watchTrades', 'fetchMyTrades',
|
|
936
943
|
'fetchClosedOrders', 'fetchAllOrders', 'buildOrder', 'submitOrder',
|
|
937
|
-
'fetchMatches', 'fetchEventMatches', 'compareMarketPrices',
|
|
944
|
+
'fetchMarketMatches', 'fetchMatches', 'fetchEventMatches', 'compareMarketPrices',
|
|
938
945
|
'fetchHedges', 'fetchArbitrage',
|
|
939
946
|
];
|
|
940
947
|
// Compile-time exhaustiveness check: fails tsc if a key exists in
|
|
@@ -947,7 +954,7 @@ class PredictionMarketExchange {
|
|
|
947
954
|
unwatchAddress: true, watchOrderBook: true, unwatchOrderBook: true,
|
|
948
955
|
watchTrades: true, fetchMyTrades: true, fetchClosedOrders: true,
|
|
949
956
|
fetchAllOrders: true, buildOrder: true, submitOrder: true,
|
|
950
|
-
fetchMatches: true, fetchEventMatches: true, compareMarketPrices: true,
|
|
957
|
+
fetchMarketMatches: true, fetchMatches: true, fetchEventMatches: true, compareMarketPrices: true,
|
|
951
958
|
fetchHedges: true, fetchArbitrage: true,
|
|
952
959
|
};
|
|
953
960
|
/**
|
|
@@ -959,6 +966,7 @@ class PredictionMarketExchange {
|
|
|
959
966
|
static _capabilityDelegates = {
|
|
960
967
|
fetchMarkets: 'fetchMarketsImpl',
|
|
961
968
|
fetchEvents: 'fetchEventsImpl',
|
|
969
|
+
fetchMatches: 'fetchMarketMatches',
|
|
962
970
|
};
|
|
963
971
|
/**
|
|
964
972
|
* Derive the capability map by comparing this instance's prototype chain
|
|
@@ -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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.664Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.664Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -72,10 +72,10 @@ class KalshiNormalizer {
|
|
|
72
72
|
description: market.rules_primary || market.rules_secondary || '',
|
|
73
73
|
outcomes,
|
|
74
74
|
resolutionDate: new Date(market.expiration_time),
|
|
75
|
-
volume24h: Number(market.volume_24h || market.volume || 0),
|
|
76
|
-
volume: Number(market.volume || 0),
|
|
75
|
+
volume24h: parseFloat(market.volume_24h_fp ?? '') || Number(market.volume_24h || market.volume || 0),
|
|
76
|
+
volume: parseFloat(market.volume_fp ?? '') || Number(market.volume || 0),
|
|
77
77
|
liquidity: Number(market.liquidity || 0),
|
|
78
|
-
openInterest: Number(market.open_interest || 0),
|
|
78
|
+
openInterest: parseFloat(market.open_interest_fp ?? '') || Number(market.open_interest || 0),
|
|
79
79
|
url: `https://kalshi.com/events/${event.event_ticker}`,
|
|
80
80
|
category: event.category,
|
|
81
81
|
tags: unifiedTags,
|
|
@@ -321,10 +321,10 @@ class KalshiNormalizer {
|
|
|
321
321
|
exports.KalshiNormalizer = KalshiNormalizer;
|
|
322
322
|
// -- Event sorting utility (exported for fetchEvents) -------------------------
|
|
323
323
|
function eventVolume(event) {
|
|
324
|
-
return (event.markets || []).reduce((sum, m) => sum + Number(m.volume || 0), 0);
|
|
324
|
+
return (event.markets || []).reduce((sum, m) => sum + (parseFloat(m.volume_fp ?? '') || Number(m.volume || 0)), 0);
|
|
325
325
|
}
|
|
326
326
|
function eventLiquidity(event) {
|
|
327
|
-
return (event.markets || []).reduce((sum, m) => sum + Number(m.open_interest || m.liquidity || 0), 0);
|
|
327
|
+
return (event.markets || []).reduce((sum, m) => sum + (parseFloat(m.open_interest_fp ?? '') || Number(m.open_interest || m.liquidity || 0)), 0);
|
|
328
328
|
}
|
|
329
329
|
function eventNewest(event) {
|
|
330
330
|
const times = (event.markets || [])
|
|
@@ -73,10 +73,10 @@ function mapMarketToUnified(event, market) {
|
|
|
73
73
|
description: market.rules_primary || market.rules_secondary || "",
|
|
74
74
|
outcomes: outcomes,
|
|
75
75
|
resolutionDate: new Date(market.expiration_time),
|
|
76
|
-
volume24h: Number(market.volume_24h || market.volume || 0),
|
|
77
|
-
volume: Number(market.volume || 0),
|
|
78
|
-
liquidity: Number(market.liquidity || 0),
|
|
79
|
-
openInterest: Number(market.open_interest || 0),
|
|
76
|
+
volume24h: parseFloat(market.volume_24h_fp ?? '') || Number(market.volume_24h || market.volume || 0),
|
|
77
|
+
volume: parseFloat(market.volume_fp ?? '') || Number(market.volume || 0),
|
|
78
|
+
liquidity: Number(market.liquidity || 0),
|
|
79
|
+
openInterest: parseFloat(market.open_interest_fp ?? '') || Number(market.open_interest || 0),
|
|
80
80
|
url: `https://kalshi.com/events/${event.event_ticker}`,
|
|
81
81
|
category: event.category,
|
|
82
82
|
tags: unifiedTags,
|
|
@@ -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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.703Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.703Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.714Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.714Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.719Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.719Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.670Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.670Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.686Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.686Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.684Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.684Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-23T12:27:49.709Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-23T12:27:49.709Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
|
@@ -38,7 +38,18 @@ function mapMarketToUnified(market, event) {
|
|
|
38
38
|
volume: Number(market.volume || 0),
|
|
39
39
|
liquidity: Number(market.liquidity || 0),
|
|
40
40
|
openInterest: 0,
|
|
41
|
-
url:
|
|
41
|
+
url: (() => {
|
|
42
|
+
const eventSlug = event?.slug || market._parentEvent?.slug;
|
|
43
|
+
const marketId = market.id;
|
|
44
|
+
if (eventSlug) {
|
|
45
|
+
return `https://probable.markets/event/${eventSlug}?market=${marketId}`;
|
|
46
|
+
}
|
|
47
|
+
const eventId = event?.id || market.event_id;
|
|
48
|
+
if (eventId) {
|
|
49
|
+
return `https://probable.markets/event/${eventId}?market=${marketId}`;
|
|
50
|
+
}
|
|
51
|
+
return `https://probable.markets/event/?market=${marketId}`;
|
|
52
|
+
})(),
|
|
42
53
|
image: market.icon || event?.icon || event?.image || undefined,
|
|
43
54
|
category: event?.category || market.category || undefined,
|
|
44
55
|
tags: market.tags || event?.tags || [],
|
|
@@ -65,7 +76,7 @@ function mapEventToUnified(event) {
|
|
|
65
76
|
markets,
|
|
66
77
|
volume24h: markets.reduce((sum, m) => sum + m.volume24h, 0),
|
|
67
78
|
volume: markets.some(m => m.volume !== undefined) ? markets.reduce((sum, m) => sum + (m.volume ?? 0), 0) : undefined,
|
|
68
|
-
url: `https://probable.markets/
|
|
79
|
+
url: `https://probable.markets/event/${event.slug || event.id}`,
|
|
69
80
|
image: event.icon || event.image || undefined,
|
|
70
81
|
category: event.category || undefined,
|
|
71
82
|
tags: event.tags || [],
|
package/dist/router/Router.d.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
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, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams } from './types';
|
|
3
|
+
import type { RouterOptions, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity, FetchMarketMatchesParams, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams } 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[]>;
|
|
11
|
+
/** @deprecated Use {@link fetchMarketMatches} instead. */
|
|
10
12
|
fetchMatches(params: FetchMatchesParams): Promise<MatchResult[]>;
|
|
11
13
|
fetchEventMatches(params: FetchEventMatchesParams): Promise<EventMatchResult[]>;
|
|
12
|
-
compareMarketPrices(params:
|
|
13
|
-
fetchHedges(params:
|
|
14
|
+
compareMarketPrices(params: FetchMarketMatchesParams): Promise<PriceComparison[]>;
|
|
15
|
+
fetchHedges(params: FetchMarketMatchesParams): Promise<PriceComparison[]>;
|
|
14
16
|
fetchArbitrage(params?: FetchArbitrageParams): Promise<ArbitrageOpportunity[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Bulk arbitrage via `GET /v0/arbitrage`. One round-trip.
|
|
19
|
+
*/
|
|
20
|
+
private fetchArbitrageBulk;
|
|
21
|
+
/**
|
|
22
|
+
* Legacy N+1 fallback: fetch markets, then fetch matches per-market.
|
|
23
|
+
*/
|
|
24
|
+
private fetchArbitrageFallback;
|
|
15
25
|
}
|
package/dist/router/Router.js
CHANGED
|
@@ -38,7 +38,10 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
|
38
38
|
// -----------------------------------------------------------------------
|
|
39
39
|
// Cross-exchange market matches
|
|
40
40
|
// -----------------------------------------------------------------------
|
|
41
|
-
async
|
|
41
|
+
async fetchMarketMatches(params) {
|
|
42
|
+
if (params.market && !params.marketId) {
|
|
43
|
+
params = { ...params, marketId: params.market.marketId };
|
|
44
|
+
}
|
|
42
45
|
const response = await this.client.getMarketMatches(params);
|
|
43
46
|
const matches = response.matches ?? [];
|
|
44
47
|
return matches.map((m) => ({
|
|
@@ -50,10 +53,18 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
|
50
53
|
bestAsk: m.market?.bestAsk ?? null,
|
|
51
54
|
}));
|
|
52
55
|
}
|
|
56
|
+
/** @deprecated Use {@link fetchMarketMatches} instead. */
|
|
57
|
+
async fetchMatches(params) {
|
|
58
|
+
console.warn('[pmxt] fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
59
|
+
return this.fetchMarketMatches(params);
|
|
60
|
+
}
|
|
53
61
|
// -----------------------------------------------------------------------
|
|
54
62
|
// Cross-exchange event matches
|
|
55
63
|
// -----------------------------------------------------------------------
|
|
56
64
|
async fetchEventMatches(params) {
|
|
65
|
+
if (params.event && !params.eventId) {
|
|
66
|
+
params = { ...params, eventId: params.event.id };
|
|
67
|
+
}
|
|
57
68
|
const response = await this.client.getEventMatches(params);
|
|
58
69
|
return response.matches ?? [];
|
|
59
70
|
}
|
|
@@ -61,7 +72,10 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
|
61
72
|
// Price comparison: identity matches with live prices
|
|
62
73
|
// -----------------------------------------------------------------------
|
|
63
74
|
async compareMarketPrices(params) {
|
|
64
|
-
|
|
75
|
+
if (params.market && !params.marketId) {
|
|
76
|
+
params = { ...params, marketId: params.market.marketId };
|
|
77
|
+
}
|
|
78
|
+
const matches = await this.fetchMarketMatches({
|
|
65
79
|
...params,
|
|
66
80
|
relation: 'identity',
|
|
67
81
|
includePrices: true,
|
|
@@ -80,7 +94,10 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
|
80
94
|
// Hedging: subset/superset matches with live prices
|
|
81
95
|
// -----------------------------------------------------------------------
|
|
82
96
|
async fetchHedges(params) {
|
|
83
|
-
|
|
97
|
+
if (params.market && !params.marketId) {
|
|
98
|
+
params = { ...params, marketId: params.market.marketId };
|
|
99
|
+
}
|
|
100
|
+
const matches = await this.fetchMarketMatches({
|
|
84
101
|
...params,
|
|
85
102
|
includePrices: true,
|
|
86
103
|
});
|
|
@@ -97,57 +114,104 @@ class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
|
97
114
|
}));
|
|
98
115
|
}
|
|
99
116
|
// -----------------------------------------------------------------------
|
|
100
|
-
// Arbitrage: scan
|
|
117
|
+
// Arbitrage: scan matches for price spreads
|
|
101
118
|
// -----------------------------------------------------------------------
|
|
102
119
|
async fetchArbitrage(params) {
|
|
120
|
+
// Try the dedicated bulk endpoint first (single DB query).
|
|
121
|
+
try {
|
|
122
|
+
return await this.fetchArbitrageBulk(params);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Dedicated endpoint not available — fall back to N+1 approach.
|
|
126
|
+
return this.fetchArbitrageFallback(params);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Bulk arbitrage via `GET /v0/arbitrage`. One round-trip.
|
|
131
|
+
*/
|
|
132
|
+
async fetchArbitrageBulk(params) {
|
|
133
|
+
const query = {};
|
|
134
|
+
const relations = params?.relations ?? ['identity'];
|
|
135
|
+
query.relations = relations.join(',');
|
|
136
|
+
if (params?.minSpread !== undefined)
|
|
137
|
+
query.minSpread = String(params.minSpread);
|
|
138
|
+
if (params?.category)
|
|
139
|
+
query.category = params.category;
|
|
140
|
+
if (params?.limit !== undefined)
|
|
141
|
+
query.limit = String(params.limit);
|
|
142
|
+
const res = await this.client.getArbitrage(query);
|
|
143
|
+
const items = res.data ?? [];
|
|
144
|
+
return items.map((r) => ({
|
|
145
|
+
marketA: r.marketA,
|
|
146
|
+
marketB: r.marketB,
|
|
147
|
+
spread: r.spread ?? 0,
|
|
148
|
+
buyVenue: r.buyVenue ?? '',
|
|
149
|
+
sellVenue: r.sellVenue ?? '',
|
|
150
|
+
buyPrice: r.buyPrice ?? 0,
|
|
151
|
+
sellPrice: r.sellPrice ?? 0,
|
|
152
|
+
relation: r.relation,
|
|
153
|
+
confidence: r.confidence,
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Legacy N+1 fallback: fetch markets, then fetch matches per-market.
|
|
158
|
+
*/
|
|
159
|
+
async fetchArbitrageFallback(params) {
|
|
103
160
|
const minSpread = params?.minSpread ?? 0;
|
|
104
161
|
const limit = params?.limit ?? 50;
|
|
162
|
+
const relations = params?.relations ?? ['identity'];
|
|
105
163
|
const markets = await this.fetchMarkets({
|
|
106
164
|
category: params?.category,
|
|
107
165
|
limit,
|
|
108
166
|
});
|
|
109
167
|
const opportunities = [];
|
|
110
168
|
for (const market of markets) {
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
for (const relation of relations) {
|
|
170
|
+
const matches = await this.fetchMarketMatches({
|
|
171
|
+
marketId: market.marketId,
|
|
172
|
+
relation,
|
|
173
|
+
includePrices: true,
|
|
174
|
+
});
|
|
175
|
+
if (matches.length === 0)
|
|
176
|
+
continue;
|
|
177
|
+
const sourceAsk = market.outcomes[0]?.price ?? null;
|
|
178
|
+
const sourceBid = sourceAsk;
|
|
179
|
+
const sourceVenue = market.sourceExchange ?? '';
|
|
180
|
+
for (const match of matches) {
|
|
181
|
+
const matchBid = match.bestBid;
|
|
182
|
+
const matchAsk = match.bestAsk;
|
|
183
|
+
const matchVenue = match.market.sourceExchange ?? '';
|
|
184
|
+
if (sourceAsk !== null && matchBid !== null) {
|
|
185
|
+
const spread = matchBid - sourceAsk;
|
|
186
|
+
if (spread >= minSpread) {
|
|
187
|
+
opportunities.push({
|
|
188
|
+
marketA: market,
|
|
189
|
+
marketB: match.market,
|
|
190
|
+
spread,
|
|
191
|
+
buyVenue: sourceVenue,
|
|
192
|
+
sellVenue: matchVenue,
|
|
193
|
+
buyPrice: sourceAsk,
|
|
194
|
+
sellPrice: matchBid,
|
|
195
|
+
relation: match.relation,
|
|
196
|
+
confidence: match.confidence,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
137
199
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
if (matchAsk !== null && sourceBid !== null) {
|
|
201
|
+
const spread = sourceBid - matchAsk;
|
|
202
|
+
if (spread >= minSpread) {
|
|
203
|
+
opportunities.push({
|
|
204
|
+
marketA: match.market,
|
|
205
|
+
marketB: market,
|
|
206
|
+
spread,
|
|
207
|
+
buyVenue: matchVenue,
|
|
208
|
+
sellVenue: sourceVenue,
|
|
209
|
+
buyPrice: matchAsk,
|
|
210
|
+
sellPrice: sourceBid,
|
|
211
|
+
relation: match.relation,
|
|
212
|
+
confidence: match.confidence,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
151
215
|
}
|
|
152
216
|
}
|
|
153
217
|
}
|
|
@@ -21,7 +21,7 @@ describe('Router', () => {
|
|
|
21
21
|
expect(() => new Router_1.Router({ apiKey: 'key' })).not.toThrow();
|
|
22
22
|
});
|
|
23
23
|
});
|
|
24
|
-
describe('
|
|
24
|
+
describe('fetchMarketMatches', () => {
|
|
25
25
|
it('returns matches from the API using marketId', async () => {
|
|
26
26
|
const mockApiResponse = [
|
|
27
27
|
{
|
|
@@ -32,7 +32,7 @@ describe('Router', () => {
|
|
|
32
32
|
},
|
|
33
33
|
];
|
|
34
34
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockApiResponse });
|
|
35
|
-
const result = await router.
|
|
35
|
+
const result = await router.fetchMarketMatches({ marketId: 'm1', relation: 'identity' });
|
|
36
36
|
expect(clientInstance.getMarketMatches).toHaveBeenCalledWith({ marketId: 'm1', relation: 'identity' });
|
|
37
37
|
expect(result[0].confidence).toBe(0.95);
|
|
38
38
|
expect(result[0].bestBid).toBe(0.60);
|
|
@@ -40,15 +40,33 @@ describe('Router', () => {
|
|
|
40
40
|
});
|
|
41
41
|
it('accepts slug as identifier', async () => {
|
|
42
42
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: [] });
|
|
43
|
-
await router.
|
|
43
|
+
await router.fetchMarketMatches({ slug: 'btc-100k' });
|
|
44
44
|
expect(clientInstance.getMarketMatches).toHaveBeenCalledWith({ slug: 'btc-100k' });
|
|
45
45
|
});
|
|
46
46
|
it('returns empty array when no matches', async () => {
|
|
47
47
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({});
|
|
48
|
-
const result = await router.
|
|
48
|
+
const result = await router.fetchMarketMatches({ marketId: 'm1' });
|
|
49
49
|
expect(result).toEqual([]);
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
|
+
describe('fetchMatches (deprecated)', () => {
|
|
53
|
+
it('delegates to fetchMarketMatches and logs deprecation warning', async () => {
|
|
54
|
+
const mockApiResponse = [
|
|
55
|
+
{
|
|
56
|
+
market: { marketId: 'k1', sourceExchange: 'kalshi', bestBid: 0.60, bestAsk: 0.65 },
|
|
57
|
+
relation: 'identity',
|
|
58
|
+
confidence: 0.95,
|
|
59
|
+
reasoning: 'Same resolution condition.',
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockApiResponse });
|
|
63
|
+
const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => { });
|
|
64
|
+
const result = await router.fetchMatches({ marketId: 'm1' });
|
|
65
|
+
expect(warnSpy).toHaveBeenCalledWith('[pmxt] fetchMatches is deprecated, use fetchMarketMatches instead');
|
|
66
|
+
expect(result[0].confidence).toBe(0.95);
|
|
67
|
+
warnSpy.mockRestore();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
52
70
|
describe('fetchEventMatches', () => {
|
|
53
71
|
it('returns event matches from the API', async () => {
|
|
54
72
|
const mockMatches = [
|
|
@@ -139,6 +157,7 @@ describe('Router', () => {
|
|
|
139
157
|
});
|
|
140
158
|
describe('capabilities', () => {
|
|
141
159
|
it('reports matching methods as supported', () => {
|
|
160
|
+
expect(router.has.fetchMarketMatches).toBe(true);
|
|
142
161
|
expect(router.has.fetchMatches).toBe(true);
|
|
143
162
|
expect(router.has.fetchEventMatches).toBe(true);
|
|
144
163
|
expect(router.has.compareMarketPrices).toBe(true);
|
package/dist/router/client.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare class PmxtApiClient {
|
|
|
6
6
|
getEventMatches(params: FetchEventMatchesParams): Promise<any>;
|
|
7
7
|
searchMarkets(params?: RouterMarketSearchParams): Promise<any>;
|
|
8
8
|
searchEvents(params?: RouterEventSearchParams): Promise<any>;
|
|
9
|
+
getArbitrage(query?: Record<string, string>): Promise<any>;
|
|
9
10
|
private request;
|
|
10
11
|
private mapError;
|
|
11
12
|
}
|
package/dist/router/client.js
CHANGED
|
@@ -85,6 +85,10 @@ class PmxtApiClient {
|
|
|
85
85
|
const res = await this.request('GET', '/v0/events', query);
|
|
86
86
|
return res.data;
|
|
87
87
|
}
|
|
88
|
+
async getArbitrage(query) {
|
|
89
|
+
const res = await this.request('GET', '/v0/arbitrage', query);
|
|
90
|
+
return res.data;
|
|
91
|
+
}
|
|
88
92
|
// -----------------------------------------------------------------------
|
|
89
93
|
// Internal
|
|
90
94
|
// -----------------------------------------------------------------------
|
package/dist/router/types.d.ts
CHANGED
|
@@ -33,8 +33,14 @@ export interface ArbitrageOpportunity {
|
|
|
33
33
|
sellVenue: string;
|
|
34
34
|
buyPrice: number;
|
|
35
35
|
sellPrice: number;
|
|
36
|
+
/** The set-theoretic relation between the two markets (e.g. identity, subset). */
|
|
37
|
+
relation?: MatchRelation;
|
|
38
|
+
/** Match confidence score (0.0 to 1.0). */
|
|
39
|
+
confidence?: number;
|
|
36
40
|
}
|
|
37
|
-
export interface
|
|
41
|
+
export interface FetchMarketMatchesParams {
|
|
42
|
+
/** Pass a UnifiedMarket directly instead of marketId/slug/url. */
|
|
43
|
+
market?: UnifiedMarket;
|
|
38
44
|
marketId?: string;
|
|
39
45
|
slug?: string;
|
|
40
46
|
url?: string;
|
|
@@ -43,7 +49,11 @@ export interface FetchMatchesParams {
|
|
|
43
49
|
limit?: number;
|
|
44
50
|
includePrices?: boolean;
|
|
45
51
|
}
|
|
52
|
+
/** @deprecated Use {@link FetchMarketMatchesParams} instead. */
|
|
53
|
+
export type FetchMatchesParams = FetchMarketMatchesParams;
|
|
46
54
|
export interface FetchEventMatchesParams {
|
|
55
|
+
/** Pass a UnifiedEvent directly instead of eventId/slug. */
|
|
56
|
+
event?: UnifiedEvent;
|
|
47
57
|
eventId?: string;
|
|
48
58
|
slug?: string;
|
|
49
59
|
relation?: MatchRelation;
|
|
@@ -55,6 +65,8 @@ export interface FetchArbitrageParams {
|
|
|
55
65
|
minSpread?: number;
|
|
56
66
|
category?: string;
|
|
57
67
|
limit?: number;
|
|
68
|
+
/** Comma-separated relation types to include (default: 'identity'). */
|
|
69
|
+
relations?: MatchRelation[];
|
|
58
70
|
}
|
|
59
71
|
export interface RouterMarketSearchParams {
|
|
60
72
|
query?: string;
|
|
@@ -358,6 +358,16 @@
|
|
|
358
358
|
"verb": "post",
|
|
359
359
|
"args": []
|
|
360
360
|
},
|
|
361
|
+
"fetchMarketMatches": {
|
|
362
|
+
"verb": "get",
|
|
363
|
+
"args": [
|
|
364
|
+
{
|
|
365
|
+
"name": "params",
|
|
366
|
+
"kind": "object",
|
|
367
|
+
"optional": false
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
},
|
|
361
371
|
"fetchMatches": {
|
|
362
372
|
"verb": "get",
|
|
363
373
|
"args": [
|
package/dist/server/openapi.yaml
CHANGED
|
@@ -1464,12 +1464,19 @@ paths:
|
|
|
1464
1464
|
description: >-
|
|
1465
1465
|
Close all WebSocket connections and clean up resources. Call this when you're done streaming to properly release
|
|
1466
1466
|
connections.
|
|
1467
|
-
'/api/{exchange}/
|
|
1467
|
+
'/api/{exchange}/fetchMarketMatches':
|
|
1468
1468
|
get:
|
|
1469
1469
|
summary: Find Similar Markets
|
|
1470
|
-
operationId:
|
|
1470
|
+
operationId: fetchMarketMatches
|
|
1471
1471
|
parameters:
|
|
1472
1472
|
- $ref: '#/components/parameters/ExchangeParam'
|
|
1473
|
+
- in: query
|
|
1474
|
+
name: market
|
|
1475
|
+
required: false
|
|
1476
|
+
schema:
|
|
1477
|
+
allOf:
|
|
1478
|
+
- $ref: '#/components/schemas/UnifiedMarket'
|
|
1479
|
+
description: Pass a UnifiedMarket directly instead of marketId/slug/url.
|
|
1473
1480
|
- in: query
|
|
1474
1481
|
name: marketId
|
|
1475
1482
|
required: false
|
|
@@ -1529,12 +1536,88 @@ paths:
|
|
|
1529
1536
|
Find the same or related market on other venues. Given a market on one venue, discover semantically equivalent
|
|
1530
1537
|
markets across every other venue PMXT ingests — each with a relation type (identity, subset, superset, overlap,
|
|
1531
1538
|
disjoint), confidence score, and reasoning.
|
|
1539
|
+
'/api/{exchange}/fetchMatches':
|
|
1540
|
+
get:
|
|
1541
|
+
summary: Find Similar Markets (Deprecated)
|
|
1542
|
+
operationId: fetchMatches
|
|
1543
|
+
parameters:
|
|
1544
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1545
|
+
- in: query
|
|
1546
|
+
name: market
|
|
1547
|
+
required: false
|
|
1548
|
+
schema:
|
|
1549
|
+
allOf:
|
|
1550
|
+
- $ref: '#/components/schemas/UnifiedMarket'
|
|
1551
|
+
description: Pass a UnifiedMarket directly instead of marketId/slug/url.
|
|
1552
|
+
- in: query
|
|
1553
|
+
name: marketId
|
|
1554
|
+
required: false
|
|
1555
|
+
schema:
|
|
1556
|
+
type: string
|
|
1557
|
+
- in: query
|
|
1558
|
+
name: slug
|
|
1559
|
+
required: false
|
|
1560
|
+
schema:
|
|
1561
|
+
type: string
|
|
1562
|
+
- in: query
|
|
1563
|
+
name: url
|
|
1564
|
+
required: false
|
|
1565
|
+
schema:
|
|
1566
|
+
type: string
|
|
1567
|
+
- in: query
|
|
1568
|
+
name: relation
|
|
1569
|
+
required: false
|
|
1570
|
+
schema:
|
|
1571
|
+
type: string
|
|
1572
|
+
enum:
|
|
1573
|
+
- identity
|
|
1574
|
+
- subset
|
|
1575
|
+
- superset
|
|
1576
|
+
- overlap
|
|
1577
|
+
- disjoint
|
|
1578
|
+
- in: query
|
|
1579
|
+
name: minConfidence
|
|
1580
|
+
required: false
|
|
1581
|
+
schema:
|
|
1582
|
+
type: number
|
|
1583
|
+
- in: query
|
|
1584
|
+
name: limit
|
|
1585
|
+
required: false
|
|
1586
|
+
schema:
|
|
1587
|
+
type: number
|
|
1588
|
+
- in: query
|
|
1589
|
+
name: includePrices
|
|
1590
|
+
required: false
|
|
1591
|
+
schema:
|
|
1592
|
+
type: boolean
|
|
1593
|
+
responses:
|
|
1594
|
+
'200':
|
|
1595
|
+
description: Find Similar Markets (Deprecated) response
|
|
1596
|
+
content:
|
|
1597
|
+
application/json:
|
|
1598
|
+
schema:
|
|
1599
|
+
allOf:
|
|
1600
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1601
|
+
- type: object
|
|
1602
|
+
properties:
|
|
1603
|
+
data:
|
|
1604
|
+
type: array
|
|
1605
|
+
items:
|
|
1606
|
+
$ref: '#/components/schemas/MatchResult'
|
|
1607
|
+
deprecated: true
|
|
1532
1608
|
'/api/{exchange}/fetchEventMatches':
|
|
1533
1609
|
get:
|
|
1534
1610
|
summary: Find Similar Events
|
|
1535
1611
|
operationId: fetchEventMatches
|
|
1536
1612
|
parameters:
|
|
1537
1613
|
- $ref: '#/components/parameters/ExchangeParam'
|
|
1614
|
+
- in: query
|
|
1615
|
+
name: event
|
|
1616
|
+
required: false
|
|
1617
|
+
schema:
|
|
1618
|
+
allOf:
|
|
1619
|
+
- $ref: '#/components/schemas/UnifiedEvent'
|
|
1620
|
+
description: Pass a UnifiedEvent directly instead of eventId/slug.
|
|
1538
1621
|
- in: query
|
|
1539
1622
|
name: eventId
|
|
1540
1623
|
required: false
|
|
@@ -1605,7 +1688,7 @@ paths:
|
|
|
1605
1688
|
type: array
|
|
1606
1689
|
maxItems: 1
|
|
1607
1690
|
items:
|
|
1608
|
-
$ref: '#/components/schemas/
|
|
1691
|
+
$ref: '#/components/schemas/FetchMarketMatchesParams'
|
|
1609
1692
|
minItems: 1
|
|
1610
1693
|
credentials:
|
|
1611
1694
|
$ref: '#/components/schemas/ExchangeCredentials'
|
|
@@ -1634,6 +1717,13 @@ paths:
|
|
|
1634
1717
|
operationId: fetchHedges
|
|
1635
1718
|
parameters:
|
|
1636
1719
|
- $ref: '#/components/parameters/ExchangeParam'
|
|
1720
|
+
- in: query
|
|
1721
|
+
name: market
|
|
1722
|
+
required: false
|
|
1723
|
+
schema:
|
|
1724
|
+
allOf:
|
|
1725
|
+
- $ref: '#/components/schemas/UnifiedMarket'
|
|
1726
|
+
description: Pass a UnifiedMarket directly instead of marketId/slug/url.
|
|
1637
1727
|
- in: query
|
|
1638
1728
|
name: marketId
|
|
1639
1729
|
required: false
|
|
@@ -1713,6 +1803,20 @@ paths:
|
|
|
1713
1803
|
required: false
|
|
1714
1804
|
schema:
|
|
1715
1805
|
type: number
|
|
1806
|
+
- in: query
|
|
1807
|
+
name: relations
|
|
1808
|
+
required: false
|
|
1809
|
+
schema:
|
|
1810
|
+
type: array
|
|
1811
|
+
items:
|
|
1812
|
+
type: string
|
|
1813
|
+
enum:
|
|
1814
|
+
- identity
|
|
1815
|
+
- subset
|
|
1816
|
+
- superset
|
|
1817
|
+
- overlap
|
|
1818
|
+
- disjoint
|
|
1819
|
+
description: 'Comma-separated relation types to include (default: ''identity'').'
|
|
1716
1820
|
responses:
|
|
1717
1821
|
'200':
|
|
1718
1822
|
description: Find Arbitrage Opportunities response
|
|
@@ -1842,6 +1946,9 @@ components:
|
|
|
1842
1946
|
contractAddress:
|
|
1843
1947
|
type: string
|
|
1844
1948
|
description: 'On-chain contract / condition identifier where applicable (Polymarket conditionId, etc.).'
|
|
1949
|
+
sourceExchange:
|
|
1950
|
+
type: string
|
|
1951
|
+
description: 'The exchange/venue this market originates from (e.g. ''polymarket'', ''kalshi''). Populated by the Router.'
|
|
1845
1952
|
'yes':
|
|
1846
1953
|
allOf:
|
|
1847
1954
|
- $ref: '#/components/schemas/MarketOutcome'
|
|
@@ -1934,6 +2041,9 @@ components:
|
|
|
1934
2041
|
items:
|
|
1935
2042
|
type: string
|
|
1936
2043
|
description: Optional list of tags associated with the event.
|
|
2044
|
+
sourceExchange:
|
|
2045
|
+
type: string
|
|
2046
|
+
description: 'The exchange/venue this event originates from (e.g. ''polymarket'', ''kalshi''). Populated by the Router.'
|
|
1937
2047
|
required:
|
|
1938
2048
|
- id
|
|
1939
2049
|
- title
|
|
@@ -2639,9 +2749,13 @@ components:
|
|
|
2639
2749
|
max:
|
|
2640
2750
|
type: number
|
|
2641
2751
|
description: Sum of market volumes
|
|
2642
|
-
|
|
2752
|
+
FetchMarketMatchesParams:
|
|
2643
2753
|
type: object
|
|
2644
2754
|
properties:
|
|
2755
|
+
market:
|
|
2756
|
+
allOf:
|
|
2757
|
+
- $ref: '#/components/schemas/UnifiedMarket'
|
|
2758
|
+
description: Pass a UnifiedMarket directly instead of marketId/slug/url.
|
|
2645
2759
|
marketId:
|
|
2646
2760
|
type: string
|
|
2647
2761
|
slug:
|
|
@@ -2665,6 +2779,10 @@ components:
|
|
|
2665
2779
|
FetchEventMatchesParams:
|
|
2666
2780
|
type: object
|
|
2667
2781
|
properties:
|
|
2782
|
+
event:
|
|
2783
|
+
allOf:
|
|
2784
|
+
- $ref: '#/components/schemas/UnifiedEvent'
|
|
2785
|
+
description: Pass a UnifiedEvent directly instead of eventId/slug.
|
|
2668
2786
|
eventId:
|
|
2669
2787
|
type: string
|
|
2670
2788
|
slug:
|
|
@@ -2692,6 +2810,17 @@ components:
|
|
|
2692
2810
|
type: string
|
|
2693
2811
|
limit:
|
|
2694
2812
|
type: number
|
|
2813
|
+
relations:
|
|
2814
|
+
type: array
|
|
2815
|
+
items:
|
|
2816
|
+
type: string
|
|
2817
|
+
enum:
|
|
2818
|
+
- identity
|
|
2819
|
+
- subset
|
|
2820
|
+
- superset
|
|
2821
|
+
- overlap
|
|
2822
|
+
- disjoint
|
|
2823
|
+
description: 'Comma-separated relation types to include (default: ''identity'').'
|
|
2695
2824
|
MatchResult:
|
|
2696
2825
|
type: object
|
|
2697
2826
|
properties:
|
|
@@ -2792,6 +2921,18 @@ components:
|
|
|
2792
2921
|
type: number
|
|
2793
2922
|
sellPrice:
|
|
2794
2923
|
type: number
|
|
2924
|
+
relation:
|
|
2925
|
+
type: string
|
|
2926
|
+
enum:
|
|
2927
|
+
- identity
|
|
2928
|
+
- subset
|
|
2929
|
+
- superset
|
|
2930
|
+
- overlap
|
|
2931
|
+
- disjoint
|
|
2932
|
+
description: 'The set-theoretic relation between the two markets (e.g. identity, subset).'
|
|
2933
|
+
confidence:
|
|
2934
|
+
type: number
|
|
2935
|
+
description: Match confidence score (0.0 to 1.0).
|
|
2795
2936
|
required:
|
|
2796
2937
|
- marketA
|
|
2797
2938
|
- marketB
|
package/dist/types.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface UnifiedEvent {
|
|
|
37
37
|
category?: string;
|
|
38
38
|
/** Optional list of tags associated with the event. */
|
|
39
39
|
tags?: string[];
|
|
40
|
+
/** The exchange/venue this event originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router. */
|
|
41
|
+
sourceExchange?: string;
|
|
40
42
|
}
|
|
41
43
|
export interface UnifiedMarket {
|
|
42
44
|
/** The unique identifier for this market */
|
|
@@ -73,6 +75,8 @@ export interface UnifiedMarket {
|
|
|
73
75
|
status?: string;
|
|
74
76
|
/** On-chain contract / condition identifier where applicable (Polymarket conditionId, etc.). */
|
|
75
77
|
contractAddress?: string;
|
|
78
|
+
/** The exchange/venue this market originates from (e.g. 'polymarket', 'kalshi'). Populated by the Router. */
|
|
79
|
+
sourceExchange?: string;
|
|
76
80
|
/** Convenience accessor for the YES outcome on a binary market. */
|
|
77
81
|
yes?: MarketOutcome;
|
|
78
82
|
/** Convenience accessor for the NO outcome on a binary market. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.34.0",
|
|
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.
|
|
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.
|
|
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.34.0,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.34.0,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",
|