pmxt-core 2.37.10 → 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.
Files changed (72) hide show
  1. package/dist/BaseExchange.d.ts +5 -0
  2. package/dist/BaseExchange.js +6 -0
  3. package/dist/exchanges/kalshi/api.d.ts +1 -1
  4. package/dist/exchanges/kalshi/api.js +1 -1
  5. package/dist/exchanges/kalshi/config.d.ts +3 -3
  6. package/dist/exchanges/kalshi/config.js +4 -4
  7. package/dist/exchanges/kalshi/index.js +1 -1
  8. package/dist/exchanges/limitless/api.d.ts +1 -1
  9. package/dist/exchanges/limitless/api.js +1 -1
  10. package/dist/exchanges/limitless/auth.d.ts +1 -0
  11. package/dist/exchanges/limitless/auth.js +4 -2
  12. package/dist/exchanges/limitless/client.d.ts +1 -1
  13. package/dist/exchanges/limitless/client.js +3 -3
  14. package/dist/exchanges/limitless/fetcher.d.ts +7 -1
  15. package/dist/exchanges/limitless/fetcher.js +61 -16
  16. package/dist/exchanges/limitless/index.js +2 -2
  17. package/dist/exchanges/limitless/utils.d.ts +2 -1
  18. package/dist/exchanges/limitless/utils.js +3 -2
  19. package/dist/exchanges/metaculus/cancelOrder.d.ts +2 -0
  20. package/dist/exchanges/metaculus/cancelOrder.js +1 -1
  21. package/dist/exchanges/metaculus/createOrder.d.ts +2 -0
  22. package/dist/exchanges/metaculus/createOrder.js +1 -1
  23. package/dist/exchanges/metaculus/index.d.ts +1 -0
  24. package/dist/exchanges/metaculus/index.js +5 -1
  25. package/dist/exchanges/metaculus/utils.d.ts +2 -1
  26. package/dist/exchanges/metaculus/utils.js +3 -2
  27. package/dist/exchanges/myriad/api.d.ts +1 -1
  28. package/dist/exchanges/myriad/api.js +1 -1
  29. package/dist/exchanges/myriad/fetcher.d.ts +2 -1
  30. package/dist/exchanges/myriad/fetcher.js +9 -7
  31. package/dist/exchanges/myriad/index.js +3 -2
  32. package/dist/exchanges/myriad/utils.d.ts +2 -1
  33. package/dist/exchanges/myriad/utils.js +3 -2
  34. package/dist/exchanges/opinion/api.d.ts +1 -1
  35. package/dist/exchanges/opinion/api.js +1 -1
  36. package/dist/exchanges/opinion/config.d.ts +2 -1
  37. package/dist/exchanges/opinion/config.js +3 -2
  38. package/dist/exchanges/opinion/fetcher.d.ts +2 -1
  39. package/dist/exchanges/opinion/fetcher.js +10 -8
  40. package/dist/exchanges/opinion/index.js +3 -2
  41. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  42. package/dist/exchanges/polymarket/api-clob.js +1 -1
  43. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  44. package/dist/exchanges/polymarket/api-data.js +1 -1
  45. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  46. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  47. package/dist/exchanges/polymarket/auth.d.ts +1 -0
  48. package/dist/exchanges/polymarket/auth.js +7 -4
  49. package/dist/exchanges/polymarket/fetcher.js +1 -1
  50. package/dist/exchanges/polymarket/utils.d.ts +4 -4
  51. package/dist/exchanges/polymarket/utils.js +4 -4
  52. package/dist/exchanges/polymarket_us/config.d.ts +3 -3
  53. package/dist/exchanges/polymarket_us/config.js +4 -4
  54. package/dist/exchanges/polymarket_us/index.js +1 -1
  55. package/dist/exchanges/probable/api.d.ts +1 -1
  56. package/dist/exchanges/probable/api.js +1 -1
  57. package/dist/exchanges/probable/fetcher.d.ts +2 -1
  58. package/dist/exchanges/probable/fetcher.js +9 -7
  59. package/dist/exchanges/probable/index.js +3 -2
  60. package/dist/exchanges/probable/utils.d.ts +2 -1
  61. package/dist/exchanges/probable/utils.js +3 -2
  62. package/dist/exchanges/smarkets/config.d.ts +3 -2
  63. package/dist/exchanges/smarkets/config.js +5 -4
  64. package/dist/exchanges/smarkets/fetcher.js +2 -1
  65. package/dist/exchanges/smarkets/index.js +1 -1
  66. package/dist/router/Router.d.ts +3 -1
  67. package/dist/router/Router.js +65 -0
  68. package/dist/router/Router.test.js +131 -1
  69. package/dist/router/types.d.ts +3 -0
  70. package/dist/server/method-verbs.json +10 -0
  71. package/dist/server/openapi.yaml +35 -3
  72. package/package.json +3 -3
@@ -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:
@@ -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-08T14:38:32.269Z
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-08T14:38:32.269Z
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 = "https://api.elections.kalshi.com";
18
- export declare const KALSHI_DEMO_API_URL = "https://demo-api.kalshi.co";
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-08T14:38:32.317Z
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-08T14:38:32.317Z
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 = {
@@ -18,6 +18,7 @@ export declare class LimitlessAuth {
18
18
  private httpClient?;
19
19
  private apiKey?;
20
20
  private hmacCreds?;
21
+ readonly host: string;
21
22
  constructor(credentials: ExchangeCredentials);
22
23
  getApiKey(): string;
23
24
  /**
@@ -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 LIMITLESS_HOST = 'https://api.limitless.exchange';
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: LIMITLESS_HOST,
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 LIMITLESS_API_URL = 'https://api.limitless.exchange';
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: LIMITLESS_API_URL,
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
- constructor(ctx: FetcherContext, http: AxiosInstance, apiKey?: string);
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
- constructor(ctx, http, apiKey) {
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: utils_1.LIMITLESS_API_URL,
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 response = await this.http.get('https://api.limitless.exchange/portfolio/trades', {
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: utils_1.LIMITLESS_API_URL });
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 allGroups = [];
219
- while (allGroups.length < limit && page <= MAX_PAGES) {
220
- const response = await this.http.get(`${utils_1.LIMITLESS_API_URL}/markets/active`, {
221
- params: {
222
- page,
223
- limit: pageSize,
224
- tradeType: 'group',
225
- sortBy: params?.sort === 'newest' ? 'newest' : params?.sort === 'liquidity' ? 'lp_rewards' : 'high_value',
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 (allGroups.length >= limit)
277
+ if (results.length >= limit)
233
278
  break;
234
- allGroups.push(item);
279
+ results.push(item);
235
280
  }
236
281
  if (items.length < pageSize)
237
282
  break;
238
283
  page++;
239
284
  }
240
- return allGroups;
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 LIMITLESS_API_URL = "https://api.limitless.exchange";
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.LIMITLESS_API_URL = 'https://api.limitless.exchange';
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.BASE_URL}/questions/withdraw/`,
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.BASE_URL}/questions/forecast/`,
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
- const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.metaculusApiSpec, utils_1.BASE_URL);
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 BASE_URL = "https://www.metaculus.com/api";
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.BASE_URL = "https://www.metaculus.com/api";
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-08T14:38:32.331Z
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-08T14:38:32.331Z
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
- constructor(ctx: FetcherContext);
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
- constructor(ctx) {
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(`${utils_1.BASE_URL}/markets`, {
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(`${utils_1.BASE_URL}/markets`, {
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(`${utils_1.BASE_URL}/questions`, {
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(`${utils_1.BASE_URL}/markets/${id}`, {
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(`${utils_1.BASE_URL}/markets/${slug}`, {
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(`${utils_1.BASE_URL}/questions/${id}`, {
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 descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.myriadApiSpec, utils_1.BASE_URL);
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 BASE_URL = "https://api-v2.myriadprotocol.com";
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;