pmxt-core 2.32.4 → 2.33.2
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 +46 -0
- package/dist/BaseExchange.js +52 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- 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/router/Router.d.ts +6 -6
- package/dist/router/Router.js +40 -22
- package/dist/router/Router.test.js +31 -21
- package/dist/server/app.js +5 -0
- package/dist/server/method-verbs.json +50 -0
- package/dist/server/openapi.yaml +424 -0
- package/package.json +3 -3
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -2,6 +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
6
|
export interface ApiEndpoint {
|
|
6
7
|
/** HTTP verb for the endpoint (e.g. GET, POST). */
|
|
7
8
|
method: string;
|
|
@@ -227,6 +228,16 @@ export interface ExchangeHas {
|
|
|
227
228
|
buildOrder: ExchangeCapability;
|
|
228
229
|
/** Whether this exchange supports submitting a pre-built order. */
|
|
229
230
|
submitOrder: ExchangeCapability;
|
|
231
|
+
/** Whether this exchange supports fetching cross-venue market matches. */
|
|
232
|
+
fetchMatches: ExchangeCapability;
|
|
233
|
+
/** Whether this exchange supports fetching cross-venue event matches. */
|
|
234
|
+
fetchEventMatches: ExchangeCapability;
|
|
235
|
+
/** Whether this exchange supports comparing prices across venues. */
|
|
236
|
+
compareMarketPrices: ExchangeCapability;
|
|
237
|
+
/** Whether this exchange supports finding hedging opportunities across venues. */
|
|
238
|
+
fetchHedges: ExchangeCapability;
|
|
239
|
+
/** Whether this exchange supports scanning for arbitrage opportunities. */
|
|
240
|
+
fetchArbitrage: ExchangeCapability;
|
|
230
241
|
}
|
|
231
242
|
/**
|
|
232
243
|
* Optional authentication credentials for exchange operations.
|
|
@@ -559,6 +570,41 @@ export declare abstract class PredictionMarketExchange {
|
|
|
559
570
|
* Call this when you're done streaming to properly release connections.
|
|
560
571
|
*/
|
|
561
572
|
close(): Promise<void>;
|
|
573
|
+
/**
|
|
574
|
+
* Fetch cross-venue matches for a given market.
|
|
575
|
+
*
|
|
576
|
+
* @param params - Match filter parameters (marketId, relation, minConfidence, etc.)
|
|
577
|
+
* @returns Array of matched markets with relation and confidence
|
|
578
|
+
*/
|
|
579
|
+
fetchMatches(params: FetchMatchesParams): Promise<MatchResult[]>;
|
|
580
|
+
/**
|
|
581
|
+
* Fetch cross-venue matches for a given event.
|
|
582
|
+
*
|
|
583
|
+
* @param params - Event match filter parameters (eventId, relation, etc.)
|
|
584
|
+
* @returns Array of matched events with market-level match details
|
|
585
|
+
*/
|
|
586
|
+
fetchEventMatches(params: FetchEventMatchesParams): Promise<EventMatchResult[]>;
|
|
587
|
+
/**
|
|
588
|
+
* Compare prices across venues for identity matches of a market.
|
|
589
|
+
*
|
|
590
|
+
* @param params - Match filter parameters (uses relation: 'identity' internally)
|
|
591
|
+
* @returns Array of price comparisons across venues
|
|
592
|
+
*/
|
|
593
|
+
compareMarketPrices(params: FetchMatchesParams): Promise<PriceComparison[]>;
|
|
594
|
+
/**
|
|
595
|
+
* Find hedging opportunities via subset/superset matches across venues.
|
|
596
|
+
*
|
|
597
|
+
* @param params - Match filter parameters
|
|
598
|
+
* @returns Array of subset/superset matches with live prices
|
|
599
|
+
*/
|
|
600
|
+
fetchHedges(params: FetchMatchesParams): Promise<PriceComparison[]>;
|
|
601
|
+
/**
|
|
602
|
+
* Scan for arbitrage opportunities across identity matches.
|
|
603
|
+
*
|
|
604
|
+
* @param params - Arbitrage scan parameters (minSpread, category, limit)
|
|
605
|
+
* @returns Array of arbitrage opportunities sorted by spread
|
|
606
|
+
*/
|
|
607
|
+
fetchArbitrage(params?: FetchArbitrageParams): Promise<ArbitrageOpportunity[]>;
|
|
562
608
|
/**
|
|
563
609
|
* @internal
|
|
564
610
|
* Implementation for fetching/searching markets.
|
package/dist/BaseExchange.js
CHANGED
|
@@ -760,6 +760,54 @@ class PredictionMarketExchange {
|
|
|
760
760
|
// Default implementation: no-op
|
|
761
761
|
// Exchanges with WebSocket support should override this
|
|
762
762
|
}
|
|
763
|
+
// ----------------------------------------------------------------------------
|
|
764
|
+
// Matching Methods (Router-only; stubs throw for standard exchanges)
|
|
765
|
+
// ----------------------------------------------------------------------------
|
|
766
|
+
/**
|
|
767
|
+
* Fetch cross-venue matches for a given market.
|
|
768
|
+
*
|
|
769
|
+
* @param params - Match filter parameters (marketId, relation, minConfidence, etc.)
|
|
770
|
+
* @returns Array of matched markets with relation and confidence
|
|
771
|
+
*/
|
|
772
|
+
async fetchMatches(params) {
|
|
773
|
+
throw new Error("Method fetchMatches not implemented.");
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Fetch cross-venue matches for a given event.
|
|
777
|
+
*
|
|
778
|
+
* @param params - Event match filter parameters (eventId, relation, etc.)
|
|
779
|
+
* @returns Array of matched events with market-level match details
|
|
780
|
+
*/
|
|
781
|
+
async fetchEventMatches(params) {
|
|
782
|
+
throw new Error("Method fetchEventMatches not implemented.");
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Compare prices across venues for identity matches of a market.
|
|
786
|
+
*
|
|
787
|
+
* @param params - Match filter parameters (uses relation: 'identity' internally)
|
|
788
|
+
* @returns Array of price comparisons across venues
|
|
789
|
+
*/
|
|
790
|
+
async compareMarketPrices(params) {
|
|
791
|
+
throw new Error("Method compareMarketPrices not implemented.");
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Find hedging opportunities via subset/superset matches across venues.
|
|
795
|
+
*
|
|
796
|
+
* @param params - Match filter parameters
|
|
797
|
+
* @returns Array of subset/superset matches with live prices
|
|
798
|
+
*/
|
|
799
|
+
async fetchHedges(params) {
|
|
800
|
+
throw new Error("Method fetchHedges not implemented.");
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Scan for arbitrage opportunities across identity matches.
|
|
804
|
+
*
|
|
805
|
+
* @param params - Arbitrage scan parameters (minSpread, category, limit)
|
|
806
|
+
* @returns Array of arbitrage opportunities sorted by spread
|
|
807
|
+
*/
|
|
808
|
+
async fetchArbitrage(params) {
|
|
809
|
+
throw new Error("Method fetchArbitrage not implemented.");
|
|
810
|
+
}
|
|
763
811
|
/**
|
|
764
812
|
* @internal
|
|
765
813
|
* Implementation for fetching/searching markets.
|
|
@@ -886,6 +934,8 @@ class PredictionMarketExchange {
|
|
|
886
934
|
'watchAddress', 'unwatchAddress', 'watchOrderBook',
|
|
887
935
|
'unwatchOrderBook', 'watchTrades', 'fetchMyTrades',
|
|
888
936
|
'fetchClosedOrders', 'fetchAllOrders', 'buildOrder', 'submitOrder',
|
|
937
|
+
'fetchMatches', 'fetchEventMatches', 'compareMarketPrices',
|
|
938
|
+
'fetchHedges', 'fetchArbitrage',
|
|
889
939
|
];
|
|
890
940
|
// Compile-time exhaustiveness check: fails tsc if a key exists in
|
|
891
941
|
// ExchangeHas but is missing from _capabilityKeys above.
|
|
@@ -897,6 +947,8 @@ class PredictionMarketExchange {
|
|
|
897
947
|
unwatchAddress: true, watchOrderBook: true, unwatchOrderBook: true,
|
|
898
948
|
watchTrades: true, fetchMyTrades: true, fetchClosedOrders: true,
|
|
899
949
|
fetchAllOrders: true, buildOrder: true, submitOrder: true,
|
|
950
|
+
fetchMatches: true, fetchEventMatches: true, compareMarketPrices: true,
|
|
951
|
+
fetchHedges: true, fetchArbitrage: true,
|
|
900
952
|
};
|
|
901
953
|
/**
|
|
902
954
|
* Map from capability keys to the actual method(s) whose override status
|
|
@@ -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-23T07:50:04.153Z
|
|
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-23T07:50:04.153Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -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-23T07:50:04.190Z
|
|
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-23T07:50:04.190Z
|
|
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-23T07:50:04.201Z
|
|
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-23T07:50:04.201Z
|
|
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-23T07:50:04.206Z
|
|
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-23T07:50:04.206Z
|
|
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-23T07:50:04.161Z
|
|
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-23T07:50:04.161Z
|
|
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-23T07:50:04.172Z
|
|
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-23T07:50:04.172Z
|
|
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-23T07:50:04.170Z
|
|
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-23T07:50:04.170Z
|
|
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-23T07:50:04.194Z
|
|
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-23T07:50:04.194Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
package/dist/router/Router.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import { PredictionMarketExchange, type MarketFetchParams, type EventFetchParams } from '../BaseExchange';
|
|
1
2
|
import type { UnifiedMarket, UnifiedEvent } from '../types';
|
|
2
|
-
import type { RouterOptions, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams
|
|
3
|
-
export declare class Router {
|
|
4
|
-
readonly name = "Router";
|
|
3
|
+
import type { RouterOptions, MatchResult, EventMatchResult, PriceComparison, ArbitrageOpportunity, FetchMatchesParams, FetchEventMatchesParams, FetchArbitrageParams } from './types';
|
|
4
|
+
export declare class Router extends PredictionMarketExchange {
|
|
5
5
|
private readonly client;
|
|
6
6
|
constructor(options: RouterOptions);
|
|
7
|
+
get name(): string;
|
|
8
|
+
protected fetchMarketsImpl(params?: MarketFetchParams): Promise<UnifiedMarket[]>;
|
|
9
|
+
protected fetchEventsImpl(params?: EventFetchParams): Promise<UnifiedEvent[]>;
|
|
7
10
|
fetchMatches(params: FetchMatchesParams): Promise<MatchResult[]>;
|
|
8
11
|
fetchEventMatches(params: FetchEventMatchesParams): Promise<EventMatchResult[]>;
|
|
9
12
|
compareMarketPrices(params: FetchMatchesParams): Promise<PriceComparison[]>;
|
|
10
13
|
fetchHedges(params: FetchMatchesParams): Promise<PriceComparison[]>;
|
|
11
14
|
fetchArbitrage(params?: FetchArbitrageParams): Promise<ArbitrageOpportunity[]>;
|
|
12
|
-
fetchMarkets(params?: RouterMarketSearchParams): Promise<UnifiedMarket[]>;
|
|
13
|
-
fetchEvents(params?: RouterEventSearchParams): Promise<UnifiedEvent[]>;
|
|
14
|
-
createOrder(): Promise<never>;
|
|
15
15
|
}
|
package/dist/router/Router.js
CHANGED
|
@@ -1,19 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Router = void 0;
|
|
4
|
+
const BaseExchange_1 = require("../BaseExchange");
|
|
4
5
|
const client_1 = require("./client");
|
|
5
|
-
class Router {
|
|
6
|
-
name = 'Router';
|
|
6
|
+
class Router extends BaseExchange_1.PredictionMarketExchange {
|
|
7
7
|
client;
|
|
8
8
|
constructor(options) {
|
|
9
|
+
super({ apiKey: options.apiKey });
|
|
9
10
|
this.client = new client_1.PmxtApiClient(options.apiKey, options.baseUrl);
|
|
11
|
+
this.rateLimit = 100;
|
|
12
|
+
}
|
|
13
|
+
get name() {
|
|
14
|
+
return 'Router';
|
|
10
15
|
}
|
|
11
16
|
// -----------------------------------------------------------------------
|
|
12
|
-
//
|
|
17
|
+
// BaseExchange implementation delegates
|
|
18
|
+
// -----------------------------------------------------------------------
|
|
19
|
+
async fetchMarketsImpl(params) {
|
|
20
|
+
const response = await this.client.searchMarkets({
|
|
21
|
+
query: params?.query,
|
|
22
|
+
category: params?.category,
|
|
23
|
+
limit: params?.limit,
|
|
24
|
+
offset: params?.offset,
|
|
25
|
+
closed: params?.status === 'closed' || params?.status === 'inactive',
|
|
26
|
+
});
|
|
27
|
+
return response ?? [];
|
|
28
|
+
}
|
|
29
|
+
async fetchEventsImpl(params) {
|
|
30
|
+
const response = await this.client.searchEvents({
|
|
31
|
+
query: params?.query,
|
|
32
|
+
category: params?.category,
|
|
33
|
+
limit: params?.limit,
|
|
34
|
+
offset: params?.offset,
|
|
35
|
+
});
|
|
36
|
+
return response ?? [];
|
|
37
|
+
}
|
|
38
|
+
// -----------------------------------------------------------------------
|
|
39
|
+
// Cross-exchange market matches
|
|
13
40
|
// -----------------------------------------------------------------------
|
|
14
41
|
async fetchMatches(params) {
|
|
15
42
|
const response = await this.client.getMarketMatches(params);
|
|
16
|
-
|
|
43
|
+
const matches = response.matches ?? [];
|
|
44
|
+
return matches.map((m) => ({
|
|
45
|
+
market: m.market,
|
|
46
|
+
relation: m.relation,
|
|
47
|
+
confidence: m.confidence,
|
|
48
|
+
reasoning: m.reasoning ?? null,
|
|
49
|
+
bestBid: m.market?.bestBid ?? null,
|
|
50
|
+
bestAsk: m.market?.bestAsk ?? null,
|
|
51
|
+
}));
|
|
17
52
|
}
|
|
18
53
|
// -----------------------------------------------------------------------
|
|
19
54
|
// Cross-exchange event matches
|
|
@@ -81,7 +116,7 @@ class Router {
|
|
|
81
116
|
if (matches.length === 0)
|
|
82
117
|
continue;
|
|
83
118
|
const sourceAsk = market.outcomes[0]?.price ?? null;
|
|
84
|
-
const sourceBid = sourceAsk;
|
|
119
|
+
const sourceBid = sourceAsk;
|
|
85
120
|
const sourceVenue = market.sourceExchange ?? '';
|
|
86
121
|
for (const match of matches) {
|
|
87
122
|
const matchBid = match.bestBid;
|
|
@@ -120,22 +155,5 @@ class Router {
|
|
|
120
155
|
opportunities.sort((a, b) => b.spread - a.spread);
|
|
121
156
|
return opportunities;
|
|
122
157
|
}
|
|
123
|
-
// -----------------------------------------------------------------------
|
|
124
|
-
// Cross-venue search
|
|
125
|
-
// -----------------------------------------------------------------------
|
|
126
|
-
async fetchMarkets(params) {
|
|
127
|
-
const response = await this.client.searchMarkets(params);
|
|
128
|
-
return response ?? [];
|
|
129
|
-
}
|
|
130
|
-
async fetchEvents(params) {
|
|
131
|
-
const response = await this.client.searchEvents(params);
|
|
132
|
-
return response ?? [];
|
|
133
|
-
}
|
|
134
|
-
// -----------------------------------------------------------------------
|
|
135
|
-
// Disabled: order routing (future)
|
|
136
|
-
// -----------------------------------------------------------------------
|
|
137
|
-
async createOrder() {
|
|
138
|
-
throw new Error('Router order routing is not yet implemented');
|
|
139
|
-
}
|
|
140
158
|
}
|
|
141
159
|
exports.Router = Router;
|
|
@@ -23,20 +23,20 @@ describe('Router', () => {
|
|
|
23
23
|
});
|
|
24
24
|
describe('fetchMatches', () => {
|
|
25
25
|
it('returns matches from the API using marketId', async () => {
|
|
26
|
-
const
|
|
26
|
+
const mockApiResponse = [
|
|
27
27
|
{
|
|
28
|
-
market: { marketId: 'k1', sourceExchange: 'kalshi' },
|
|
28
|
+
market: { marketId: 'k1', sourceExchange: 'kalshi', bestBid: 0.60, bestAsk: 0.65 },
|
|
29
29
|
relation: 'identity',
|
|
30
30
|
confidence: 0.95,
|
|
31
31
|
reasoning: 'Same resolution condition.',
|
|
32
|
-
bestBid: 0.60,
|
|
33
|
-
bestAsk: 0.65,
|
|
34
32
|
},
|
|
35
33
|
];
|
|
36
|
-
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches:
|
|
34
|
+
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockApiResponse });
|
|
37
35
|
const result = await router.fetchMatches({ marketId: 'm1', relation: 'identity' });
|
|
38
36
|
expect(clientInstance.getMarketMatches).toHaveBeenCalledWith({ marketId: 'm1', relation: 'identity' });
|
|
39
|
-
expect(result).
|
|
37
|
+
expect(result[0].confidence).toBe(0.95);
|
|
38
|
+
expect(result[0].bestBid).toBe(0.60);
|
|
39
|
+
expect(result[0].bestAsk).toBe(0.65);
|
|
40
40
|
});
|
|
41
41
|
it('accepts slug as identifier', async () => {
|
|
42
42
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: [] });
|
|
@@ -64,12 +64,10 @@ describe('Router', () => {
|
|
|
64
64
|
it('fetches identity matches with includePrices and maps to PriceComparison', async () => {
|
|
65
65
|
const mockMatches = [
|
|
66
66
|
{
|
|
67
|
-
market: { marketId: 'k1', sourceExchange: 'kalshi', outcomes: [] },
|
|
67
|
+
market: { marketId: 'k1', sourceExchange: 'kalshi', outcomes: [], bestBid: 0.55, bestAsk: 0.62 },
|
|
68
68
|
relation: 'identity',
|
|
69
69
|
confidence: 0.9,
|
|
70
70
|
reasoning: 'Same market.',
|
|
71
|
-
bestBid: 0.55,
|
|
72
|
-
bestAsk: 0.62,
|
|
73
71
|
},
|
|
74
72
|
];
|
|
75
73
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockMatches });
|
|
@@ -90,28 +88,22 @@ describe('Router', () => {
|
|
|
90
88
|
it('returns only subset/superset matches with reasoning', async () => {
|
|
91
89
|
const mockMatches = [
|
|
92
90
|
{
|
|
93
|
-
market: { marketId: 'k1', sourceExchange: 'kalshi' },
|
|
91
|
+
market: { marketId: 'k1', sourceExchange: 'kalshi', bestBid: 0.60, bestAsk: 0.65 },
|
|
94
92
|
relation: 'identity',
|
|
95
93
|
confidence: 0.95,
|
|
96
94
|
reasoning: 'Same.',
|
|
97
|
-
bestBid: 0.60,
|
|
98
|
-
bestAsk: 0.65,
|
|
99
95
|
},
|
|
100
96
|
{
|
|
101
|
-
market: { marketId: 'k2', sourceExchange: 'kalshi' },
|
|
97
|
+
market: { marketId: 'k2', sourceExchange: 'kalshi', bestBid: 0.40, bestAsk: 0.45 },
|
|
102
98
|
relation: 'subset',
|
|
103
99
|
confidence: 0.8,
|
|
104
100
|
reasoning: 'Narrower market — nomination implies candidacy.',
|
|
105
|
-
bestBid: 0.40,
|
|
106
|
-
bestAsk: 0.45,
|
|
107
101
|
},
|
|
108
102
|
{
|
|
109
|
-
market: { marketId: 'k3', sourceExchange: 'polymarket' },
|
|
103
|
+
market: { marketId: 'k3', sourceExchange: 'polymarket', bestBid: 0.70, bestAsk: 0.73 },
|
|
110
104
|
relation: 'superset',
|
|
111
105
|
confidence: 0.7,
|
|
112
106
|
reasoning: 'Broader — popular vote does not guarantee election win.',
|
|
113
|
-
bestBid: 0.70,
|
|
114
|
-
bestAsk: 0.73,
|
|
115
107
|
},
|
|
116
108
|
];
|
|
117
109
|
clientInstance.getMarketMatches = jest.fn().mockResolvedValue({ matches: mockMatches });
|
|
@@ -127,7 +119,7 @@ describe('Router', () => {
|
|
|
127
119
|
const mockMarkets = [{ marketId: 'm1', title: 'BTC' }];
|
|
128
120
|
clientInstance.searchMarkets = jest.fn().mockResolvedValue(mockMarkets);
|
|
129
121
|
const result = await router.fetchMarkets({ query: 'bitcoin' });
|
|
130
|
-
expect(clientInstance.searchMarkets).
|
|
122
|
+
expect(clientInstance.searchMarkets).toHaveBeenCalled();
|
|
131
123
|
expect(result).toEqual(mockMarkets);
|
|
132
124
|
});
|
|
133
125
|
});
|
|
@@ -136,13 +128,31 @@ describe('Router', () => {
|
|
|
136
128
|
const mockEvents = [{ id: 'e1', title: 'Election' }];
|
|
137
129
|
clientInstance.searchEvents = jest.fn().mockResolvedValue(mockEvents);
|
|
138
130
|
const result = await router.fetchEvents({ query: 'election' });
|
|
139
|
-
expect(clientInstance.searchEvents).
|
|
131
|
+
expect(clientInstance.searchEvents).toHaveBeenCalled();
|
|
140
132
|
expect(result).toEqual(mockEvents);
|
|
141
133
|
});
|
|
142
134
|
});
|
|
143
135
|
describe('createOrder', () => {
|
|
144
136
|
it('throws not implemented error', async () => {
|
|
145
|
-
await expect(router.createOrder()).rejects.toThrow('
|
|
137
|
+
await expect(router.createOrder({})).rejects.toThrow('not implemented');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('capabilities', () => {
|
|
141
|
+
it('reports matching methods as supported', () => {
|
|
142
|
+
expect(router.has.fetchMatches).toBe(true);
|
|
143
|
+
expect(router.has.fetchEventMatches).toBe(true);
|
|
144
|
+
expect(router.has.compareMarketPrices).toBe(true);
|
|
145
|
+
expect(router.has.fetchHedges).toBe(true);
|
|
146
|
+
expect(router.has.fetchArbitrage).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
it('reports trading methods as unsupported', () => {
|
|
149
|
+
expect(router.has.createOrder).toBe(false);
|
|
150
|
+
expect(router.has.cancelOrder).toBe(false);
|
|
151
|
+
expect(router.has.fetchOrderBook).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
it('reports search methods as supported', () => {
|
|
154
|
+
expect(router.has.fetchMarkets).toBe(true);
|
|
155
|
+
expect(router.has.fetchEvents).toBe(true);
|
|
146
156
|
});
|
|
147
157
|
});
|
|
148
158
|
});
|
package/dist/server/app.js
CHANGED
|
@@ -20,6 +20,7 @@ const opinion_1 = require("../exchanges/opinion");
|
|
|
20
20
|
const metaculus_1 = require("../exchanges/metaculus");
|
|
21
21
|
const smarkets_1 = require("../exchanges/smarkets");
|
|
22
22
|
const polymarket_us_1 = require("../exchanges/polymarket_us");
|
|
23
|
+
const router_1 = require("../router");
|
|
23
24
|
const errors_1 = require("../errors");
|
|
24
25
|
function loadMethodVerbs() {
|
|
25
26
|
const candidates = [
|
|
@@ -410,6 +411,10 @@ function createExchange(name, credentials) {
|
|
|
410
411
|
apiKey: credentials?.apiKey || process.env.POLYMARKET_US_KEY_ID,
|
|
411
412
|
privateKey: credentials?.privateKey || process.env.POLYMARKET_US_SECRET_KEY,
|
|
412
413
|
});
|
|
414
|
+
case "router":
|
|
415
|
+
return new router_1.Router({
|
|
416
|
+
apiKey: process.env.PMXT_API_KEY || '',
|
|
417
|
+
});
|
|
413
418
|
default:
|
|
414
419
|
throw new Error(`Unknown exchange: ${name}`);
|
|
415
420
|
}
|
|
@@ -357,5 +357,55 @@
|
|
|
357
357
|
"close": {
|
|
358
358
|
"verb": "post",
|
|
359
359
|
"args": []
|
|
360
|
+
},
|
|
361
|
+
"fetchMatches": {
|
|
362
|
+
"verb": "get",
|
|
363
|
+
"args": [
|
|
364
|
+
{
|
|
365
|
+
"name": "params",
|
|
366
|
+
"kind": "object",
|
|
367
|
+
"optional": false
|
|
368
|
+
}
|
|
369
|
+
]
|
|
370
|
+
},
|
|
371
|
+
"fetchEventMatches": {
|
|
372
|
+
"verb": "get",
|
|
373
|
+
"args": [
|
|
374
|
+
{
|
|
375
|
+
"name": "params",
|
|
376
|
+
"kind": "object",
|
|
377
|
+
"optional": false
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
"compareMarketPrices": {
|
|
382
|
+
"verb": "post",
|
|
383
|
+
"args": [
|
|
384
|
+
{
|
|
385
|
+
"name": "params",
|
|
386
|
+
"kind": "object",
|
|
387
|
+
"optional": false
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
"fetchHedges": {
|
|
392
|
+
"verb": "get",
|
|
393
|
+
"args": [
|
|
394
|
+
{
|
|
395
|
+
"name": "params",
|
|
396
|
+
"kind": "object",
|
|
397
|
+
"optional": false
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
},
|
|
401
|
+
"fetchArbitrage": {
|
|
402
|
+
"verb": "get",
|
|
403
|
+
"args": [
|
|
404
|
+
{
|
|
405
|
+
"name": "params",
|
|
406
|
+
"kind": "object",
|
|
407
|
+
"optional": true
|
|
408
|
+
}
|
|
409
|
+
]
|
|
360
410
|
}
|
|
361
411
|
}
|
package/dist/server/openapi.yaml
CHANGED
|
@@ -1464,6 +1464,261 @@ 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}/fetchMatches':
|
|
1468
|
+
get:
|
|
1469
|
+
summary: Fetch Matches
|
|
1470
|
+
operationId: fetchMatches
|
|
1471
|
+
parameters:
|
|
1472
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1473
|
+
- in: query
|
|
1474
|
+
name: marketId
|
|
1475
|
+
required: false
|
|
1476
|
+
schema:
|
|
1477
|
+
type: string
|
|
1478
|
+
- in: query
|
|
1479
|
+
name: slug
|
|
1480
|
+
required: false
|
|
1481
|
+
schema:
|
|
1482
|
+
type: string
|
|
1483
|
+
- in: query
|
|
1484
|
+
name: url
|
|
1485
|
+
required: false
|
|
1486
|
+
schema:
|
|
1487
|
+
type: string
|
|
1488
|
+
- in: query
|
|
1489
|
+
name: relation
|
|
1490
|
+
required: false
|
|
1491
|
+
schema:
|
|
1492
|
+
type: string
|
|
1493
|
+
enum:
|
|
1494
|
+
- identity
|
|
1495
|
+
- subset
|
|
1496
|
+
- superset
|
|
1497
|
+
- overlap
|
|
1498
|
+
- disjoint
|
|
1499
|
+
- in: query
|
|
1500
|
+
name: minConfidence
|
|
1501
|
+
required: false
|
|
1502
|
+
schema:
|
|
1503
|
+
type: number
|
|
1504
|
+
- in: query
|
|
1505
|
+
name: limit
|
|
1506
|
+
required: false
|
|
1507
|
+
schema:
|
|
1508
|
+
type: number
|
|
1509
|
+
- in: query
|
|
1510
|
+
name: includePrices
|
|
1511
|
+
required: false
|
|
1512
|
+
schema:
|
|
1513
|
+
type: boolean
|
|
1514
|
+
responses:
|
|
1515
|
+
'200':
|
|
1516
|
+
description: Fetch Matches response
|
|
1517
|
+
content:
|
|
1518
|
+
application/json:
|
|
1519
|
+
schema:
|
|
1520
|
+
allOf:
|
|
1521
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1522
|
+
- type: object
|
|
1523
|
+
properties:
|
|
1524
|
+
data:
|
|
1525
|
+
type: array
|
|
1526
|
+
items:
|
|
1527
|
+
$ref: '#/components/schemas/MatchResult'
|
|
1528
|
+
description: Fetch cross-venue matches for a given market.
|
|
1529
|
+
'/api/{exchange}/fetchEventMatches':
|
|
1530
|
+
get:
|
|
1531
|
+
summary: Fetch Event Matches
|
|
1532
|
+
operationId: fetchEventMatches
|
|
1533
|
+
parameters:
|
|
1534
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1535
|
+
- in: query
|
|
1536
|
+
name: eventId
|
|
1537
|
+
required: false
|
|
1538
|
+
schema:
|
|
1539
|
+
type: string
|
|
1540
|
+
- in: query
|
|
1541
|
+
name: slug
|
|
1542
|
+
required: false
|
|
1543
|
+
schema:
|
|
1544
|
+
type: string
|
|
1545
|
+
- in: query
|
|
1546
|
+
name: relation
|
|
1547
|
+
required: false
|
|
1548
|
+
schema:
|
|
1549
|
+
type: string
|
|
1550
|
+
enum:
|
|
1551
|
+
- identity
|
|
1552
|
+
- subset
|
|
1553
|
+
- superset
|
|
1554
|
+
- overlap
|
|
1555
|
+
- disjoint
|
|
1556
|
+
- in: query
|
|
1557
|
+
name: minConfidence
|
|
1558
|
+
required: false
|
|
1559
|
+
schema:
|
|
1560
|
+
type: number
|
|
1561
|
+
- in: query
|
|
1562
|
+
name: limit
|
|
1563
|
+
required: false
|
|
1564
|
+
schema:
|
|
1565
|
+
type: number
|
|
1566
|
+
- in: query
|
|
1567
|
+
name: includePrices
|
|
1568
|
+
required: false
|
|
1569
|
+
schema:
|
|
1570
|
+
type: boolean
|
|
1571
|
+
responses:
|
|
1572
|
+
'200':
|
|
1573
|
+
description: Fetch Event Matches response
|
|
1574
|
+
content:
|
|
1575
|
+
application/json:
|
|
1576
|
+
schema:
|
|
1577
|
+
allOf:
|
|
1578
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1579
|
+
- type: object
|
|
1580
|
+
properties:
|
|
1581
|
+
data:
|
|
1582
|
+
type: array
|
|
1583
|
+
items:
|
|
1584
|
+
$ref: '#/components/schemas/EventMatchResult'
|
|
1585
|
+
description: Fetch cross-venue matches for a given event.
|
|
1586
|
+
'/api/{exchange}/compareMarketPrices':
|
|
1587
|
+
post:
|
|
1588
|
+
summary: Compare Market Prices
|
|
1589
|
+
operationId: compareMarketPrices
|
|
1590
|
+
parameters:
|
|
1591
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1592
|
+
requestBody:
|
|
1593
|
+
content:
|
|
1594
|
+
application/json:
|
|
1595
|
+
schema:
|
|
1596
|
+
title: CompareMarketPricesRequest
|
|
1597
|
+
type: object
|
|
1598
|
+
properties:
|
|
1599
|
+
args:
|
|
1600
|
+
type: array
|
|
1601
|
+
maxItems: 1
|
|
1602
|
+
items:
|
|
1603
|
+
$ref: '#/components/schemas/FetchMatchesParams'
|
|
1604
|
+
minItems: 1
|
|
1605
|
+
credentials:
|
|
1606
|
+
$ref: '#/components/schemas/ExchangeCredentials'
|
|
1607
|
+
required:
|
|
1608
|
+
- args
|
|
1609
|
+
responses:
|
|
1610
|
+
'200':
|
|
1611
|
+
description: Compare Market Prices response
|
|
1612
|
+
content:
|
|
1613
|
+
application/json:
|
|
1614
|
+
schema:
|
|
1615
|
+
allOf:
|
|
1616
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1617
|
+
- type: object
|
|
1618
|
+
properties:
|
|
1619
|
+
data:
|
|
1620
|
+
type: array
|
|
1621
|
+
items:
|
|
1622
|
+
$ref: '#/components/schemas/PriceComparison'
|
|
1623
|
+
description: Compare prices across venues for identity matches of a market.
|
|
1624
|
+
'/api/{exchange}/fetchHedges':
|
|
1625
|
+
get:
|
|
1626
|
+
summary: Fetch Hedges
|
|
1627
|
+
operationId: fetchHedges
|
|
1628
|
+
parameters:
|
|
1629
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1630
|
+
- in: query
|
|
1631
|
+
name: marketId
|
|
1632
|
+
required: false
|
|
1633
|
+
schema:
|
|
1634
|
+
type: string
|
|
1635
|
+
- in: query
|
|
1636
|
+
name: slug
|
|
1637
|
+
required: false
|
|
1638
|
+
schema:
|
|
1639
|
+
type: string
|
|
1640
|
+
- in: query
|
|
1641
|
+
name: url
|
|
1642
|
+
required: false
|
|
1643
|
+
schema:
|
|
1644
|
+
type: string
|
|
1645
|
+
- in: query
|
|
1646
|
+
name: relation
|
|
1647
|
+
required: false
|
|
1648
|
+
schema:
|
|
1649
|
+
type: string
|
|
1650
|
+
enum:
|
|
1651
|
+
- identity
|
|
1652
|
+
- subset
|
|
1653
|
+
- superset
|
|
1654
|
+
- overlap
|
|
1655
|
+
- disjoint
|
|
1656
|
+
- in: query
|
|
1657
|
+
name: minConfidence
|
|
1658
|
+
required: false
|
|
1659
|
+
schema:
|
|
1660
|
+
type: number
|
|
1661
|
+
- in: query
|
|
1662
|
+
name: limit
|
|
1663
|
+
required: false
|
|
1664
|
+
schema:
|
|
1665
|
+
type: number
|
|
1666
|
+
- in: query
|
|
1667
|
+
name: includePrices
|
|
1668
|
+
required: false
|
|
1669
|
+
schema:
|
|
1670
|
+
type: boolean
|
|
1671
|
+
responses:
|
|
1672
|
+
'200':
|
|
1673
|
+
description: Fetch Hedges response
|
|
1674
|
+
content:
|
|
1675
|
+
application/json:
|
|
1676
|
+
schema:
|
|
1677
|
+
allOf:
|
|
1678
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1679
|
+
- type: object
|
|
1680
|
+
properties:
|
|
1681
|
+
data:
|
|
1682
|
+
type: array
|
|
1683
|
+
items:
|
|
1684
|
+
$ref: '#/components/schemas/PriceComparison'
|
|
1685
|
+
description: Find hedging opportunities via subset/superset matches across venues.
|
|
1686
|
+
'/api/{exchange}/fetchArbitrage':
|
|
1687
|
+
get:
|
|
1688
|
+
summary: Fetch Arbitrage
|
|
1689
|
+
operationId: fetchArbitrage
|
|
1690
|
+
parameters:
|
|
1691
|
+
- $ref: '#/components/parameters/ExchangeParam'
|
|
1692
|
+
- in: query
|
|
1693
|
+
name: minSpread
|
|
1694
|
+
required: false
|
|
1695
|
+
schema:
|
|
1696
|
+
type: number
|
|
1697
|
+
- in: query
|
|
1698
|
+
name: category
|
|
1699
|
+
required: false
|
|
1700
|
+
schema:
|
|
1701
|
+
type: string
|
|
1702
|
+
- in: query
|
|
1703
|
+
name: limit
|
|
1704
|
+
required: false
|
|
1705
|
+
schema:
|
|
1706
|
+
type: number
|
|
1707
|
+
responses:
|
|
1708
|
+
'200':
|
|
1709
|
+
description: Fetch Arbitrage response
|
|
1710
|
+
content:
|
|
1711
|
+
application/json:
|
|
1712
|
+
schema:
|
|
1713
|
+
allOf:
|
|
1714
|
+
- $ref: '#/components/schemas/BaseResponse'
|
|
1715
|
+
- type: object
|
|
1716
|
+
properties:
|
|
1717
|
+
data:
|
|
1718
|
+
type: array
|
|
1719
|
+
items:
|
|
1720
|
+
$ref: '#/components/schemas/ArbitrageOpportunity'
|
|
1721
|
+
description: Scan for arbitrage opportunities across identity matches.
|
|
1467
1722
|
components:
|
|
1468
1723
|
parameters:
|
|
1469
1724
|
ExchangeParam:
|
|
@@ -1483,6 +1738,7 @@ components:
|
|
|
1483
1738
|
- metaculus
|
|
1484
1739
|
- smarkets
|
|
1485
1740
|
- polymarket_us
|
|
1741
|
+
- router
|
|
1486
1742
|
required: true
|
|
1487
1743
|
description: The prediction market exchange to target.
|
|
1488
1744
|
schemas:
|
|
@@ -2372,6 +2628,167 @@ components:
|
|
|
2372
2628
|
max:
|
|
2373
2629
|
type: number
|
|
2374
2630
|
description: Sum of market volumes
|
|
2631
|
+
FetchMatchesParams:
|
|
2632
|
+
type: object
|
|
2633
|
+
properties:
|
|
2634
|
+
marketId:
|
|
2635
|
+
type: string
|
|
2636
|
+
slug:
|
|
2637
|
+
type: string
|
|
2638
|
+
url:
|
|
2639
|
+
type: string
|
|
2640
|
+
relation:
|
|
2641
|
+
type: string
|
|
2642
|
+
enum:
|
|
2643
|
+
- identity
|
|
2644
|
+
- subset
|
|
2645
|
+
- superset
|
|
2646
|
+
- overlap
|
|
2647
|
+
- disjoint
|
|
2648
|
+
minConfidence:
|
|
2649
|
+
type: number
|
|
2650
|
+
limit:
|
|
2651
|
+
type: number
|
|
2652
|
+
includePrices:
|
|
2653
|
+
type: boolean
|
|
2654
|
+
FetchEventMatchesParams:
|
|
2655
|
+
type: object
|
|
2656
|
+
properties:
|
|
2657
|
+
eventId:
|
|
2658
|
+
type: string
|
|
2659
|
+
slug:
|
|
2660
|
+
type: string
|
|
2661
|
+
relation:
|
|
2662
|
+
type: string
|
|
2663
|
+
enum:
|
|
2664
|
+
- identity
|
|
2665
|
+
- subset
|
|
2666
|
+
- superset
|
|
2667
|
+
- overlap
|
|
2668
|
+
- disjoint
|
|
2669
|
+
minConfidence:
|
|
2670
|
+
type: number
|
|
2671
|
+
limit:
|
|
2672
|
+
type: number
|
|
2673
|
+
includePrices:
|
|
2674
|
+
type: boolean
|
|
2675
|
+
FetchArbitrageParams:
|
|
2676
|
+
type: object
|
|
2677
|
+
properties:
|
|
2678
|
+
minSpread:
|
|
2679
|
+
type: number
|
|
2680
|
+
category:
|
|
2681
|
+
type: string
|
|
2682
|
+
limit:
|
|
2683
|
+
type: number
|
|
2684
|
+
MatchResult:
|
|
2685
|
+
type: object
|
|
2686
|
+
properties:
|
|
2687
|
+
market:
|
|
2688
|
+
$ref: '#/components/schemas/UnifiedMarket'
|
|
2689
|
+
relation:
|
|
2690
|
+
type: string
|
|
2691
|
+
enum:
|
|
2692
|
+
- identity
|
|
2693
|
+
- subset
|
|
2694
|
+
- superset
|
|
2695
|
+
- overlap
|
|
2696
|
+
- disjoint
|
|
2697
|
+
confidence:
|
|
2698
|
+
type: number
|
|
2699
|
+
reasoning:
|
|
2700
|
+
oneOf:
|
|
2701
|
+
- type: string
|
|
2702
|
+
- {}
|
|
2703
|
+
bestBid:
|
|
2704
|
+
oneOf:
|
|
2705
|
+
- type: number
|
|
2706
|
+
- {}
|
|
2707
|
+
bestAsk:
|
|
2708
|
+
oneOf:
|
|
2709
|
+
- type: number
|
|
2710
|
+
- {}
|
|
2711
|
+
required:
|
|
2712
|
+
- market
|
|
2713
|
+
- relation
|
|
2714
|
+
- confidence
|
|
2715
|
+
- reasoning
|
|
2716
|
+
- bestBid
|
|
2717
|
+
- bestAsk
|
|
2718
|
+
EventMatchResult:
|
|
2719
|
+
type: object
|
|
2720
|
+
properties:
|
|
2721
|
+
event:
|
|
2722
|
+
$ref: '#/components/schemas/UnifiedEvent'
|
|
2723
|
+
marketMatches:
|
|
2724
|
+
type: array
|
|
2725
|
+
items:
|
|
2726
|
+
$ref: '#/components/schemas/MatchResult'
|
|
2727
|
+
required:
|
|
2728
|
+
- event
|
|
2729
|
+
- marketMatches
|
|
2730
|
+
PriceComparison:
|
|
2731
|
+
type: object
|
|
2732
|
+
properties:
|
|
2733
|
+
market:
|
|
2734
|
+
$ref: '#/components/schemas/UnifiedMarket'
|
|
2735
|
+
relation:
|
|
2736
|
+
type: string
|
|
2737
|
+
enum:
|
|
2738
|
+
- identity
|
|
2739
|
+
- subset
|
|
2740
|
+
- superset
|
|
2741
|
+
- overlap
|
|
2742
|
+
- disjoint
|
|
2743
|
+
confidence:
|
|
2744
|
+
type: number
|
|
2745
|
+
reasoning:
|
|
2746
|
+
oneOf:
|
|
2747
|
+
- type: string
|
|
2748
|
+
- {}
|
|
2749
|
+
bestBid:
|
|
2750
|
+
oneOf:
|
|
2751
|
+
- type: number
|
|
2752
|
+
- {}
|
|
2753
|
+
bestAsk:
|
|
2754
|
+
oneOf:
|
|
2755
|
+
- type: number
|
|
2756
|
+
- {}
|
|
2757
|
+
venue:
|
|
2758
|
+
type: string
|
|
2759
|
+
required:
|
|
2760
|
+
- market
|
|
2761
|
+
- relation
|
|
2762
|
+
- confidence
|
|
2763
|
+
- reasoning
|
|
2764
|
+
- bestBid
|
|
2765
|
+
- bestAsk
|
|
2766
|
+
- venue
|
|
2767
|
+
ArbitrageOpportunity:
|
|
2768
|
+
type: object
|
|
2769
|
+
properties:
|
|
2770
|
+
marketA:
|
|
2771
|
+
$ref: '#/components/schemas/UnifiedMarket'
|
|
2772
|
+
marketB:
|
|
2773
|
+
$ref: '#/components/schemas/UnifiedMarket'
|
|
2774
|
+
spread:
|
|
2775
|
+
type: number
|
|
2776
|
+
buyVenue:
|
|
2777
|
+
type: string
|
|
2778
|
+
sellVenue:
|
|
2779
|
+
type: string
|
|
2780
|
+
buyPrice:
|
|
2781
|
+
type: number
|
|
2782
|
+
sellPrice:
|
|
2783
|
+
type: number
|
|
2784
|
+
required:
|
|
2785
|
+
- marketA
|
|
2786
|
+
- marketB
|
|
2787
|
+
- spread
|
|
2788
|
+
- buyVenue
|
|
2789
|
+
- sellVenue
|
|
2790
|
+
- buyPrice
|
|
2791
|
+
- sellPrice
|
|
2375
2792
|
ExchangeCredentials:
|
|
2376
2793
|
type: object
|
|
2377
2794
|
description: Optional authentication credentials for exchange operations.
|
|
@@ -2593,3 +3010,10 @@ x-sdk-constructors:
|
|
|
2593
3010
|
tsName: privateKey
|
|
2594
3011
|
type: string
|
|
2595
3012
|
description: Private key for authentication
|
|
3013
|
+
router:
|
|
3014
|
+
className: Router
|
|
3015
|
+
params:
|
|
3016
|
+
- name: pmxt_api_key
|
|
3017
|
+
tsName: pmxtApiKey
|
|
3018
|
+
type: string
|
|
3019
|
+
description: PMXT API key for hosted access
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.33.2",
|
|
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.33.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.33.2,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",
|