pmxt-core 2.11.0 → 2.12.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/BaseExchange.d.ts +58 -2
- package/dist/BaseExchange.js +70 -1
- package/dist/exchanges/baozi/index.d.ts +3 -0
- package/dist/exchanges/baozi/index.js +3 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/kalshi/index.d.ts +9 -2
- package/dist/exchanges/kalshi/index.js +83 -27
- package/dist/exchanges/kalshi/kalshi.test.js +180 -0
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/limitless/index.d.ts +8 -2
- package/dist/exchanges/limitless/index.js +65 -0
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/myriad/index.d.ts +6 -2
- package/dist/exchanges/myriad/index.js +31 -0
- 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/polymarket/index.d.ts +6 -2
- package/dist/exchanges/polymarket/index.js +26 -0
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/index.d.ts +6 -2
- package/dist/exchanges/probable/index.js +22 -0
- package/dist/types.d.ts +3 -0
- package/package.json +3 -3
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, CandleInterval, OrderBook, Trade, Order, Position, Balance, CreateOrderParams } from './types';
|
|
1
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, CandleInterval, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from './types';
|
|
2
2
|
import { ExecutionPriceResult } from './utils/math';
|
|
3
3
|
import { AxiosInstance } from 'axios';
|
|
4
4
|
export interface ApiEndpoint {
|
|
@@ -59,6 +59,21 @@ export interface TradesParams {
|
|
|
59
59
|
end?: Date;
|
|
60
60
|
limit?: number;
|
|
61
61
|
}
|
|
62
|
+
export interface MyTradesParams {
|
|
63
|
+
outcomeId?: string;
|
|
64
|
+
marketId?: string;
|
|
65
|
+
since?: Date;
|
|
66
|
+
until?: Date;
|
|
67
|
+
limit?: number;
|
|
68
|
+
cursor?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface OrderHistoryParams {
|
|
71
|
+
marketId?: string;
|
|
72
|
+
since?: Date;
|
|
73
|
+
until?: Date;
|
|
74
|
+
limit?: number;
|
|
75
|
+
cursor?: string;
|
|
76
|
+
}
|
|
62
77
|
export type MarketFilterCriteria = {
|
|
63
78
|
text?: string;
|
|
64
79
|
searchIn?: ('title' | 'description' | 'category' | 'tags' | 'outcomes')[];
|
|
@@ -126,6 +141,9 @@ export interface ExchangeHas {
|
|
|
126
141
|
fetchBalance: ExchangeCapability;
|
|
127
142
|
watchOrderBook: ExchangeCapability;
|
|
128
143
|
watchTrades: ExchangeCapability;
|
|
144
|
+
fetchMyTrades: ExchangeCapability;
|
|
145
|
+
fetchClosedOrders: ExchangeCapability;
|
|
146
|
+
fetchAllOrders: ExchangeCapability;
|
|
129
147
|
}
|
|
130
148
|
export interface ExchangeCredentials {
|
|
131
149
|
apiKey?: string;
|
|
@@ -135,6 +153,20 @@ export interface ExchangeCredentials {
|
|
|
135
153
|
signatureType?: number | string;
|
|
136
154
|
funderAddress?: string;
|
|
137
155
|
}
|
|
156
|
+
export interface ExchangeOptions {
|
|
157
|
+
/**
|
|
158
|
+
* How long (ms) a market snapshot created by `fetchMarketsPaginated` remains valid
|
|
159
|
+
* before being discarded and re-fetched from the API on the next call.
|
|
160
|
+
* Defaults to 0 (no TTL — the snapshot is re-fetched on every initial call).
|
|
161
|
+
*/
|
|
162
|
+
snapshotTTL?: number;
|
|
163
|
+
}
|
|
164
|
+
/** Shape returned by fetchMarketsPaginated */
|
|
165
|
+
export interface PaginatedMarketsResult {
|
|
166
|
+
data: UnifiedMarket[];
|
|
167
|
+
total: number;
|
|
168
|
+
nextCursor?: string;
|
|
169
|
+
}
|
|
138
170
|
export declare abstract class PredictionMarketExchange {
|
|
139
171
|
[key: string]: any;
|
|
140
172
|
protected credentials?: ExchangeCredentials;
|
|
@@ -143,6 +175,8 @@ export declare abstract class PredictionMarketExchange {
|
|
|
143
175
|
enableRateLimit: boolean;
|
|
144
176
|
private _rateLimit;
|
|
145
177
|
private _throttler;
|
|
178
|
+
private _snapshotTTL;
|
|
179
|
+
private _snapshot?;
|
|
146
180
|
get rateLimit(): number;
|
|
147
181
|
set rateLimit(value: number);
|
|
148
182
|
markets: Record<string, UnifiedMarket>;
|
|
@@ -151,7 +185,7 @@ export declare abstract class PredictionMarketExchange {
|
|
|
151
185
|
protected apiDescriptor?: ApiDescriptor;
|
|
152
186
|
private apiDescriptors;
|
|
153
187
|
readonly has: ExchangeHas;
|
|
154
|
-
constructor(credentials?: ExchangeCredentials);
|
|
188
|
+
constructor(credentials?: ExchangeCredentials, options?: ExchangeOptions);
|
|
155
189
|
abstract get name(): string;
|
|
156
190
|
/**
|
|
157
191
|
* Load and cache all markets from the exchange into `this.markets` and `this.marketsBySlug`.
|
|
@@ -213,6 +247,25 @@ export declare abstract class PredictionMarketExchange {
|
|
|
213
247
|
* markets = exchange.fetch_markets(slug='will-trump-win')
|
|
214
248
|
*/
|
|
215
249
|
fetchMarkets(params?: MarketFetchParams): Promise<UnifiedMarket[]>;
|
|
250
|
+
/**
|
|
251
|
+
* Fetch markets with cursor-based pagination backed by a stable in-memory snapshot.
|
|
252
|
+
*
|
|
253
|
+
* On the first call (or when no cursor is supplied), fetches all markets once and
|
|
254
|
+
* caches them. Subsequent calls with a cursor returned from a previous call slice
|
|
255
|
+
* directly from the cached snapshot — no additional API calls are made.
|
|
256
|
+
*
|
|
257
|
+
* The snapshot is invalidated after `snapshotTTL` ms (configured via `ExchangeOptions`
|
|
258
|
+
* in the constructor). A request using a cursor from an expired snapshot throws
|
|
259
|
+
* `'Cursor has expired'`.
|
|
260
|
+
*
|
|
261
|
+
* @param params.limit - Page size (default: return all markets)
|
|
262
|
+
* @param params.cursor - Opaque cursor returned by a previous call
|
|
263
|
+
* @returns PaginatedMarketsResult with data, total, and optional nextCursor
|
|
264
|
+
*/
|
|
265
|
+
fetchMarketsPaginated(params?: {
|
|
266
|
+
limit?: number;
|
|
267
|
+
cursor?: string;
|
|
268
|
+
}): Promise<PaginatedMarketsResult>;
|
|
216
269
|
/**
|
|
217
270
|
* Fetch events with optional keyword search.
|
|
218
271
|
* Events group related markets together (e.g., "Who will be Fed Chair?" contains multiple candidate markets).
|
|
@@ -450,6 +503,9 @@ export declare abstract class PredictionMarketExchange {
|
|
|
450
503
|
* orders = exchange.fetch_open_orders('FED-25JAN')
|
|
451
504
|
*/
|
|
452
505
|
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
506
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
507
|
+
fetchClosedOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
508
|
+
fetchAllOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
453
509
|
/**
|
|
454
510
|
* Fetch current user positions across all markets.
|
|
455
511
|
*
|
package/dist/BaseExchange.js
CHANGED
|
@@ -18,6 +18,9 @@ class PredictionMarketExchange {
|
|
|
18
18
|
enableRateLimit = true;
|
|
19
19
|
_rateLimit = 1000;
|
|
20
20
|
_throttler;
|
|
21
|
+
// Snapshot state for cursor-based pagination
|
|
22
|
+
_snapshotTTL;
|
|
23
|
+
_snapshot;
|
|
21
24
|
get rateLimit() {
|
|
22
25
|
return this._rateLimit;
|
|
23
26
|
}
|
|
@@ -50,9 +53,13 @@ class PredictionMarketExchange {
|
|
|
50
53
|
fetchBalance: false,
|
|
51
54
|
watchOrderBook: false,
|
|
52
55
|
watchTrades: false,
|
|
56
|
+
fetchMyTrades: false,
|
|
57
|
+
fetchClosedOrders: false,
|
|
58
|
+
fetchAllOrders: false,
|
|
53
59
|
};
|
|
54
|
-
constructor(credentials) {
|
|
60
|
+
constructor(credentials, options) {
|
|
55
61
|
this.credentials = credentials;
|
|
62
|
+
this._snapshotTTL = options?.snapshotTTL ?? 0;
|
|
56
63
|
this.http = axios_1.default.create();
|
|
57
64
|
this._throttler = new throttler_1.Throttler({
|
|
58
65
|
refillRate: 1 / this._rateLimit,
|
|
@@ -177,6 +184,59 @@ class PredictionMarketExchange {
|
|
|
177
184
|
async fetchMarkets(params) {
|
|
178
185
|
return this.fetchMarketsImpl(params);
|
|
179
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Fetch markets with cursor-based pagination backed by a stable in-memory snapshot.
|
|
189
|
+
*
|
|
190
|
+
* On the first call (or when no cursor is supplied), fetches all markets once and
|
|
191
|
+
* caches them. Subsequent calls with a cursor returned from a previous call slice
|
|
192
|
+
* directly from the cached snapshot — no additional API calls are made.
|
|
193
|
+
*
|
|
194
|
+
* The snapshot is invalidated after `snapshotTTL` ms (configured via `ExchangeOptions`
|
|
195
|
+
* in the constructor). A request using a cursor from an expired snapshot throws
|
|
196
|
+
* `'Cursor has expired'`.
|
|
197
|
+
*
|
|
198
|
+
* @param params.limit - Page size (default: return all markets)
|
|
199
|
+
* @param params.cursor - Opaque cursor returned by a previous call
|
|
200
|
+
* @returns PaginatedMarketsResult with data, total, and optional nextCursor
|
|
201
|
+
*/
|
|
202
|
+
async fetchMarketsPaginated(params) {
|
|
203
|
+
const limit = params?.limit;
|
|
204
|
+
const cursor = params?.cursor;
|
|
205
|
+
if (cursor) {
|
|
206
|
+
// Cursor encodes: snapshotId:offset
|
|
207
|
+
const sep = cursor.indexOf(':');
|
|
208
|
+
const snapshotId = cursor.substring(0, sep);
|
|
209
|
+
const offset = parseInt(cursor.substring(sep + 1), 10);
|
|
210
|
+
if (!this._snapshot ||
|
|
211
|
+
this._snapshot.id !== snapshotId ||
|
|
212
|
+
(this._snapshotTTL > 0 && Date.now() - this._snapshot.takenAt > this._snapshotTTL)) {
|
|
213
|
+
throw new Error('Cursor has expired');
|
|
214
|
+
}
|
|
215
|
+
const markets = this._snapshot.markets;
|
|
216
|
+
const slice = limit !== undefined ? markets.slice(offset, offset + limit) : markets.slice(offset);
|
|
217
|
+
const nextOffset = offset + slice.length;
|
|
218
|
+
const nextCursor = nextOffset < markets.length ? `${snapshotId}:${nextOffset}` : undefined;
|
|
219
|
+
return { data: slice, total: markets.length, nextCursor };
|
|
220
|
+
}
|
|
221
|
+
// No cursor — (re)fetch snapshot
|
|
222
|
+
if (!this._snapshot ||
|
|
223
|
+
this._snapshotTTL === 0 ||
|
|
224
|
+
Date.now() - this._snapshot.takenAt > this._snapshotTTL) {
|
|
225
|
+
const markets = await this.fetchMarketsImpl();
|
|
226
|
+
this._snapshot = {
|
|
227
|
+
markets,
|
|
228
|
+
takenAt: Date.now(),
|
|
229
|
+
id: Math.random().toString(36).slice(2),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
const markets = this._snapshot.markets;
|
|
233
|
+
if (!limit) {
|
|
234
|
+
return { data: markets, total: markets.length, nextCursor: undefined };
|
|
235
|
+
}
|
|
236
|
+
const slice = markets.slice(0, limit);
|
|
237
|
+
const nextCursor = limit < markets.length ? `${this._snapshot.id}:${limit}` : undefined;
|
|
238
|
+
return { data: slice, total: markets.length, nextCursor };
|
|
239
|
+
}
|
|
180
240
|
/**
|
|
181
241
|
* Fetch events with optional keyword search.
|
|
182
242
|
* Events group related markets together (e.g., "Who will be Fed Chair?" contains multiple candidate markets).
|
|
@@ -471,6 +531,15 @@ class PredictionMarketExchange {
|
|
|
471
531
|
async fetchOpenOrders(marketId) {
|
|
472
532
|
throw new Error("Method fetchOpenOrders not implemented.");
|
|
473
533
|
}
|
|
534
|
+
async fetchMyTrades(params) {
|
|
535
|
+
throw new Error("Method fetchMyTrades not implemented.");
|
|
536
|
+
}
|
|
537
|
+
async fetchClosedOrders(params) {
|
|
538
|
+
throw new Error("Method fetchClosedOrders not implemented.");
|
|
539
|
+
}
|
|
540
|
+
async fetchAllOrders(params) {
|
|
541
|
+
throw new Error("Method fetchAllOrders not implemented.");
|
|
542
|
+
}
|
|
474
543
|
/**
|
|
475
544
|
* Fetch current user positions across all markets.
|
|
476
545
|
*
|
|
@@ -19,6 +19,9 @@ export declare class BaoziExchange extends PredictionMarketExchange {
|
|
|
19
19
|
fetchBalance: true;
|
|
20
20
|
watchOrderBook: true;
|
|
21
21
|
watchTrades: false;
|
|
22
|
+
fetchMyTrades: false;
|
|
23
|
+
fetchClosedOrders: false;
|
|
24
|
+
fetchAllOrders: false;
|
|
22
25
|
};
|
|
23
26
|
private auth?;
|
|
24
27
|
private connection;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.786Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const kalshiApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.kalshiApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.786Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Balance, Order, Position, CreateOrderParams } from '../../types';
|
|
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
3
|
import { KalshiWebSocketConfig } from './websocket';
|
|
4
4
|
export type { KalshiWebSocketConfig };
|
|
5
5
|
export interface KalshiExchangeOptions {
|
|
@@ -21,6 +21,9 @@ export declare class KalshiExchange extends PredictionMarketExchange {
|
|
|
21
21
|
fetchBalance: true;
|
|
22
22
|
watchOrderBook: true;
|
|
23
23
|
watchTrades: true;
|
|
24
|
+
fetchMyTrades: true;
|
|
25
|
+
fetchClosedOrders: true;
|
|
26
|
+
fetchAllOrders: true;
|
|
24
27
|
};
|
|
25
28
|
private auth?;
|
|
26
29
|
private wsConfig?;
|
|
@@ -39,7 +42,11 @@ export declare class KalshiExchange extends PredictionMarketExchange {
|
|
|
39
42
|
cancelOrder(orderId: string): Promise<Order>;
|
|
40
43
|
fetchOrder(orderId: string): Promise<Order>;
|
|
41
44
|
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
45
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
46
|
+
fetchClosedOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
47
|
+
fetchAllOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
42
48
|
fetchPositions(): Promise<Position[]>;
|
|
49
|
+
private mapKalshiOrder;
|
|
43
50
|
private mapKalshiOrderStatus;
|
|
44
51
|
private ws?;
|
|
45
52
|
watchOrderBook(id: string, limit?: number): Promise<OrderBook>;
|
|
@@ -27,6 +27,9 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
27
27
|
fetchBalance: true,
|
|
28
28
|
watchOrderBook: true,
|
|
29
29
|
watchTrades: true,
|
|
30
|
+
fetchMyTrades: true,
|
|
31
|
+
fetchClosedOrders: true,
|
|
32
|
+
fetchAllOrders: true,
|
|
30
33
|
};
|
|
31
34
|
auth;
|
|
32
35
|
wsConfig;
|
|
@@ -206,20 +209,7 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
206
209
|
}
|
|
207
210
|
async fetchOrder(orderId) {
|
|
208
211
|
const data = await this.callApi('GetOrder', { order_id: orderId });
|
|
209
|
-
|
|
210
|
-
return {
|
|
211
|
-
id: order.order_id,
|
|
212
|
-
marketId: order.ticker,
|
|
213
|
-
outcomeId: order.ticker,
|
|
214
|
-
side: order.side === 'yes' ? 'buy' : 'sell',
|
|
215
|
-
type: order.type === 'limit' ? 'limit' : 'market',
|
|
216
|
-
price: order.yes_price ? order.yes_price / 100 : undefined,
|
|
217
|
-
amount: order.count,
|
|
218
|
-
status: this.mapKalshiOrderStatus(order.status),
|
|
219
|
-
filled: order.count - (order.remaining_count || 0),
|
|
220
|
-
remaining: order.remaining_count || 0,
|
|
221
|
-
timestamp: new Date(order.created_time).getTime(),
|
|
222
|
-
};
|
|
212
|
+
return this.mapKalshiOrder(data.order);
|
|
223
213
|
}
|
|
224
214
|
async fetchOpenOrders(marketId) {
|
|
225
215
|
const queryParams = { status: 'resting' };
|
|
@@ -228,20 +218,70 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
228
218
|
}
|
|
229
219
|
const data = await this.callApi('GetOrders', queryParams);
|
|
230
220
|
const orders = data.orders || [];
|
|
231
|
-
return orders.map((order) => (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
221
|
+
return orders.map((order) => this.mapKalshiOrder(order));
|
|
222
|
+
}
|
|
223
|
+
async fetchMyTrades(params) {
|
|
224
|
+
const queryParams = {};
|
|
225
|
+
if (params?.outcomeId || params?.marketId) {
|
|
226
|
+
queryParams.ticker = (params.outcomeId || params.marketId).replace(/-NO$/, '');
|
|
227
|
+
}
|
|
228
|
+
if (params?.since)
|
|
229
|
+
queryParams.min_ts = Math.floor(params.since.getTime() / 1000);
|
|
230
|
+
if (params?.until)
|
|
231
|
+
queryParams.max_ts = Math.floor(params.until.getTime() / 1000);
|
|
232
|
+
if (params?.limit)
|
|
233
|
+
queryParams.limit = params.limit;
|
|
234
|
+
if (params?.cursor)
|
|
235
|
+
queryParams.cursor = params.cursor;
|
|
236
|
+
const data = await this.callApi('GetFills', queryParams);
|
|
237
|
+
return (data.fills || []).map((f) => ({
|
|
238
|
+
id: f.fill_id,
|
|
239
|
+
timestamp: new Date(f.created_time).getTime(),
|
|
240
|
+
price: f.yes_price / 100,
|
|
241
|
+
amount: f.count,
|
|
242
|
+
side: f.side === 'yes' ? 'buy' : 'sell',
|
|
243
|
+
orderId: f.order_id,
|
|
243
244
|
}));
|
|
244
245
|
}
|
|
246
|
+
async fetchClosedOrders(params) {
|
|
247
|
+
const queryParams = {};
|
|
248
|
+
if (params?.marketId)
|
|
249
|
+
queryParams.ticker = params.marketId;
|
|
250
|
+
if (params?.until)
|
|
251
|
+
queryParams.max_ts = Math.floor(params.until.getTime() / 1000);
|
|
252
|
+
if (params?.limit)
|
|
253
|
+
queryParams.limit = params.limit;
|
|
254
|
+
if (params?.cursor)
|
|
255
|
+
queryParams.cursor = params.cursor;
|
|
256
|
+
const data = await this.callApi('GetHistoricalOrders', queryParams);
|
|
257
|
+
return (data.orders || []).map((o) => this.mapKalshiOrder(o));
|
|
258
|
+
}
|
|
259
|
+
async fetchAllOrders(params) {
|
|
260
|
+
const queryParams = {};
|
|
261
|
+
if (params?.marketId)
|
|
262
|
+
queryParams.ticker = params.marketId;
|
|
263
|
+
if (params?.since)
|
|
264
|
+
queryParams.min_ts = Math.floor(params.since.getTime() / 1000);
|
|
265
|
+
if (params?.until)
|
|
266
|
+
queryParams.max_ts = Math.floor(params.until.getTime() / 1000);
|
|
267
|
+
if (params?.limit)
|
|
268
|
+
queryParams.limit = params.limit;
|
|
269
|
+
const historicalParams = { ...queryParams };
|
|
270
|
+
delete historicalParams.min_ts; // GetHistoricalOrders only supports max_ts
|
|
271
|
+
const [liveData, historicalData] = await Promise.all([
|
|
272
|
+
this.callApi('GetOrders', queryParams),
|
|
273
|
+
this.callApi('GetHistoricalOrders', historicalParams),
|
|
274
|
+
]);
|
|
275
|
+
const seen = new Set();
|
|
276
|
+
const all = [];
|
|
277
|
+
for (const o of [...(liveData.orders || []), ...(historicalData.orders || [])]) {
|
|
278
|
+
if (!seen.has(o.order_id)) {
|
|
279
|
+
seen.add(o.order_id);
|
|
280
|
+
all.push(this.mapKalshiOrder(o));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return all.sort((a, b) => b.timestamp - a.timestamp);
|
|
284
|
+
}
|
|
245
285
|
async fetchPositions() {
|
|
246
286
|
const data = await this.callApi('GetPositions');
|
|
247
287
|
const positions = data.market_positions || [];
|
|
@@ -260,9 +300,25 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
260
300
|
};
|
|
261
301
|
});
|
|
262
302
|
}
|
|
303
|
+
// Helper to map a raw Kalshi order object to a unified Order
|
|
304
|
+
mapKalshiOrder(order) {
|
|
305
|
+
return {
|
|
306
|
+
id: order.order_id,
|
|
307
|
+
marketId: order.ticker,
|
|
308
|
+
outcomeId: order.ticker,
|
|
309
|
+
side: order.side === 'yes' ? 'buy' : 'sell',
|
|
310
|
+
type: order.type === 'limit' ? 'limit' : 'market',
|
|
311
|
+
price: order.yes_price ? order.yes_price / 100 : undefined,
|
|
312
|
+
amount: order.count,
|
|
313
|
+
status: this.mapKalshiOrderStatus(order.status),
|
|
314
|
+
filled: order.count - (order.remaining_count || 0),
|
|
315
|
+
remaining: order.remaining_count || 0,
|
|
316
|
+
timestamp: new Date(order.created_time).getTime(),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
263
319
|
// Helper to map Kalshi order status to unified status
|
|
264
320
|
mapKalshiOrderStatus(status) {
|
|
265
|
-
switch (status.toLowerCase()) {
|
|
321
|
+
switch ((status ?? '').toLowerCase()) {
|
|
266
322
|
case 'resting':
|
|
267
323
|
return 'open';
|
|
268
324
|
case 'canceled':
|
|
@@ -318,6 +318,186 @@ describe('KalshiExchange', () => {
|
|
|
318
318
|
});
|
|
319
319
|
});
|
|
320
320
|
});
|
|
321
|
+
describe('Trading History Methods', () => {
|
|
322
|
+
beforeEach(() => {
|
|
323
|
+
exchange = new kalshi_1.KalshiExchange(mockCredentials);
|
|
324
|
+
});
|
|
325
|
+
describe('fetchMyTrades', () => {
|
|
326
|
+
it('should map GetFills response to UserTrade array', async () => {
|
|
327
|
+
const mockResponse = {
|
|
328
|
+
data: {
|
|
329
|
+
fills: [
|
|
330
|
+
{
|
|
331
|
+
fill_id: 'fill-abc',
|
|
332
|
+
order_id: 'order-123',
|
|
333
|
+
created_time: '2026-01-13T12:00:00Z',
|
|
334
|
+
yes_price: 55,
|
|
335
|
+
count: 10,
|
|
336
|
+
side: 'yes',
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
fill_id: 'fill-def',
|
|
340
|
+
order_id: 'order-456',
|
|
341
|
+
created_time: '2026-01-13T13:00:00Z',
|
|
342
|
+
yes_price: 45,
|
|
343
|
+
count: 5,
|
|
344
|
+
side: 'no',
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
mockAxiosInstance.request.mockResolvedValue(mockResponse);
|
|
350
|
+
const trades = await exchange.fetchMyTrades();
|
|
351
|
+
expect(Array.isArray(trades)).toBe(true);
|
|
352
|
+
expect(trades).toHaveLength(2);
|
|
353
|
+
expect(trades[0].id).toBe('fill-abc');
|
|
354
|
+
expect(trades[0].orderId).toBe('order-123');
|
|
355
|
+
expect(trades[0].price).toBe(0.55); // 55 / 100
|
|
356
|
+
expect(trades[0].amount).toBe(10);
|
|
357
|
+
expect(trades[0].side).toBe('buy'); // 'yes' => 'buy'
|
|
358
|
+
expect(trades[1].id).toBe('fill-def');
|
|
359
|
+
expect(trades[1].side).toBe('sell'); // 'no' => 'sell'
|
|
360
|
+
expect(trades[1].price).toBe(0.45); // 45 / 100
|
|
361
|
+
});
|
|
362
|
+
it('should pass outcomeId as ticker (stripping -NO suffix) and date params', async () => {
|
|
363
|
+
const mockResponse = { data: { fills: [] } };
|
|
364
|
+
mockAxiosInstance.request.mockResolvedValue(mockResponse);
|
|
365
|
+
await exchange.fetchMyTrades({
|
|
366
|
+
outcomeId: 'TEST-MARKET-NO',
|
|
367
|
+
since: new Date('2026-01-01T00:00:00Z'),
|
|
368
|
+
until: new Date('2026-01-31T00:00:00Z'),
|
|
369
|
+
limit: 50,
|
|
370
|
+
});
|
|
371
|
+
expect(mockAxiosInstance.request).toHaveBeenCalledWith(expect.objectContaining({
|
|
372
|
+
params: expect.objectContaining({
|
|
373
|
+
ticker: 'TEST-MARKET', // -NO stripped
|
|
374
|
+
min_ts: Math.floor(new Date('2026-01-01T00:00:00Z').getTime() / 1000),
|
|
375
|
+
max_ts: Math.floor(new Date('2026-01-31T00:00:00Z').getTime() / 1000),
|
|
376
|
+
limit: 50,
|
|
377
|
+
}),
|
|
378
|
+
}));
|
|
379
|
+
});
|
|
380
|
+
it('should return empty array when fills is missing', async () => {
|
|
381
|
+
mockAxiosInstance.request.mockResolvedValue({ data: {} });
|
|
382
|
+
const trades = await exchange.fetchMyTrades();
|
|
383
|
+
expect(trades).toHaveLength(0);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
describe('fetchClosedOrders', () => {
|
|
387
|
+
it('should map GetHistoricalOrders response to Order array', async () => {
|
|
388
|
+
const mockResponse = {
|
|
389
|
+
data: {
|
|
390
|
+
orders: [
|
|
391
|
+
{
|
|
392
|
+
order_id: 'hist-order-1',
|
|
393
|
+
ticker: 'TEST-MARKET',
|
|
394
|
+
side: 'yes',
|
|
395
|
+
type: 'limit',
|
|
396
|
+
yes_price: 60,
|
|
397
|
+
count: 8,
|
|
398
|
+
remaining_count: 0,
|
|
399
|
+
status: 'executed',
|
|
400
|
+
created_time: '2026-01-10T10:00:00Z',
|
|
401
|
+
},
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
mockAxiosInstance.request.mockResolvedValue(mockResponse);
|
|
406
|
+
const orders = await exchange.fetchClosedOrders();
|
|
407
|
+
expect(orders).toHaveLength(1);
|
|
408
|
+
expect(orders[0].id).toBe('hist-order-1');
|
|
409
|
+
expect(orders[0].marketId).toBe('TEST-MARKET');
|
|
410
|
+
expect(orders[0].side).toBe('buy'); // 'yes' => 'buy'
|
|
411
|
+
expect(orders[0].price).toBe(0.60); // 60 / 100
|
|
412
|
+
expect(orders[0].amount).toBe(8);
|
|
413
|
+
expect(orders[0].filled).toBe(8); // count - remaining_count (0)
|
|
414
|
+
expect(orders[0].remaining).toBe(0);
|
|
415
|
+
expect(orders[0].status).toBe('filled'); // 'executed' => 'filled'
|
|
416
|
+
});
|
|
417
|
+
it('should pass marketId as ticker and limit', async () => {
|
|
418
|
+
const mockResponse = { data: { orders: [] } };
|
|
419
|
+
mockAxiosInstance.request.mockResolvedValue(mockResponse);
|
|
420
|
+
await exchange.fetchClosedOrders({ marketId: 'TEST-MARKET', limit: 25 });
|
|
421
|
+
expect(mockAxiosInstance.request).toHaveBeenCalledWith(expect.objectContaining({
|
|
422
|
+
params: expect.objectContaining({
|
|
423
|
+
ticker: 'TEST-MARKET',
|
|
424
|
+
limit: 25,
|
|
425
|
+
}),
|
|
426
|
+
}));
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
describe('fetchAllOrders', () => {
|
|
430
|
+
it('should merge live and historical orders, dedup, and sort descending by timestamp', async () => {
|
|
431
|
+
const liveResponse = {
|
|
432
|
+
data: {
|
|
433
|
+
orders: [
|
|
434
|
+
{
|
|
435
|
+
order_id: 'order-live-1',
|
|
436
|
+
ticker: 'TEST',
|
|
437
|
+
side: 'yes',
|
|
438
|
+
type: 'limit',
|
|
439
|
+
yes_price: 50,
|
|
440
|
+
count: 5,
|
|
441
|
+
remaining_count: 5,
|
|
442
|
+
status: 'resting',
|
|
443
|
+
created_time: '2026-01-15T10:00:00Z',
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
// duplicate that also appears in historical
|
|
447
|
+
order_id: 'order-hist-1',
|
|
448
|
+
ticker: 'TEST',
|
|
449
|
+
side: 'no',
|
|
450
|
+
type: 'limit',
|
|
451
|
+
yes_price: 40,
|
|
452
|
+
count: 3,
|
|
453
|
+
remaining_count: 0,
|
|
454
|
+
status: 'executed',
|
|
455
|
+
created_time: '2026-01-10T08:00:00Z',
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
const historicalResponse = {
|
|
461
|
+
data: {
|
|
462
|
+
orders: [
|
|
463
|
+
{
|
|
464
|
+
order_id: 'order-hist-1', // duplicate
|
|
465
|
+
ticker: 'TEST',
|
|
466
|
+
side: 'no',
|
|
467
|
+
type: 'limit',
|
|
468
|
+
yes_price: 40,
|
|
469
|
+
count: 3,
|
|
470
|
+
remaining_count: 0,
|
|
471
|
+
status: 'executed',
|
|
472
|
+
created_time: '2026-01-10T08:00:00Z',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
order_id: 'order-hist-2',
|
|
476
|
+
ticker: 'TEST',
|
|
477
|
+
side: 'yes',
|
|
478
|
+
type: 'limit',
|
|
479
|
+
yes_price: 55,
|
|
480
|
+
count: 10,
|
|
481
|
+
remaining_count: 0,
|
|
482
|
+
status: 'executed',
|
|
483
|
+
created_time: '2026-01-05T06:00:00Z',
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
mockAxiosInstance.request
|
|
489
|
+
.mockResolvedValueOnce(liveResponse)
|
|
490
|
+
.mockResolvedValueOnce(historicalResponse);
|
|
491
|
+
const orders = await exchange.fetchAllOrders();
|
|
492
|
+
// 3 unique orders (order-hist-1 deduped)
|
|
493
|
+
expect(orders).toHaveLength(3);
|
|
494
|
+
// sorted descending: order-live-1, order-hist-1, order-hist-2
|
|
495
|
+
expect(orders[0].id).toBe('order-live-1');
|
|
496
|
+
expect(orders[1].id).toBe('order-hist-1');
|
|
497
|
+
expect(orders[2].id).toBe('order-hist-2');
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}); // Trading History Methods
|
|
321
501
|
describe('Order Status Mapping', () => {
|
|
322
502
|
beforeEach(() => {
|
|
323
503
|
exchange = new kalshi_1.KalshiExchange(mockCredentials);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.831Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const limitlessApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.limitlessApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.831Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.limitlessApiSpec = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFetchParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
1
|
+
import { PredictionMarketExchange, MarketFetchParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams, OrderHistoryParams } from '../../BaseExchange';
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
3
3
|
import { LimitlessWebSocketConfig } from './websocket';
|
|
4
4
|
export type { LimitlessWebSocketConfig };
|
|
5
5
|
export interface LimitlessExchangeOptions {
|
|
@@ -21,6 +21,9 @@ export declare class LimitlessExchange extends PredictionMarketExchange {
|
|
|
21
21
|
fetchBalance: true;
|
|
22
22
|
watchOrderBook: true;
|
|
23
23
|
watchTrades: true;
|
|
24
|
+
fetchMyTrades: true;
|
|
25
|
+
fetchClosedOrders: true;
|
|
26
|
+
fetchAllOrders: true;
|
|
24
27
|
};
|
|
25
28
|
private auth?;
|
|
26
29
|
private client?;
|
|
@@ -42,6 +45,9 @@ export declare class LimitlessExchange extends PredictionMarketExchange {
|
|
|
42
45
|
cancelOrder(orderId: string): Promise<Order>;
|
|
43
46
|
fetchOrder(orderId: string): Promise<Order>;
|
|
44
47
|
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
48
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
49
|
+
fetchClosedOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
50
|
+
fetchAllOrders(params?: OrderHistoryParams): Promise<Order[]>;
|
|
45
51
|
fetchPositions(): Promise<Position[]>;
|
|
46
52
|
fetchBalance(): Promise<Balance[]>;
|
|
47
53
|
private ws?;
|
|
@@ -31,6 +31,9 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
31
31
|
fetchBalance: true,
|
|
32
32
|
watchOrderBook: true,
|
|
33
33
|
watchTrades: true,
|
|
34
|
+
fetchMyTrades: true,
|
|
35
|
+
fetchClosedOrders: true,
|
|
36
|
+
fetchAllOrders: true,
|
|
34
37
|
};
|
|
35
38
|
auth;
|
|
36
39
|
client;
|
|
@@ -226,6 +229,68 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
226
229
|
throw errors_1.limitlessErrorMapper.mapError(error);
|
|
227
230
|
}
|
|
228
231
|
}
|
|
232
|
+
async fetchMyTrades(params) {
|
|
233
|
+
const auth = this.ensureAuth();
|
|
234
|
+
try {
|
|
235
|
+
const response = await this.http.get('https://api.limitless.exchange/portfolio/trades', {
|
|
236
|
+
headers: { Authorization: `Bearer ${auth.getApiKey()}` },
|
|
237
|
+
});
|
|
238
|
+
const trades = Array.isArray(response.data) ? response.data : (response.data?.data || []);
|
|
239
|
+
return trades.map((t) => ({
|
|
240
|
+
id: t.id || String(t.timestamp),
|
|
241
|
+
timestamp: t.createdAt ? new Date(t.createdAt).getTime() : (t.timestamp || 0),
|
|
242
|
+
price: parseFloat(t.price || '0'),
|
|
243
|
+
amount: parseFloat(t.quantity || t.amount || '0'),
|
|
244
|
+
side: (t.side || '').toLowerCase() === 'buy' ? 'buy' : 'sell',
|
|
245
|
+
orderId: t.orderId,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
throw errors_1.limitlessErrorMapper.mapError(error);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async fetchClosedOrders(params) {
|
|
253
|
+
const client = this.ensureClient();
|
|
254
|
+
if (!params?.marketId) {
|
|
255
|
+
console.warn('Limitless: fetchClosedOrders requires marketId (slug). Returning [].');
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
const orders = await client.getOrders(params.marketId, ['MATCHED']);
|
|
259
|
+
return orders.map((o) => ({
|
|
260
|
+
id: o.id,
|
|
261
|
+
marketId: params.marketId,
|
|
262
|
+
outcomeId: o.tokenId || 'unknown',
|
|
263
|
+
side: o.side.toLowerCase(),
|
|
264
|
+
type: 'limit',
|
|
265
|
+
price: parseFloat(o.price),
|
|
266
|
+
amount: parseFloat(o.quantity),
|
|
267
|
+
status: 'filled',
|
|
268
|
+
filled: parseFloat(o.quantity),
|
|
269
|
+
remaining: 0,
|
|
270
|
+
timestamp: o.createdAt ? new Date(o.createdAt).getTime() : Date.now(),
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
async fetchAllOrders(params) {
|
|
274
|
+
const client = this.ensureClient();
|
|
275
|
+
if (!params?.marketId) {
|
|
276
|
+
console.warn('Limitless: fetchAllOrders requires marketId (slug). Returning [].');
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
const orders = await client.getOrders(params.marketId, ['LIVE', 'MATCHED']);
|
|
280
|
+
return orders.map((o) => ({
|
|
281
|
+
id: o.id,
|
|
282
|
+
marketId: params.marketId,
|
|
283
|
+
outcomeId: o.tokenId || 'unknown',
|
|
284
|
+
side: o.side.toLowerCase(),
|
|
285
|
+
type: 'limit',
|
|
286
|
+
price: parseFloat(o.price),
|
|
287
|
+
amount: parseFloat(o.quantity),
|
|
288
|
+
status: o.status === 'LIVE' ? 'open' : 'filled',
|
|
289
|
+
filled: o.status === 'MATCHED' ? parseFloat(o.quantity) : 0,
|
|
290
|
+
remaining: o.status === 'LIVE' ? parseFloat(o.quantity) : 0,
|
|
291
|
+
timestamp: o.createdAt ? new Date(o.createdAt).getTime() : Date.now(),
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
229
294
|
async fetchPositions() {
|
|
230
295
|
const auth = this.ensureAuth();
|
|
231
296
|
const address = auth.getAddress();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.842Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const myriadApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.myriadApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/myriad/myriad.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.842Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.myriadApiSpec = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Balance, Order, Position, CreateOrderParams } from '../../types';
|
|
1
|
+
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams } from '../../BaseExchange';
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Balance, Order, Position, CreateOrderParams } from '../../types';
|
|
3
3
|
export declare class MyriadExchange extends PredictionMarketExchange {
|
|
4
4
|
readonly has: {
|
|
5
5
|
fetchMarkets: true;
|
|
@@ -15,6 +15,9 @@ export declare class MyriadExchange extends PredictionMarketExchange {
|
|
|
15
15
|
fetchBalance: "emulated";
|
|
16
16
|
watchOrderBook: "emulated";
|
|
17
17
|
watchTrades: "emulated";
|
|
18
|
+
fetchMyTrades: true;
|
|
19
|
+
fetchClosedOrders: false;
|
|
20
|
+
fetchAllOrders: false;
|
|
18
21
|
};
|
|
19
22
|
private auth?;
|
|
20
23
|
private ws?;
|
|
@@ -29,6 +32,7 @@ export declare class MyriadExchange extends PredictionMarketExchange {
|
|
|
29
32
|
fetchOHLCV(id: string, params: OHLCVParams | HistoryFilterParams): Promise<PriceCandle[]>;
|
|
30
33
|
fetchOrderBook(id: string): Promise<OrderBook>;
|
|
31
34
|
fetchTrades(id: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
|
|
35
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
32
36
|
createOrder(params: CreateOrderParams): Promise<Order>;
|
|
33
37
|
cancelOrder(_orderId: string): Promise<Order>;
|
|
34
38
|
fetchOrder(_orderId: string): Promise<Order>;
|
|
@@ -28,6 +28,9 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
28
28
|
fetchBalance: 'emulated',
|
|
29
29
|
watchOrderBook: 'emulated',
|
|
30
30
|
watchTrades: 'emulated',
|
|
31
|
+
fetchMyTrades: true,
|
|
32
|
+
fetchClosedOrders: false,
|
|
33
|
+
fetchAllOrders: false,
|
|
31
34
|
};
|
|
32
35
|
auth;
|
|
33
36
|
ws;
|
|
@@ -119,6 +122,34 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
119
122
|
side: t.action === 'buy' ? 'buy' : 'sell',
|
|
120
123
|
}));
|
|
121
124
|
}
|
|
125
|
+
async fetchMyTrades(params) {
|
|
126
|
+
const walletAddress = this.ensureAuth().walletAddress;
|
|
127
|
+
if (!walletAddress) {
|
|
128
|
+
throw new errors_2.AuthenticationError('fetchMyTrades requires a wallet address. Pass privateKey as the wallet address in credentials.', 'Myriad');
|
|
129
|
+
}
|
|
130
|
+
const queryParams = { address: walletAddress };
|
|
131
|
+
if (params?.marketId) {
|
|
132
|
+
const parts = params.marketId.split(':');
|
|
133
|
+
if (parts.length >= 2)
|
|
134
|
+
queryParams.market_id = parts[1];
|
|
135
|
+
}
|
|
136
|
+
if (params?.since)
|
|
137
|
+
queryParams.since = Math.floor(params.since.getTime() / 1000);
|
|
138
|
+
if (params?.until)
|
|
139
|
+
queryParams.until = Math.floor(params.until.getTime() / 1000);
|
|
140
|
+
if (params?.limit)
|
|
141
|
+
queryParams.limit = params.limit;
|
|
142
|
+
const data = await this.callApi('getUsersEvents', queryParams);
|
|
143
|
+
const events = data.data || data.events || [];
|
|
144
|
+
const tradeEvents = events.filter((e) => e.action === 'buy' || e.action === 'sell');
|
|
145
|
+
return tradeEvents.map((t, i) => ({
|
|
146
|
+
id: `${t.blockNumber || t.timestamp}-${i}`,
|
|
147
|
+
timestamp: (t.timestamp || 0) * 1000,
|
|
148
|
+
price: t.shares > 0 ? Number(t.value) / Number(t.shares) : 0,
|
|
149
|
+
amount: Number(t.shares || 0),
|
|
150
|
+
side: t.action === 'buy' ? 'buy' : 'sell',
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
122
153
|
// ------------------------------------------------------------------------
|
|
123
154
|
// Trading
|
|
124
155
|
// ------------------------------------------------------------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.794Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketClobSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketClobSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketClobAPI.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.794Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketClobSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.812Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketDataSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketDataSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/Polymarket_Data_API.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.812Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketDataSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.808Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const polymarketGammaSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.polymarketGammaSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/polymarket/PolymarketGammaAPI.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.808Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketGammaSpec = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
1
|
+
import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams } from '../../BaseExchange';
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
3
3
|
import { PolymarketWebSocketConfig } from './websocket';
|
|
4
4
|
export type { PolymarketWebSocketConfig };
|
|
5
5
|
export interface PolymarketExchangeOptions {
|
|
@@ -21,6 +21,9 @@ export declare class PolymarketExchange extends PredictionMarketExchange {
|
|
|
21
21
|
fetchBalance: true;
|
|
22
22
|
watchOrderBook: true;
|
|
23
23
|
watchTrades: true;
|
|
24
|
+
fetchMyTrades: true;
|
|
25
|
+
fetchClosedOrders: false;
|
|
26
|
+
fetchAllOrders: false;
|
|
24
27
|
};
|
|
25
28
|
private auth?;
|
|
26
29
|
private wsConfig?;
|
|
@@ -71,6 +74,7 @@ export declare class PolymarketExchange extends PredictionMarketExchange {
|
|
|
71
74
|
cancelOrder(orderId: string): Promise<Order>;
|
|
72
75
|
fetchOrder(orderId: string): Promise<Order>;
|
|
73
76
|
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
77
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
74
78
|
fetchPositions(): Promise<Position[]>;
|
|
75
79
|
fetchBalance(): Promise<Balance[]>;
|
|
76
80
|
private ws?;
|
|
@@ -33,6 +33,9 @@ class PolymarketExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
33
33
|
fetchBalance: true,
|
|
34
34
|
watchOrderBook: true,
|
|
35
35
|
watchTrades: true,
|
|
36
|
+
fetchMyTrades: true,
|
|
37
|
+
fetchClosedOrders: false,
|
|
38
|
+
fetchAllOrders: false,
|
|
36
39
|
};
|
|
37
40
|
auth;
|
|
38
41
|
wsConfig;
|
|
@@ -342,6 +345,29 @@ class PolymarketExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
342
345
|
throw errors_1.polymarketErrorMapper.mapError(error);
|
|
343
346
|
}
|
|
344
347
|
}
|
|
348
|
+
async fetchMyTrades(params) {
|
|
349
|
+
const auth = this.ensureAuth();
|
|
350
|
+
const address = await auth.getEffectiveFunderAddress();
|
|
351
|
+
const queryParams = { user: address };
|
|
352
|
+
if (params?.marketId)
|
|
353
|
+
queryParams.market = params.marketId;
|
|
354
|
+
if (params?.limit)
|
|
355
|
+
queryParams.limit = params.limit;
|
|
356
|
+
if (params?.since)
|
|
357
|
+
queryParams.start = Math.floor(params.since.getTime() / 1000);
|
|
358
|
+
if (params?.until)
|
|
359
|
+
queryParams.end = Math.floor(params.until.getTime() / 1000);
|
|
360
|
+
const data = await this.callApi('getTrades', queryParams);
|
|
361
|
+
const trades = Array.isArray(data) ? data : (data.data || []);
|
|
362
|
+
return trades.map((t) => ({
|
|
363
|
+
id: t.id || t.transactionHash || String(t.timestamp),
|
|
364
|
+
timestamp: typeof t.timestamp === 'number' ? t.timestamp * 1000 : Date.now(),
|
|
365
|
+
price: parseFloat(t.price || '0'),
|
|
366
|
+
amount: parseFloat(t.size || t.amount || '0'),
|
|
367
|
+
side: t.side === 'BUY' ? 'buy' : t.side === 'SELL' ? 'sell' : 'unknown',
|
|
368
|
+
orderId: t.orderId,
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
345
371
|
async fetchPositions() {
|
|
346
372
|
try {
|
|
347
373
|
const auth = this.ensureAuth();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
|
|
3
|
-
* Generated at: 2026-02-
|
|
3
|
+
* Generated at: 2026-02-22T14:48:41.835Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const probableApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.probableApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
|
|
6
|
-
* Generated at: 2026-02-
|
|
6
|
+
* Generated at: 2026-02-22T14:48:41.835Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PredictionMarketExchange, MarketFetchParams, EventFetchParams, ExchangeCredentials, OHLCVParams, HistoryFilterParams, TradesParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket, UnifiedEvent, OrderBook, PriceCandle, Trade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
1
|
+
import { PredictionMarketExchange, MarketFetchParams, EventFetchParams, ExchangeCredentials, OHLCVParams, HistoryFilterParams, TradesParams, MyTradesParams } from '../../BaseExchange';
|
|
2
|
+
import { UnifiedMarket, UnifiedEvent, OrderBook, PriceCandle, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from '../../types';
|
|
3
3
|
import { ProbableWebSocketConfig } from './websocket';
|
|
4
4
|
export declare class ProbableExchange extends PredictionMarketExchange {
|
|
5
5
|
readonly has: {
|
|
@@ -16,6 +16,9 @@ export declare class ProbableExchange extends PredictionMarketExchange {
|
|
|
16
16
|
fetchBalance: true;
|
|
17
17
|
watchOrderBook: true;
|
|
18
18
|
watchTrades: false;
|
|
19
|
+
fetchMyTrades: true;
|
|
20
|
+
fetchClosedOrders: false;
|
|
21
|
+
fetchAllOrders: false;
|
|
19
22
|
};
|
|
20
23
|
private auth?;
|
|
21
24
|
private ws?;
|
|
@@ -66,6 +69,7 @@ export declare class ProbableExchange extends PredictionMarketExchange {
|
|
|
66
69
|
getEventBySlug(slug: string): Promise<UnifiedEvent | null>;
|
|
67
70
|
fetchOrderBook(id: string): Promise<OrderBook>;
|
|
68
71
|
fetchOHLCV(id: string, params: OHLCVParams | HistoryFilterParams): Promise<PriceCandle[]>;
|
|
72
|
+
fetchMyTrades(params?: MyTradesParams): Promise<UserTrade[]>;
|
|
69
73
|
createOrder(params: CreateOrderParams): Promise<Order>;
|
|
70
74
|
/**
|
|
71
75
|
* Cancel an order.
|
|
@@ -47,6 +47,9 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
47
47
|
fetchBalance: true,
|
|
48
48
|
watchOrderBook: true,
|
|
49
49
|
watchTrades: false,
|
|
50
|
+
fetchMyTrades: true,
|
|
51
|
+
fetchClosedOrders: false,
|
|
52
|
+
fetchAllOrders: false,
|
|
50
53
|
};
|
|
51
54
|
auth;
|
|
52
55
|
ws;
|
|
@@ -179,6 +182,25 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
179
182
|
}
|
|
180
183
|
return candles;
|
|
181
184
|
}
|
|
185
|
+
async fetchMyTrades(params) {
|
|
186
|
+
const auth = this.ensureAuth();
|
|
187
|
+
const address = auth.getAddress();
|
|
188
|
+
const queryParams = { user: address };
|
|
189
|
+
if (params?.limit)
|
|
190
|
+
queryParams.limit = params.limit;
|
|
191
|
+
const data = await this.callApi('getPublicApiV1Trades', queryParams);
|
|
192
|
+
const trades = Array.isArray(data) ? data : (data.data || []);
|
|
193
|
+
return trades.map((t) => ({
|
|
194
|
+
id: String(t.tradeId || t.id || t.timestamp),
|
|
195
|
+
timestamp: typeof t.time === 'number'
|
|
196
|
+
? (t.time > 1e12 ? t.time : t.time * 1000)
|
|
197
|
+
: Date.now(),
|
|
198
|
+
price: parseFloat(t.price || '0'),
|
|
199
|
+
amount: parseFloat(t.qty || t.size || t.amount || '0'),
|
|
200
|
+
side: (t.side || '').toLowerCase() === 'buy' ? 'buy' : 'sell',
|
|
201
|
+
orderId: t.orderId,
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
182
204
|
// --------------------------------------------------------------------------
|
|
183
205
|
// Trading Methods
|
|
184
206
|
// --------------------------------------------------------------------------
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test": "jest -c jest.config.js",
|
|
30
30
|
"server": "tsx watch src/server/index.ts",
|
|
31
31
|
"server:prod": "node dist/server/index.js",
|
|
32
|
-
"generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.
|
|
33
|
-
"generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.
|
|
32
|
+
"generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.12.0,library=urllib3",
|
|
33
|
+
"generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.12.0,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
|
|
34
34
|
"fetch:openapi": "node scripts/fetch-openapi-specs.js",
|
|
35
35
|
"extract:jsdoc": "node ../scripts/extract-jsdoc.js",
|
|
36
36
|
"generate:docs": "npm run extract:jsdoc && node ../scripts/generate-api-docs.js",
|