@newyorkcompute/kalshi-core 0.1.0 → 0.2.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.
- package/dist/cache.d.ts +71 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +96 -0
- package/dist/cache.js.map +1 -0
- package/dist/cache.test.d.ts +5 -0
- package/dist/cache.test.d.ts.map +1 -0
- package/dist/cache.test.js +108 -0
- package/dist/cache.test.js.map +1 -0
- package/dist/format.d.ts +39 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +80 -0
- package/dist/format.js.map +1 -1
- package/dist/format.test.js +66 -2
- package/dist/format.test.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/rate-limiter.d.ts +80 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +180 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/rate-limiter.test.d.ts +5 -0
- package/dist/rate-limiter.test.d.ts.map +1 -0
- package/dist/rate-limiter.test.js +175 -0
- package/dist/rate-limiter.test.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-order.d.ts +32 -0
- package/dist/validate-order.d.ts.map +1 -0
- package/dist/validate-order.js +82 -0
- package/dist/validate-order.js.map +1 -0
- package/dist/validate-order.test.d.ts +2 -0
- package/dist/validate-order.test.d.ts.map +1 -0
- package/dist/validate-order.test.js +234 -0
- package/dist/validate-order.test.js.map +1 -0
- package/dist/with-timeout.d.ts +25 -0
- package/dist/with-timeout.d.ts.map +1 -0
- package/dist/with-timeout.js +33 -0
- package/dist/with-timeout.js.map +1 -0
- package/dist/with-timeout.test.d.ts +2 -0
- package/dist/with-timeout.test.d.ts.map +1 -0
- package/dist/with-timeout.test.js +72 -0
- package/dist/with-timeout.test.js.map +1 -0
- package/package.json +1 -2
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { validateOrder } from "./validate-order.js";
|
|
3
|
+
describe("validateOrder", () => {
|
|
4
|
+
const mockGetMarket = vi.fn();
|
|
5
|
+
const mockGetBalance = vi.fn();
|
|
6
|
+
const mockMarketApi = {
|
|
7
|
+
getMarket: mockGetMarket,
|
|
8
|
+
};
|
|
9
|
+
const mockPortfolioApi = {
|
|
10
|
+
getBalance: mockGetBalance,
|
|
11
|
+
};
|
|
12
|
+
it("should validate successful order", async () => {
|
|
13
|
+
mockGetMarket.mockResolvedValue({
|
|
14
|
+
data: {
|
|
15
|
+
market: {
|
|
16
|
+
ticker: "TEST-MARKET",
|
|
17
|
+
status: "open",
|
|
18
|
+
yes_ask: 50,
|
|
19
|
+
yes_bid: 48,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
mockGetBalance.mockResolvedValue({
|
|
24
|
+
data: { balance: 10000 },
|
|
25
|
+
});
|
|
26
|
+
const result = await validateOrder({
|
|
27
|
+
ticker: "TEST-MARKET",
|
|
28
|
+
side: "yes",
|
|
29
|
+
action: "buy",
|
|
30
|
+
count: 10,
|
|
31
|
+
price: 50,
|
|
32
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
33
|
+
expect(result.valid).toBe(true);
|
|
34
|
+
expect(result.errors).toHaveLength(0);
|
|
35
|
+
expect(result.estimatedCost).toBe(500);
|
|
36
|
+
});
|
|
37
|
+
it("should reject order on closed market", async () => {
|
|
38
|
+
mockGetMarket.mockResolvedValue({
|
|
39
|
+
data: {
|
|
40
|
+
market: {
|
|
41
|
+
ticker: "TEST-MARKET",
|
|
42
|
+
status: "closed",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
mockGetBalance.mockResolvedValue({
|
|
47
|
+
data: { balance: 10000 },
|
|
48
|
+
});
|
|
49
|
+
const result = await validateOrder({
|
|
50
|
+
ticker: "TEST-MARKET",
|
|
51
|
+
side: "yes",
|
|
52
|
+
action: "buy",
|
|
53
|
+
count: 10,
|
|
54
|
+
price: 50,
|
|
55
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
56
|
+
expect(result.valid).toBe(false);
|
|
57
|
+
expect(result.errors.some((e) => e.includes("closed"))).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
it("should reject order with insufficient balance", async () => {
|
|
60
|
+
mockGetMarket.mockResolvedValue({
|
|
61
|
+
data: {
|
|
62
|
+
market: {
|
|
63
|
+
ticker: "TEST-MARKET",
|
|
64
|
+
status: "open",
|
|
65
|
+
yes_ask: 50,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
mockGetBalance.mockResolvedValue({
|
|
70
|
+
data: { balance: 100 }, // Only 100¢
|
|
71
|
+
});
|
|
72
|
+
const result = await validateOrder({
|
|
73
|
+
ticker: "TEST-MARKET",
|
|
74
|
+
side: "yes",
|
|
75
|
+
action: "buy",
|
|
76
|
+
count: 10,
|
|
77
|
+
price: 50, // Costs 500¢
|
|
78
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
79
|
+
expect(result.valid).toBe(false);
|
|
80
|
+
expect(result.errors.some((e) => e.includes("Insufficient balance"))).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
it("should warn on price far from market", async () => {
|
|
83
|
+
mockGetMarket.mockResolvedValue({
|
|
84
|
+
data: {
|
|
85
|
+
market: {
|
|
86
|
+
ticker: "TEST-MARKET",
|
|
87
|
+
status: "open",
|
|
88
|
+
yes_ask: 50,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
mockGetBalance.mockResolvedValue({
|
|
93
|
+
data: { balance: 10000 },
|
|
94
|
+
});
|
|
95
|
+
const result = await validateOrder({
|
|
96
|
+
ticker: "TEST-MARKET",
|
|
97
|
+
side: "yes",
|
|
98
|
+
action: "buy",
|
|
99
|
+
count: 10,
|
|
100
|
+
price: 80, // 30¢ away from market
|
|
101
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
102
|
+
expect(result.valid).toBe(true);
|
|
103
|
+
expect(result.warnings.length).toBeGreaterThan(0);
|
|
104
|
+
expect(result.warnings.some((w) => w.includes("away from market"))).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
it("should reject negative quantity", async () => {
|
|
107
|
+
mockGetMarket.mockResolvedValue({
|
|
108
|
+
data: {
|
|
109
|
+
market: {
|
|
110
|
+
ticker: "TEST-MARKET",
|
|
111
|
+
status: "open",
|
|
112
|
+
yes_ask: 50,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
mockGetBalance.mockResolvedValue({
|
|
117
|
+
data: { balance: 10000 },
|
|
118
|
+
});
|
|
119
|
+
const result = await validateOrder({
|
|
120
|
+
ticker: "TEST-MARKET",
|
|
121
|
+
side: "yes",
|
|
122
|
+
action: "buy",
|
|
123
|
+
count: -5,
|
|
124
|
+
price: 50,
|
|
125
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
126
|
+
expect(result.valid).toBe(false);
|
|
127
|
+
expect(result.errors).toContain("Order quantity must be positive");
|
|
128
|
+
});
|
|
129
|
+
it("should warn on large order size", async () => {
|
|
130
|
+
mockGetMarket.mockResolvedValue({
|
|
131
|
+
data: {
|
|
132
|
+
market: {
|
|
133
|
+
ticker: "TEST-MARKET",
|
|
134
|
+
status: "open",
|
|
135
|
+
yes_ask: 50,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
mockGetBalance.mockResolvedValue({
|
|
140
|
+
data: { balance: 100000 },
|
|
141
|
+
});
|
|
142
|
+
const result = await validateOrder({
|
|
143
|
+
ticker: "TEST-MARKET",
|
|
144
|
+
side: "yes",
|
|
145
|
+
action: "buy",
|
|
146
|
+
count: 1500,
|
|
147
|
+
price: 50,
|
|
148
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
149
|
+
expect(result.valid).toBe(true);
|
|
150
|
+
expect(result.warnings).toContain("Large order size may have poor execution");
|
|
151
|
+
});
|
|
152
|
+
it("should reject invalid price range", async () => {
|
|
153
|
+
mockGetMarket.mockResolvedValue({
|
|
154
|
+
data: {
|
|
155
|
+
market: {
|
|
156
|
+
ticker: "TEST-MARKET",
|
|
157
|
+
status: "open",
|
|
158
|
+
yes_ask: 50,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
mockGetBalance.mockResolvedValue({
|
|
163
|
+
data: { balance: 10000 },
|
|
164
|
+
});
|
|
165
|
+
const result = await validateOrder({
|
|
166
|
+
ticker: "TEST-MARKET",
|
|
167
|
+
side: "yes",
|
|
168
|
+
action: "buy",
|
|
169
|
+
count: 10,
|
|
170
|
+
price: 150, // Invalid: >99
|
|
171
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
172
|
+
expect(result.valid).toBe(false);
|
|
173
|
+
expect(result.errors).toContain("Price must be between 1¢ and 99¢");
|
|
174
|
+
});
|
|
175
|
+
it("should allow sell orders without balance check", async () => {
|
|
176
|
+
mockGetMarket.mockResolvedValue({
|
|
177
|
+
data: {
|
|
178
|
+
market: {
|
|
179
|
+
ticker: "TEST-MARKET",
|
|
180
|
+
status: "open",
|
|
181
|
+
yes_bid: 50,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
mockGetBalance.mockResolvedValue({
|
|
186
|
+
data: { balance: 0 }, // No balance
|
|
187
|
+
});
|
|
188
|
+
const result = await validateOrder({
|
|
189
|
+
ticker: "TEST-MARKET",
|
|
190
|
+
side: "yes",
|
|
191
|
+
action: "sell",
|
|
192
|
+
count: 10,
|
|
193
|
+
price: 50,
|
|
194
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
195
|
+
expect(result.valid).toBe(true);
|
|
196
|
+
expect(result.estimatedCost).toBe(0);
|
|
197
|
+
});
|
|
198
|
+
it("should handle API errors gracefully", async () => {
|
|
199
|
+
mockGetMarket.mockRejectedValue(new Error("Network error"));
|
|
200
|
+
const result = await validateOrder({
|
|
201
|
+
ticker: "TEST-MARKET",
|
|
202
|
+
side: "yes",
|
|
203
|
+
action: "buy",
|
|
204
|
+
count: 10,
|
|
205
|
+
price: 50,
|
|
206
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
207
|
+
expect(result.valid).toBe(false);
|
|
208
|
+
expect(result.errors.some((e) => e.includes("Validation failed"))).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
it("should use default price if not provided", async () => {
|
|
211
|
+
mockGetMarket.mockResolvedValue({
|
|
212
|
+
data: {
|
|
213
|
+
market: {
|
|
214
|
+
ticker: "TEST-MARKET",
|
|
215
|
+
status: "open",
|
|
216
|
+
yes_ask: 60,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
mockGetBalance.mockResolvedValue({
|
|
221
|
+
data: { balance: 10000 },
|
|
222
|
+
});
|
|
223
|
+
const result = await validateOrder({
|
|
224
|
+
ticker: "TEST-MARKET",
|
|
225
|
+
side: "yes",
|
|
226
|
+
action: "buy",
|
|
227
|
+
count: 10,
|
|
228
|
+
// No price provided
|
|
229
|
+
}, mockMarketApi, mockPortfolioApi);
|
|
230
|
+
expect(result.valid).toBe(true);
|
|
231
|
+
expect(result.estimatedCost).toBe(600); // Uses market price (60)
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
//# sourceMappingURL=validate-order.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-order.test.js","sourceRoot":"","sources":["../src/validate-order.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for timeout errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class TimeoutError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Wraps a promise with a timeout
|
|
9
|
+
*
|
|
10
|
+
* @param promise - The promise to wrap
|
|
11
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
12
|
+
* @param errorMessage - Custom error message for timeout
|
|
13
|
+
* @returns The promise result or throws TimeoutError
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const result = await withTimeout(
|
|
18
|
+
* fetch('https://api.example.com'),
|
|
19
|
+
* 5000,
|
|
20
|
+
* 'API request timed out'
|
|
21
|
+
* );
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage?: string): Promise<T>;
|
|
25
|
+
//# sourceMappingURL=with-timeout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-timeout.d.ts","sourceRoot":"","sources":["../src/with-timeout.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,YAAY,SAAoB,GAC/B,OAAO,CAAC,CAAC,CAAC,CAMZ"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error class for timeout errors
|
|
3
|
+
*/
|
|
4
|
+
export class TimeoutError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "TimeoutError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Wraps a promise with a timeout
|
|
12
|
+
*
|
|
13
|
+
* @param promise - The promise to wrap
|
|
14
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
15
|
+
* @param errorMessage - Custom error message for timeout
|
|
16
|
+
* @returns The promise result or throws TimeoutError
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const result = await withTimeout(
|
|
21
|
+
* fetch('https://api.example.com'),
|
|
22
|
+
* 5000,
|
|
23
|
+
* 'API request timed out'
|
|
24
|
+
* );
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export async function withTimeout(promise, timeoutMs, errorMessage = "Request timeout") {
|
|
28
|
+
const timeout = new Promise((_, reject) => {
|
|
29
|
+
setTimeout(() => reject(new TimeoutError(errorMessage)), timeoutMs);
|
|
30
|
+
});
|
|
31
|
+
return Promise.race([promise, timeout]);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=with-timeout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-timeout.js","sourceRoot":"","sources":["../src/with-timeout.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAmB,EACnB,SAAiB,EACjB,YAAY,GAAG,iBAAiB;IAEhC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-timeout.test.d.ts","sourceRoot":"","sources":["../src/with-timeout.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { withTimeout, TimeoutError } from "./with-timeout.js";
|
|
3
|
+
describe("withTimeout", () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.useFakeTimers();
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.useRealTimers();
|
|
9
|
+
});
|
|
10
|
+
it("should resolve if promise completes before timeout", async () => {
|
|
11
|
+
const promise = Promise.resolve("success");
|
|
12
|
+
const resultPromise = withTimeout(promise, 1000);
|
|
13
|
+
const result = await resultPromise;
|
|
14
|
+
expect(result).toBe("success");
|
|
15
|
+
});
|
|
16
|
+
it("should reject with TimeoutError if promise takes too long", async () => {
|
|
17
|
+
const promise = new Promise((resolve) => {
|
|
18
|
+
setTimeout(() => resolve("too late"), 2000);
|
|
19
|
+
});
|
|
20
|
+
const resultPromise = withTimeout(promise, 100, "Custom timeout message");
|
|
21
|
+
vi.advanceTimersByTime(100);
|
|
22
|
+
await expect(resultPromise).rejects.toThrow(TimeoutError);
|
|
23
|
+
await expect(resultPromise).rejects.toThrow("Custom timeout message");
|
|
24
|
+
});
|
|
25
|
+
it("should reject with original error if promise rejects", async () => {
|
|
26
|
+
const promise = Promise.reject(new Error("Network error"));
|
|
27
|
+
await expect(withTimeout(promise, 1000)).rejects.toThrow("Network error");
|
|
28
|
+
});
|
|
29
|
+
it("should use default error message if not provided", async () => {
|
|
30
|
+
const promise = new Promise((resolve) => {
|
|
31
|
+
setTimeout(() => resolve("too late"), 2000);
|
|
32
|
+
});
|
|
33
|
+
const resultPromise = withTimeout(promise, 100);
|
|
34
|
+
vi.advanceTimersByTime(100);
|
|
35
|
+
await expect(resultPromise).rejects.toThrow("Request timeout");
|
|
36
|
+
});
|
|
37
|
+
it("should handle promise that resolves exactly at timeout", async () => {
|
|
38
|
+
let resolvePromise;
|
|
39
|
+
const promise = new Promise((resolve) => {
|
|
40
|
+
resolvePromise = resolve;
|
|
41
|
+
});
|
|
42
|
+
const resultPromise = withTimeout(promise, 1000);
|
|
43
|
+
// Resolve just before timeout
|
|
44
|
+
vi.advanceTimersByTime(999);
|
|
45
|
+
resolvePromise("just in time");
|
|
46
|
+
const result = await resultPromise;
|
|
47
|
+
expect(result).toBe("just in time");
|
|
48
|
+
});
|
|
49
|
+
it("should handle different data types", async () => {
|
|
50
|
+
const numberPromise = Promise.resolve(42);
|
|
51
|
+
expect(await withTimeout(numberPromise, 1000)).toBe(42);
|
|
52
|
+
const objectPromise = Promise.resolve({ foo: "bar" });
|
|
53
|
+
expect(await withTimeout(objectPromise, 1000)).toEqual({ foo: "bar" });
|
|
54
|
+
const arrayPromise = Promise.resolve([1, 2, 3]);
|
|
55
|
+
expect(await withTimeout(arrayPromise, 1000)).toEqual([1, 2, 3]);
|
|
56
|
+
});
|
|
57
|
+
it("should have correct error name", async () => {
|
|
58
|
+
const promise = new Promise((resolve) => {
|
|
59
|
+
setTimeout(() => resolve("too late"), 2000);
|
|
60
|
+
});
|
|
61
|
+
const resultPromise = withTimeout(promise, 100);
|
|
62
|
+
vi.advanceTimersByTime(100);
|
|
63
|
+
try {
|
|
64
|
+
await resultPromise;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
expect(error).toBeInstanceOf(TimeoutError);
|
|
68
|
+
expect(error.name).toBe("TimeoutError");
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=with-timeout.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-timeout.test.js","sourceRoot":"","sources":["../src/with-timeout.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newyorkcompute/kalshi-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Shared utilities for Kalshi prediction market tools — SDK configuration, formatting, and types",
|
|
5
5
|
"author": "NewYorkCompute",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,4 +52,3 @@
|
|
|
52
52
|
"vitest": "^3.2.3"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
|