@newyorkcompute/kalshi-core 0.2.0 → 0.4.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 (75) 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 +2 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +4 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/mm/index.d.ts +10 -0
  20. package/dist/mm/index.d.ts.map +1 -0
  21. package/dist/mm/index.js +12 -0
  22. package/dist/mm/index.js.map +1 -0
  23. package/dist/mm/inventory.d.ts +70 -0
  24. package/dist/mm/inventory.d.ts.map +1 -0
  25. package/dist/mm/inventory.js +171 -0
  26. package/dist/mm/inventory.js.map +1 -0
  27. package/dist/mm/inventory.test.d.ts +2 -0
  28. package/dist/mm/inventory.test.d.ts.map +1 -0
  29. package/dist/mm/inventory.test.js +358 -0
  30. package/dist/mm/inventory.test.js.map +1 -0
  31. package/dist/mm/order-manager.d.ts +81 -0
  32. package/dist/mm/order-manager.d.ts.map +1 -0
  33. package/dist/mm/order-manager.js +216 -0
  34. package/dist/mm/order-manager.js.map +1 -0
  35. package/dist/mm/order-manager.test.d.ts +2 -0
  36. package/dist/mm/order-manager.test.d.ts.map +1 -0
  37. package/dist/mm/order-manager.test.js +333 -0
  38. package/dist/mm/order-manager.test.js.map +1 -0
  39. package/dist/mm/risk.d.ts +77 -0
  40. package/dist/mm/risk.d.ts.map +1 -0
  41. package/dist/mm/risk.js +179 -0
  42. package/dist/mm/risk.js.map +1 -0
  43. package/dist/mm/risk.test.d.ts +2 -0
  44. package/dist/mm/risk.test.d.ts.map +1 -0
  45. package/dist/mm/risk.test.js +297 -0
  46. package/dist/mm/risk.test.js.map +1 -0
  47. package/dist/mm/types.d.ts +128 -0
  48. package/dist/mm/types.d.ts.map +1 -0
  49. package/dist/mm/types.js +7 -0
  50. package/dist/mm/types.js.map +1 -0
  51. package/dist/websocket/auth.d.ts +35 -0
  52. package/dist/websocket/auth.d.ts.map +1 -0
  53. package/dist/websocket/auth.js +60 -0
  54. package/dist/websocket/auth.js.map +1 -0
  55. package/dist/websocket/auth.test.d.ts +2 -0
  56. package/dist/websocket/auth.test.d.ts.map +1 -0
  57. package/dist/websocket/auth.test.js +65 -0
  58. package/dist/websocket/auth.test.js.map +1 -0
  59. package/dist/websocket/client.d.ts +95 -0
  60. package/dist/websocket/client.d.ts.map +1 -0
  61. package/dist/websocket/client.js +358 -0
  62. package/dist/websocket/client.js.map +1 -0
  63. package/dist/websocket/index.d.ts +9 -0
  64. package/dist/websocket/index.d.ts.map +1 -0
  65. package/dist/websocket/index.js +9 -0
  66. package/dist/websocket/index.js.map +1 -0
  67. package/dist/websocket/types.d.ts +172 -0
  68. package/dist/websocket/types.d.ts.map +1 -0
  69. package/dist/websocket/types.js +12 -0
  70. package/dist/websocket/types.js.map +1 -0
  71. package/dist/websocket/types.test.d.ts +2 -0
  72. package/dist/websocket/types.test.d.ts.map +1 -0
  73. package/dist/websocket/types.test.js +17 -0
  74. package/dist/websocket/types.test.js.map +1 -0
  75. package/package.json +8 -4
@@ -0,0 +1,297 @@
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
+ import { RiskManager, DEFAULT_RISK_LIMITS } from "./risk.js";
3
+ import { InventoryTracker } from "./inventory.js";
4
+ describe("RiskManager", () => {
5
+ let risk;
6
+ let inventory;
7
+ beforeEach(() => {
8
+ risk = new RiskManager();
9
+ inventory = new InventoryTracker();
10
+ });
11
+ describe("constructor", () => {
12
+ it("should use default limits", () => {
13
+ const limits = risk.getLimits();
14
+ expect(limits).toEqual(DEFAULT_RISK_LIMITS);
15
+ });
16
+ it("should allow custom limits", () => {
17
+ const customLimits = {
18
+ maxPositionPerMarket: 50,
19
+ maxDailyLoss: 1000,
20
+ };
21
+ const customRisk = new RiskManager(customLimits);
22
+ const limits = customRisk.getLimits();
23
+ expect(limits.maxPositionPerMarket).toBe(50);
24
+ expect(limits.maxDailyLoss).toBe(1000);
25
+ expect(limits.maxTotalExposure).toBe(DEFAULT_RISK_LIMITS.maxTotalExposure);
26
+ });
27
+ });
28
+ describe("checkQuote", () => {
29
+ it("should allow valid quote", () => {
30
+ const quote = {
31
+ ticker: "TEST-MARKET",
32
+ side: "yes",
33
+ bidPrice: 45,
34
+ bidSize: 10,
35
+ askPrice: 55,
36
+ askSize: 10,
37
+ };
38
+ const result = risk.checkQuote(quote, inventory);
39
+ expect(result.allowed).toBe(true);
40
+ });
41
+ it("should reject quote when halted", () => {
42
+ risk.halt("Test halt");
43
+ const quote = {
44
+ ticker: "TEST-MARKET",
45
+ side: "yes",
46
+ bidPrice: 45,
47
+ bidSize: 10,
48
+ askPrice: 55,
49
+ askSize: 10,
50
+ };
51
+ const result = risk.checkQuote(quote, inventory);
52
+ expect(result.allowed).toBe(false);
53
+ expect(result.reason).toContain("halted");
54
+ });
55
+ it("should reject quote with spread below minimum", () => {
56
+ const quote = {
57
+ ticker: "TEST-MARKET",
58
+ side: "yes",
59
+ bidPrice: 49,
60
+ bidSize: 10,
61
+ askPrice: 50, // Spread = 1, below default min of 2
62
+ askSize: 10,
63
+ };
64
+ const result = risk.checkQuote(quote, inventory);
65
+ expect(result.allowed).toBe(false);
66
+ expect(result.reason).toContain("Spread");
67
+ });
68
+ it("should reject quote with bid size exceeding max", () => {
69
+ const quote = {
70
+ ticker: "TEST-MARKET",
71
+ side: "yes",
72
+ bidPrice: 45,
73
+ bidSize: 100, // Exceeds default max of 25
74
+ askPrice: 55,
75
+ askSize: 10,
76
+ };
77
+ const result = risk.checkQuote(quote, inventory);
78
+ expect(result.allowed).toBe(false);
79
+ expect(result.reason).toContain("Bid size");
80
+ });
81
+ it("should reject quote with ask size exceeding max", () => {
82
+ const quote = {
83
+ ticker: "TEST-MARKET",
84
+ side: "yes",
85
+ bidPrice: 45,
86
+ bidSize: 10,
87
+ askPrice: 55,
88
+ askSize: 100, // Exceeds default max of 25
89
+ };
90
+ const result = risk.checkQuote(quote, inventory);
91
+ expect(result.allowed).toBe(false);
92
+ expect(result.reason).toContain("Ask size");
93
+ });
94
+ it("should reject quote that would exceed position limit", () => {
95
+ // Add existing position near limit
96
+ inventory.onFill({
97
+ orderId: "order1",
98
+ ticker: "TEST-MARKET",
99
+ side: "yes",
100
+ action: "buy",
101
+ count: 90, // Near default limit of 100
102
+ price: 50,
103
+ timestamp: new Date(),
104
+ });
105
+ const quote = {
106
+ ticker: "TEST-MARKET",
107
+ side: "yes",
108
+ bidPrice: 45,
109
+ bidSize: 20, // Would bring to 110, exceeding 100
110
+ askPrice: 55,
111
+ askSize: 20,
112
+ };
113
+ const result = risk.checkQuote(quote, inventory);
114
+ expect(result.allowed).toBe(false);
115
+ expect(result.reason).toContain("Position");
116
+ });
117
+ it("should reject quote that would exceed total exposure", () => {
118
+ const customRisk = new RiskManager({ maxTotalExposure: 50 });
119
+ // Add existing exposure
120
+ inventory.onFill({
121
+ orderId: "order1",
122
+ ticker: "MARKET-A",
123
+ side: "yes",
124
+ action: "buy",
125
+ count: 40,
126
+ price: 50,
127
+ timestamp: new Date(),
128
+ });
129
+ const quote = {
130
+ ticker: "MARKET-B",
131
+ side: "yes",
132
+ bidPrice: 45,
133
+ bidSize: 20, // Would bring total to 60, exceeding 50
134
+ askPrice: 55,
135
+ askSize: 20,
136
+ };
137
+ const result = customRisk.checkQuote(quote, inventory);
138
+ expect(result.allowed).toBe(false);
139
+ expect(result.reason).toContain("Total exposure");
140
+ });
141
+ });
142
+ describe("checkOrder", () => {
143
+ it("should allow valid order", () => {
144
+ const result = risk.checkOrder({ ticker: "TEST-MARKET", count: 10 }, inventory);
145
+ expect(result.allowed).toBe(true);
146
+ });
147
+ it("should reject order when halted", () => {
148
+ risk.halt("Test halt");
149
+ const result = risk.checkOrder({ ticker: "TEST-MARKET", count: 10 }, inventory);
150
+ expect(result.allowed).toBe(false);
151
+ });
152
+ it("should reject order exceeding max size", () => {
153
+ const result = risk.checkOrder({ ticker: "TEST-MARKET", count: 100 }, inventory);
154
+ expect(result.allowed).toBe(false);
155
+ expect(result.reason).toContain("Order size");
156
+ });
157
+ it("should reject order that would exceed position limit", () => {
158
+ // Add existing position near limit
159
+ inventory.onFill({
160
+ orderId: "order1",
161
+ ticker: "TEST-MARKET",
162
+ side: "yes",
163
+ action: "buy",
164
+ count: 95, // Near default limit of 100
165
+ price: 50,
166
+ timestamp: new Date(),
167
+ });
168
+ // Try to add 10 more - would exceed 100
169
+ const result = risk.checkOrder({ ticker: "TEST-MARKET", count: 10 }, inventory);
170
+ expect(result.allowed).toBe(false);
171
+ expect(result.reason).toContain("position limit");
172
+ });
173
+ it("should reject order that would exceed total exposure limit", () => {
174
+ const customRisk = new RiskManager({ maxTotalExposure: 50 });
175
+ // Add existing exposure
176
+ inventory.onFill({
177
+ orderId: "order1",
178
+ ticker: "MARKET-A",
179
+ side: "yes",
180
+ action: "buy",
181
+ count: 45,
182
+ price: 50,
183
+ timestamp: new Date(),
184
+ });
185
+ // Try to add 10 more in different market - would exceed 50
186
+ const result = customRisk.checkOrder({ ticker: "MARKET-B", count: 10 }, inventory);
187
+ expect(result.allowed).toBe(false);
188
+ expect(result.reason).toContain("total exposure");
189
+ });
190
+ });
191
+ describe("halt/resume", () => {
192
+ it("should halt trading", () => {
193
+ expect(risk.shouldHalt()).toBe(false);
194
+ risk.halt("Emergency stop");
195
+ expect(risk.shouldHalt()).toBe(true);
196
+ expect(risk.getHaltReason()).toBe("Emergency stop");
197
+ });
198
+ it("should resume trading", () => {
199
+ risk.halt("Emergency stop");
200
+ risk.resume();
201
+ expect(risk.shouldHalt()).toBe(false);
202
+ expect(risk.getHaltReason()).toBeUndefined();
203
+ });
204
+ });
205
+ describe("onFill", () => {
206
+ it("should track daily PnL", () => {
207
+ const fill = {
208
+ orderId: "order1",
209
+ ticker: "TEST-MARKET",
210
+ side: "yes",
211
+ action: "sell",
212
+ count: 10,
213
+ price: 55,
214
+ timestamp: new Date(),
215
+ };
216
+ risk.onFill(fill, 50); // 50 cents profit
217
+ expect(risk.getDailyPnL()).toBe(50);
218
+ });
219
+ it("should halt when daily loss limit reached", () => {
220
+ const customRisk = new RiskManager({ maxDailyLoss: 100 });
221
+ const fill = {
222
+ orderId: "order1",
223
+ ticker: "TEST-MARKET",
224
+ side: "yes",
225
+ action: "sell",
226
+ count: 10,
227
+ price: 40,
228
+ timestamp: new Date(),
229
+ };
230
+ customRisk.onFill(fill, -150); // 150 cents loss
231
+ expect(customRisk.shouldHalt()).toBe(true);
232
+ expect(customRisk.getHaltReason()).toContain("Daily loss limit");
233
+ });
234
+ });
235
+ describe("resetDaily", () => {
236
+ it("should reset daily PnL", () => {
237
+ const fill = {
238
+ orderId: "order1",
239
+ ticker: "TEST-MARKET",
240
+ side: "yes",
241
+ action: "sell",
242
+ count: 10,
243
+ price: 55,
244
+ timestamp: new Date(),
245
+ };
246
+ risk.onFill(fill, 50);
247
+ expect(risk.getDailyPnL()).toBe(50);
248
+ risk.resetDaily();
249
+ expect(risk.getDailyPnL()).toBe(0);
250
+ });
251
+ it("should not auto-resume if halted", () => {
252
+ risk.halt("Loss limit");
253
+ risk.resetDaily();
254
+ expect(risk.shouldHalt()).toBe(true);
255
+ });
256
+ });
257
+ describe("updateLimits", () => {
258
+ it("should update limits", () => {
259
+ risk.updateLimits({ maxPositionPerMarket: 200 });
260
+ expect(risk.getLimits().maxPositionPerMarket).toBe(200);
261
+ });
262
+ it("should preserve other limits", () => {
263
+ const originalMaxDaily = risk.getLimits().maxDailyLoss;
264
+ risk.updateLimits({ maxPositionPerMarket: 200 });
265
+ expect(risk.getLimits().maxDailyLoss).toBe(originalMaxDaily);
266
+ });
267
+ });
268
+ describe("getStatus", () => {
269
+ it("should return correct status", () => {
270
+ inventory.onFill({
271
+ orderId: "order1",
272
+ ticker: "TEST-MARKET",
273
+ side: "yes",
274
+ action: "buy",
275
+ count: 50,
276
+ price: 50,
277
+ timestamp: new Date(),
278
+ });
279
+ const fill = {
280
+ orderId: "order2",
281
+ ticker: "TEST-MARKET",
282
+ side: "yes",
283
+ action: "sell",
284
+ count: 10,
285
+ price: 55,
286
+ timestamp: new Date(),
287
+ };
288
+ risk.onFill(fill, 50);
289
+ const status = risk.getStatus(inventory);
290
+ expect(status.halted).toBe(false);
291
+ expect(status.dailyPnL).toBe(50);
292
+ expect(status.totalExposure).toBe(50);
293
+ expect(status.utilizationPercent).toBe(10); // 50/500 * 100
294
+ });
295
+ });
296
+ });
297
+ //# sourceMappingURL=risk.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risk.test.js","sourceRoot":"","sources":["../../src/mm/risk.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Market Maker Types
3
+ *
4
+ * Core types for the market making system.
5
+ */
6
+ /** Order side (YES or NO contract) */
7
+ export type Side = "yes" | "no";
8
+ /** Order action (buy or sell) */
9
+ export type Action = "buy" | "sell";
10
+ /** Order status in lifecycle */
11
+ export type OrderStatus = "pending" | "open" | "partial" | "filled" | "cancelled" | "failed";
12
+ /**
13
+ * A managed order tracked by the OrderManager
14
+ */
15
+ export interface ManagedOrder {
16
+ /** Kalshi order ID (assigned after placement) */
17
+ id?: string;
18
+ /** Client-generated order ID for tracking */
19
+ clientOrderId: string;
20
+ /** Market ticker */
21
+ ticker: string;
22
+ /** YES or NO */
23
+ side: Side;
24
+ /** Buy or sell */
25
+ action: Action;
26
+ /** Price in cents (1-99) */
27
+ price: number;
28
+ /** Number of contracts */
29
+ count: number;
30
+ /** Current order status */
31
+ status: OrderStatus;
32
+ /** When the order was created */
33
+ createdAt: Date;
34
+ /** Number of contracts filled */
35
+ filledCount: number;
36
+ /** Average fill price (cents) */
37
+ avgFillPrice?: number;
38
+ }
39
+ /**
40
+ * Quote generated by a strategy
41
+ */
42
+ export interface Quote {
43
+ ticker: string;
44
+ side: Side;
45
+ /** Bid price in cents */
46
+ bidPrice: number;
47
+ /** Bid size in contracts */
48
+ bidSize: number;
49
+ /** Ask price in cents */
50
+ askPrice: number;
51
+ /** Ask size in contracts */
52
+ askSize: number;
53
+ }
54
+ /**
55
+ * Position in a single market
56
+ */
57
+ export interface Position {
58
+ ticker: string;
59
+ /** Number of YES contracts held (positive = long, negative = short) */
60
+ yesContracts: number;
61
+ /** Number of NO contracts held (positive = long, negative = short) */
62
+ noContracts: number;
63
+ /** Net exposure: yesContracts - noContracts */
64
+ netExposure: number;
65
+ /** Total cost basis in cents */
66
+ costBasis: number;
67
+ /** Unrealized PnL in cents */
68
+ unrealizedPnL: number;
69
+ }
70
+ /**
71
+ * Risk limits configuration
72
+ */
73
+ export interface RiskLimits {
74
+ /** Max contracts per market (absolute value) */
75
+ maxPositionPerMarket: number;
76
+ /** Max total contracts across all markets */
77
+ maxTotalExposure: number;
78
+ /** Max daily loss in cents before halting */
79
+ maxDailyLoss: number;
80
+ /** Max contracts per single order */
81
+ maxOrderSize: number;
82
+ /** Minimum spread to quote (cents) */
83
+ minSpread: number;
84
+ }
85
+ /**
86
+ * Result of a risk check
87
+ */
88
+ export interface RiskCheckResult {
89
+ /** Whether the action is allowed */
90
+ allowed: boolean;
91
+ /** Reason if not allowed */
92
+ reason?: string;
93
+ }
94
+ /**
95
+ * Fill event from Kalshi
96
+ */
97
+ export interface Fill {
98
+ /** Order ID that was filled */
99
+ orderId: string;
100
+ /** Market ticker */
101
+ ticker: string;
102
+ /** YES or NO */
103
+ side: Side;
104
+ /** Buy or sell */
105
+ action: Action;
106
+ /** Number of contracts filled */
107
+ count: number;
108
+ /** Fill price in cents */
109
+ price: number;
110
+ /** Timestamp */
111
+ timestamp: Date;
112
+ }
113
+ /**
114
+ * PnL summary
115
+ */
116
+ export interface PnLSummary {
117
+ /** Realized PnL today (cents) */
118
+ realizedToday: number;
119
+ /** Unrealized PnL (cents) */
120
+ unrealized: number;
121
+ /** Total PnL (cents) */
122
+ total: number;
123
+ /** Number of fills today */
124
+ fillsToday: number;
125
+ /** Total volume traded today (contracts) */
126
+ volumeToday: number;
127
+ }
128
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mm/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Market Maker Types
3
+ *
4
+ * Core types for the market making system.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mm/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Kalshi WebSocket Authentication
3
+ *
4
+ * Handles signature generation for authenticated WebSocket connections.
5
+ * Uses the same RSA-PSS signing as the REST API.
6
+ */
7
+ /** WebSocket API path for signing */
8
+ declare const WS_PATH = "/trade-api/ws/v2";
9
+ /**
10
+ * Generate authentication headers for WebSocket connection
11
+ *
12
+ * The message to sign is: timestamp + method + path
13
+ * e.g., "1703702400000GET/trade-api/ws/v2"
14
+ *
15
+ * @param apiKeyId - Your Kalshi API key ID
16
+ * @param privateKeyPem - Your private key in PEM format
17
+ * @param timestamp - Unix timestamp in milliseconds
18
+ * @returns Headers object for WebSocket connection
19
+ */
20
+ export declare function generateWsAuthHeaders(apiKeyId: string, privateKeyPem: string, timestamp?: number): Record<string, string>;
21
+ /**
22
+ * Generate a signed WebSocket URL with auth params
23
+ *
24
+ * Some WebSocket implementations don't support custom headers,
25
+ * so we can pass auth as query parameters instead.
26
+ *
27
+ * @param baseUrl - WebSocket endpoint URL
28
+ * @param apiKeyId - Your Kalshi API key ID
29
+ * @param privateKey - Your private key in PEM format
30
+ * @returns Full WebSocket URL with auth parameters
31
+ */
32
+ export declare function generateSignedWsUrl(baseUrl: string, apiKeyId: string, privateKey: string): string;
33
+ /** Export path for testing */
34
+ export { WS_PATH };
35
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/websocket/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,qCAAqC;AACrC,QAAA,MAAM,OAAO,qBAAqB,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,SAAS,GAAE,MAAmB,GAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CASR;AAED,8BAA8B;AAC9B,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Kalshi WebSocket Authentication
3
+ *
4
+ * Handles signature generation for authenticated WebSocket connections.
5
+ * Uses the same RSA-PSS signing as the REST API.
6
+ */
7
+ import * as crypto from 'crypto';
8
+ /** WebSocket API path for signing */
9
+ const WS_PATH = '/trade-api/ws/v2';
10
+ /**
11
+ * Generate authentication headers for WebSocket connection
12
+ *
13
+ * The message to sign is: timestamp + method + path
14
+ * e.g., "1703702400000GET/trade-api/ws/v2"
15
+ *
16
+ * @param apiKeyId - Your Kalshi API key ID
17
+ * @param privateKeyPem - Your private key in PEM format
18
+ * @param timestamp - Unix timestamp in milliseconds
19
+ * @returns Headers object for WebSocket connection
20
+ */
21
+ export function generateWsAuthHeaders(apiKeyId, privateKeyPem, timestamp = Date.now()) {
22
+ const timestampStr = timestamp.toString();
23
+ // Message format: timestamp + method + path
24
+ const message = timestampStr + 'GET' + WS_PATH;
25
+ // Convert PEM string to KeyObject (required for proper signing)
26
+ const privateKey = crypto.createPrivateKey(privateKeyPem);
27
+ // Sign using RSA-PSS with SHA-256
28
+ const signature = crypto.sign('sha256', Buffer.from(message), {
29
+ key: privateKey,
30
+ padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
31
+ saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
32
+ });
33
+ return {
34
+ 'KALSHI-ACCESS-KEY': apiKeyId,
35
+ 'KALSHI-ACCESS-SIGNATURE': signature.toString('base64'),
36
+ 'KALSHI-ACCESS-TIMESTAMP': timestampStr,
37
+ };
38
+ }
39
+ /**
40
+ * Generate a signed WebSocket URL with auth params
41
+ *
42
+ * Some WebSocket implementations don't support custom headers,
43
+ * so we can pass auth as query parameters instead.
44
+ *
45
+ * @param baseUrl - WebSocket endpoint URL
46
+ * @param apiKeyId - Your Kalshi API key ID
47
+ * @param privateKey - Your private key in PEM format
48
+ * @returns Full WebSocket URL with auth parameters
49
+ */
50
+ export function generateSignedWsUrl(baseUrl, apiKeyId, privateKey) {
51
+ const headers = generateWsAuthHeaders(apiKeyId, privateKey);
52
+ const url = new URL(baseUrl);
53
+ url.searchParams.set('api_key', headers['KALSHI-ACCESS-KEY']);
54
+ url.searchParams.set('signature', headers['KALSHI-ACCESS-SIGNATURE']);
55
+ url.searchParams.set('timestamp', headers['KALSHI-ACCESS-TIMESTAMP']);
56
+ return url.toString();
57
+ }
58
+ /** Export path for testing */
59
+ export { WS_PATH };
60
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/websocket/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,qCAAqC;AACrC,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,aAAqB,EACrB,YAAoB,IAAI,CAAC,GAAG,EAAE;IAE9B,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAE1C,4CAA4C;IAC5C,MAAM,OAAO,GAAG,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;IAE/C,gEAAgE;IAChE,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAE1D,kCAAkC;IAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5D,GAAG,EAAE,UAAU;QACf,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,qBAAqB;QAC/C,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,sBAAsB;KACpD,CAAC,CAAC;IAEH,OAAO;QACL,mBAAmB,EAAE,QAAQ;QAC7B,yBAAyB,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACvD,yBAAyB,EAAE,YAAY;KACxC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,QAAgB,EAChB,UAAkB;IAElB,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAE5D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC9D,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC;IACtE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAEtE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED,8BAA8B;AAC9B,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.test.d.ts","sourceRoot":"","sources":["../../src/websocket/auth.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import * as crypto from 'crypto';
3
+ // Mock crypto module since we can't use real RSA keys in tests easily
4
+ vi.mock('crypto', async () => {
5
+ const actual = await vi.importActual('crypto');
6
+ return {
7
+ ...actual,
8
+ createPrivateKey: vi.fn(() => 'mocked-key-object'),
9
+ sign: vi.fn(() => Buffer.from('mocked-signature-base64')),
10
+ };
11
+ });
12
+ import { generateWsAuthHeaders, generateSignedWsUrl, WS_PATH } from './auth.js';
13
+ describe('WebSocket Auth', () => {
14
+ describe('generateWsAuthHeaders', () => {
15
+ it('generates all required headers', () => {
16
+ const headers = generateWsAuthHeaders('test-api-key', 'fake-private-key');
17
+ expect(headers).toHaveProperty('KALSHI-ACCESS-KEY');
18
+ expect(headers).toHaveProperty('KALSHI-ACCESS-SIGNATURE');
19
+ expect(headers).toHaveProperty('KALSHI-ACCESS-TIMESTAMP');
20
+ });
21
+ it('uses the provided API key', () => {
22
+ const headers = generateWsAuthHeaders('my-api-key-123', 'fake-key');
23
+ expect(headers['KALSHI-ACCESS-KEY']).toBe('my-api-key-123');
24
+ });
25
+ it('uses the provided timestamp', () => {
26
+ const timestamp = 1703721600000; // Fixed timestamp
27
+ const headers = generateWsAuthHeaders('test-key', 'fake-key', timestamp);
28
+ expect(headers['KALSHI-ACCESS-TIMESTAMP']).toBe('1703721600000');
29
+ });
30
+ it('returns a signature', () => {
31
+ const headers = generateWsAuthHeaders('test-key', 'fake-key');
32
+ expect(headers['KALSHI-ACCESS-SIGNATURE']).toBeDefined();
33
+ expect(headers['KALSHI-ACCESS-SIGNATURE'].length).toBeGreaterThan(0);
34
+ });
35
+ it('signs the correct message format (timestamp + GET + path)', () => {
36
+ const timestamp = 1703721600000;
37
+ generateWsAuthHeaders('test-key', 'fake-key-pem', timestamp);
38
+ // Verify crypto.createPrivateKey was called with the PEM
39
+ expect(crypto.createPrivateKey).toHaveBeenCalledWith('fake-key-pem');
40
+ // Verify crypto.sign was called with correct message format
41
+ expect(crypto.sign).toHaveBeenCalledWith('sha256', Buffer.from(`${timestamp}GET${WS_PATH}`), expect.objectContaining({
42
+ key: 'mocked-key-object',
43
+ padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
44
+ }));
45
+ });
46
+ });
47
+ describe('generateSignedWsUrl', () => {
48
+ it('appends auth parameters to URL', () => {
49
+ const url = generateSignedWsUrl('wss://api.example.com/ws', 'test-api-key', 'fake-key');
50
+ expect(url).toContain('api_key=test-api-key');
51
+ expect(url).toContain('signature=');
52
+ expect(url).toContain('timestamp=');
53
+ });
54
+ it('preserves the base URL', () => {
55
+ const url = generateSignedWsUrl('wss://api.elections.kalshi.com/trade-api/ws/v2', 'test-key', 'fake-key');
56
+ expect(url.startsWith('wss://api.elections.kalshi.com/trade-api/ws/v2')).toBe(true);
57
+ });
58
+ it('properly encodes parameters', () => {
59
+ const url = generateSignedWsUrl('wss://api.example.com/ws', 'test+key', 'fake-key');
60
+ // URL should properly encode the + character
61
+ expect(url).toContain('api_key=test%2Bkey');
62
+ });
63
+ });
64
+ });
65
+ //# sourceMappingURL=auth.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../src/websocket/auth.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAEjC,sEAAsE;AACtE,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC3B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAgB,QAAQ,CAAC,CAAC;IAC9D,OAAO;QACL,GAAG,MAAM;QACT,gBAAgB,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC;QAClD,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEhF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,OAAO,GAAG,qBAAqB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAE1E,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;YACpD,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;YAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,OAAO,GAAG,qBAAqB,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;YAEpE,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,kBAAkB;YACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;YAEzE,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;YAE9D,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACzD,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,SAAS,GAAG,aAAa,CAAC;YAChC,qBAAqB,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;YAE7D,yDAAyD;YACzD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,cAAc,CAAC,CAAC;YAErE,4DAA4D;YAC5D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,oBAAoB,CACtC,QAAQ,EACR,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,MAAM,OAAO,EAAE,CAAC,EACxC,MAAM,CAAC,gBAAgB,CAAC;gBACtB,GAAG,EAAE,mBAAmB;gBACxB,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,qBAAqB;aAChD,CAAC,CACH,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,GAAG,GAAG,mBAAmB,CAC7B,0BAA0B,EAC1B,cAAc,EACd,UAAU,CACX,CAAC;YAEF,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;YAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;YAChC,MAAM,GAAG,GAAG,mBAAmB,CAC7B,gDAAgD,EAChD,UAAU,EACV,UAAU,CACX,CAAC;YAEF,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,gDAAgD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,GAAG,GAAG,mBAAmB,CAC7B,0BAA0B,EAC1B,UAAU,EACV,UAAU,CACX,CAAC;YAEF,6CAA6C;YAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}