@newyorkcompute/kalshi-core 0.2.0 → 0.3.0

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 (43) hide show
  1. package/dist/config.d.ts +61 -6
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +56 -5
  4. package/dist/config.js.map +1 -1
  5. package/dist/config.test.d.ts +2 -0
  6. package/dist/config.test.d.ts.map +1 -0
  7. package/dist/config.test.js +94 -0
  8. package/dist/config.test.js.map +1 -0
  9. package/dist/format.d.ts +71 -2
  10. package/dist/format.d.ts.map +1 -1
  11. package/dist/format.js +71 -2
  12. package/dist/format.js.map +1 -1
  13. package/dist/format.test.js +42 -1
  14. package/dist/format.test.js.map +1 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/websocket/auth.d.ts +28 -0
  20. package/dist/websocket/auth.d.ts.map +1 -0
  21. package/dist/websocket/auth.js +55 -0
  22. package/dist/websocket/auth.js.map +1 -0
  23. package/dist/websocket/auth.test.d.ts +2 -0
  24. package/dist/websocket/auth.test.d.ts.map +1 -0
  25. package/dist/websocket/auth.test.js +56 -0
  26. package/dist/websocket/auth.test.js.map +1 -0
  27. package/dist/websocket/client.d.ts +95 -0
  28. package/dist/websocket/client.d.ts.map +1 -0
  29. package/dist/websocket/client.js +352 -0
  30. package/dist/websocket/client.js.map +1 -0
  31. package/dist/websocket/index.d.ts +9 -0
  32. package/dist/websocket/index.d.ts.map +1 -0
  33. package/dist/websocket/index.js +9 -0
  34. package/dist/websocket/index.js.map +1 -0
  35. package/dist/websocket/types.d.ts +160 -0
  36. package/dist/websocket/types.d.ts.map +1 -0
  37. package/dist/websocket/types.js +12 -0
  38. package/dist/websocket/types.js.map +1 -0
  39. package/dist/websocket/types.test.d.ts +2 -0
  40. package/dist/websocket/types.test.d.ts.map +1 -0
  41. package/dist/websocket/types.test.js +17 -0
  42. package/dist/websocket/types.test.js.map +1 -0
  43. package/package.json +8 -4
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Kalshi WebSocket Client
3
+ *
4
+ * Provides real-time market data streaming from Kalshi.
5
+ * Features:
6
+ * - Automatic reconnection with exponential backoff
7
+ * - Subscription management
8
+ * - Event-based message handling
9
+ * - Connection health monitoring
10
+ */
11
+ import WebSocket from 'ws';
12
+ import { WS_ENDPOINTS, } from './types.js';
13
+ import { generateWsAuthHeaders } from './auth.js';
14
+ /** Default configuration values */
15
+ const DEFAULTS = {
16
+ autoReconnect: true,
17
+ reconnectDelay: 1000,
18
+ maxReconnectAttempts: 10,
19
+ pingInterval: 30000, // 30 seconds
20
+ pongTimeout: 10000, // 10 seconds
21
+ };
22
+ /**
23
+ * Kalshi WebSocket Client
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const client = new KalshiWsClient({
28
+ * apiKeyId: 'your-api-key',
29
+ * privateKey: 'your-private-key',
30
+ * });
31
+ *
32
+ * client.on('ticker', (data) => {
33
+ * console.log('Price update:', data.market_ticker, data.yes_bid);
34
+ * });
35
+ *
36
+ * await client.connect();
37
+ * client.subscribe(['ticker'], ['KXBTC-25JAN03']);
38
+ * ```
39
+ */
40
+ export class KalshiWsClient {
41
+ config;
42
+ ws = null;
43
+ handlers = {};
44
+ state = 'disconnected';
45
+ reconnectAttempts = 0;
46
+ commandId = 0;
47
+ pingTimer = null;
48
+ pongTimer = null;
49
+ subscriptions = {
50
+ orderbook_delta: new Set(),
51
+ ticker: new Set(),
52
+ trade: new Set(),
53
+ fill: false,
54
+ };
55
+ constructor(config) {
56
+ this.config = {
57
+ ...config,
58
+ demo: config.demo ?? false,
59
+ autoReconnect: config.autoReconnect ?? DEFAULTS.autoReconnect,
60
+ reconnectDelay: config.reconnectDelay ?? DEFAULTS.reconnectDelay,
61
+ maxReconnectAttempts: config.maxReconnectAttempts ?? DEFAULTS.maxReconnectAttempts,
62
+ };
63
+ }
64
+ // ===========================================================================
65
+ // Public API
66
+ // ===========================================================================
67
+ /**
68
+ * Get current connection state
69
+ */
70
+ get connectionState() {
71
+ return this.state;
72
+ }
73
+ /**
74
+ * Check if connected
75
+ */
76
+ get isConnected() {
77
+ return this.state === 'connected';
78
+ }
79
+ /**
80
+ * Register event handlers
81
+ */
82
+ on(event, handler) {
83
+ this.handlers[event] = handler;
84
+ }
85
+ /**
86
+ * Connect to WebSocket server
87
+ */
88
+ async connect() {
89
+ if (this.state === 'connected' || this.state === 'connecting') {
90
+ return;
91
+ }
92
+ this.state = 'connecting';
93
+ return new Promise((resolve, reject) => {
94
+ const endpoint = this.config.demo
95
+ ? WS_ENDPOINTS.demo
96
+ : WS_ENDPOINTS.production;
97
+ const headers = generateWsAuthHeaders(this.config.apiKeyId, this.config.privateKey);
98
+ this.ws = new WebSocket(endpoint, { headers });
99
+ this.ws.on('open', () => {
100
+ this.state = 'connected';
101
+ this.reconnectAttempts = 0;
102
+ this.startPingPong();
103
+ this.handlers.onConnect?.();
104
+ this.resubscribeAll();
105
+ resolve();
106
+ });
107
+ this.ws.on('message', (data) => {
108
+ this.handleMessage(data);
109
+ });
110
+ this.ws.on('close', (code, reason) => {
111
+ this.handleClose(code, reason.toString());
112
+ });
113
+ this.ws.on('error', (error) => {
114
+ this.handlers.onError?.(error);
115
+ if (this.state === 'connecting') {
116
+ reject(error);
117
+ }
118
+ });
119
+ this.ws.on('pong', () => {
120
+ this.clearPongTimeout();
121
+ });
122
+ });
123
+ }
124
+ /**
125
+ * Disconnect from WebSocket server
126
+ */
127
+ disconnect() {
128
+ this.state = 'disconnected';
129
+ this.stopPingPong();
130
+ if (this.ws) {
131
+ this.ws.close(1000, 'Client disconnect');
132
+ this.ws = null;
133
+ }
134
+ }
135
+ /**
136
+ * Subscribe to channels for specific market tickers
137
+ *
138
+ * @param channels - Channels to subscribe to
139
+ * @param marketTickers - Market tickers (not needed for 'fill' channel)
140
+ */
141
+ subscribe(channels, marketTickers) {
142
+ if (!this.ws || this.state !== 'connected') {
143
+ // Store for later subscription when connected
144
+ this.updateLocalSubscriptions(channels, marketTickers, 'add');
145
+ return;
146
+ }
147
+ const command = {
148
+ id: ++this.commandId,
149
+ cmd: 'subscribe',
150
+ params: {
151
+ channels,
152
+ ...(marketTickers && { market_tickers: marketTickers }),
153
+ },
154
+ };
155
+ this.send(command);
156
+ this.updateLocalSubscriptions(channels, marketTickers, 'add');
157
+ }
158
+ /**
159
+ * Unsubscribe from channels
160
+ */
161
+ unsubscribe(channels, marketTickers) {
162
+ if (!this.ws || this.state !== 'connected') {
163
+ this.updateLocalSubscriptions(channels, marketTickers, 'remove');
164
+ return;
165
+ }
166
+ const command = {
167
+ id: ++this.commandId,
168
+ cmd: 'unsubscribe',
169
+ params: {
170
+ channels,
171
+ ...(marketTickers && { market_tickers: marketTickers }),
172
+ },
173
+ };
174
+ this.send(command);
175
+ this.updateLocalSubscriptions(channels, marketTickers, 'remove');
176
+ }
177
+ /**
178
+ * Add markets to existing subscription
179
+ */
180
+ addMarkets(channels, marketTickers) {
181
+ if (!this.ws || this.state !== 'connected') {
182
+ this.updateLocalSubscriptions(channels, marketTickers, 'add');
183
+ return;
184
+ }
185
+ const command = {
186
+ id: ++this.commandId,
187
+ cmd: 'update_subscription',
188
+ params: {
189
+ channels,
190
+ market_tickers: marketTickers,
191
+ action: 'add_markets',
192
+ },
193
+ };
194
+ this.send(command);
195
+ this.updateLocalSubscriptions(channels, marketTickers, 'add');
196
+ }
197
+ /**
198
+ * Remove markets from existing subscription
199
+ */
200
+ removeMarkets(channels, marketTickers) {
201
+ if (!this.ws || this.state !== 'connected') {
202
+ this.updateLocalSubscriptions(channels, marketTickers, 'remove');
203
+ return;
204
+ }
205
+ const command = {
206
+ id: ++this.commandId,
207
+ cmd: 'update_subscription',
208
+ params: {
209
+ channels,
210
+ market_tickers: marketTickers,
211
+ action: 'remove_markets',
212
+ },
213
+ };
214
+ this.send(command);
215
+ this.updateLocalSubscriptions(channels, marketTickers, 'remove');
216
+ }
217
+ /**
218
+ * Get currently subscribed tickers for a channel
219
+ */
220
+ getSubscribedTickers(channel) {
221
+ if (channel === 'fill')
222
+ return [];
223
+ return Array.from(this.subscriptions[channel]);
224
+ }
225
+ // ===========================================================================
226
+ // Private Methods
227
+ // ===========================================================================
228
+ send(data) {
229
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
230
+ this.ws.send(JSON.stringify(data));
231
+ }
232
+ }
233
+ handleMessage(data) {
234
+ try {
235
+ const message = JSON.parse(data.toString());
236
+ switch (message.type) {
237
+ case 'subscribed':
238
+ this.handlers.onSubscribed?.(message.msg.channel, message.msg.market_tickers);
239
+ break;
240
+ case 'error':
241
+ this.handlers.onError?.(new Error(`WebSocket error ${message.msg.code}: ${message.msg.message}`));
242
+ break;
243
+ case 'orderbook_delta':
244
+ this.handlers.onOrderbookDelta?.(message.msg);
245
+ break;
246
+ case 'ticker':
247
+ this.handlers.onTicker?.(message.msg);
248
+ break;
249
+ case 'trade':
250
+ this.handlers.onTrade?.(message.msg);
251
+ break;
252
+ case 'fill':
253
+ this.handlers.onFill?.(message.msg);
254
+ break;
255
+ }
256
+ }
257
+ catch (error) {
258
+ this.handlers.onError?.(error instanceof Error ? error : new Error('Failed to parse message'));
259
+ }
260
+ }
261
+ handleClose(code, reason) {
262
+ this.stopPingPong();
263
+ this.handlers.onDisconnect?.(code, reason);
264
+ if (this.config.autoReconnect &&
265
+ this.state !== 'disconnected' &&
266
+ this.reconnectAttempts < this.config.maxReconnectAttempts) {
267
+ this.scheduleReconnect();
268
+ }
269
+ else {
270
+ this.state = 'disconnected';
271
+ }
272
+ }
273
+ scheduleReconnect() {
274
+ this.state = 'reconnecting';
275
+ this.reconnectAttempts++;
276
+ // Exponential backoff
277
+ const delay = this.config.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
278
+ setTimeout(() => {
279
+ if (this.state === 'reconnecting') {
280
+ this.connect().catch((error) => {
281
+ this.handlers.onError?.(error);
282
+ });
283
+ }
284
+ }, delay);
285
+ }
286
+ resubscribeAll() {
287
+ // Resubscribe to all previously active subscriptions
288
+ const channels = [];
289
+ const tickers = [];
290
+ for (const [channel, data] of Object.entries(this.subscriptions)) {
291
+ if (channel === 'fill') {
292
+ if (data === true) {
293
+ this.subscribe(['fill']);
294
+ }
295
+ }
296
+ else if (data instanceof Set && data.size > 0) {
297
+ channels.push(channel);
298
+ tickers.push(...data);
299
+ }
300
+ }
301
+ if (channels.length > 0 && tickers.length > 0) {
302
+ const uniqueTickers = [...new Set(tickers)];
303
+ this.subscribe(channels, uniqueTickers);
304
+ }
305
+ }
306
+ updateLocalSubscriptions(channels, tickers, action) {
307
+ for (const channel of channels) {
308
+ if (channel === 'fill') {
309
+ this.subscriptions.fill = action === 'add';
310
+ }
311
+ else if (tickers) {
312
+ for (const ticker of tickers) {
313
+ if (action === 'add') {
314
+ this.subscriptions[channel].add(ticker);
315
+ }
316
+ else {
317
+ this.subscriptions[channel].delete(ticker);
318
+ }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ startPingPong() {
324
+ this.pingTimer = setInterval(() => {
325
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
326
+ this.ws.ping();
327
+ this.setPongTimeout();
328
+ }
329
+ }, DEFAULTS.pingInterval);
330
+ }
331
+ stopPingPong() {
332
+ if (this.pingTimer) {
333
+ clearInterval(this.pingTimer);
334
+ this.pingTimer = null;
335
+ }
336
+ this.clearPongTimeout();
337
+ }
338
+ setPongTimeout() {
339
+ this.pongTimer = setTimeout(() => {
340
+ // No pong received, connection might be dead
341
+ this.handlers.onError?.(new Error('Pong timeout - connection may be dead'));
342
+ this.ws?.terminate();
343
+ }, DEFAULTS.pongTimeout);
344
+ }
345
+ clearPongTimeout() {
346
+ if (this.pongTimer) {
347
+ clearTimeout(this.pongTimer);
348
+ this.pongTimer = null;
349
+ }
350
+ }
351
+ }
352
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/websocket/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Kalshi WebSocket Module
3
+ *
4
+ * Real-time market data streaming from Kalshi.
5
+ */
6
+ export { KalshiWsClient } from './client.js';
7
+ export { generateWsAuthHeaders, generateSignedWsUrl } from './auth.js';
8
+ export { type KalshiWsConfig, type KalshiWsEventHandlers, type SubscriptionChannel, type ConnectionState, type ActiveSubscriptions, type OrderbookDeltaMessage, type TickerMessage, type TradeMessage, type FillMessage, type WsMessage, WS_ENDPOINTS, } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,YAAY,GACb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Kalshi WebSocket Module
3
+ *
4
+ * Real-time market data streaming from Kalshi.
5
+ */
6
+ export { KalshiWsClient } from './client.js';
7
+ export { generateWsAuthHeaders, generateSignedWsUrl } from './auth.js';
8
+ export { WS_ENDPOINTS, } from './types.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/websocket/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAWL,YAAY,GACb,MAAM,YAAY,CAAC"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Kalshi WebSocket Types
3
+ *
4
+ * Message formats for Kalshi's WebSocket API
5
+ * Based on: https://docs.kalshi.com/websockets
6
+ */
7
+ /** WebSocket connection configuration */
8
+ export interface KalshiWsConfig {
9
+ /** API Key ID */
10
+ apiKeyId: string;
11
+ /** API Private Key (PEM format) */
12
+ privateKey: string;
13
+ /** Use demo environment (default: false) */
14
+ demo?: boolean;
15
+ /** Auto-reconnect on disconnect (default: true) */
16
+ autoReconnect?: boolean;
17
+ /** Reconnect delay in ms (default: 1000) */
18
+ reconnectDelay?: number;
19
+ /** Max reconnect attempts (default: 10) */
20
+ maxReconnectAttempts?: number;
21
+ }
22
+ /** WebSocket endpoints */
23
+ export declare const WS_ENDPOINTS: {
24
+ readonly production: "wss://api.elections.kalshi.com/trade-api/ws/v2";
25
+ readonly demo: "wss://demo-api.kalshi.co/trade-api/ws/v2";
26
+ };
27
+ /** Available subscription channels */
28
+ export type SubscriptionChannel = 'orderbook_delta' | 'ticker' | 'trade' | 'fill';
29
+ /** Subscription command */
30
+ export interface SubscribeCommand {
31
+ id: number;
32
+ cmd: 'subscribe';
33
+ params: {
34
+ channels: SubscriptionChannel[];
35
+ market_tickers?: string[];
36
+ };
37
+ }
38
+ /** Unsubscribe command */
39
+ export interface UnsubscribeCommand {
40
+ id: number;
41
+ cmd: 'unsubscribe';
42
+ params: {
43
+ channels: SubscriptionChannel[];
44
+ market_tickers?: string[];
45
+ };
46
+ }
47
+ /** Update subscription command */
48
+ export interface UpdateSubscriptionCommand {
49
+ id: number;
50
+ cmd: 'update_subscription';
51
+ params: {
52
+ channels: SubscriptionChannel[];
53
+ market_tickers: string[];
54
+ action: 'add_markets' | 'remove_markets';
55
+ };
56
+ }
57
+ export type WsCommand = SubscribeCommand | UnsubscribeCommand | UpdateSubscriptionCommand;
58
+ /** Base message structure */
59
+ interface BaseMessage {
60
+ type: string;
61
+ sid?: number;
62
+ }
63
+ /** Subscription confirmation */
64
+ export interface SubscribedMessage extends BaseMessage {
65
+ type: 'subscribed';
66
+ msg: {
67
+ channel: SubscriptionChannel;
68
+ market_tickers?: string[];
69
+ };
70
+ }
71
+ /** Error message */
72
+ export interface ErrorMessage extends BaseMessage {
73
+ type: 'error';
74
+ msg: {
75
+ code: number;
76
+ message: string;
77
+ };
78
+ }
79
+ /** Orderbook delta update */
80
+ export interface OrderbookDeltaMessage extends BaseMessage {
81
+ type: 'orderbook_delta';
82
+ msg: {
83
+ market_ticker: string;
84
+ price: number;
85
+ delta: number;
86
+ side: 'yes' | 'no';
87
+ };
88
+ }
89
+ /** Ticker update (market price change) */
90
+ export interface TickerMessage extends BaseMessage {
91
+ type: 'ticker';
92
+ msg: {
93
+ market_ticker: string;
94
+ yes_bid: number;
95
+ yes_ask: number;
96
+ no_bid: number;
97
+ no_ask: number;
98
+ last_price: number;
99
+ volume: number;
100
+ open_interest: number;
101
+ };
102
+ }
103
+ /** Trade execution */
104
+ export interface TradeMessage extends BaseMessage {
105
+ type: 'trade';
106
+ msg: {
107
+ market_ticker: string;
108
+ trade_id: string;
109
+ price: number;
110
+ count: number;
111
+ taker_side: 'yes' | 'no';
112
+ created_time: string;
113
+ };
114
+ }
115
+ /** User fill notification (authenticated) */
116
+ export interface FillMessage extends BaseMessage {
117
+ type: 'fill';
118
+ msg: {
119
+ trade_id: string;
120
+ order_id: string;
121
+ market_ticker: string;
122
+ side: 'yes' | 'no';
123
+ action: 'buy' | 'sell';
124
+ count: number;
125
+ price: number;
126
+ created_time: string;
127
+ };
128
+ }
129
+ /** All possible server messages */
130
+ export type WsMessage = SubscribedMessage | ErrorMessage | OrderbookDeltaMessage | TickerMessage | TradeMessage | FillMessage;
131
+ /** WebSocket event handlers */
132
+ export interface KalshiWsEventHandlers {
133
+ /** Called when connection is established */
134
+ onConnect?: () => void;
135
+ /** Called when connection is closed */
136
+ onDisconnect?: (code: number, reason: string) => void;
137
+ /** Called on any error */
138
+ onError?: (error: Error) => void;
139
+ /** Called when subscription is confirmed */
140
+ onSubscribed?: (channel: SubscriptionChannel, tickers?: string[]) => void;
141
+ /** Called on orderbook update */
142
+ onOrderbookDelta?: (data: OrderbookDeltaMessage['msg']) => void;
143
+ /** Called on ticker update */
144
+ onTicker?: (data: TickerMessage['msg']) => void;
145
+ /** Called on trade */
146
+ onTrade?: (data: TradeMessage['msg']) => void;
147
+ /** Called on fill (user's order filled) */
148
+ onFill?: (data: FillMessage['msg']) => void;
149
+ }
150
+ /** WebSocket connection state */
151
+ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
152
+ /** Active subscriptions */
153
+ export interface ActiveSubscriptions {
154
+ orderbook_delta: Set<string>;
155
+ ticker: Set<string>;
156
+ trade: Set<string>;
157
+ fill: boolean;
158
+ }
159
+ export {};
160
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/websocket/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Kalshi WebSocket Types
3
+ *
4
+ * Message formats for Kalshi's WebSocket API
5
+ * Based on: https://docs.kalshi.com/websockets
6
+ */
7
+ /** WebSocket endpoints */
8
+ export const WS_ENDPOINTS = {
9
+ production: 'wss://api.elections.kalshi.com/trade-api/ws/v2',
10
+ demo: 'wss://demo-api.kalshi.co/trade-api/ws/v2',
11
+ };
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/websocket/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,0BAA0B;AAC1B,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,UAAU,EAAE,gDAAgD;IAC5D,IAAI,EAAE,0CAA0C;CACxC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/websocket/types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { WS_ENDPOINTS } from './types.js';
3
+ describe('WebSocket Types', () => {
4
+ describe('WS_ENDPOINTS', () => {
5
+ it('has production endpoint', () => {
6
+ expect(WS_ENDPOINTS.production).toBe('wss://api.elections.kalshi.com/trade-api/ws/v2');
7
+ });
8
+ it('has demo endpoint', () => {
9
+ expect(WS_ENDPOINTS.demo).toBe('wss://demo-api.kalshi.co/trade-api/ws/v2');
10
+ });
11
+ it('endpoints use secure WebSocket protocol', () => {
12
+ expect(WS_ENDPOINTS.production.startsWith('wss://')).toBe(true);
13
+ expect(WS_ENDPOINTS.demo.startsWith('wss://')).toBe(true);
14
+ });
15
+ });
16
+ });
17
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/websocket/types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newyorkcompute/kalshi-core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Shared utilities for Kalshi prediction market tools — SDK configuration, formatting, and types",
5
5
  "author": "NewYorkCompute",
6
6
  "license": "MIT",
@@ -39,15 +39,19 @@
39
39
  "lint": "eslint src/",
40
40
  "lint:fix": "eslint src/ --fix",
41
41
  "test": "vitest run",
42
- "test:watch": "vitest"
42
+ "test:watch": "vitest",
43
+ "test:coverage": "vitest run --coverage"
43
44
  },
44
45
  "dependencies": {
45
- "kalshi-typescript": "^3.3.0"
46
+ "kalshi-typescript": "^3.3.0",
47
+ "ws": "^8.18.0"
46
48
  },
47
49
  "devDependencies": {
50
+ "@eslint/js": "^9.28.0",
48
51
  "@types/node": "^22.15.29",
52
+ "@types/ws": "^8.5.13",
53
+ "@vitest/coverage-v8": "^3.2.4",
49
54
  "eslint": "^9.28.0",
50
- "@eslint/js": "^9.28.0",
51
55
  "typescript-eslint": "^8.33.1",
52
56
  "vitest": "^3.2.3"
53
57
  }