pmxt-core 2.12.1 → 2.14.1

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 (39) hide show
  1. package/dist/exchanges/kalshi/api.d.ts +7 -1
  2. package/dist/exchanges/kalshi/api.js +11 -2
  3. package/dist/exchanges/kalshi/config.d.ts +103 -0
  4. package/dist/exchanges/kalshi/config.js +144 -0
  5. package/dist/exchanges/kalshi/fetchEvents.d.ts +2 -2
  6. package/dist/exchanges/kalshi/fetchEvents.js +19 -16
  7. package/dist/exchanges/kalshi/fetchMarkets.d.ts +2 -2
  8. package/dist/exchanges/kalshi/fetchMarkets.js +36 -25
  9. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +2 -2
  10. package/dist/exchanges/kalshi/fetchOHLCV.js +20 -17
  11. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +2 -0
  12. package/dist/exchanges/kalshi/fetchOrderBook.js +60 -0
  13. package/dist/exchanges/kalshi/fetchTrades.d.ts +3 -0
  14. package/dist/exchanges/kalshi/fetchTrades.js +32 -0
  15. package/dist/exchanges/kalshi/index.d.ts +8 -3
  16. package/dist/exchanges/kalshi/index.js +82 -70
  17. package/dist/exchanges/kalshi/kalshi.test.js +294 -292
  18. package/dist/exchanges/kalshi/utils.d.ts +1 -3
  19. package/dist/exchanges/kalshi/utils.js +14 -16
  20. package/dist/exchanges/kalshi/websocket.d.ts +4 -3
  21. package/dist/exchanges/kalshi/websocket.js +87 -61
  22. package/dist/exchanges/kalshi-demo/index.d.ts +10 -0
  23. package/dist/exchanges/kalshi-demo/index.js +23 -0
  24. package/dist/exchanges/limitless/api.d.ts +1 -1
  25. package/dist/exchanges/limitless/api.js +1 -1
  26. package/dist/exchanges/myriad/api.d.ts +1 -1
  27. package/dist/exchanges/myriad/api.js +1 -1
  28. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  29. package/dist/exchanges/polymarket/api-clob.js +1 -1
  30. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  31. package/dist/exchanges/polymarket/api-data.js +1 -1
  32. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  33. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  34. package/dist/exchanges/probable/api.d.ts +1 -1
  35. package/dist/exchanges/probable/api.js +1 -1
  36. package/dist/index.d.ts +4 -0
  37. package/dist/index.js +5 -1
  38. package/dist/server/app.js +56 -48
  39. package/package.json +5 -4
@@ -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-02-22T15:41:57.405Z
3
+ * Generated at: 2026-02-23T07:41:05.138Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const kalshiApiSpec: {
@@ -11,6 +11,12 @@ export declare const kalshiApiSpec: {
11
11
  };
12
12
  servers: {
13
13
  url: string;
14
+ variables: {
15
+ env: {
16
+ default: string;
17
+ enum: string[];
18
+ };
19
+ };
14
20
  }[];
15
21
  paths: {
16
22
  "/historical/cutoff": {
@@ -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-02-22T15:41:57.405Z
6
+ * Generated at: 2026-02-23T07:41:05.138Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.kalshiApiSpec = {
@@ -14,7 +14,16 @@ exports.kalshiApiSpec = {
14
14
  },
15
15
  "servers": [
16
16
  {
17
- "url": "https://api.elections.kalshi.com/trade-api/v2"
17
+ "url": "https://{env}.elections.kalshi.com/trade-api/v2",
18
+ "variables": {
19
+ "env": {
20
+ "default": "api",
21
+ "enum": [
22
+ "api",
23
+ "demo-api"
24
+ ]
25
+ }
26
+ }
18
27
  }
19
28
  ],
20
29
  "paths": {
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Kalshi runtime configuration.
3
+ *
4
+ * This file is hand-authored and is the single source of truth for:
5
+ * - Base URL constants for production and demo environments
6
+ * - API path constants (KALSHI_PATHS)
7
+ * - URL helper functions used by fetch functions and the exchange class
8
+ *
9
+ * The OpenAPI spec lives in core/specs/kalshi/Kalshi.yaml and is compiled
10
+ * into core/src/exchanges/kalshi/api.ts by `npm run fetch:openapi`.
11
+ * Do NOT put runtime config into api.ts — it will be overwritten.
12
+ *
13
+ * Environment mapping (aligns with the `{env}` server variable in Kalshi.yaml):
14
+ * env = "api" → production: https://api.elections.kalshi.com
15
+ * env = "demo-api" → demo/paper: https://demo-api.elections.kalshi.com
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";
19
+ export declare const KALSHI_PROD_WS_URL = "wss://api.elections.kalshi.com/trade-api/ws/v2";
20
+ export declare const KALSHI_DEMO_WS_URL = "wss://demo-api.kalshi.co/trade-api/ws/v2";
21
+ export declare const KALSHI_PATHS: {
22
+ TRADE_API: string;
23
+ EVENTS: string;
24
+ SERIES: string;
25
+ PORTFOLIO: string;
26
+ MARKETS: string;
27
+ BALANCE: string;
28
+ ORDERS: string;
29
+ POSITIONS: string;
30
+ };
31
+ export interface KalshiApiConfig {
32
+ /** Base REST API URL — production or demo */
33
+ apiUrl: string;
34
+ /** WebSocket URL — production or demo */
35
+ wsUrl?: string;
36
+ /** Whether the demo environment is active */
37
+ demoMode: boolean;
38
+ }
39
+ /**
40
+ * Return a typed config object for the requested environment.
41
+ *
42
+ * @param demoMode - Pass `true` to target demo-api.elections.kalshi.com.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const config = getKalshiConfig(true);
47
+ * // config.apiUrl === "https://demo-api.elections.kalshi.com"
48
+ * ```
49
+ */
50
+ export declare function getKalshiConfig(demoMode?: boolean): KalshiApiConfig;
51
+ /**
52
+ * Build the full path (including `/trade-api/v2` prefix) for use in
53
+ * `KalshiAuth.getHeaders()` signing.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * getApiPath("/portfolio/balance")
58
+ * // → "/trade-api/v2/portfolio/balance"
59
+ * ```
60
+ */
61
+ export declare function getApiPath(operationPath: string): string;
62
+ /**
63
+ * Build the full URL for the events endpoint.
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * getEventsUrl(baseUrl) // .../events
68
+ * getEventsUrl(baseUrl, ['FED-25']) // .../events/FED-25
69
+ * ```
70
+ */
71
+ export declare function getEventsUrl(baseUrl: string, pathSegments?: string[]): string;
72
+ /**
73
+ * Build the full URL for the series endpoint, with optional nested segments.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * getSeriesUrl(baseUrl) // .../series
78
+ * getSeriesUrl(baseUrl, 'FED') // .../series/FED
79
+ * getSeriesUrl(baseUrl, 'FED', ['markets', 'FED-B4.75', 'candlesticks'])
80
+ * // .../series/FED/markets/FED-B4.75/candlesticks
81
+ * ```
82
+ */
83
+ export declare function getSeriesUrl(baseUrl: string, seriesTicker?: string, pathSegments?: string[]): string;
84
+ /**
85
+ * Build the full URL for the portfolio endpoint.
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * getPortfolioUrl(baseUrl, '/balance') // .../portfolio/balance
90
+ * ```
91
+ */
92
+ export declare function getPortfolioUrl(baseUrl: string, subPath?: string): string;
93
+ /**
94
+ * Build the full URL for the markets endpoint, with optional nested segments.
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * getMarketsUrl(baseUrl) // .../markets
99
+ * getMarketsUrl(baseUrl, 'FED-B4.75') // .../markets/FED-B4.75
100
+ * getMarketsUrl(baseUrl, 'FED-B4.75', ['orderbook']) // .../markets/FED-B4.75/orderbook
101
+ * ```
102
+ */
103
+ export declare function getMarketsUrl(baseUrl: string, marketId?: string, pathSegments?: string[]): string;
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ /**
3
+ * Kalshi runtime configuration.
4
+ *
5
+ * This file is hand-authored and is the single source of truth for:
6
+ * - Base URL constants for production and demo environments
7
+ * - API path constants (KALSHI_PATHS)
8
+ * - URL helper functions used by fetch functions and the exchange class
9
+ *
10
+ * The OpenAPI spec lives in core/specs/kalshi/Kalshi.yaml and is compiled
11
+ * into core/src/exchanges/kalshi/api.ts by `npm run fetch:openapi`.
12
+ * Do NOT put runtime config into api.ts — it will be overwritten.
13
+ *
14
+ * Environment mapping (aligns with the `{env}` server variable in Kalshi.yaml):
15
+ * env = "api" → production: https://api.elections.kalshi.com
16
+ * env = "demo-api" → demo/paper: https://demo-api.elections.kalshi.com
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.KALSHI_PATHS = exports.KALSHI_DEMO_WS_URL = exports.KALSHI_PROD_WS_URL = exports.KALSHI_DEMO_API_URL = exports.KALSHI_PROD_API_URL = void 0;
20
+ exports.getKalshiConfig = getKalshiConfig;
21
+ exports.getApiPath = getApiPath;
22
+ exports.getEventsUrl = getEventsUrl;
23
+ exports.getSeriesUrl = getSeriesUrl;
24
+ exports.getPortfolioUrl = getPortfolioUrl;
25
+ exports.getMarketsUrl = getMarketsUrl;
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";
29
+ exports.KALSHI_PROD_WS_URL = "wss://api.elections.kalshi.com/trade-api/ws/v2";
30
+ exports.KALSHI_DEMO_WS_URL = "wss://demo-api.kalshi.co/trade-api/ws/v2";
31
+ // ── Path constants ────────────────────────────────────────────────────────────
32
+ exports.KALSHI_PATHS = {
33
+ TRADE_API: "/trade-api/v2",
34
+ EVENTS: "/events",
35
+ SERIES: "/series",
36
+ PORTFOLIO: "/portfolio",
37
+ MARKETS: "/markets",
38
+ BALANCE: "/balance",
39
+ ORDERS: "/orders",
40
+ POSITIONS: "/positions",
41
+ };
42
+ /**
43
+ * Return a typed config object for the requested environment.
44
+ *
45
+ * @param demoMode - Pass `true` to target demo-api.elections.kalshi.com.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const config = getKalshiConfig(true);
50
+ * // config.apiUrl === "https://demo-api.elections.kalshi.com"
51
+ * ```
52
+ */
53
+ function getKalshiConfig(demoMode = false) {
54
+ return {
55
+ apiUrl: demoMode ? exports.KALSHI_DEMO_API_URL : exports.KALSHI_PROD_API_URL,
56
+ wsUrl: demoMode ? exports.KALSHI_DEMO_WS_URL : exports.KALSHI_PROD_WS_URL,
57
+ demoMode,
58
+ };
59
+ }
60
+ // ── URL builder helpers ───────────────────────────────────────────────────────
61
+ /**
62
+ * Build a full URL from a base and an arbitrary list of path segments.
63
+ * Empty segments are filtered out; leading/trailing slashes are normalised.
64
+ */
65
+ function buildApiUrl(baseUrl, ...segments) {
66
+ const flatSegments = segments.flat().filter(Boolean);
67
+ const path = flatSegments.map((s) => s.replace(/^\/+|\/+$/g, "")).join("/");
68
+ return path ? `${baseUrl}/${path}` : baseUrl;
69
+ }
70
+ /**
71
+ * Build the full path (including `/trade-api/v2` prefix) for use in
72
+ * `KalshiAuth.getHeaders()` signing.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * getApiPath("/portfolio/balance")
77
+ * // → "/trade-api/v2/portfolio/balance"
78
+ * ```
79
+ */
80
+ function getApiPath(operationPath) {
81
+ return exports.KALSHI_PATHS.TRADE_API + operationPath;
82
+ }
83
+ /**
84
+ * Build the full URL for the events endpoint.
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * getEventsUrl(baseUrl) // .../events
89
+ * getEventsUrl(baseUrl, ['FED-25']) // .../events/FED-25
90
+ * ```
91
+ */
92
+ function getEventsUrl(baseUrl, pathSegments = []) {
93
+ return buildApiUrl(baseUrl, exports.KALSHI_PATHS.TRADE_API, exports.KALSHI_PATHS.EVENTS, pathSegments);
94
+ }
95
+ /**
96
+ * Build the full URL for the series endpoint, with optional nested segments.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * getSeriesUrl(baseUrl) // .../series
101
+ * getSeriesUrl(baseUrl, 'FED') // .../series/FED
102
+ * getSeriesUrl(baseUrl, 'FED', ['markets', 'FED-B4.75', 'candlesticks'])
103
+ * // .../series/FED/markets/FED-B4.75/candlesticks
104
+ * ```
105
+ */
106
+ function getSeriesUrl(baseUrl, seriesTicker, pathSegments = []) {
107
+ const segments = [
108
+ exports.KALSHI_PATHS.TRADE_API,
109
+ exports.KALSHI_PATHS.SERIES,
110
+ seriesTicker || "",
111
+ ...pathSegments,
112
+ ];
113
+ return buildApiUrl(baseUrl, ...segments);
114
+ }
115
+ /**
116
+ * Build the full URL for the portfolio endpoint.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * getPortfolioUrl(baseUrl, '/balance') // .../portfolio/balance
121
+ * ```
122
+ */
123
+ function getPortfolioUrl(baseUrl, subPath) {
124
+ return buildApiUrl(baseUrl, exports.KALSHI_PATHS.TRADE_API, exports.KALSHI_PATHS.PORTFOLIO, subPath || "");
125
+ }
126
+ /**
127
+ * Build the full URL for the markets endpoint, with optional nested segments.
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * getMarketsUrl(baseUrl) // .../markets
132
+ * getMarketsUrl(baseUrl, 'FED-B4.75') // .../markets/FED-B4.75
133
+ * getMarketsUrl(baseUrl, 'FED-B4.75', ['orderbook']) // .../markets/FED-B4.75/orderbook
134
+ * ```
135
+ */
136
+ function getMarketsUrl(baseUrl, marketId, pathSegments = []) {
137
+ const segments = [
138
+ exports.KALSHI_PATHS.TRADE_API,
139
+ exports.KALSHI_PATHS.MARKETS,
140
+ marketId || "",
141
+ ...pathSegments,
142
+ ];
143
+ return buildApiUrl(baseUrl, ...segments);
144
+ }
@@ -1,5 +1,5 @@
1
- import { EventFetchParams } from '../../BaseExchange';
2
- import { UnifiedEvent } from '../../types';
1
+ import { EventFetchParams } from "../../BaseExchange";
2
+ import { UnifiedEvent } from "../../types";
3
3
  type CallApi = (operationId: string, params?: Record<string, any>) => Promise<any>;
4
4
  export declare function fetchEvents(params: EventFetchParams, callApi: CallApi): Promise<UnifiedEvent[]>;
5
5
  export {};
@@ -5,7 +5,10 @@ const utils_1 = require("./utils");
5
5
  const errors_1 = require("./errors");
6
6
  async function fetchEventByTicker(eventTicker, callApi) {
7
7
  const normalizedTicker = eventTicker.toUpperCase();
8
- const data = await callApi('GetEvent', { event_ticker: normalizedTicker, with_nested_markets: true });
8
+ const data = await callApi("GetEvent", {
9
+ event_ticker: normalizedTicker,
10
+ with_nested_markets: true,
11
+ });
9
12
  const event = data.event;
10
13
  if (!event)
11
14
  return [];
@@ -27,7 +30,7 @@ async function fetchEventByTicker(eventTicker, callApi) {
27
30
  url: `https://kalshi.com/events/${event.event_ticker}`,
28
31
  image: event.image_url,
29
32
  category: event.category,
30
- tags: event.tags || []
33
+ tags: event.tags || [],
31
34
  };
32
35
  return [unifiedEvent];
33
36
  }
@@ -41,9 +44,9 @@ async function fetchEvents(params, callApi) {
41
44
  if (params.slug) {
42
45
  return await fetchEventByTicker(params.slug, callApi);
43
46
  }
44
- const status = params?.status || 'active';
47
+ const status = params?.status || "active";
45
48
  const limit = params?.limit || 10000;
46
- const query = (params?.query || '').toLowerCase();
49
+ const query = (params?.query || "").toLowerCase();
47
50
  const fetchAllWithStatus = async (apiStatus) => {
48
51
  let allEvents = [];
49
52
  let cursor = null;
@@ -54,11 +57,11 @@ async function fetchEvents(params, callApi) {
54
57
  const queryParams = {
55
58
  limit: BATCH_SIZE,
56
59
  with_nested_markets: true,
57
- status: apiStatus
60
+ status: apiStatus,
58
61
  };
59
62
  if (cursor)
60
63
  queryParams.cursor = cursor;
61
- const data = await callApi('GetEvents', queryParams);
64
+ const data = await callApi("GetEvents", queryParams);
62
65
  const events = data.events || [];
63
66
  if (events.length === 0)
64
67
  break;
@@ -73,26 +76,26 @@ async function fetchEvents(params, callApi) {
73
76
  return allEvents;
74
77
  };
75
78
  let events = [];
76
- if (status === 'all') {
79
+ if (status === "all") {
77
80
  const [openEvents, closedEvents, settledEvents] = await Promise.all([
78
- fetchAllWithStatus('open'),
79
- fetchAllWithStatus('closed'),
80
- fetchAllWithStatus('settled')
81
+ fetchAllWithStatus("open"),
82
+ fetchAllWithStatus("closed"),
83
+ fetchAllWithStatus("settled"),
81
84
  ]);
82
85
  events = [...openEvents, ...closedEvents, ...settledEvents];
83
86
  }
84
- else if (status === 'closed' || status === 'inactive') {
87
+ else if (status === "closed" || status === "inactive") {
85
88
  const [closedEvents, settledEvents] = await Promise.all([
86
- fetchAllWithStatus('closed'),
87
- fetchAllWithStatus('settled')
89
+ fetchAllWithStatus("closed"),
90
+ fetchAllWithStatus("settled"),
88
91
  ]);
89
92
  events = [...closedEvents, ...settledEvents];
90
93
  }
91
94
  else {
92
- events = await fetchAllWithStatus('open');
95
+ events = await fetchAllWithStatus("open");
93
96
  }
94
97
  const filtered = events.filter((event) => {
95
- return (event.title || '').toLowerCase().includes(query);
98
+ return (event.title || "").toLowerCase().includes(query);
96
99
  });
97
100
  const unifiedEvents = filtered.map((event) => {
98
101
  const markets = [];
@@ -113,7 +116,7 @@ async function fetchEvents(params, callApi) {
113
116
  url: `https://kalshi.com/events/${event.event_ticker}`,
114
117
  image: event.image_url,
115
118
  category: event.category,
116
- tags: event.tags || []
119
+ tags: event.tags || [],
117
120
  };
118
121
  return unifiedEvent;
119
122
  });
@@ -1,5 +1,5 @@
1
- import { MarketFetchParams } from '../../BaseExchange';
2
- import { UnifiedMarket } from '../../types';
1
+ import { MarketFetchParams } from "../../BaseExchange";
2
+ import { UnifiedMarket } from "../../types";
3
3
  type CallApi = (operationId: string, params?: Record<string, any>) => Promise<any>;
4
4
  export declare function resetCache(): void;
5
5
  export declare function fetchMarkets(params: MarketFetchParams | undefined, callApi: CallApi): Promise<UnifiedMarket[]>;
@@ -4,7 +4,7 @@ exports.resetCache = resetCache;
4
4
  exports.fetchMarkets = fetchMarkets;
5
5
  const utils_1 = require("./utils");
6
6
  const errors_1 = require("./errors");
7
- async function fetchActiveEvents(callApi, targetMarketCount, status = 'open') {
7
+ async function fetchActiveEvents(callApi, targetMarketCount, status = "open") {
8
8
  let allEvents = [];
9
9
  let totalMarketCount = 0;
10
10
  let cursor = null;
@@ -19,11 +19,11 @@ async function fetchActiveEvents(callApi, targetMarketCount, status = 'open') {
19
19
  const queryParams = {
20
20
  limit: BATCH_SIZE,
21
21
  with_nested_markets: true,
22
- status: status // Filter by status (default 'open')
22
+ status: status, // Filter by status (default 'open')
23
23
  };
24
24
  if (cursor)
25
25
  queryParams.cursor = cursor;
26
- const data = await callApi('GetEvents', queryParams);
26
+ const data = await callApi("GetEvents", queryParams);
27
27
  const events = data.events || [];
28
28
  if (events.length === 0)
29
29
  break;
@@ -54,7 +54,7 @@ async function fetchActiveEvents(callApi, targetMarketCount, status = 'open') {
54
54
  }
55
55
  async function fetchSeriesMap(callApi) {
56
56
  try {
57
- const data = await callApi('GetSeriesList');
57
+ const data = await callApi("GetSeriesList");
58
58
  const seriesList = data.series || [];
59
59
  const map = new Map();
60
60
  for (const series of seriesList) {
@@ -91,7 +91,7 @@ async function fetchMarkets(params, callApi) {
91
91
  }
92
92
  // Handle outcomeId lookup (strip -NO suffix, use as ticker)
93
93
  if (params?.outcomeId) {
94
- const ticker = params.outcomeId.replace(/-NO$/, '');
94
+ const ticker = params.outcomeId.replace(/-NO$/, "");
95
95
  return await fetchMarketsBySlug(ticker, callApi);
96
96
  }
97
97
  // Handle eventId lookup (event ticker works the same way)
@@ -112,14 +112,19 @@ async function fetchMarkets(params, callApi) {
112
112
  async function fetchMarketsBySlug(eventTicker, callApi) {
113
113
  // Kalshi API expects uppercase tickers, but URLs use lowercase
114
114
  const normalizedTicker = eventTicker.toUpperCase();
115
- const data = await callApi('GetEvent', { event_ticker: normalizedTicker, with_nested_markets: true });
115
+ const data = await callApi("GetEvent", {
116
+ event_ticker: normalizedTicker,
117
+ with_nested_markets: true,
118
+ });
116
119
  const event = data.event;
117
120
  if (!event)
118
121
  return [];
119
122
  // Enrichment: Fetch series tags if they exist
120
123
  if (event.series_ticker) {
121
124
  try {
122
- const seriesData = await callApi('GetSeries', { series_ticker: event.series_ticker });
125
+ const seriesData = await callApi("GetSeries", {
126
+ series_ticker: event.series_ticker,
127
+ });
123
128
  const series = seriesData.series;
124
129
  if (series && series.tags && series.tags.length > 0) {
125
130
  if (!event.tags || event.tags.length === 0) {
@@ -146,13 +151,15 @@ async function searchMarkets(query, params, callApi) {
146
151
  const searchLimit = 250000;
147
152
  const markets = await fetchMarketsDefault({ ...params, limit: searchLimit }, callApi);
148
153
  const lowerQuery = query.toLowerCase();
149
- const searchIn = params?.searchIn || 'title'; // Default to title-only search
150
- const filtered = markets.filter(market => {
151
- const titleMatch = (market.title || '').toLowerCase().includes(lowerQuery);
152
- const descMatch = (market.description || '').toLowerCase().includes(lowerQuery);
153
- if (searchIn === 'title')
154
+ const searchIn = params?.searchIn || "title"; // Default to title-only search
155
+ const filtered = markets.filter((market) => {
156
+ const titleMatch = (market.title || "").toLowerCase().includes(lowerQuery);
157
+ const descMatch = (market.description || "")
158
+ .toLowerCase()
159
+ .includes(lowerQuery);
160
+ if (searchIn === "title")
154
161
  return titleMatch;
155
- if (searchIn === 'description')
162
+ if (searchIn === "description")
156
163
  return descMatch;
157
164
  return titleMatch || descMatch; // 'both'
158
165
  });
@@ -163,21 +170,24 @@ async function fetchMarketsDefault(params, callApi) {
163
170
  const limit = params?.limit || 250000;
164
171
  const offset = params?.offset || 0;
165
172
  const now = Date.now();
166
- const status = params?.status || 'active'; // Default to 'active'
173
+ const status = params?.status || "active"; // Default to 'active'
167
174
  // Map 'active' -> 'open', 'closed' -> 'closed'
168
175
  // Kalshi statuses: 'open', 'closed', 'settled'
169
- let apiStatus = 'open';
170
- if (status === 'closed' || status === 'inactive')
171
- apiStatus = 'closed';
172
- else if (status === 'all')
173
- apiStatus = 'open'; // Fallback for all? Or loop? For now default to open.
176
+ let apiStatus = "open";
177
+ if (status === "closed" || status === "inactive")
178
+ apiStatus = "closed";
179
+ else if (status === "all")
180
+ apiStatus = "open"; // Fallback for all? Or loop? For now default to open.
174
181
  try {
175
182
  let events;
176
183
  let seriesMap;
177
184
  // Check if we have valid cached data
178
185
  // Only use global cache for the default 'active'/'open' case
179
- const useCache = (status === 'active' || !params?.status);
180
- if (useCache && cachedEvents && cachedSeriesMap && (now - lastCacheTime < CACHE_TTL)) {
186
+ const useCache = status === "active" || !params?.status;
187
+ if (useCache &&
188
+ cachedEvents &&
189
+ cachedSeriesMap &&
190
+ now - lastCacheTime < CACHE_TTL) {
181
191
  events = cachedEvents;
182
192
  seriesMap = cachedSeriesMap;
183
193
  }
@@ -185,11 +195,12 @@ async function fetchMarketsDefault(params, callApi) {
185
195
  // Optimize fetch limit based on request parameters
186
196
  // If sorting is required (e.g. by volume), we need to fetch a larger set (or all) to sort correctly.
187
197
  // If no sorting is requested, we only need to fetch enough to satisfy the limit.
188
- const isSorted = params?.sort && (params.sort === 'volume' || params.sort === 'liquidity');
198
+ const isSorted = params?.sort &&
199
+ (params.sort === "volume" || params.sort === "liquidity");
189
200
  const fetchLimit = isSorted ? 1000 : limit;
190
201
  const [allEvents, fetchedSeriesMap] = await Promise.all([
191
202
  fetchActiveEvents(callApi, fetchLimit, apiStatus),
192
- fetchSeriesMap(callApi)
203
+ fetchSeriesMap(callApi),
193
204
  ]);
194
205
  events = allEvents;
195
206
  seriesMap = fetchedSeriesMap;
@@ -222,10 +233,10 @@ async function fetchMarketsDefault(params, callApi) {
222
233
  }
223
234
  }
224
235
  // Sort by 24h volume
225
- if (params?.sort === 'volume') {
236
+ if (params?.sort === "volume") {
226
237
  allMarkets.sort((a, b) => b.volume24h - a.volume24h);
227
238
  }
228
- else if (params?.sort === 'liquidity') {
239
+ else if (params?.sort === "liquidity") {
229
240
  allMarkets.sort((a, b) => b.liquidity - a.liquidity);
230
241
  }
231
242
  return allMarkets.slice(offset, offset + limit);
@@ -1,3 +1,3 @@
1
- import { HistoryFilterParams, OHLCVParams } from '../../BaseExchange';
2
- import { PriceCandle } from '../../types';
1
+ import { HistoryFilterParams, OHLCVParams } from "../../BaseExchange";
2
+ import { PriceCandle } from "../../types";
3
3
  export declare function fetchOHLCV(id: string, params: OHLCVParams | HistoryFilterParams, callApi: (operationId: string, params?: Record<string, any>) => Promise<any>): Promise<PriceCandle[]>;
@@ -5,34 +5,34 @@ const utils_1 = require("./utils");
5
5
  const validation_1 = require("../../utils/validation");
6
6
  const errors_1 = require("./errors");
7
7
  async function fetchOHLCV(id, params, callApi) {
8
- (0, validation_1.validateIdFormat)(id, 'OHLCV');
8
+ (0, validation_1.validateIdFormat)(id, "OHLCV");
9
9
  // Validate resolution is provided
10
10
  if (!params.resolution) {
11
- throw new Error('fetchOHLCV requires a resolution parameter. Use OHLCVParams with resolution specified.');
11
+ throw new Error("fetchOHLCV requires a resolution parameter. Use OHLCVParams with resolution specified.");
12
12
  }
13
13
  try {
14
14
  // Kalshi API expects uppercase tickers
15
15
  // Handle virtual "-NO" suffix by stripping it (fetching the underlying market history)
16
- const cleanedId = id.replace(/-NO$/, '');
16
+ const cleanedId = id.replace(/-NO$/, "");
17
17
  const normalizedId = cleanedId.toUpperCase();
18
18
  const interval = (0, utils_1.mapIntervalToKalshi)(params.resolution);
19
19
  // Heuristic for series_ticker
20
- const parts = normalizedId.split('-');
20
+ const parts = normalizedId.split("-");
21
21
  if (parts.length < 2) {
22
22
  throw new Error(`Invalid Kalshi Ticker format: "${id}". Expected format like "FED-25JAN29-B4.75".`);
23
23
  }
24
- const seriesTicker = parts.slice(0, -1).join('-');
24
+ const seriesTicker = parts.slice(0, -1).join("-");
25
25
  const now = Math.floor(Date.now() / 1000);
26
- let startTs = now - (24 * 60 * 60);
26
+ let startTs = now - 24 * 60 * 60;
27
27
  let endTs = now;
28
28
  // Helper to handle string dates (from JSON)
29
29
  // IMPORTANT: Python sends naive datetimes as ISO strings without 'Z' suffix.
30
30
  // We must treat these as UTC, not local time.
31
31
  const ensureDate = (d) => {
32
- if (typeof d === 'string') {
32
+ if (typeof d === "string") {
33
33
  // If string doesn't end with 'Z' and doesn't have timezone offset, append 'Z'
34
- if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/)) {
35
- return new Date(d + 'Z');
34
+ if (!d.endsWith("Z") && !d.match(/[+-]\d{2}:\d{2}$/)) {
35
+ return new Date(d + "Z");
36
36
  }
37
37
  return new Date(d);
38
38
  }
@@ -46,10 +46,10 @@ async function fetchOHLCV(id, params, callApi) {
46
46
  if (pEnd) {
47
47
  endTs = Math.floor(pEnd.getTime() / 1000);
48
48
  if (!pStart) {
49
- startTs = endTs - (24 * 60 * 60);
49
+ startTs = endTs - 24 * 60 * 60;
50
50
  }
51
51
  }
52
- const data = await callApi('GetMarketCandlesticks', {
52
+ const data = await callApi("GetMarketCandlesticks", {
53
53
  series_ticker: seriesTicker,
54
54
  ticker: normalizedId,
55
55
  period_interval: interval,
@@ -68,18 +68,21 @@ async function fetchOHLCV(id, params, callApi) {
68
68
  const getVal = (field) => {
69
69
  if (p[field] !== null && p[field] !== undefined)
70
70
  return p[field];
71
- if (ask[field] !== null && bid[field] !== null && ask[field] !== undefined && bid[field] !== undefined) {
71
+ if (ask[field] !== null &&
72
+ bid[field] !== null &&
73
+ ask[field] !== undefined &&
74
+ bid[field] !== undefined) {
72
75
  return (ask[field] + bid[field]) / 2;
73
76
  }
74
77
  return p.previous || 0;
75
78
  };
76
79
  return {
77
80
  timestamp: c.end_period_ts * 1000,
78
- open: getVal('open') / 100,
79
- high: getVal('high') / 100,
80
- low: getVal('low') / 100,
81
- close: getVal('close') / 100,
82
- volume: c.volume || 0
81
+ open: getVal("open") / 100,
82
+ high: getVal("high") / 100,
83
+ low: getVal("low") / 100,
84
+ close: getVal("close") / 100,
85
+ volume: c.volume || 0,
83
86
  };
84
87
  });
85
88
  if (params.limit && mappedCandles.length > params.limit) {
@@ -0,0 +1,2 @@
1
+ import { OrderBook } from "../../types";
2
+ export declare function fetchOrderBook(baseUrl: string, id: string): Promise<OrderBook>;