pmxt-core 2.13.2 → 2.15.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/exchanges/kalshi/api.d.ts +7 -1
- package/dist/exchanges/kalshi/api.js +11 -2
- package/dist/exchanges/kalshi/config.d.ts +103 -0
- package/dist/exchanges/kalshi/config.js +144 -0
- package/dist/exchanges/kalshi/fetchEvents.d.ts +2 -2
- package/dist/exchanges/kalshi/fetchEvents.js +19 -16
- package/dist/exchanges/kalshi/fetchMarkets.d.ts +2 -2
- package/dist/exchanges/kalshi/fetchMarkets.js +36 -25
- package/dist/exchanges/kalshi/fetchOHLCV.d.ts +2 -2
- package/dist/exchanges/kalshi/fetchOHLCV.js +20 -17
- package/dist/exchanges/kalshi/fetchOrderBook.d.ts +2 -0
- package/dist/exchanges/kalshi/fetchOrderBook.js +60 -0
- package/dist/exchanges/kalshi/fetchTrades.d.ts +3 -0
- package/dist/exchanges/kalshi/fetchTrades.js +32 -0
- package/dist/exchanges/kalshi/index.d.ts +8 -3
- package/dist/exchanges/kalshi/index.js +82 -70
- package/dist/exchanges/kalshi/kalshi.test.js +294 -292
- package/dist/exchanges/kalshi/utils.d.ts +1 -3
- package/dist/exchanges/kalshi/utils.js +14 -16
- package/dist/exchanges/kalshi/websocket.d.ts +4 -3
- package/dist/exchanges/kalshi/websocket.js +87 -61
- package/dist/exchanges/kalshi-demo/index.d.ts +10 -0
- package/dist/exchanges/kalshi-demo/index.js +23 -0
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
- package/dist/exchanges/polymarket/api-clob.js +1 -1
- package/dist/exchanges/polymarket/api-data.d.ts +1 -1
- package/dist/exchanges/polymarket/api-data.js +1 -1
- package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
- package/dist/exchanges/polymarket/api-gamma.js +1 -1
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -1
- package/dist/server/app.js +56 -48
- package/package.json +3 -3
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fetchOrderBook = fetchOrderBook;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const validation_1 = require("../../utils/validation");
|
|
9
|
+
const errors_1 = require("./errors");
|
|
10
|
+
const config_1 = require("./config");
|
|
11
|
+
async function fetchOrderBook(baseUrl, id) {
|
|
12
|
+
(0, validation_1.validateIdFormat)(id, "OrderBook");
|
|
13
|
+
try {
|
|
14
|
+
// Check if this is a NO outcome request
|
|
15
|
+
const isNoOutcome = id.endsWith("-NO");
|
|
16
|
+
const ticker = id.replace(/-NO$/, "");
|
|
17
|
+
const url = (0, config_1.getMarketsUrl)(baseUrl, ticker, ["orderbook"]);
|
|
18
|
+
const response = await axios_1.default.get(url);
|
|
19
|
+
const data = response.data.orderbook;
|
|
20
|
+
// Structure: { yes: [[price, qty], ...], no: [[price, qty], ...] }
|
|
21
|
+
// Kalshi returns bids at their actual prices (not inverted)
|
|
22
|
+
// - yes: bids for buying YES at price X
|
|
23
|
+
// - no: bids for buying NO at price X
|
|
24
|
+
let bids;
|
|
25
|
+
let asks;
|
|
26
|
+
if (isNoOutcome) {
|
|
27
|
+
// NO outcome order book:
|
|
28
|
+
// - Bids: people buying NO (use data.no directly)
|
|
29
|
+
// - Asks: people selling NO = people buying YES (invert data.yes)
|
|
30
|
+
bids = (data.no || []).map((level) => ({
|
|
31
|
+
price: level[0] / 100,
|
|
32
|
+
size: level[1],
|
|
33
|
+
}));
|
|
34
|
+
asks = (data.yes || []).map((level) => ({
|
|
35
|
+
price: 1 - level[0] / 100, // Invert YES price to get NO ask price
|
|
36
|
+
size: level[1],
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// YES outcome order book:
|
|
41
|
+
// - Bids: people buying YES (use data.yes directly)
|
|
42
|
+
// - Asks: people selling YES = people buying NO (invert data.no)
|
|
43
|
+
bids = (data.yes || []).map((level) => ({
|
|
44
|
+
price: level[0] / 100,
|
|
45
|
+
size: level[1],
|
|
46
|
+
}));
|
|
47
|
+
asks = (data.no || []).map((level) => ({
|
|
48
|
+
price: 1 - level[0] / 100, // Invert NO price to get YES ask price
|
|
49
|
+
size: level[1],
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
// Sort bids desc, asks asc
|
|
53
|
+
bids.sort((a, b) => b.price - a.price);
|
|
54
|
+
asks.sort((a, b) => a.price - b.price);
|
|
55
|
+
return { bids, asks, timestamp: Date.now() };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fetchTrades = fetchTrades;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
async function fetchTrades(baseUrl, id, params) {
|
|
11
|
+
try {
|
|
12
|
+
const ticker = id.replace(/-NO$/, "");
|
|
13
|
+
const url = (0, config_1.getMarketsUrl)(baseUrl, undefined, ["trades"]);
|
|
14
|
+
const response = await axios_1.default.get(url, {
|
|
15
|
+
params: {
|
|
16
|
+
ticker: ticker,
|
|
17
|
+
limit: params.limit || 100,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const trades = response.data.trades || [];
|
|
21
|
+
return trades.map((t) => ({
|
|
22
|
+
id: t.trade_id,
|
|
23
|
+
timestamp: new Date(t.created_time).getTime(),
|
|
24
|
+
price: t.yes_price / 100,
|
|
25
|
+
amount: t.count,
|
|
26
|
+
side: t.taker_side === "yes" ? "buy" : "sell",
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams, OrderHistoryParams } from
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Balance, Order, Position, CreateOrderParams } from
|
|
3
|
-
import { KalshiWebSocketConfig } from
|
|
1
|
+
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams, OrderHistoryParams } from "../../BaseExchange";
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Balance, Order, Position, CreateOrderParams } from "../../types";
|
|
3
|
+
import { KalshiWebSocketConfig } from "./websocket";
|
|
4
4
|
export type { KalshiWebSocketConfig };
|
|
5
5
|
export interface KalshiExchangeOptions {
|
|
6
6
|
credentials?: ExchangeCredentials;
|
|
7
7
|
websocket?: KalshiWebSocketConfig;
|
|
8
8
|
}
|
|
9
|
+
/** @internal */
|
|
10
|
+
export interface KalshiInternalOptions extends KalshiExchangeOptions {
|
|
11
|
+
demoMode?: boolean;
|
|
12
|
+
}
|
|
9
13
|
export declare class KalshiExchange extends PredictionMarketExchange {
|
|
10
14
|
readonly has: {
|
|
11
15
|
fetchMarkets: true;
|
|
@@ -27,6 +31,7 @@ export declare class KalshiExchange extends PredictionMarketExchange {
|
|
|
27
31
|
};
|
|
28
32
|
private auth?;
|
|
29
33
|
private wsConfig?;
|
|
34
|
+
private config;
|
|
30
35
|
constructor(options?: ExchangeCredentials | KalshiExchangeOptions);
|
|
31
36
|
get name(): string;
|
|
32
37
|
protected sign(method: string, path: string, _params: Record<string, any>): Record<string, string>;
|
|
@@ -12,6 +12,7 @@ const errors_1 = require("./errors");
|
|
|
12
12
|
const errors_2 = require("../../errors");
|
|
13
13
|
const openapi_1 = require("../../utils/openapi");
|
|
14
14
|
const api_1 = require("./api");
|
|
15
|
+
const config_1 = require("./config");
|
|
15
16
|
class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
16
17
|
has = {
|
|
17
18
|
fetchMarkets: true,
|
|
@@ -33,14 +34,17 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
33
34
|
};
|
|
34
35
|
auth;
|
|
35
36
|
wsConfig;
|
|
37
|
+
config;
|
|
36
38
|
constructor(options) {
|
|
37
39
|
// Support both old signature (credentials only) and new signature (options object)
|
|
38
40
|
let credentials;
|
|
39
41
|
let wsConfig;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
let demoMode = false;
|
|
43
|
+
if (options && "credentials" in options) {
|
|
44
|
+
// New signature: KalshiExchangeOptions / KalshiInternalOptions
|
|
42
45
|
credentials = options.credentials;
|
|
43
46
|
wsConfig = options.websocket;
|
|
47
|
+
demoMode = options.demoMode || false;
|
|
44
48
|
}
|
|
45
49
|
else {
|
|
46
50
|
// Old signature: ExchangeCredentials directly
|
|
@@ -49,10 +53,11 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
49
53
|
super(credentials);
|
|
50
54
|
this.rateLimit = 100;
|
|
51
55
|
this.wsConfig = wsConfig;
|
|
56
|
+
this.config = (0, config_1.getKalshiConfig)(demoMode);
|
|
52
57
|
if (credentials?.apiKey && credentials?.privateKey) {
|
|
53
58
|
this.auth = new auth_1.KalshiAuth(credentials);
|
|
54
59
|
}
|
|
55
|
-
const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.kalshiApiSpec);
|
|
60
|
+
const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.kalshiApiSpec, this.config.apiUrl + config_1.KALSHI_PATHS.TRADE_API);
|
|
56
61
|
this.defineImplicitApi(descriptor);
|
|
57
62
|
}
|
|
58
63
|
get name() {
|
|
@@ -65,7 +70,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
65
70
|
const auth = this.ensureAuth();
|
|
66
71
|
// The implicit API passes just the spec path (e.g. /portfolio/balance),
|
|
67
72
|
// but Kalshi's signature requires the full path including /trade-api/v2.
|
|
68
|
-
return auth.getHeaders(method,
|
|
73
|
+
return auth.getHeaders(method, "/trade-api/v2" + path);
|
|
69
74
|
}
|
|
70
75
|
mapImplicitApiError(error) {
|
|
71
76
|
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
@@ -75,8 +80,8 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
75
80
|
// ----------------------------------------------------------------------------
|
|
76
81
|
ensureAuth() {
|
|
77
82
|
if (!this.auth) {
|
|
78
|
-
throw new errors_2.AuthenticationError(
|
|
79
|
-
|
|
83
|
+
throw new errors_2.AuthenticationError("Trading operations require authentication. " +
|
|
84
|
+
"Initialize KalshiExchange with credentials (apiKey and privateKey).", "Kalshi");
|
|
80
85
|
}
|
|
81
86
|
return this.auth;
|
|
82
87
|
}
|
|
@@ -93,10 +98,11 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
93
98
|
return (0, fetchOHLCV_1.fetchOHLCV)(id, params, this.callApi.bind(this));
|
|
94
99
|
}
|
|
95
100
|
async fetchOrderBook(id) {
|
|
96
|
-
(0, validation_1.validateIdFormat)(id,
|
|
97
|
-
const isNoOutcome = id.endsWith(
|
|
98
|
-
const ticker = id.replace(/-NO$/,
|
|
99
|
-
const data = (await this.callApi(
|
|
101
|
+
(0, validation_1.validateIdFormat)(id, "OrderBook");
|
|
102
|
+
const isNoOutcome = id.endsWith("-NO");
|
|
103
|
+
const ticker = id.replace(/-NO$/, "");
|
|
104
|
+
const data = (await this.callApi("GetMarketOrderbook", { ticker }))
|
|
105
|
+
.orderbook;
|
|
100
106
|
let bids;
|
|
101
107
|
let asks;
|
|
102
108
|
if (isNoOutcome) {
|
|
@@ -105,7 +111,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
105
111
|
size: level[1],
|
|
106
112
|
}));
|
|
107
113
|
asks = (data.yes || []).map((level) => ({
|
|
108
|
-
price: 1 -
|
|
114
|
+
price: 1 - level[0] / 100,
|
|
109
115
|
size: level[1],
|
|
110
116
|
}));
|
|
111
117
|
}
|
|
@@ -115,7 +121,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
115
121
|
size: level[1],
|
|
116
122
|
}));
|
|
117
123
|
asks = (data.no || []).map((level) => ({
|
|
118
|
-
price: 1 -
|
|
124
|
+
price: 1 - level[0] / 100,
|
|
119
125
|
size: level[1],
|
|
120
126
|
}));
|
|
121
127
|
}
|
|
@@ -124,47 +130,52 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
124
130
|
return { bids, asks, timestamp: Date.now() };
|
|
125
131
|
}
|
|
126
132
|
async fetchTrades(id, params) {
|
|
127
|
-
if (
|
|
133
|
+
if ("resolution" in params && params.resolution !== undefined) {
|
|
128
134
|
console.warn('[pmxt] Warning: The "resolution" parameter is deprecated for fetchTrades() and will be ignored. ' +
|
|
129
|
-
|
|
135
|
+
"It will be removed in v3.0.0. Please remove it from your code.");
|
|
130
136
|
}
|
|
131
|
-
const ticker = id.replace(/-NO$/,
|
|
132
|
-
const data = await this.callApi(
|
|
137
|
+
const ticker = id.replace(/-NO$/, "");
|
|
138
|
+
const data = await this.callApi("GetTrades", {
|
|
139
|
+
ticker,
|
|
140
|
+
limit: params.limit || 100,
|
|
141
|
+
});
|
|
133
142
|
const trades = data.trades || [];
|
|
134
143
|
return trades.map((t) => ({
|
|
135
144
|
id: t.trade_id,
|
|
136
145
|
timestamp: new Date(t.created_time).getTime(),
|
|
137
146
|
price: t.yes_price / 100,
|
|
138
147
|
amount: t.count,
|
|
139
|
-
side: t.taker_side ===
|
|
148
|
+
side: t.taker_side === "yes" ? "buy" : "sell",
|
|
140
149
|
}));
|
|
141
150
|
}
|
|
142
151
|
// ----------------------------------------------------------------------------
|
|
143
152
|
// User Data Methods
|
|
144
153
|
// ----------------------------------------------------------------------------
|
|
145
154
|
async fetchBalance() {
|
|
146
|
-
const data = await this.callApi(
|
|
155
|
+
const data = await this.callApi("GetBalance");
|
|
147
156
|
const available = data.balance / 100;
|
|
148
157
|
const total = data.portfolio_value / 100;
|
|
149
|
-
return [
|
|
150
|
-
|
|
158
|
+
return [
|
|
159
|
+
{
|
|
160
|
+
currency: "USD",
|
|
151
161
|
total,
|
|
152
162
|
available,
|
|
153
163
|
locked: total - available,
|
|
154
|
-
}
|
|
164
|
+
},
|
|
165
|
+
];
|
|
155
166
|
}
|
|
156
167
|
// ----------------------------------------------------------------------------
|
|
157
168
|
// Trading Methods
|
|
158
169
|
// ----------------------------------------------------------------------------
|
|
159
170
|
async createOrder(params) {
|
|
160
|
-
const isYesSide = params.side ===
|
|
171
|
+
const isYesSide = params.side === "buy";
|
|
161
172
|
const kalshiOrder = {
|
|
162
173
|
ticker: params.marketId,
|
|
163
174
|
client_order_id: `pmxt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
164
|
-
side: isYesSide ?
|
|
165
|
-
action: params.side ===
|
|
175
|
+
side: isYesSide ? "yes" : "no",
|
|
176
|
+
action: params.side === "buy" ? "buy" : "sell",
|
|
166
177
|
count: params.amount,
|
|
167
|
-
type: params.type ===
|
|
178
|
+
type: params.type === "limit" ? "limit" : "market",
|
|
168
179
|
};
|
|
169
180
|
if (params.price) {
|
|
170
181
|
const priceInCents = Math.round(params.price * 100);
|
|
@@ -175,55 +186,43 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
175
186
|
kalshiOrder.no_price = priceInCents;
|
|
176
187
|
}
|
|
177
188
|
}
|
|
178
|
-
const data = await this.callApi(
|
|
189
|
+
const data = await this.callApi("CreateOrder", kalshiOrder);
|
|
179
190
|
const order = data.order;
|
|
180
|
-
return
|
|
181
|
-
id: order.order_id,
|
|
182
|
-
marketId: params.marketId,
|
|
183
|
-
outcomeId: params.outcomeId,
|
|
184
|
-
side: params.side,
|
|
185
|
-
type: params.type,
|
|
186
|
-
price: params.price,
|
|
187
|
-
amount: params.amount,
|
|
188
|
-
status: this.mapKalshiOrderStatus(order.status),
|
|
189
|
-
filled: order.queue_position === 0 ? params.amount : 0,
|
|
190
|
-
remaining: order.remaining_count || params.amount,
|
|
191
|
-
timestamp: new Date(order.created_time).getTime(),
|
|
192
|
-
};
|
|
191
|
+
return this.mapKalshiOrder(order);
|
|
193
192
|
}
|
|
194
193
|
async cancelOrder(orderId) {
|
|
195
|
-
const data = await this.callApi(
|
|
194
|
+
const data = await this.callApi("CancelOrder", { order_id: orderId });
|
|
196
195
|
const order = data.order;
|
|
197
196
|
return {
|
|
198
197
|
id: order.order_id,
|
|
199
198
|
marketId: order.ticker,
|
|
200
199
|
outcomeId: order.ticker,
|
|
201
|
-
side: order.side ===
|
|
202
|
-
type:
|
|
200
|
+
side: order.side === "yes" ? "buy" : "sell",
|
|
201
|
+
type: "limit",
|
|
203
202
|
amount: order.count,
|
|
204
|
-
status:
|
|
203
|
+
status: "cancelled",
|
|
205
204
|
filled: order.count - (order.remaining_count || 0),
|
|
206
205
|
remaining: 0,
|
|
207
206
|
timestamp: new Date(order.created_time).getTime(),
|
|
208
207
|
};
|
|
209
208
|
}
|
|
210
209
|
async fetchOrder(orderId) {
|
|
211
|
-
const data = await this.callApi(
|
|
210
|
+
const data = await this.callApi("GetOrder", { order_id: orderId });
|
|
212
211
|
return this.mapKalshiOrder(data.order);
|
|
213
212
|
}
|
|
214
213
|
async fetchOpenOrders(marketId) {
|
|
215
|
-
const queryParams = { status:
|
|
214
|
+
const queryParams = { status: "resting" };
|
|
216
215
|
if (marketId) {
|
|
217
216
|
queryParams.ticker = marketId;
|
|
218
217
|
}
|
|
219
|
-
const data = await this.callApi(
|
|
218
|
+
const data = await this.callApi("GetOrders", queryParams);
|
|
220
219
|
const orders = data.orders || [];
|
|
221
220
|
return orders.map((order) => this.mapKalshiOrder(order));
|
|
222
221
|
}
|
|
223
222
|
async fetchMyTrades(params) {
|
|
224
223
|
const queryParams = {};
|
|
225
224
|
if (params?.outcomeId || params?.marketId) {
|
|
226
|
-
queryParams.ticker = (params.outcomeId || params.marketId).replace(/-NO$/,
|
|
225
|
+
queryParams.ticker = (params.outcomeId || params.marketId).replace(/-NO$/, "");
|
|
227
226
|
}
|
|
228
227
|
if (params?.since)
|
|
229
228
|
queryParams.min_ts = Math.floor(params.since.getTime() / 1000);
|
|
@@ -233,13 +232,13 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
233
232
|
queryParams.limit = params.limit;
|
|
234
233
|
if (params?.cursor)
|
|
235
234
|
queryParams.cursor = params.cursor;
|
|
236
|
-
const data = await this.callApi(
|
|
235
|
+
const data = await this.callApi("GetFills", queryParams);
|
|
237
236
|
return (data.fills || []).map((f) => ({
|
|
238
237
|
id: f.fill_id,
|
|
239
238
|
timestamp: new Date(f.created_time).getTime(),
|
|
240
239
|
price: f.yes_price / 100,
|
|
241
240
|
amount: f.count,
|
|
242
|
-
side: f.side ===
|
|
241
|
+
side: f.side === "yes" ? "buy" : "sell",
|
|
243
242
|
orderId: f.order_id,
|
|
244
243
|
}));
|
|
245
244
|
}
|
|
@@ -253,7 +252,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
253
252
|
queryParams.limit = params.limit;
|
|
254
253
|
if (params?.cursor)
|
|
255
254
|
queryParams.cursor = params.cursor;
|
|
256
|
-
const data = await this.callApi(
|
|
255
|
+
const data = await this.callApi("GetHistoricalOrders", queryParams);
|
|
257
256
|
return (data.orders || []).map((o) => this.mapKalshiOrder(o));
|
|
258
257
|
}
|
|
259
258
|
async fetchAllOrders(params) {
|
|
@@ -269,12 +268,15 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
269
268
|
const historicalParams = { ...queryParams };
|
|
270
269
|
delete historicalParams.min_ts; // GetHistoricalOrders only supports max_ts
|
|
271
270
|
const [liveData, historicalData] = await Promise.all([
|
|
272
|
-
this.callApi(
|
|
273
|
-
this.callApi(
|
|
271
|
+
this.callApi("GetOrders", queryParams),
|
|
272
|
+
this.callApi("GetHistoricalOrders", historicalParams),
|
|
274
273
|
]);
|
|
275
274
|
const seen = new Set();
|
|
276
275
|
const all = [];
|
|
277
|
-
for (const o of [
|
|
276
|
+
for (const o of [
|
|
277
|
+
...(liveData.orders || []),
|
|
278
|
+
...(historicalData.orders || []),
|
|
279
|
+
]) {
|
|
278
280
|
if (!seen.has(o.order_id)) {
|
|
279
281
|
seen.add(o.order_id);
|
|
280
282
|
all.push(this.mapKalshiOrder(o));
|
|
@@ -283,7 +285,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
283
285
|
return all.sort((a, b) => b.timestamp - a.timestamp);
|
|
284
286
|
}
|
|
285
287
|
async fetchPositions() {
|
|
286
|
-
const data = await this.callApi(
|
|
288
|
+
const data = await this.callApi("GetPositions");
|
|
287
289
|
const positions = data.market_positions || [];
|
|
288
290
|
return positions.map((pos) => {
|
|
289
291
|
const absPosition = Math.abs(pos.position);
|
|
@@ -306,8 +308,8 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
306
308
|
id: order.order_id,
|
|
307
309
|
marketId: order.ticker,
|
|
308
310
|
outcomeId: order.ticker,
|
|
309
|
-
side: order.side ===
|
|
310
|
-
type: order.type ===
|
|
311
|
+
side: order.side === "yes" ? "buy" : "sell",
|
|
312
|
+
type: order.type === "limit" ? "limit" : "market",
|
|
311
313
|
price: order.yes_price ? order.yes_price / 100 : undefined,
|
|
312
314
|
amount: order.count,
|
|
313
315
|
status: this.mapKalshiOrderStatus(order.status),
|
|
@@ -318,17 +320,17 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
318
320
|
}
|
|
319
321
|
// Helper to map Kalshi order status to unified status
|
|
320
322
|
mapKalshiOrderStatus(status) {
|
|
321
|
-
switch ((status ??
|
|
322
|
-
case
|
|
323
|
-
return
|
|
324
|
-
case
|
|
325
|
-
case
|
|
326
|
-
return
|
|
327
|
-
case
|
|
328
|
-
case
|
|
329
|
-
return
|
|
323
|
+
switch ((status ?? "").toLowerCase()) {
|
|
324
|
+
case "resting":
|
|
325
|
+
return "open";
|
|
326
|
+
case "canceled":
|
|
327
|
+
case "cancelled":
|
|
328
|
+
return "cancelled";
|
|
329
|
+
case "executed":
|
|
330
|
+
case "filled":
|
|
331
|
+
return "filled";
|
|
330
332
|
default:
|
|
331
|
-
return
|
|
333
|
+
return "open";
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
336
|
// ----------------------------------------------------------------------------
|
|
@@ -338,19 +340,29 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
338
340
|
async watchOrderBook(id, limit) {
|
|
339
341
|
const auth = this.ensureAuth();
|
|
340
342
|
if (!this.ws) {
|
|
341
|
-
|
|
343
|
+
// Merge wsConfig with wsUrl from config
|
|
344
|
+
const wsConfigWithUrl = {
|
|
345
|
+
...this.wsConfig,
|
|
346
|
+
wsUrl: this.wsConfig?.wsUrl || this.config.wsUrl,
|
|
347
|
+
};
|
|
348
|
+
this.ws = new websocket_1.KalshiWebSocket(auth, wsConfigWithUrl);
|
|
342
349
|
}
|
|
343
350
|
// Normalize ticker (strip -NO suffix if present)
|
|
344
|
-
const marketTicker = id.replace(/-NO$/,
|
|
351
|
+
const marketTicker = id.replace(/-NO$/, "");
|
|
345
352
|
return this.ws.watchOrderBook(marketTicker);
|
|
346
353
|
}
|
|
347
354
|
async watchTrades(id, since, limit) {
|
|
348
355
|
const auth = this.ensureAuth();
|
|
349
356
|
if (!this.ws) {
|
|
350
|
-
|
|
357
|
+
// Merge wsConfig with wsUrl from config
|
|
358
|
+
const wsConfigWithUrl = {
|
|
359
|
+
...this.wsConfig,
|
|
360
|
+
wsUrl: this.wsConfig?.wsUrl || this.config.wsUrl,
|
|
361
|
+
};
|
|
362
|
+
this.ws = new websocket_1.KalshiWebSocket(auth, wsConfigWithUrl);
|
|
351
363
|
}
|
|
352
364
|
// Normalize ticker (strip -NO suffix if present)
|
|
353
|
-
const marketTicker = id.replace(/-NO$/,
|
|
365
|
+
const marketTicker = id.replace(/-NO$/, "");
|
|
354
366
|
return this.ws.watchTrades(marketTicker);
|
|
355
367
|
}
|
|
356
368
|
async close() {
|