pmxt-core 2.20.0 → 2.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/exchanges/baozi/fetcher.d.ts +40 -0
  2. package/dist/exchanges/baozi/fetcher.js +155 -0
  3. package/dist/exchanges/baozi/index.d.ts +2 -0
  4. package/dist/exchanges/baozi/index.js +60 -131
  5. package/dist/exchanges/baozi/normalizer.d.ts +14 -0
  6. package/dist/exchanges/baozi/normalizer.js +208 -0
  7. package/dist/exchanges/interfaces.d.ts +28 -0
  8. package/dist/exchanges/interfaces.js +2 -0
  9. package/dist/exchanges/kalshi/api.d.ts +1 -1
  10. package/dist/exchanges/kalshi/api.js +1 -1
  11. package/dist/exchanges/kalshi/fetcher.d.ts +126 -0
  12. package/dist/exchanges/kalshi/fetcher.js +313 -0
  13. package/dist/exchanges/kalshi/index.d.ts +6 -6
  14. package/dist/exchanges/kalshi/index.js +119 -202
  15. package/dist/exchanges/kalshi/normalizer.d.ts +25 -0
  16. package/dist/exchanges/kalshi/normalizer.js +294 -0
  17. package/dist/exchanges/limitless/api.d.ts +1 -1
  18. package/dist/exchanges/limitless/api.js +1 -1
  19. package/dist/exchanges/limitless/fetcher.d.ts +81 -0
  20. package/dist/exchanges/limitless/fetcher.js +238 -0
  21. package/dist/exchanges/limitless/index.d.ts +6 -9
  22. package/dist/exchanges/limitless/index.js +81 -79
  23. package/dist/exchanges/limitless/normalizer.d.ts +14 -0
  24. package/dist/exchanges/limitless/normalizer.js +117 -0
  25. package/dist/exchanges/limitless/websocket.d.ts +3 -0
  26. package/dist/exchanges/limitless/websocket.js +5 -4
  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 +73 -0
  30. package/dist/exchanges/myriad/fetcher.js +217 -0
  31. package/dist/exchanges/myriad/index.d.ts +2 -0
  32. package/dist/exchanges/myriad/index.js +40 -97
  33. package/dist/exchanges/myriad/normalizer.d.ts +14 -0
  34. package/dist/exchanges/myriad/normalizer.js +167 -0
  35. package/dist/exchanges/myriad/websocket.d.ts +3 -1
  36. package/dist/exchanges/myriad/websocket.js +4 -3
  37. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  38. package/dist/exchanges/polymarket/api-clob.js +1 -1
  39. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  40. package/dist/exchanges/polymarket/api-data.js +1 -1
  41. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  42. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  43. package/dist/exchanges/polymarket/fetcher.d.ts +99 -0
  44. package/dist/exchanges/polymarket/fetcher.js +335 -0
  45. package/dist/exchanges/polymarket/index.d.ts +2 -0
  46. package/dist/exchanges/polymarket/index.js +80 -66
  47. package/dist/exchanges/polymarket/normalizer.d.ts +18 -0
  48. package/dist/exchanges/polymarket/normalizer.js +126 -0
  49. package/dist/exchanges/probable/api.d.ts +1 -1
  50. package/dist/exchanges/probable/api.js +1 -1
  51. package/dist/exchanges/probable/fetcher.d.ts +106 -0
  52. package/dist/exchanges/probable/fetcher.js +357 -0
  53. package/dist/exchanges/probable/index.d.ts +3 -1
  54. package/dist/exchanges/probable/index.js +73 -105
  55. package/dist/exchanges/probable/normalizer.d.ts +14 -0
  56. package/dist/exchanges/probable/normalizer.js +109 -0
  57. package/dist/utils/error-mapper.d.ts +8 -0
  58. package/dist/utils/error-mapper.js +58 -26
  59. package/package.json +3 -3
  60. package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
  61. package/dist/exchanges/baozi/fetchEvents.js +0 -39
  62. package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
  63. package/dist/exchanges/baozi/fetchMarkets.js +0 -160
  64. package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
  65. package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
  66. package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
  67. package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
  68. package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
  69. package/dist/exchanges/baozi/fetchTrades.js +0 -10
  70. package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
  71. package/dist/exchanges/kalshi/fetchEvents.js +0 -196
  72. package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
  73. package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
  74. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
  75. package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
  76. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
  77. package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
  78. package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
  79. package/dist/exchanges/kalshi/fetchTrades.js +0 -33
  80. package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
  81. package/dist/exchanges/limitless/fetchEvents.js +0 -173
  82. package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
  83. package/dist/exchanges/limitless/fetchMarkets.js +0 -152
  84. package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
  85. package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
  86. package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
  87. package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
  88. package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
  89. package/dist/exchanges/limitless/fetchTrades.js +0 -27
  90. package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
  91. package/dist/exchanges/myriad/fetchEvents.js +0 -48
  92. package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
  93. package/dist/exchanges/myriad/fetchMarkets.js +0 -102
  94. package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
  95. package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
  96. package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
  97. package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
  98. package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
  99. package/dist/exchanges/polymarket/fetchEvents.js +0 -135
  100. package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
  101. package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
  102. package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
  103. package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
  104. package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
  105. package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
  106. package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
  107. package/dist/exchanges/polymarket/fetchTrades.js +0 -43
  108. package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
  109. package/dist/exchanges/probable/fetchEvents.js +0 -151
  110. package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
  111. package/dist/exchanges/probable/fetchMarkets.js +0 -239
  112. package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
  113. package/dist/exchanges/probable/fetchTrades.js +0 -40
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaoziNormalizer = void 0;
4
+ const utils_1 = require("./utils");
5
+ const fetcher_1 = require("./fetcher");
6
+ // ---------------------------------------------------------------------------
7
+ // Normalizer -- pure data mapping, no I/O
8
+ // ---------------------------------------------------------------------------
9
+ class BaoziNormalizer {
10
+ normalizeMarket(raw) {
11
+ if (!raw)
12
+ return null;
13
+ if ((0, fetcher_1.isRawBooleanMarket)(raw)) {
14
+ return (0, utils_1.mapBooleanToUnified)(raw.parsed, raw.pubkey);
15
+ }
16
+ if ((0, fetcher_1.isRawRaceMarket)(raw)) {
17
+ return (0, utils_1.mapRaceToUnified)(raw.parsed, raw.pubkey);
18
+ }
19
+ return null;
20
+ }
21
+ normalizeEvent(raw) {
22
+ const market = this.normalizeMarket(raw);
23
+ if (!market)
24
+ return null;
25
+ return {
26
+ id: market.marketId,
27
+ title: market.title,
28
+ description: market.description,
29
+ slug: market.marketId,
30
+ markets: [market],
31
+ volume24h: market.volume24h,
32
+ volume: market.volume,
33
+ url: market.url,
34
+ image: market.image,
35
+ category: market.category,
36
+ tags: market.tags,
37
+ };
38
+ }
39
+ normalizeMarkets(rawMarkets, params) {
40
+ const markets = [];
41
+ for (const raw of rawMarkets) {
42
+ const m = this.normalizeMarket(raw);
43
+ if (m)
44
+ markets.push(m);
45
+ }
46
+ return applyFilters(markets, params);
47
+ }
48
+ normalizeEvents(rawMarkets, params) {
49
+ const markets = this.normalizeMarkets(rawMarkets, params);
50
+ return markets.map(m => ({
51
+ id: m.marketId,
52
+ title: m.title,
53
+ description: m.description,
54
+ slug: m.marketId,
55
+ markets: [m],
56
+ volume24h: m.volume24h,
57
+ volume: m.volume,
58
+ url: m.url,
59
+ image: m.image,
60
+ category: m.category,
61
+ tags: m.tags,
62
+ }));
63
+ }
64
+ normalizeOrderBook(raw, outcomeId) {
65
+ if (!raw) {
66
+ throw new Error(`Market not found for outcome: ${outcomeId}`);
67
+ }
68
+ const market = this.normalizeMarket(raw);
69
+ if (!market) {
70
+ throw new Error(`Could not parse market for outcome: ${outcomeId}`);
71
+ }
72
+ const outcome = market.outcomes.find(o => o.outcomeId === outcomeId);
73
+ const price = outcome?.price ?? 0.5;
74
+ const totalLiquidity = market.liquidity;
75
+ return {
76
+ bids: [{ price, size: totalLiquidity }],
77
+ asks: [{ price, size: totalLiquidity }],
78
+ timestamp: Date.now(),
79
+ };
80
+ }
81
+ normalizeBooleanPositions(positions, marketLookup) {
82
+ const result = [];
83
+ for (const { parsed: pos } of positions) {
84
+ if (pos.claimed)
85
+ continue;
86
+ const marketPda = (0, utils_1.deriveMarketPda)(pos.marketId);
87
+ const marketPdaStr = marketPda.toString();
88
+ const market = marketLookup.get(marketPdaStr);
89
+ let currentYesPrice = 0;
90
+ let currentNoPrice = 0;
91
+ if (market) {
92
+ currentYesPrice = market.yes?.price ?? 0;
93
+ currentNoPrice = market.no?.price ?? 0;
94
+ }
95
+ const yesSOL = Number(pos.yesAmount) / utils_1.LAMPORTS_PER_SOL;
96
+ const noSOL = Number(pos.noAmount) / utils_1.LAMPORTS_PER_SOL;
97
+ if (yesSOL > 0) {
98
+ result.push({
99
+ marketId: marketPdaStr,
100
+ outcomeId: `${marketPdaStr}-YES`,
101
+ outcomeLabel: 'Yes',
102
+ size: yesSOL,
103
+ entryPrice: 0,
104
+ currentPrice: currentYesPrice,
105
+ unrealizedPnL: 0,
106
+ });
107
+ }
108
+ if (noSOL > 0) {
109
+ result.push({
110
+ marketId: marketPdaStr,
111
+ outcomeId: `${marketPdaStr}-NO`,
112
+ outcomeLabel: 'No',
113
+ size: noSOL,
114
+ entryPrice: 0,
115
+ currentPrice: currentNoPrice,
116
+ unrealizedPnL: 0,
117
+ });
118
+ }
119
+ }
120
+ return result;
121
+ }
122
+ normalizeRacePositions(positions, marketLookup) {
123
+ const result = [];
124
+ for (const { parsed: pos } of positions) {
125
+ if (pos.claimed)
126
+ continue;
127
+ const racePda = (0, utils_1.deriveRaceMarketPda)(pos.marketId);
128
+ const racePdaStr = racePda.toString();
129
+ const market = marketLookup.get(racePdaStr);
130
+ const outcomePrices = market ? market.outcomes.map(o => o.price) : [];
131
+ const outcomeLabels = market ? market.outcomes.map(o => o.label) : [];
132
+ for (let i = 0; i < pos.bets.length; i++) {
133
+ const betSOL = Number(pos.bets[i]) / utils_1.LAMPORTS_PER_SOL;
134
+ if (betSOL <= 0)
135
+ continue;
136
+ result.push({
137
+ marketId: racePdaStr,
138
+ outcomeId: `${racePdaStr}-${i}`,
139
+ outcomeLabel: outcomeLabels[i] || `Outcome ${i}`,
140
+ size: betSOL,
141
+ entryPrice: 0,
142
+ currentPrice: outcomePrices[i] ?? 0,
143
+ unrealizedPnL: 0,
144
+ });
145
+ }
146
+ }
147
+ return result;
148
+ }
149
+ normalizeBalance(raw) {
150
+ const solBalance = raw.lamports / utils_1.LAMPORTS_PER_SOL;
151
+ return [{
152
+ currency: 'SOL',
153
+ total: solBalance,
154
+ available: solBalance,
155
+ locked: 0,
156
+ }];
157
+ }
158
+ }
159
+ exports.BaoziNormalizer = BaoziNormalizer;
160
+ // ---------------------------------------------------------------------------
161
+ // Filtering / sorting (pure, no I/O)
162
+ // ---------------------------------------------------------------------------
163
+ function applyFilters(markets, params) {
164
+ let result = [...markets];
165
+ // Status filter
166
+ const status = params?.status || 'active';
167
+ if (status !== 'all') {
168
+ const now = Date.now();
169
+ if (status === 'active') {
170
+ result = result.filter(m => m.resolutionDate.getTime() > now);
171
+ }
172
+ else {
173
+ result = result.filter(m => m.resolutionDate.getTime() <= now);
174
+ }
175
+ }
176
+ // Text search
177
+ if (params?.query) {
178
+ const lowerQuery = params.query.toLowerCase();
179
+ const searchIn = params.searchIn || 'title';
180
+ result = result.filter(m => {
181
+ const titleMatch = m.title.toLowerCase().includes(lowerQuery);
182
+ const descMatch = (m.description || '').toLowerCase().includes(lowerQuery);
183
+ if (searchIn === 'title')
184
+ return titleMatch;
185
+ if (searchIn === 'description')
186
+ return descMatch;
187
+ return titleMatch || descMatch;
188
+ });
189
+ }
190
+ // Sort
191
+ if (params?.sort === 'volume') {
192
+ result.sort((a, b) => (b.volume || 0) - (a.volume || 0));
193
+ }
194
+ else if (params?.sort === 'liquidity') {
195
+ result.sort((a, b) => b.liquidity - a.liquidity);
196
+ }
197
+ else if (params?.sort === 'newest') {
198
+ result.sort((a, b) => b.resolutionDate.getTime() - a.resolutionDate.getTime());
199
+ }
200
+ else {
201
+ result.sort((a, b) => (b.volume || 0) - (a.volume || 0));
202
+ }
203
+ // Pagination
204
+ const offset = params?.offset || 0;
205
+ const limit = params?.limit || 10000;
206
+ result = result.slice(offset, offset + limit);
207
+ return result;
208
+ }
@@ -0,0 +1,28 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { MarketFilterParams, EventFetchParams, OHLCVParams, TradesParams, MyTradesParams } from '../BaseExchange';
3
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Position, Balance } from '../types';
4
+ export interface FetcherContext {
5
+ readonly http: AxiosInstance;
6
+ callApi(operationId: string, params?: Record<string, any>): Promise<any>;
7
+ getHeaders(): Record<string, string>;
8
+ }
9
+ export interface IExchangeFetcher<TRawMarket = unknown, TRawEvent = unknown> {
10
+ fetchRawMarkets(params?: MarketFilterParams): Promise<TRawMarket[]>;
11
+ fetchRawEvents(params: EventFetchParams): Promise<TRawEvent[]>;
12
+ fetchRawOHLCV?(id: string, params: OHLCVParams): Promise<unknown>;
13
+ fetchRawOrderBook?(id: string): Promise<unknown>;
14
+ fetchRawTrades?(id: string, params: TradesParams): Promise<unknown[]>;
15
+ fetchRawMyTrades?(params: MyTradesParams, walletAddress: string): Promise<unknown[]>;
16
+ fetchRawPositions?(walletAddress: string): Promise<unknown[]>;
17
+ fetchRawBalance?(walletAddress: string): Promise<unknown>;
18
+ }
19
+ export interface IExchangeNormalizer<TRawMarket = unknown, TRawEvent = unknown> {
20
+ normalizeMarket(raw: TRawMarket): UnifiedMarket | null;
21
+ normalizeEvent(raw: TRawEvent): UnifiedEvent | null;
22
+ normalizeOHLCV?(raw: unknown, params: OHLCVParams): PriceCandle[];
23
+ normalizeOrderBook?(raw: unknown, id: string): OrderBook;
24
+ normalizeTrade?(raw: unknown, index: number): Trade;
25
+ normalizeUserTrade?(raw: unknown, index: number): UserTrade;
26
+ normalizePosition?(raw: unknown): Position;
27
+ normalizeBalance?(raw: unknown): Balance[];
28
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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-03-14T16:22:11.385Z
3
+ * Generated at: 2026-03-14T21:28:31.833Z
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-03-14T16:22:11.385Z
6
+ * Generated at: 2026-03-14T21:28:31.833Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.kalshiApiSpec = {
@@ -0,0 +1,126 @@
1
+ import { MarketFilterParams, EventFetchParams, OHLCVParams, TradesParams, MyTradesParams } from '../../BaseExchange';
2
+ import { IExchangeFetcher, FetcherContext } from '../interfaces';
3
+ export interface KalshiRawMarket {
4
+ ticker: string;
5
+ last_price?: number;
6
+ yes_ask?: number;
7
+ yes_bid?: number;
8
+ subtitle?: string;
9
+ yes_sub_title?: string;
10
+ previous_price_dollars?: number;
11
+ last_price_dollars?: number;
12
+ rules_primary?: string;
13
+ rules_secondary?: string;
14
+ expiration_time: string;
15
+ volume_24h?: number;
16
+ volume?: number;
17
+ liquidity?: number;
18
+ open_interest?: number;
19
+ close_time?: string;
20
+ [key: string]: unknown;
21
+ }
22
+ export interface KalshiRawEvent {
23
+ event_ticker: string;
24
+ title: string;
25
+ mututals_description?: string;
26
+ image_url?: string;
27
+ category?: string;
28
+ tags?: string[];
29
+ series_ticker?: string;
30
+ markets?: KalshiRawMarket[];
31
+ [key: string]: unknown;
32
+ }
33
+ export interface KalshiRawCandlestick {
34
+ end_period_ts: number;
35
+ volume?: number;
36
+ price?: {
37
+ open?: number;
38
+ high?: number;
39
+ low?: number;
40
+ close?: number;
41
+ previous?: number;
42
+ };
43
+ yes_ask?: {
44
+ open?: number;
45
+ high?: number;
46
+ low?: number;
47
+ close?: number;
48
+ };
49
+ yes_bid?: {
50
+ open?: number;
51
+ high?: number;
52
+ low?: number;
53
+ close?: number;
54
+ };
55
+ [key: string]: unknown;
56
+ }
57
+ export interface KalshiRawOrderBookFp {
58
+ yes_dollars?: string[][];
59
+ no_dollars?: string[][];
60
+ }
61
+ export interface KalshiRawTrade {
62
+ trade_id: string;
63
+ created_time: string;
64
+ yes_price: number;
65
+ count: number;
66
+ taker_side: string;
67
+ [key: string]: unknown;
68
+ }
69
+ export interface KalshiRawFill {
70
+ fill_id: string;
71
+ created_time: string;
72
+ yes_price: number;
73
+ count: number;
74
+ side: string;
75
+ order_id: string;
76
+ [key: string]: unknown;
77
+ }
78
+ export interface KalshiRawOrder {
79
+ order_id: string;
80
+ ticker: string;
81
+ side: string;
82
+ type?: string;
83
+ yes_price?: number;
84
+ count: number;
85
+ remaining_count?: number;
86
+ status?: string;
87
+ created_time: string;
88
+ [key: string]: unknown;
89
+ }
90
+ export interface KalshiRawPosition {
91
+ ticker: string;
92
+ position: number;
93
+ total_cost: number;
94
+ market_price?: number;
95
+ market_exposure?: number;
96
+ realized_pnl?: number;
97
+ [key: string]: unknown;
98
+ }
99
+ export declare class KalshiFetcher implements IExchangeFetcher<KalshiRawEvent, KalshiRawEvent> {
100
+ private readonly ctx;
101
+ private cachedEvents;
102
+ private cachedSeriesMap;
103
+ private lastCacheTime;
104
+ constructor(ctx: FetcherContext);
105
+ resetCache(): void;
106
+ fetchRawMarkets(params?: MarketFilterParams): Promise<KalshiRawEvent[]>;
107
+ fetchRawEvents(params: EventFetchParams): Promise<KalshiRawEvent[]>;
108
+ fetchRawOHLCV(id: string, params: OHLCVParams): Promise<KalshiRawCandlestick[]>;
109
+ fetchRawOrderBook(id: string): Promise<{
110
+ orderbook_fp: KalshiRawOrderBookFp;
111
+ }>;
112
+ fetchRawTrades(id: string, params: TradesParams): Promise<KalshiRawTrade[]>;
113
+ fetchRawMyTrades(params: MyTradesParams): Promise<KalshiRawFill[]>;
114
+ fetchRawPositions(): Promise<KalshiRawPosition[]>;
115
+ fetchRawBalance(): Promise<{
116
+ balance: number;
117
+ portfolio_value: number;
118
+ }>;
119
+ fetchRawOrders(queryParams: Record<string, any>): Promise<KalshiRawOrder[]>;
120
+ fetchRawHistoricalOrders(queryParams: Record<string, any>): Promise<KalshiRawOrder[]>;
121
+ fetchRawSeriesMap(): Promise<Map<string, string[]>>;
122
+ fetchRawEventByTicker(eventTicker: string): Promise<KalshiRawEvent[]>;
123
+ private fetchRawEventsDefault;
124
+ private fetchActiveEvents;
125
+ private fetchAllWithStatus;
126
+ }
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KalshiFetcher = void 0;
4
+ const errors_1 = require("./errors");
5
+ const validation_1 = require("../../utils/validation");
6
+ const utils_1 = require("./utils");
7
+ // ----------------------------------------------------------------------------
8
+ // Fetcher
9
+ // ----------------------------------------------------------------------------
10
+ const BATCH_SIZE = 200;
11
+ const MAX_PAGES = 1000;
12
+ const CACHE_TTL = 5 * 60 * 1000;
13
+ class KalshiFetcher {
14
+ ctx;
15
+ // Instance-level cache (moved from module-level)
16
+ cachedEvents = null;
17
+ cachedSeriesMap = null;
18
+ lastCacheTime = 0;
19
+ constructor(ctx) {
20
+ this.ctx = ctx;
21
+ }
22
+ resetCache() {
23
+ this.cachedEvents = null;
24
+ this.cachedSeriesMap = null;
25
+ this.lastCacheTime = 0;
26
+ }
27
+ // -- Markets (returns raw events containing nested markets) ----------------
28
+ async fetchRawMarkets(params) {
29
+ try {
30
+ if (params?.marketId) {
31
+ return this.fetchRawEventByTicker(params.marketId);
32
+ }
33
+ if (params?.slug) {
34
+ return this.fetchRawEventByTicker(params.slug);
35
+ }
36
+ if (params?.outcomeId) {
37
+ const ticker = params.outcomeId.replace(/-NO$/, '');
38
+ return this.fetchRawEventByTicker(ticker);
39
+ }
40
+ if (params?.eventId) {
41
+ return this.fetchRawEventByTicker(params.eventId);
42
+ }
43
+ // Default + query cases: fetch all events, caller does filtering
44
+ return this.fetchRawEventsDefault(params);
45
+ }
46
+ catch (error) {
47
+ throw errors_1.kalshiErrorMapper.mapError(error);
48
+ }
49
+ }
50
+ // -- Events ---------------------------------------------------------------
51
+ async fetchRawEvents(params) {
52
+ try {
53
+ if (params.eventId) {
54
+ return this.fetchRawEventByTicker(params.eventId);
55
+ }
56
+ if (params.slug) {
57
+ return this.fetchRawEventByTicker(params.slug);
58
+ }
59
+ const status = params?.status || 'active';
60
+ if (status === 'all') {
61
+ const [openEvents, closedEvents, settledEvents] = await Promise.all([
62
+ this.fetchAllWithStatus('open'),
63
+ this.fetchAllWithStatus('closed'),
64
+ this.fetchAllWithStatus('settled'),
65
+ ]);
66
+ return [...openEvents, ...closedEvents, ...settledEvents];
67
+ }
68
+ else if (status === 'closed' || status === 'inactive') {
69
+ const [closedEvents, settledEvents] = await Promise.all([
70
+ this.fetchAllWithStatus('closed'),
71
+ this.fetchAllWithStatus('settled'),
72
+ ]);
73
+ return [...closedEvents, ...settledEvents];
74
+ }
75
+ return this.fetchAllWithStatus('open');
76
+ }
77
+ catch (error) {
78
+ throw errors_1.kalshiErrorMapper.mapError(error);
79
+ }
80
+ }
81
+ // -- OHLCV ----------------------------------------------------------------
82
+ async fetchRawOHLCV(id, params) {
83
+ (0, validation_1.validateIdFormat)(id, 'OHLCV');
84
+ if (!params.resolution) {
85
+ throw new Error('fetchOHLCV requires a resolution parameter.');
86
+ }
87
+ try {
88
+ const cleanedId = id.replace(/-NO$/, '');
89
+ const normalizedId = cleanedId.toUpperCase();
90
+ const interval = (0, utils_1.mapIntervalToKalshi)(params.resolution);
91
+ const parts = normalizedId.split('-');
92
+ if (parts.length < 2) {
93
+ throw new Error(`Invalid Kalshi Ticker format: "${id}". Expected format like "FED-25JAN29-B4.75".`);
94
+ }
95
+ const seriesTicker = parts.slice(0, -1).join('-');
96
+ const now = Math.floor(Date.now() / 1000);
97
+ let startTs = now - 24 * 60 * 60;
98
+ let endTs = now;
99
+ const ensureDate = (d) => {
100
+ if (typeof d === 'string') {
101
+ if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/)) {
102
+ return new Date(d + 'Z');
103
+ }
104
+ return new Date(d);
105
+ }
106
+ return d;
107
+ };
108
+ const pStart = params.start ? ensureDate(params.start) : undefined;
109
+ const pEnd = params.end ? ensureDate(params.end) : undefined;
110
+ if (pStart)
111
+ startTs = Math.floor(pStart.getTime() / 1000);
112
+ if (pEnd) {
113
+ endTs = Math.floor(pEnd.getTime() / 1000);
114
+ if (!pStart)
115
+ startTs = endTs - 24 * 60 * 60;
116
+ }
117
+ const data = await this.ctx.callApi('GetMarketCandlesticks', {
118
+ series_ticker: seriesTicker,
119
+ ticker: normalizedId,
120
+ period_interval: interval,
121
+ start_ts: startTs,
122
+ end_ts: endTs,
123
+ });
124
+ return data.candlesticks || [];
125
+ }
126
+ catch (error) {
127
+ throw errors_1.kalshiErrorMapper.mapError(error);
128
+ }
129
+ }
130
+ // -- OrderBook -------------------------------------------------------------
131
+ async fetchRawOrderBook(id) {
132
+ (0, validation_1.validateIdFormat)(id, 'OrderBook');
133
+ const ticker = id.replace(/-NO$/, '');
134
+ const data = await this.ctx.callApi('GetMarketOrderbook', { ticker });
135
+ return data;
136
+ }
137
+ // -- Trades ----------------------------------------------------------------
138
+ async fetchRawTrades(id, params) {
139
+ const ticker = id.replace(/-NO$/, '');
140
+ const data = await this.ctx.callApi('GetTrades', {
141
+ ticker,
142
+ limit: params.limit || 100,
143
+ });
144
+ return data.trades || [];
145
+ }
146
+ // -- User data -------------------------------------------------------------
147
+ async fetchRawMyTrades(params) {
148
+ const queryParams = {};
149
+ if (params?.outcomeId || params?.marketId) {
150
+ queryParams.ticker = (params.outcomeId || params.marketId).replace(/-NO$/, '');
151
+ }
152
+ if (params?.since)
153
+ queryParams.min_ts = Math.floor(params.since.getTime() / 1000);
154
+ if (params?.until)
155
+ queryParams.max_ts = Math.floor(params.until.getTime() / 1000);
156
+ if (params?.limit)
157
+ queryParams.limit = params.limit;
158
+ if (params?.cursor)
159
+ queryParams.cursor = params.cursor;
160
+ const data = await this.ctx.callApi('GetFills', queryParams);
161
+ return data.fills || [];
162
+ }
163
+ async fetchRawPositions() {
164
+ const data = await this.ctx.callApi('GetPositions');
165
+ return data.market_positions || [];
166
+ }
167
+ async fetchRawBalance() {
168
+ return this.ctx.callApi('GetBalance');
169
+ }
170
+ async fetchRawOrders(queryParams) {
171
+ const data = await this.ctx.callApi('GetOrders', queryParams);
172
+ return data.orders || [];
173
+ }
174
+ async fetchRawHistoricalOrders(queryParams) {
175
+ const data = await this.ctx.callApi('GetHistoricalOrders', queryParams);
176
+ return data.orders || [];
177
+ }
178
+ async fetchRawSeriesMap() {
179
+ try {
180
+ const data = await this.ctx.callApi('GetSeriesList');
181
+ const seriesList = data.series || [];
182
+ const map = new Map();
183
+ for (const series of seriesList) {
184
+ if (series.tags && series.tags.length > 0) {
185
+ map.set(series.ticker, series.tags);
186
+ }
187
+ }
188
+ return map;
189
+ }
190
+ catch (e) {
191
+ throw errors_1.kalshiErrorMapper.mapError(e);
192
+ }
193
+ }
194
+ // -- Private helpers -------------------------------------------------------
195
+ async fetchRawEventByTicker(eventTicker) {
196
+ const normalizedTicker = eventTicker.toUpperCase();
197
+ const data = await this.ctx.callApi('GetEvent', {
198
+ event_ticker: normalizedTicker,
199
+ with_nested_markets: true,
200
+ });
201
+ const event = data.event;
202
+ if (!event)
203
+ return [];
204
+ // Enrich with series tags
205
+ if (event.series_ticker) {
206
+ try {
207
+ const seriesData = await this.ctx.callApi('GetSeries', {
208
+ series_ticker: event.series_ticker,
209
+ });
210
+ const series = seriesData.series;
211
+ if (series?.tags?.length > 0 && (!event.tags || event.tags.length === 0)) {
212
+ event.tags = series.tags;
213
+ }
214
+ }
215
+ catch {
216
+ // Non-critical
217
+ }
218
+ }
219
+ return [event];
220
+ }
221
+ async fetchRawEventsDefault(params) {
222
+ const limit = params?.limit || 250000;
223
+ const now = Date.now();
224
+ const status = params?.status || 'active';
225
+ let apiStatus = 'open';
226
+ if (status === 'closed' || status === 'inactive')
227
+ apiStatus = 'closed';
228
+ const useCache = status === 'active' || !params?.status;
229
+ if (useCache && this.cachedEvents && this.cachedSeriesMap && now - this.lastCacheTime < CACHE_TTL) {
230
+ return this.cachedEvents;
231
+ }
232
+ const isSorted = params?.sort && (params.sort === 'volume' || params.sort === 'liquidity');
233
+ const fetchLimit = isSorted ? 1000 : limit;
234
+ const [allEvents, fetchedSeriesMap] = await Promise.all([
235
+ this.fetchActiveEvents(fetchLimit, apiStatus),
236
+ this.fetchRawSeriesMap(),
237
+ ]);
238
+ // Enrich events with series tags
239
+ for (const event of allEvents) {
240
+ if (event.series_ticker && fetchedSeriesMap.has(event.series_ticker)) {
241
+ if (!event.tags || event.tags.length === 0) {
242
+ event.tags = fetchedSeriesMap.get(event.series_ticker);
243
+ }
244
+ }
245
+ }
246
+ if (fetchLimit >= 1000 && useCache) {
247
+ this.cachedEvents = allEvents;
248
+ this.cachedSeriesMap = fetchedSeriesMap;
249
+ this.lastCacheTime = now;
250
+ }
251
+ return allEvents;
252
+ }
253
+ async fetchActiveEvents(targetMarketCount, status = 'open') {
254
+ let allEvents = [];
255
+ let totalMarketCount = 0;
256
+ let cursor = null;
257
+ let page = 0;
258
+ do {
259
+ try {
260
+ const queryParams = {
261
+ limit: BATCH_SIZE,
262
+ with_nested_markets: true,
263
+ status,
264
+ };
265
+ if (cursor)
266
+ queryParams.cursor = cursor;
267
+ const data = await this.ctx.callApi('GetEvents', queryParams);
268
+ const events = data.events || [];
269
+ if (events.length === 0)
270
+ break;
271
+ allEvents = allEvents.concat(events);
272
+ if (targetMarketCount) {
273
+ for (const event of events) {
274
+ totalMarketCount += (event.markets || []).length;
275
+ }
276
+ if (totalMarketCount >= targetMarketCount * 1.5)
277
+ break;
278
+ }
279
+ cursor = data.cursor;
280
+ page++;
281
+ if (!targetMarketCount && page >= 10)
282
+ break;
283
+ }
284
+ catch (e) {
285
+ throw errors_1.kalshiErrorMapper.mapError(e);
286
+ }
287
+ } while (cursor && page < MAX_PAGES);
288
+ return allEvents;
289
+ }
290
+ async fetchAllWithStatus(apiStatus) {
291
+ let allEvents = [];
292
+ let cursor = null;
293
+ let page = 0;
294
+ do {
295
+ const queryParams = {
296
+ limit: BATCH_SIZE,
297
+ with_nested_markets: true,
298
+ status: apiStatus,
299
+ };
300
+ if (cursor)
301
+ queryParams.cursor = cursor;
302
+ const data = await this.ctx.callApi('GetEvents', queryParams);
303
+ const events = data.events || [];
304
+ if (events.length === 0)
305
+ break;
306
+ allEvents = allEvents.concat(events);
307
+ cursor = data.cursor;
308
+ page++;
309
+ } while (cursor && page < MAX_PAGES);
310
+ return allEvents;
311
+ }
312
+ }
313
+ exports.KalshiFetcher = KalshiFetcher;