@newyorkcompute/kalshi-core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- 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
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,6 @@
|
|
|
6
6
|
export { type KalshiConfig, DEFAULT_BASE_PATH, DEMO_BASE_PATH, getKalshiConfig, createSdkConfig, createMarketApi, createPortfolioApi, createOrdersApi, createEventsApi, } from "./config.js";
|
|
7
7
|
export { formatPrice, formatCurrency, formatPercent, formatPriceChange, formatCompactNumber, formatRelativeTime, truncate, padString, } from "./format.js";
|
|
8
8
|
export * from "./types.js";
|
|
9
|
+
export { withTimeout, TimeoutError } from "./with-timeout.js";
|
|
10
|
+
export { validateOrder, type OrderValidationInput, type OrderValidationResult, } from "./validate-order.js";
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,YAAY,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,YAAY,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -9,4 +9,8 @@ export { DEFAULT_BASE_PATH, DEMO_BASE_PATH, getKalshiConfig, createSdkConfig, cr
|
|
|
9
9
|
export { formatPrice, formatCurrency, formatPercent, formatPriceChange, formatCompactNumber, formatRelativeTime, truncate, padString, } from "./format.js";
|
|
10
10
|
// Types
|
|
11
11
|
export * from "./types.js";
|
|
12
|
+
// Utilities
|
|
13
|
+
export { withTimeout, TimeoutError } from "./with-timeout.js";
|
|
14
|
+
// Validation
|
|
15
|
+
export { validateOrder, } from "./validate-order.js";
|
|
12
16
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EAEL,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,uBAAuB;AACvB,OAAO,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,QAAQ;AACR,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,gBAAgB;AAChB,OAAO,EAEL,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,uBAAuB;AACvB,OAAO,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,EACR,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE9D,aAAa;AACb,OAAO,EACL,aAAa,GAGd,MAAM,qBAAqB,CAAC"}
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EACT,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,cAAc,EAAE,CAAC;IACtB,EAAE,EAAE,cAAc,EAAE,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,SAAS,EACT,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC;AAEhC;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,cAAc,EAAE,CAAC;IACtB,EAAE,EAAE,cAAc,EAAE,CAAC;CACtB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MarketApi, PortfolioApi } from "kalshi-typescript";
|
|
2
|
+
export interface OrderValidationInput {
|
|
3
|
+
ticker: string;
|
|
4
|
+
side: "yes" | "no";
|
|
5
|
+
action: "buy" | "sell";
|
|
6
|
+
count: number;
|
|
7
|
+
price?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface OrderValidationResult {
|
|
10
|
+
valid: boolean;
|
|
11
|
+
errors: string[];
|
|
12
|
+
warnings: string[];
|
|
13
|
+
estimatedCost?: number;
|
|
14
|
+
currentBalance?: number;
|
|
15
|
+
marketStatus?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validates an order before submission
|
|
19
|
+
*
|
|
20
|
+
* Performs pre-flight checks:
|
|
21
|
+
* - Market is open for trading
|
|
22
|
+
* - Sufficient balance for buy orders
|
|
23
|
+
* - Price is reasonable (warns if far from market)
|
|
24
|
+
* - Order quantity is valid
|
|
25
|
+
*
|
|
26
|
+
* @param input - Order parameters to validate
|
|
27
|
+
* @param marketApi - Market API client
|
|
28
|
+
* @param portfolioApi - Portfolio API client
|
|
29
|
+
* @returns Validation result with errors and warnings
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateOrder(input: OrderValidationInput, marketApi: MarketApi, portfolioApi: PortfolioApi): Promise<OrderValidationResult>;
|
|
32
|
+
//# sourceMappingURL=validate-order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-order.d.ts","sourceRoot":"","sources":["../src/validate-order.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,oBAAoB,EAC3B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,qBAAqB,CAAC,CAqFhC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates an order before submission
|
|
3
|
+
*
|
|
4
|
+
* Performs pre-flight checks:
|
|
5
|
+
* - Market is open for trading
|
|
6
|
+
* - Sufficient balance for buy orders
|
|
7
|
+
* - Price is reasonable (warns if far from market)
|
|
8
|
+
* - Order quantity is valid
|
|
9
|
+
*
|
|
10
|
+
* @param input - Order parameters to validate
|
|
11
|
+
* @param marketApi - Market API client
|
|
12
|
+
* @param portfolioApi - Portfolio API client
|
|
13
|
+
* @returns Validation result with errors and warnings
|
|
14
|
+
*/
|
|
15
|
+
export async function validateOrder(input, marketApi, portfolioApi) {
|
|
16
|
+
const errors = [];
|
|
17
|
+
const warnings = [];
|
|
18
|
+
let estimatedCost = 0;
|
|
19
|
+
let currentBalance = 0;
|
|
20
|
+
let marketStatus = "unknown";
|
|
21
|
+
try {
|
|
22
|
+
// 1. Fetch market details
|
|
23
|
+
const marketResponse = await marketApi.getMarket(input.ticker);
|
|
24
|
+
const market = marketResponse.data.market;
|
|
25
|
+
marketStatus = market.status || "unknown";
|
|
26
|
+
// Check market is open
|
|
27
|
+
if (market.status?.toLowerCase() !== "open") {
|
|
28
|
+
errors.push(`Market ${input.ticker} is ${market.status}, not open for trading`);
|
|
29
|
+
}
|
|
30
|
+
// Get current market price
|
|
31
|
+
const currentPrice = input.side === "yes"
|
|
32
|
+
? input.action === "buy"
|
|
33
|
+
? market.yes_ask
|
|
34
|
+
: market.yes_bid
|
|
35
|
+
: input.action === "buy"
|
|
36
|
+
? market.no_ask
|
|
37
|
+
: market.no_bid;
|
|
38
|
+
// Warn if user price is far from market
|
|
39
|
+
if (input.price && currentPrice) {
|
|
40
|
+
const priceDiff = Math.abs(input.price - currentPrice);
|
|
41
|
+
if (priceDiff > 20) {
|
|
42
|
+
warnings.push(`Your price (${input.price}¢) is ${priceDiff}¢ away from market (${currentPrice}¢)`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 2. Fetch balance
|
|
46
|
+
const balanceResponse = await portfolioApi.getBalance();
|
|
47
|
+
currentBalance = balanceResponse.data.balance || 0;
|
|
48
|
+
// Calculate estimated cost
|
|
49
|
+
// For buy orders: cost = count * price
|
|
50
|
+
// For sell orders: no cost (you receive money)
|
|
51
|
+
if (input.action === "buy") {
|
|
52
|
+
const price = input.price || currentPrice || 50; // Default to 50¢ if unknown
|
|
53
|
+
estimatedCost = input.count * price;
|
|
54
|
+
// Check sufficient balance
|
|
55
|
+
if (estimatedCost > currentBalance) {
|
|
56
|
+
errors.push(`Insufficient balance: need ${estimatedCost}¢, have ${currentBalance}¢`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 3. Sanity checks
|
|
60
|
+
if (input.count <= 0) {
|
|
61
|
+
errors.push("Order quantity must be positive");
|
|
62
|
+
}
|
|
63
|
+
if (input.count > 1000) {
|
|
64
|
+
warnings.push("Large order size may have poor execution");
|
|
65
|
+
}
|
|
66
|
+
if (input.price && (input.price < 1 || input.price > 99)) {
|
|
67
|
+
errors.push("Price must be between 1¢ and 99¢");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
errors.push(`Validation failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
valid: errors.length === 0,
|
|
75
|
+
errors,
|
|
76
|
+
warnings,
|
|
77
|
+
estimatedCost,
|
|
78
|
+
currentBalance,
|
|
79
|
+
marketStatus,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=validate-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-order.js","sourceRoot":"","sources":["../src/validate-order.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAA2B,EAC3B,SAAoB,EACpB,YAA0B;IAE1B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,YAAY,GAAG,SAAS,CAAC;IAE7B,IAAI,CAAC;QACH,0BAA0B;QAC1B,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,YAAY,GAAG,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC;QAE1C,uBAAuB;QACvB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CACT,UAAU,KAAK,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,wBAAwB,CACnE,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,YAAY,GAChB,KAAK,CAAC,IAAI,KAAK,KAAK;YAClB,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK;gBACtB,CAAC,CAAC,MAAM,CAAC,OAAO;gBAChB,CAAC,CAAC,MAAM,CAAC,OAAO;YAClB,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK;gBACtB,CAAC,CAAC,MAAM,CAAC,MAAM;gBACf,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QAEtB,wCAAwC;QACxC,IAAI,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,YAAY,CAAC,CAAC;YACvD,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CACX,eAAe,KAAK,CAAC,KAAK,SAAS,SAAS,uBAAuB,YAAY,IAAI,CACpF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,MAAM,eAAe,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,CAAC;QACxD,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QAEnD,2BAA2B;QAC3B,uCAAuC;QACvC,+CAA+C;QAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,YAAY,IAAI,EAAE,CAAC,CAAC,4BAA4B;YAC7E,aAAa,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAEpC,2BAA2B;YAC3B,IAAI,aAAa,GAAG,cAAc,EAAE,CAAC;gBACnC,MAAM,CAAC,IAAI,CACT,8BAA8B,aAAa,WAAW,cAAc,GAAG,CACxE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CACT,sBAAsB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;QACN,QAAQ;QACR,aAAa;QACb,cAAc;QACd,YAAY;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-order.test.d.ts","sourceRoot":"","sources":["../src/validate-order.test.ts"],"names":[],"mappings":""}
|
|
@@ -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.1.
|
|
3
|
+
"version": "0.1.1",
|
|
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
|
-
|