pmxt-core 2.37.9 → 2.37.12
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 +5 -0
- package/dist/BaseExchange.js +6 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/kalshi/config.d.ts +3 -3
- package/dist/exchanges/kalshi/config.js +4 -4
- package/dist/exchanges/kalshi/index.js +1 -1
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/limitless/auth.d.ts +1 -0
- package/dist/exchanges/limitless/auth.js +4 -2
- package/dist/exchanges/limitless/client.d.ts +1 -1
- package/dist/exchanges/limitless/client.js +3 -3
- package/dist/exchanges/limitless/fetcher.d.ts +7 -1
- package/dist/exchanges/limitless/fetcher.js +61 -16
- package/dist/exchanges/limitless/index.js +2 -2
- package/dist/exchanges/limitless/utils.d.ts +2 -1
- package/dist/exchanges/limitless/utils.js +3 -2
- package/dist/exchanges/metaculus/cancelOrder.d.ts +2 -0
- package/dist/exchanges/metaculus/cancelOrder.js +1 -1
- package/dist/exchanges/metaculus/createOrder.d.ts +2 -0
- package/dist/exchanges/metaculus/createOrder.js +1 -1
- package/dist/exchanges/metaculus/index.d.ts +1 -0
- package/dist/exchanges/metaculus/index.js +5 -1
- package/dist/exchanges/metaculus/utils.d.ts +2 -1
- package/dist/exchanges/metaculus/utils.js +3 -2
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/myriad/fetcher.d.ts +2 -1
- package/dist/exchanges/myriad/fetcher.js +9 -7
- package/dist/exchanges/myriad/index.js +3 -2
- package/dist/exchanges/myriad/utils.d.ts +2 -1
- package/dist/exchanges/myriad/utils.js +3 -2
- package/dist/exchanges/opinion/api.d.ts +1 -1
- package/dist/exchanges/opinion/api.js +1 -1
- package/dist/exchanges/opinion/config.d.ts +2 -1
- package/dist/exchanges/opinion/config.js +3 -2
- package/dist/exchanges/opinion/fetcher.d.ts +2 -1
- package/dist/exchanges/opinion/fetcher.js +10 -8
- package/dist/exchanges/opinion/index.js +3 -2
- 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/polymarket/auth.d.ts +1 -0
- package/dist/exchanges/polymarket/auth.js +7 -4
- package/dist/exchanges/polymarket/fetcher.js +1 -1
- package/dist/exchanges/polymarket/utils.d.ts +4 -4
- package/dist/exchanges/polymarket/utils.js +4 -4
- package/dist/exchanges/polymarket_us/config.d.ts +3 -3
- package/dist/exchanges/polymarket_us/config.js +4 -4
- package/dist/exchanges/polymarket_us/index.js +1 -1
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/fetcher.d.ts +2 -1
- package/dist/exchanges/probable/fetcher.js +9 -7
- package/dist/exchanges/probable/index.js +3 -2
- package/dist/exchanges/probable/utils.d.ts +2 -1
- package/dist/exchanges/probable/utils.js +3 -2
- package/dist/exchanges/smarkets/config.d.ts +3 -2
- package/dist/exchanges/smarkets/config.js +5 -4
- package/dist/exchanges/smarkets/fetcher.js +2 -1
- package/dist/exchanges/smarkets/index.js +1 -1
- package/dist/router/Router.d.ts +3 -1
- package/dist/router/Router.js +65 -0
- package/dist/router/Router.test.js +131 -1
- package/dist/router/types.d.ts +3 -0
- package/dist/server/app.js +10 -0
- package/dist/server/method-verbs.json +10 -0
- package/dist/server/openapi.yaml +99 -11
- package/package.json +3 -3
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -272,6 +272,7 @@ export interface ExchangeCredentials {
|
|
|
272
272
|
signatureType?: number | string;
|
|
273
273
|
funderAddress?: string;
|
|
274
274
|
walletAddress?: string;
|
|
275
|
+
baseUrl?: string;
|
|
275
276
|
}
|
|
276
277
|
export interface ExchangeOptions {
|
|
277
278
|
/**
|
|
@@ -634,6 +635,10 @@ export declare abstract class PredictionMarketExchange {
|
|
|
634
635
|
* Close all WebSocket connections and clean up resources.
|
|
635
636
|
* Call this when you're done streaming to properly release connections.
|
|
636
637
|
*/
|
|
638
|
+
/**
|
|
639
|
+
* Test method for auto-generation verification.
|
|
640
|
+
*/
|
|
641
|
+
testDummyMethod(param?: string): Promise<string>;
|
|
637
642
|
close(): Promise<void>;
|
|
638
643
|
/**
|
|
639
644
|
* Find the same or related market on other venues. Two modes:
|
package/dist/BaseExchange.js
CHANGED
|
@@ -840,6 +840,12 @@ class PredictionMarketExchange {
|
|
|
840
840
|
* Close all WebSocket connections and clean up resources.
|
|
841
841
|
* Call this when you're done streaming to properly release connections.
|
|
842
842
|
*/
|
|
843
|
+
/**
|
|
844
|
+
* Test method for auto-generation verification.
|
|
845
|
+
*/
|
|
846
|
+
async testDummyMethod(param) {
|
|
847
|
+
throw new Error("Test method not implemented.");
|
|
848
|
+
}
|
|
843
849
|
async close() {
|
|
844
850
|
// Default implementation: no-op
|
|
845
851
|
// Exchanges with WebSocket support should override this
|
|
@@ -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-05-
|
|
3
|
+
* Generated at: 2026-05-08T16:05:46.392Z
|
|
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-05-
|
|
6
|
+
* Generated at: 2026-05-08T16:05:46.392Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* env = "api" → production: https://api.elections.kalshi.com
|
|
15
15
|
* env = "demo-api" → demo/paper: https://demo-api.elections.kalshi.com
|
|
16
16
|
*/
|
|
17
|
-
export declare const KALSHI_PROD_API_URL
|
|
18
|
-
export declare const KALSHI_DEMO_API_URL
|
|
17
|
+
export declare const KALSHI_PROD_API_URL: string;
|
|
18
|
+
export declare const KALSHI_DEMO_API_URL: string;
|
|
19
19
|
export declare const KALSHI_PROD_WS_URL = "wss://api.elections.kalshi.com/trade-api/ws/v2";
|
|
20
20
|
export declare const KALSHI_DEMO_WS_URL = "wss://demo-api.kalshi.co/trade-api/ws/v2";
|
|
21
21
|
export declare const KALSHI_PATHS: {
|
|
@@ -47,7 +47,7 @@ export interface KalshiApiConfig {
|
|
|
47
47
|
* // config.apiUrl === "https://demo-api.elections.kalshi.com"
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
-
export declare function getKalshiConfig(demoMode?: boolean): KalshiApiConfig;
|
|
50
|
+
export declare function getKalshiConfig(demoMode?: boolean, baseUrlOverride?: string): KalshiApiConfig;
|
|
51
51
|
/**
|
|
52
52
|
* Build the full path (including `/trade-api/v2` prefix) for use in
|
|
53
53
|
* `KalshiAuth.getHeaders()` signing.
|
|
@@ -24,8 +24,8 @@ exports.getSeriesUrl = getSeriesUrl;
|
|
|
24
24
|
exports.getPortfolioUrl = getPortfolioUrl;
|
|
25
25
|
exports.getMarketsUrl = getMarketsUrl;
|
|
26
26
|
// ── Base URL constants ────────────────────────────────────────────────────────
|
|
27
|
-
exports.KALSHI_PROD_API_URL = "https://api.elections.kalshi.com";
|
|
28
|
-
exports.KALSHI_DEMO_API_URL = "https://demo-api.kalshi.co";
|
|
27
|
+
exports.KALSHI_PROD_API_URL = process.env.KALSHI_BASE_URL || "https://api.elections.kalshi.com";
|
|
28
|
+
exports.KALSHI_DEMO_API_URL = process.env.KALSHI_DEMO_BASE_URL || "https://demo-api.kalshi.co";
|
|
29
29
|
exports.KALSHI_PROD_WS_URL = "wss://api.elections.kalshi.com/trade-api/ws/v2";
|
|
30
30
|
exports.KALSHI_DEMO_WS_URL = "wss://demo-api.kalshi.co/trade-api/ws/v2";
|
|
31
31
|
// ── Path constants ────────────────────────────────────────────────────────────
|
|
@@ -50,9 +50,9 @@ exports.KALSHI_PATHS = {
|
|
|
50
50
|
* // config.apiUrl === "https://demo-api.elections.kalshi.com"
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
function getKalshiConfig(demoMode = false) {
|
|
53
|
+
function getKalshiConfig(demoMode = false, baseUrlOverride) {
|
|
54
54
|
return {
|
|
55
|
-
apiUrl: demoMode ? exports.KALSHI_DEMO_API_URL : exports.KALSHI_PROD_API_URL,
|
|
55
|
+
apiUrl: baseUrlOverride || (demoMode ? exports.KALSHI_DEMO_API_URL : exports.KALSHI_PROD_API_URL),
|
|
56
56
|
wsUrl: demoMode ? exports.KALSHI_DEMO_WS_URL : exports.KALSHI_PROD_WS_URL,
|
|
57
57
|
demoMode,
|
|
58
58
|
};
|
|
@@ -33,7 +33,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
33
33
|
super(credentials);
|
|
34
34
|
this.rateLimit = 100;
|
|
35
35
|
this.wsConfig = wsConfig;
|
|
36
|
-
this.config = (0, config_1.getKalshiConfig)(demoMode);
|
|
36
|
+
this.config = (0, config_1.getKalshiConfig)(demoMode, credentials?.baseUrl);
|
|
37
37
|
if (credentials?.apiKey && credentials?.privateKey) {
|
|
38
38
|
this.auth = new auth_1.KalshiAuth(credentials);
|
|
39
39
|
}
|
|
@@ -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-05-
|
|
3
|
+
* Generated at: 2026-05-08T16:05:46.423Z
|
|
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-05-
|
|
6
|
+
* Generated at: 2026-05-08T16:05:46.423Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.limitlessApiSpec = {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LimitlessAuth = void 0;
|
|
4
4
|
const sdk_1 = require("@limitless-exchange/sdk");
|
|
5
5
|
const ethers_1 = require("ethers");
|
|
6
|
-
const
|
|
6
|
+
const DEFAULT_LIMITLESS_HOST = process.env.LIMITLESS_BASE_URL || 'https://api.limitless.exchange';
|
|
7
7
|
/**
|
|
8
8
|
* Manages Limitless authentication.
|
|
9
9
|
*
|
|
@@ -17,8 +17,10 @@ class LimitlessAuth {
|
|
|
17
17
|
httpClient;
|
|
18
18
|
apiKey;
|
|
19
19
|
hmacCreds;
|
|
20
|
+
host;
|
|
20
21
|
constructor(credentials) {
|
|
21
22
|
this.credentials = credentials;
|
|
23
|
+
this.host = credentials.baseUrl || DEFAULT_LIMITLESS_HOST;
|
|
22
24
|
// HMAC credentials for delegated signing (partner mode).
|
|
23
25
|
// apiSecret is the base64-encoded HMAC secret from the Limitless dashboard.
|
|
24
26
|
if (credentials.apiKey && credentials.apiSecret) {
|
|
@@ -54,7 +56,7 @@ class LimitlessAuth {
|
|
|
54
56
|
return this.httpClient;
|
|
55
57
|
}
|
|
56
58
|
const config = {
|
|
57
|
-
baseURL:
|
|
59
|
+
baseURL: this.host,
|
|
58
60
|
timeout: 30000,
|
|
59
61
|
};
|
|
60
62
|
if (this.hmacCreds) {
|
|
@@ -33,7 +33,7 @@ export declare class LimitlessClient {
|
|
|
33
33
|
private cachedProfileId?;
|
|
34
34
|
private marketCache;
|
|
35
35
|
/** @deprecated Use the config-object constructor instead. */
|
|
36
|
-
constructor(privateKey: string, apiKey: string);
|
|
36
|
+
constructor(privateKey: string, apiKey: string, baseUrl?: string);
|
|
37
37
|
constructor(config: LimitlessClientConfig);
|
|
38
38
|
/**
|
|
39
39
|
* Get market details by slug.
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LimitlessClient = void 0;
|
|
4
4
|
const sdk_1 = require("@limitless-exchange/sdk");
|
|
5
5
|
const ethers_1 = require("ethers");
|
|
6
|
-
const
|
|
6
|
+
const DEFAULT_LIMITLESS_API_URL = process.env.LIMITLESS_BASE_URL || 'https://api.limitless.exchange';
|
|
7
7
|
/**
|
|
8
8
|
* Wrapper client for Limitless Exchange using the official SDK.
|
|
9
9
|
*
|
|
@@ -20,7 +20,7 @@ class LimitlessClient {
|
|
|
20
20
|
walletAddress;
|
|
21
21
|
cachedProfileId;
|
|
22
22
|
marketCache = {};
|
|
23
|
-
constructor(configOrKey, apiKey) {
|
|
23
|
+
constructor(configOrKey, apiKey, baseUrl) {
|
|
24
24
|
if (typeof configOrKey === 'string') {
|
|
25
25
|
// Legacy positional constructor: (privateKey, apiKey)
|
|
26
26
|
let privateKey = configOrKey;
|
|
@@ -30,7 +30,7 @@ class LimitlessClient {
|
|
|
30
30
|
this.signer = new ethers_1.Wallet(privateKey);
|
|
31
31
|
this.isDelegated = false;
|
|
32
32
|
this.httpClient = new sdk_1.HttpClient({
|
|
33
|
-
baseURL:
|
|
33
|
+
baseURL: baseUrl || DEFAULT_LIMITLESS_API_URL,
|
|
34
34
|
apiKey: apiKey,
|
|
35
35
|
timeout: 30000,
|
|
36
36
|
});
|
|
@@ -64,7 +64,8 @@ export declare class LimitlessFetcher implements IExchangeFetcher<LimitlessRawMa
|
|
|
64
64
|
private readonly ctx;
|
|
65
65
|
private readonly http;
|
|
66
66
|
private readonly apiKey?;
|
|
67
|
-
|
|
67
|
+
private readonly apiUrl;
|
|
68
|
+
constructor(ctx: FetcherContext, http: AxiosInstance, apiKey?: string, apiUrl?: string);
|
|
68
69
|
fetchRawMarkets(params?: MarketFetchParams): Promise<LimitlessRawMarket[]>;
|
|
69
70
|
fetchRawEvents(params: EventFetchParams): Promise<LimitlessRawEvent[]>;
|
|
70
71
|
fetchRawOHLCV(id: string, params: OHLCVParams): Promise<LimitlessRawPricePoint[]>;
|
|
@@ -78,4 +79,9 @@ export declare class LimitlessFetcher implements IExchangeFetcher<LimitlessRawMa
|
|
|
78
79
|
private fetchRawEventBySlug;
|
|
79
80
|
private searchRawEvents;
|
|
80
81
|
private fetchRawEventsDefault;
|
|
82
|
+
/**
|
|
83
|
+
* Generic paginated fetch against /markets/active.
|
|
84
|
+
* When tradeType is omitted the API returns all trade types.
|
|
85
|
+
*/
|
|
86
|
+
private fetchPaginatedActive;
|
|
81
87
|
}
|
|
@@ -44,10 +44,12 @@ class LimitlessFetcher {
|
|
|
44
44
|
ctx;
|
|
45
45
|
http;
|
|
46
46
|
apiKey;
|
|
47
|
-
|
|
47
|
+
apiUrl;
|
|
48
|
+
constructor(ctx, http, apiKey, apiUrl) {
|
|
48
49
|
this.ctx = ctx;
|
|
49
50
|
this.http = http;
|
|
50
51
|
this.apiKey = apiKey;
|
|
52
|
+
this.apiUrl = apiUrl || utils_1.DEFAULT_LIMITLESS_API_URL;
|
|
51
53
|
}
|
|
52
54
|
async fetchRawMarkets(params) {
|
|
53
55
|
if (params?.status === 'inactive' || params?.status === 'closed') {
|
|
@@ -56,7 +58,7 @@ class LimitlessFetcher {
|
|
|
56
58
|
const { HttpClient, MarketFetcher } = await Promise.resolve().then(() => __importStar(require('@limitless-exchange/sdk')));
|
|
57
59
|
try {
|
|
58
60
|
const httpClient = new HttpClient({
|
|
59
|
-
baseURL:
|
|
61
|
+
baseURL: this.apiUrl,
|
|
60
62
|
apiKey: this.apiKey,
|
|
61
63
|
});
|
|
62
64
|
const marketFetcher = new MarketFetcher(httpClient);
|
|
@@ -127,7 +129,8 @@ class LimitlessFetcher {
|
|
|
127
129
|
}
|
|
128
130
|
async fetchRawMyTrades(_params, apiKey) {
|
|
129
131
|
try {
|
|
130
|
-
const
|
|
132
|
+
const baseUrl = process.env.LIMITLESS_BASE_URL || 'https://api.limitless.exchange';
|
|
133
|
+
const response = await this.http.get(`${baseUrl}/portfolio/trades`, {
|
|
131
134
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
132
135
|
});
|
|
133
136
|
const trades = Array.isArray(response.data) ? response.data : (response.data?.data || []);
|
|
@@ -187,7 +190,7 @@ class LimitlessFetcher {
|
|
|
187
190
|
}
|
|
188
191
|
async fetchRawEventBySlug(slug) {
|
|
189
192
|
const { HttpClient, MarketFetcher } = await Promise.resolve().then(() => __importStar(require('@limitless-exchange/sdk')));
|
|
190
|
-
const httpClient = new HttpClient({ baseURL:
|
|
193
|
+
const httpClient = new HttpClient({ baseURL: this.apiUrl });
|
|
191
194
|
const marketFetcher = new MarketFetcher(httpClient);
|
|
192
195
|
const market = await marketFetcher.getMarket(slug);
|
|
193
196
|
return market ? [market] : [];
|
|
@@ -212,32 +215,74 @@ class LimitlessFetcher {
|
|
|
212
215
|
}
|
|
213
216
|
async fetchRawEventsDefault(params) {
|
|
214
217
|
const limit = params?.limit || 250000;
|
|
215
|
-
let page = 1;
|
|
216
218
|
const pageSize = 25;
|
|
217
219
|
const MAX_PAGES = 40;
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
220
|
+
const sortBy = params?.sort === 'newest' ? 'newest' : params?.sort === 'liquidity' ? 'lp_rewards' : 'high_value';
|
|
221
|
+
// Fetch group events and all markets in parallel.
|
|
222
|
+
// The second call omits tradeType so the API returns every trade type.
|
|
223
|
+
const [groupEvents, allMarkets] = await Promise.all([
|
|
224
|
+
this.fetchPaginatedActive({ tradeType: 'group', sortBy, pageSize, maxPages: MAX_PAGES, limit }),
|
|
225
|
+
this.fetchPaginatedActive({ sortBy, pageSize, maxPages: MAX_PAGES, limit }),
|
|
226
|
+
]);
|
|
227
|
+
// Collect slugs already covered by group events (the group slug
|
|
228
|
+
// itself plus every child market slug inside it)
|
|
229
|
+
const coveredSlugs = new Set();
|
|
230
|
+
for (const group of groupEvents) {
|
|
231
|
+
coveredSlugs.add(group.slug);
|
|
232
|
+
if (Array.isArray(group.markets)) {
|
|
233
|
+
for (const child of group.markets) {
|
|
234
|
+
if (child.slug)
|
|
235
|
+
coveredSlugs.add(child.slug);
|
|
226
236
|
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Keep only standalone markets not already part of a group.
|
|
240
|
+
// Wrap each as a LimitlessRawEvent without a markets array so
|
|
241
|
+
// normalizeEvent() treats it as a single-market event.
|
|
242
|
+
const standaloneEvents = allMarkets
|
|
243
|
+
.filter((m) => !coveredSlugs.has(m.slug) && m.tradeType !== 'group')
|
|
244
|
+
.map((m) => ({
|
|
245
|
+
...m,
|
|
246
|
+
// Explicitly omit the markets array so the normalizer wraps
|
|
247
|
+
// the top-level fields as a single-market event
|
|
248
|
+
markets: undefined,
|
|
249
|
+
}));
|
|
250
|
+
const combined = [...groupEvents, ...standaloneEvents];
|
|
251
|
+
return combined.slice(0, limit);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Generic paginated fetch against /markets/active.
|
|
255
|
+
* When tradeType is omitted the API returns all trade types.
|
|
256
|
+
*/
|
|
257
|
+
async fetchPaginatedActive(opts) {
|
|
258
|
+
const { tradeType, sortBy, pageSize, maxPages, limit } = opts;
|
|
259
|
+
let page = 1;
|
|
260
|
+
const results = [];
|
|
261
|
+
while (results.length < limit && page <= maxPages) {
|
|
262
|
+
const queryParams = {
|
|
263
|
+
page,
|
|
264
|
+
limit: pageSize,
|
|
265
|
+
sortBy,
|
|
266
|
+
};
|
|
267
|
+
if (tradeType) {
|
|
268
|
+
queryParams.tradeType = tradeType;
|
|
269
|
+
}
|
|
270
|
+
const response = await this.http.get(`${this.apiUrl}/markets/active`, {
|
|
271
|
+
params: queryParams,
|
|
227
272
|
});
|
|
228
273
|
const items = response.data?.data || response.data || [];
|
|
229
274
|
if (items.length === 0)
|
|
230
275
|
break;
|
|
231
276
|
for (const item of items) {
|
|
232
|
-
if (
|
|
277
|
+
if (results.length >= limit)
|
|
233
278
|
break;
|
|
234
|
-
|
|
279
|
+
results.push(item);
|
|
235
280
|
}
|
|
236
281
|
if (items.length < pageSize)
|
|
237
282
|
break;
|
|
238
283
|
page++;
|
|
239
284
|
}
|
|
240
|
-
return
|
|
285
|
+
return results;
|
|
241
286
|
}
|
|
242
287
|
}
|
|
243
288
|
exports.LimitlessFetcher = LimitlessFetcher;
|
|
@@ -70,7 +70,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
70
70
|
}
|
|
71
71
|
else {
|
|
72
72
|
const apiKey = this.auth.getApiKey();
|
|
73
|
-
this.client = new client_1.LimitlessClient(credentials.privateKey, apiKey);
|
|
73
|
+
this.client = new client_1.LimitlessClient(credentials.privateKey, apiKey, this.auth.host);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
else if (this.auth.isDelegatedSigning()) {
|
|
@@ -96,7 +96,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
96
96
|
callApi: this.callApi.bind(this),
|
|
97
97
|
getHeaders: () => this.getHeaders(),
|
|
98
98
|
};
|
|
99
|
-
this.fetcher = new fetcher_1.LimitlessFetcher(ctx, this.http, this.auth?.getApiKey());
|
|
99
|
+
this.fetcher = new fetcher_1.LimitlessFetcher(ctx, this.http, this.auth?.getApiKey(), this.auth?.host);
|
|
100
100
|
this.normalizer = new normalizer_1.LimitlessNormalizer();
|
|
101
101
|
}
|
|
102
102
|
get name() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnifiedMarket, CandleInterval } from '../../types';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const DEFAULT_LIMITLESS_API_URL = "https://api.limitless.exchange";
|
|
3
|
+
export declare const LIMITLESS_API_URL: string;
|
|
3
4
|
export declare function mapMarketToUnified(market: any): UnifiedMarket | null;
|
|
4
5
|
export declare function mapIntervalToFidelity(interval: CandleInterval): number;
|
|
5
6
|
/**
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LIMITLESS_API_URL = void 0;
|
|
3
|
+
exports.LIMITLESS_API_URL = exports.DEFAULT_LIMITLESS_API_URL = void 0;
|
|
4
4
|
exports.mapMarketToUnified = mapMarketToUnified;
|
|
5
5
|
exports.mapIntervalToFidelity = mapIntervalToFidelity;
|
|
6
6
|
exports.paginateLimitlessMarkets = paginateLimitlessMarkets;
|
|
7
7
|
const market_utils_1 = require("../../utils/market-utils");
|
|
8
|
-
exports.
|
|
8
|
+
exports.DEFAULT_LIMITLESS_API_URL = 'https://api.limitless.exchange';
|
|
9
|
+
exports.LIMITLESS_API_URL = process.env.LIMITLESS_BASE_URL || exports.DEFAULT_LIMITLESS_API_URL;
|
|
9
10
|
function mapMarketToUnified(market) {
|
|
10
11
|
if (!market)
|
|
11
12
|
return null;
|
|
@@ -8,6 +8,8 @@ export interface CancelOrderContext {
|
|
|
8
8
|
http: AxiosInstance;
|
|
9
9
|
/** Returns auth headers. Throws if no token is configured. */
|
|
10
10
|
getAuthHeaders: () => Record<string, string>;
|
|
11
|
+
/** Optional base URL override (defaults to the standard Metaculus API). */
|
|
12
|
+
baseUrl?: string;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
13
15
|
* Withdraw a forecast on Metaculus, mapped from the unified cancelOrder interface.
|
|
@@ -48,7 +48,7 @@ async function cancelOrder(orderId, ctx) {
|
|
|
48
48
|
// Bypasses callApi because the API expects an array body.
|
|
49
49
|
await ctx.http.request({
|
|
50
50
|
method: "POST",
|
|
51
|
-
url: `${utils_1.
|
|
51
|
+
url: `${ctx.baseUrl || utils_1.DEFAULT_BASE_URL}/questions/withdraw/`,
|
|
52
52
|
data: [{ question: questionId }],
|
|
53
53
|
headers: { "Content-Type": "application/json", ...headers },
|
|
54
54
|
});
|
|
@@ -60,6 +60,8 @@ export interface CreateOrderContext {
|
|
|
60
60
|
http: AxiosInstance;
|
|
61
61
|
/** Returns auth headers. Throws if no token is configured. */
|
|
62
62
|
getAuthHeaders: () => Record<string, string>;
|
|
63
|
+
/** Optional base URL override (defaults to the standard Metaculus API). */
|
|
64
|
+
baseUrl?: string;
|
|
63
65
|
/**
|
|
64
66
|
* Fetch current market outcomes to read multiple-choice probabilities.
|
|
65
67
|
* Only needed for multiple-choice questions.
|
|
@@ -256,7 +256,7 @@ async function createOrder(params, ctx) {
|
|
|
256
256
|
// array body, but the implicit API infrastructure always sends objects.
|
|
257
257
|
await ctx.http.request({
|
|
258
258
|
method: "POST",
|
|
259
|
-
url: `${utils_1.
|
|
259
|
+
url: `${ctx.baseUrl || utils_1.DEFAULT_BASE_URL}/questions/forecast/`,
|
|
260
260
|
data: payload,
|
|
261
261
|
headers: { "Content-Type": "application/json", ...headers },
|
|
262
262
|
});
|
|
@@ -38,6 +38,7 @@ import { UnifiedMarket, UnifiedEvent, CreateOrderParams, Order } from "../../typ
|
|
|
38
38
|
*/
|
|
39
39
|
export declare class MetaculusExchange extends PredictionMarketExchange {
|
|
40
40
|
private readonly apiToken?;
|
|
41
|
+
private readonly baseUrl;
|
|
41
42
|
constructor(credentials?: ExchangeCredentials);
|
|
42
43
|
get name(): string;
|
|
43
44
|
protected mapImplicitApiError(error: any): any;
|
|
@@ -49,12 +49,14 @@ const cancelOrder_1 = require("./cancelOrder");
|
|
|
49
49
|
*/
|
|
50
50
|
class MetaculusExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
51
51
|
apiToken;
|
|
52
|
+
baseUrl;
|
|
52
53
|
constructor(credentials) {
|
|
53
54
|
super(credentials);
|
|
54
55
|
this.apiToken = credentials?.apiToken;
|
|
55
56
|
// Rate-limit conservatively; authenticated users get higher Metaculus quotas
|
|
56
57
|
this.rateLimit = 500;
|
|
57
|
-
|
|
58
|
+
this.baseUrl = credentials?.baseUrl || utils_1.DEFAULT_BASE_URL;
|
|
59
|
+
const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.metaculusApiSpec, this.baseUrl);
|
|
58
60
|
this.defineImplicitApi(descriptor);
|
|
59
61
|
}
|
|
60
62
|
get name() {
|
|
@@ -115,6 +117,7 @@ class MetaculusExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
115
117
|
const ctx = {
|
|
116
118
|
http: this.http,
|
|
117
119
|
getAuthHeaders: () => this.getAuthHeaders(),
|
|
120
|
+
baseUrl: this.baseUrl,
|
|
118
121
|
fetchOutcomes: async (marketId) => {
|
|
119
122
|
const markets = await this.fetchMarkets({ marketId });
|
|
120
123
|
return markets.length > 0 ? markets[0].outcomes : [];
|
|
@@ -136,6 +139,7 @@ class MetaculusExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
136
139
|
const ctx = {
|
|
137
140
|
http: this.http,
|
|
138
141
|
getAuthHeaders: () => this.getAuthHeaders(),
|
|
142
|
+
baseUrl: this.baseUrl,
|
|
139
143
|
};
|
|
140
144
|
return (0, cancelOrder_1.cancelOrder)(orderId, ctx);
|
|
141
145
|
}
|
|
@@ -5,7 +5,8 @@ import { UnifiedMarket } from "../../types";
|
|
|
5
5
|
* so this constant must match exactly -- do NOT add a trailing slash or path suffix.
|
|
6
6
|
* Paths in the spec (/posts/, /posts/{postId}/) are appended directly by BaseExchange.
|
|
7
7
|
*/
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const DEFAULT_BASE_URL = "https://www.metaculus.com/api";
|
|
9
|
+
export declare const BASE_URL: string;
|
|
9
10
|
/**
|
|
10
11
|
* Map a Metaculus post `status` to pmxt unified status.
|
|
11
12
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BASE_URL = void 0;
|
|
3
|
+
exports.BASE_URL = exports.DEFAULT_BASE_URL = void 0;
|
|
4
4
|
exports.mapStatus = mapStatus;
|
|
5
5
|
exports.mapMarketToUnified = mapMarketToUnified;
|
|
6
6
|
exports.expandPost = expandPost;
|
|
@@ -11,7 +11,8 @@ const market_utils_1 = require("../../utils/market-utils");
|
|
|
11
11
|
* so this constant must match exactly -- do NOT add a trailing slash or path suffix.
|
|
12
12
|
* Paths in the spec (/posts/, /posts/{postId}/) are appended directly by BaseExchange.
|
|
13
13
|
*/
|
|
14
|
-
exports.
|
|
14
|
+
exports.DEFAULT_BASE_URL = "https://www.metaculus.com/api";
|
|
15
|
+
exports.BASE_URL = process.env.METACULUS_BASE_URL || exports.DEFAULT_BASE_URL;
|
|
15
16
|
/**
|
|
16
17
|
* Map a Metaculus post `status` to pmxt unified status.
|
|
17
18
|
*
|
|
@@ -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-05-
|
|
3
|
+
* Generated at: 2026-05-08T16:05:46.434Z
|
|
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-05-
|
|
6
|
+
* Generated at: 2026-05-08T16:05:46.434Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.myriadApiSpec = {
|
|
@@ -58,7 +58,8 @@ export interface MyriadRawPortfolioItem {
|
|
|
58
58
|
}
|
|
59
59
|
export declare class MyriadFetcher implements IExchangeFetcher<MyriadRawMarket, MyriadRawQuestion> {
|
|
60
60
|
private readonly ctx;
|
|
61
|
-
|
|
61
|
+
private readonly baseUrl;
|
|
62
|
+
constructor(ctx: FetcherContext, baseUrl?: string);
|
|
62
63
|
fetchRawMarkets(params?: MarketFilterParams): Promise<MyriadRawMarket[]>;
|
|
63
64
|
fetchRawEvents(params: EventFetchParams): Promise<MyriadRawQuestion[]>;
|
|
64
65
|
fetchRawOHLCV(id: string, _params: OHLCVParams): Promise<MyriadRawMarket>;
|
|
@@ -6,8 +6,10 @@ const errors_1 = require("./errors");
|
|
|
6
6
|
const MAX_PAGE_SIZE = 100;
|
|
7
7
|
class MyriadFetcher {
|
|
8
8
|
ctx;
|
|
9
|
-
|
|
9
|
+
baseUrl;
|
|
10
|
+
constructor(ctx, baseUrl) {
|
|
10
11
|
this.ctx = ctx;
|
|
12
|
+
this.baseUrl = baseUrl || utils_1.DEFAULT_BASE_URL;
|
|
11
13
|
}
|
|
12
14
|
async fetchRawMarkets(params) {
|
|
13
15
|
try {
|
|
@@ -42,7 +44,7 @@ class MyriadFetcher {
|
|
|
42
44
|
queryParams.order = 'desc';
|
|
43
45
|
}
|
|
44
46
|
if (limit <= MAX_PAGE_SIZE) {
|
|
45
|
-
const response = await this.ctx.http.get(`${
|
|
47
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/markets`, {
|
|
46
48
|
params: queryParams,
|
|
47
49
|
headers: this.ctx.getHeaders(),
|
|
48
50
|
});
|
|
@@ -55,7 +57,7 @@ class MyriadFetcher {
|
|
|
55
57
|
while (page <= maxPages) {
|
|
56
58
|
queryParams.page = page;
|
|
57
59
|
queryParams.limit = MAX_PAGE_SIZE;
|
|
58
|
-
const response = await this.ctx.http.get(`${
|
|
60
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/markets`, {
|
|
59
61
|
params: queryParams,
|
|
60
62
|
headers: this.ctx.getHeaders(),
|
|
61
63
|
});
|
|
@@ -89,7 +91,7 @@ class MyriadFetcher {
|
|
|
89
91
|
if (params.query) {
|
|
90
92
|
queryParams.keyword = params.query;
|
|
91
93
|
}
|
|
92
|
-
const response = await this.ctx.http.get(`${
|
|
94
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/questions`, {
|
|
93
95
|
params: queryParams,
|
|
94
96
|
headers: this.ctx.getHeaders(),
|
|
95
97
|
});
|
|
@@ -192,7 +194,7 @@ class MyriadFetcher {
|
|
|
192
194
|
return this.fetchRawMarketBySlug(marketId);
|
|
193
195
|
}
|
|
194
196
|
const [networkId, id] = parts;
|
|
195
|
-
const response = await this.ctx.http.get(`${
|
|
197
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/markets/${id}`, {
|
|
196
198
|
params: { network_id: Number(networkId) },
|
|
197
199
|
headers: this.ctx.getHeaders(),
|
|
198
200
|
});
|
|
@@ -200,14 +202,14 @@ class MyriadFetcher {
|
|
|
200
202
|
return market ? [market] : [];
|
|
201
203
|
}
|
|
202
204
|
async fetchRawMarketBySlug(slug) {
|
|
203
|
-
const response = await this.ctx.http.get(`${
|
|
205
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/markets/${slug}`, {
|
|
204
206
|
headers: this.ctx.getHeaders(),
|
|
205
207
|
});
|
|
206
208
|
const market = response.data.data || response.data;
|
|
207
209
|
return market ? [market] : [];
|
|
208
210
|
}
|
|
209
211
|
async fetchRawQuestionById(id) {
|
|
210
|
-
const response = await this.ctx.http.get(`${
|
|
212
|
+
const response = await this.ctx.http.get(`${this.baseUrl}/questions/${id}`, {
|
|
211
213
|
headers: this.ctx.getHeaders(),
|
|
212
214
|
});
|
|
213
215
|
const question = response.data.data || response.data;
|
|
@@ -32,14 +32,15 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
32
32
|
if (credentials?.apiKey) {
|
|
33
33
|
this.auth = new auth_1.MyriadAuth(credentials);
|
|
34
34
|
}
|
|
35
|
-
const
|
|
35
|
+
const myriadBaseUrl = credentials?.baseUrl || utils_1.DEFAULT_BASE_URL;
|
|
36
|
+
const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.myriadApiSpec, myriadBaseUrl);
|
|
36
37
|
this.defineImplicitApi(descriptor);
|
|
37
38
|
const ctx = {
|
|
38
39
|
http: this.http,
|
|
39
40
|
callApi: this.callApi.bind(this),
|
|
40
41
|
getHeaders: () => this.getHeaders(),
|
|
41
42
|
};
|
|
42
|
-
this.fetcher = new fetcher_1.MyriadFetcher(ctx);
|
|
43
|
+
this.fetcher = new fetcher_1.MyriadFetcher(ctx, myriadBaseUrl);
|
|
43
44
|
this.normalizer = new normalizer_1.MyriadNormalizer();
|
|
44
45
|
}
|
|
45
46
|
get name() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UnifiedMarket, UnifiedEvent } from '../../types';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const DEFAULT_BASE_URL = "https://api-v2.myriadprotocol.com";
|
|
3
|
+
export declare const BASE_URL: string;
|
|
3
4
|
export declare const NETWORKS: {
|
|
4
5
|
readonly ABSTRACT: 2741;
|
|
5
6
|
readonly LINEA: 59144;
|