pmxtjs 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API_REFERENCE.md +448 -51
- package/dist/BaseExchange.d.ts +38 -3
- package/dist/BaseExchange.js +43 -1
- package/dist/exchanges/Kalshi.js +10 -2
- package/dist/exchanges/Polymarket.js +12 -4
- package/dist/exchanges/kalshi/auth.d.ts +23 -0
- package/dist/exchanges/kalshi/auth.js +99 -0
- package/dist/exchanges/kalshi/fetchMarkets.d.ts +3 -0
- package/dist/exchanges/kalshi/fetchMarkets.js +84 -0
- package/dist/exchanges/kalshi/fetchOHLCV.d.ts +3 -0
- package/dist/exchanges/kalshi/fetchOHLCV.js +78 -0
- package/dist/exchanges/kalshi/fetchOrderBook.d.ts +2 -0
- package/dist/exchanges/kalshi/fetchOrderBook.js +32 -0
- package/dist/exchanges/kalshi/fetchTrades.d.ts +3 -0
- package/dist/exchanges/kalshi/fetchTrades.js +31 -0
- package/dist/exchanges/kalshi/getMarketsBySlug.d.ts +7 -0
- package/dist/exchanges/kalshi/getMarketsBySlug.js +46 -0
- package/dist/exchanges/kalshi/index.d.ts +21 -0
- package/dist/exchanges/kalshi/index.js +273 -0
- package/dist/exchanges/kalshi/kalshi.test.d.ts +1 -0
- package/dist/exchanges/kalshi/kalshi.test.js +309 -0
- package/dist/exchanges/kalshi/searchMarkets.d.ts +3 -0
- package/dist/exchanges/kalshi/searchMarkets.js +28 -0
- package/dist/exchanges/kalshi/utils.d.ts +4 -0
- package/dist/exchanges/kalshi/utils.js +70 -0
- package/dist/exchanges/polymarket/auth.d.ts +32 -0
- package/dist/exchanges/polymarket/auth.js +98 -0
- package/dist/exchanges/polymarket/fetchMarkets.d.ts +3 -0
- package/dist/exchanges/polymarket/fetchMarkets.js +75 -0
- package/dist/exchanges/polymarket/fetchOHLCV.d.ts +7 -0
- package/dist/exchanges/polymarket/fetchOHLCV.js +73 -0
- package/dist/exchanges/polymarket/fetchOrderBook.d.ts +6 -0
- package/dist/exchanges/polymarket/fetchOrderBook.js +38 -0
- package/dist/exchanges/polymarket/fetchPositions.d.ts +2 -0
- package/dist/exchanges/polymarket/fetchPositions.js +27 -0
- package/dist/exchanges/polymarket/fetchTrades.d.ts +11 -0
- package/dist/exchanges/polymarket/fetchTrades.js +59 -0
- package/dist/exchanges/polymarket/getMarketsBySlug.d.ts +7 -0
- package/dist/exchanges/polymarket/getMarketsBySlug.js +39 -0
- package/dist/exchanges/polymarket/index.d.ts +23 -0
- package/dist/exchanges/polymarket/index.js +216 -0
- package/dist/exchanges/polymarket/searchMarkets.d.ts +3 -0
- package/dist/exchanges/polymarket/searchMarkets.js +35 -0
- package/dist/exchanges/polymarket/utils.d.ts +7 -0
- package/dist/exchanges/polymarket/utils.js +95 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +8 -8
- package/dist/types.d.ts +38 -0
- package/package.json +5 -1
- package/readme.md +44 -24
package/API_REFERENCE.md
CHANGED
|
@@ -1,86 +1,483 @@
|
|
|
1
1
|
# Prediction Market API Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A unified interface for interacting with multiple prediction market exchanges (Kalshi, Polymarket) identically.
|
|
4
4
|
|
|
5
|
-
## Usage
|
|
5
|
+
## Installation & Usage
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install pmxtjs
|
|
9
|
+
```
|
|
8
10
|
|
|
9
11
|
```typescript
|
|
10
12
|
import pmxt from 'pmxtjs';
|
|
11
13
|
|
|
12
|
-
// ccxt-style instantiation
|
|
13
14
|
const polymarket = new pmxt.polymarket();
|
|
14
15
|
const kalshi = new pmxt.kalshi();
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
---
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
## Core Methods
|
|
20
21
|
|
|
21
22
|
### `fetchMarkets(params?)`
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
Get active markets from an exchange.
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
const markets = await polymarket.fetchMarkets({
|
|
27
|
+
limit: 20,
|
|
28
|
+
offset: 0,
|
|
29
|
+
sort: 'volume' // 'volume' | 'liquidity' | 'newest'
|
|
30
|
+
});
|
|
31
|
+
```
|
|
25
32
|
|
|
26
33
|
### `searchMarkets(query, params?)`
|
|
27
|
-
Search markets by
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
Search markets by keyword. By default, searches only in titles.
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
const results = await kalshi.searchMarkets('Fed rates', {
|
|
38
|
+
limit: 10,
|
|
39
|
+
searchIn: 'title' // 'title' (default) | 'description' | 'both'
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `getMarketsBySlug(slug)`
|
|
44
|
+
Fetch markets by URL slug/ticker.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// Polymarket: use URL slug
|
|
48
|
+
const polyMarkets = await polymarket.getMarketsBySlug('who-will-trump-nominate-as-fed-chair');
|
|
49
|
+
|
|
50
|
+
// Kalshi: use event ticker (auto-uppercased)
|
|
51
|
+
const kalshiMarkets = await kalshi.getMarketsBySlug('FED-25JAN');
|
|
52
|
+
```
|
|
30
53
|
|
|
31
54
|
---
|
|
32
55
|
|
|
33
|
-
##
|
|
56
|
+
## Deep-Dive Methods
|
|
57
|
+
|
|
58
|
+
### `fetchOHLCV(outcomeId, params)`
|
|
59
|
+
Get historical price candles.
|
|
60
|
+
|
|
61
|
+
**CRITICAL**: Use `outcome.id`, not `market.id`.
|
|
62
|
+
- **Polymarket**: `outcome.id` is the CLOB Token ID
|
|
63
|
+
- **Kalshi**: `outcome.id` is the Market Ticker
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const markets = await polymarket.searchMarkets('Trump');
|
|
67
|
+
const outcomeId = markets[0].outcomes[0].id; // Get the outcome ID
|
|
68
|
+
|
|
69
|
+
const candles = await polymarket.fetchOHLCV(outcomeId, {
|
|
70
|
+
resolution: '1h', // '1m' | '5m' | '15m' | '1h' | '6h' | '1d'
|
|
71
|
+
start: new Date('2024-01-01'),
|
|
72
|
+
end: new Date('2024-01-31'),
|
|
73
|
+
limit: 100
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `fetchOrderBook(outcomeId)`
|
|
78
|
+
Get current bids/asks.
|
|
34
79
|
|
|
35
|
-
|
|
80
|
+
```typescript
|
|
81
|
+
const orderBook = await kalshi.fetchOrderBook('FED-25JAN');
|
|
82
|
+
console.log('Best bid:', orderBook.bids[0].price);
|
|
83
|
+
console.log('Best ask:', orderBook.asks[0].price);
|
|
84
|
+
```
|
|
36
85
|
|
|
37
|
-
### `
|
|
38
|
-
|
|
39
|
-
- **Input**: `id`, `resolution` (1m, 1h, 1d), `start`, `end`.
|
|
40
|
-
- **Output**: `Promise<PriceCandle[]>`
|
|
41
|
-
- **Important**:
|
|
42
|
-
- **Kalshi**: Uses the Market Ticker (e.g., `FED-25DEC`). Returns **native OHLCV** (Open/High/Low/Close data is distinct).
|
|
43
|
-
- **Polymarket**: Uses the **CLOB Token ID** found in `outcome.metadata.clobTokenId`. Returns **synthetic candles** (Open=High=Low=Close) derived from raw price points.
|
|
86
|
+
### `fetchTrades(outcomeId, params)`
|
|
87
|
+
Get trade history.
|
|
44
88
|
|
|
45
|
-
|
|
46
|
-
Fetches live Bids/Asks.
|
|
47
|
-
- **Input**: `id` (Ticker for Kalshi, Token ID for Polymarket).
|
|
48
|
-
- **Output**: `Promise<OrderBook>` (Normalized: "No" bids becomes "Yes" asks).
|
|
89
|
+
**Note**: Polymarket requires API key. Use `fetchOHLCV` for public historical data.
|
|
49
90
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **Polymarket**: Requires L2 Authentication (API Key). Without a key, this method will throw an unauthorized error. Use `fetchOHLCV` for public historical data.
|
|
91
|
+
```typescript
|
|
92
|
+
const trades = await kalshi.fetchTrades('FED-25JAN', {
|
|
93
|
+
resolution: '1h',
|
|
94
|
+
limit: 100
|
|
95
|
+
});
|
|
96
|
+
```
|
|
57
97
|
|
|
58
98
|
---
|
|
59
99
|
|
|
60
|
-
##
|
|
100
|
+
## Data Models
|
|
61
101
|
|
|
62
|
-
### `UnifiedMarket`
|
|
102
|
+
### `UnifiedMarket`
|
|
63
103
|
```typescript
|
|
64
104
|
{
|
|
65
|
-
id: string;
|
|
66
|
-
title: string;
|
|
67
|
-
description: string;
|
|
68
|
-
outcomes: [
|
|
69
|
-
|
|
70
|
-
id: string,
|
|
71
|
-
label: "Trump",
|
|
72
|
-
price: 0.52,
|
|
73
|
-
priceChange24h: 0.05, // Optional: Change in price over last 24h
|
|
74
|
-
metadata: { ... } // Exchange-specific keys (clobTokenId)
|
|
75
|
-
}
|
|
76
|
-
];
|
|
105
|
+
id: string; // Market ID
|
|
106
|
+
title: string;
|
|
107
|
+
description: string;
|
|
108
|
+
outcomes: MarketOutcome[]; // All tradeable outcomes
|
|
109
|
+
|
|
77
110
|
resolutionDate: Date;
|
|
78
|
-
volume24h: number;
|
|
79
|
-
|
|
111
|
+
volume24h: number; // USD
|
|
112
|
+
volume?: number; // Total volume (USD)
|
|
113
|
+
liquidity: number; // USD
|
|
114
|
+
openInterest?: number; // USD
|
|
115
|
+
|
|
80
116
|
url: string;
|
|
81
|
-
image?: string;
|
|
82
|
-
category?: string;
|
|
83
|
-
tags?: string[];
|
|
117
|
+
image?: string;
|
|
118
|
+
category?: string;
|
|
119
|
+
tags?: string[];
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `MarketOutcome`
|
|
124
|
+
```typescript
|
|
125
|
+
{
|
|
126
|
+
id: string; // Use this for fetchOHLCV/fetchOrderBook/fetchTrades
|
|
127
|
+
// Polymarket: CLOB Token ID
|
|
128
|
+
// Kalshi: Market Ticker
|
|
129
|
+
label: string; // "Trump", "Yes", etc.
|
|
130
|
+
price: number; // 0.0 to 1.0 (probability)
|
|
131
|
+
priceChange24h?: number;
|
|
132
|
+
metadata?: {
|
|
133
|
+
clobTokenId?: string; // Polymarket only
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Other Types
|
|
139
|
+
```typescript
|
|
140
|
+
interface PriceCandle {
|
|
141
|
+
timestamp: number; // Unix ms
|
|
142
|
+
open: number; // 0.0 to 1.0
|
|
143
|
+
high: number;
|
|
144
|
+
low: number;
|
|
145
|
+
close: number;
|
|
146
|
+
volume?: number;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface OrderBook {
|
|
150
|
+
bids: OrderLevel[]; // Sorted high to low
|
|
151
|
+
asks: OrderLevel[]; // Sorted low to high
|
|
152
|
+
timestamp?: number;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
interface OrderLevel {
|
|
156
|
+
price: number; // 0.0 to 1.0
|
|
157
|
+
size: number; // Contracts
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
interface Trade {
|
|
161
|
+
id: string;
|
|
162
|
+
timestamp: number; // Unix ms
|
|
163
|
+
price: number; // 0.0 to 1.0
|
|
164
|
+
amount: number;
|
|
165
|
+
side: 'buy' | 'sell' | 'unknown';
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Complete Workflow Example
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// 1. Search for markets
|
|
175
|
+
const markets = await polymarket.searchMarkets('Fed Chair');
|
|
176
|
+
const market = markets[0];
|
|
177
|
+
|
|
178
|
+
// 2. Get outcome details
|
|
179
|
+
const outcome = market.outcomes[0];
|
|
180
|
+
console.log(`${outcome.label}: ${(outcome.price * 100).toFixed(1)}%`);
|
|
181
|
+
|
|
182
|
+
// 3. Fetch historical data (use outcome.id!)
|
|
183
|
+
const candles = await polymarket.fetchOHLCV(outcome.id, {
|
|
184
|
+
resolution: '1d',
|
|
185
|
+
limit: 30
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// 4. Get current order book
|
|
189
|
+
const orderBook = await polymarket.fetchOrderBook(outcome.id);
|
|
190
|
+
const spread = orderBook.asks[0].price - orderBook.bids[0].price;
|
|
191
|
+
console.log(`Spread: ${(spread * 100).toFixed(2)}%`);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Exchange Differences
|
|
197
|
+
|
|
198
|
+
| Feature | Polymarket | Kalshi |
|
|
199
|
+
|---------|-----------|--------|
|
|
200
|
+
| **Sorting** | Server-side | Client-side (slower for large sets) |
|
|
201
|
+
| **Market ID** | UUID | Event Ticker (e.g., "PRES-2024") |
|
|
202
|
+
| **Outcome ID** | CLOB Token ID | Market Ticker (e.g., "FED-25JAN") |
|
|
203
|
+
| **OHLCV Quality** | Synthetic (O=H=L=C) | Native (distinct values) |
|
|
204
|
+
| **Auth Required** | Only for `fetchTrades()` | No (all public) |
|
|
205
|
+
| **Slug Format** | lowercase-with-hyphens | UPPERCASE (auto-normalized) |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Error Handling
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
try {
|
|
213
|
+
const markets = await kalshi.getMarketsBySlug('INVALID-TICKER');
|
|
214
|
+
} catch (error) {
|
|
215
|
+
// Kalshi: "Event not found: INVALID-TICKER"
|
|
216
|
+
// Polymarket: Returns empty array []
|
|
217
|
+
console.error(error.message);
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Common Errors**:
|
|
222
|
+
- `404`: Market/event doesn't exist
|
|
223
|
+
- `401`: Missing API key (Polymarket `fetchTrades`)
|
|
224
|
+
- `429`: Rate limited
|
|
225
|
+
- `500`: Exchange API issue
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Type Exports
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import pmxt, {
|
|
233
|
+
UnifiedMarket,
|
|
234
|
+
MarketOutcome,
|
|
235
|
+
PriceCandle,
|
|
236
|
+
OrderBook,
|
|
237
|
+
Trade,
|
|
238
|
+
CandleInterval,
|
|
239
|
+
MarketFilterParams,
|
|
240
|
+
HistoryFilterParams
|
|
241
|
+
} from 'pmxtjs';
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Authentication & Trading
|
|
247
|
+
|
|
248
|
+
Both Polymarket and Kalshi support authenticated trading operations. You must provide credentials when initializing the exchange.
|
|
249
|
+
|
|
250
|
+
### Polymarket Authentication
|
|
251
|
+
|
|
252
|
+
Requires your **Polygon Private Key**. See [Setup Guide](docs/SETUP_POLYMARKET.md) for details.
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import pmxt from 'pmxtjs';
|
|
256
|
+
|
|
257
|
+
const polymarket = new pmxt.Polymarket({
|
|
258
|
+
privateKey: process.env.POLYMARKET_PRIVATE_KEY
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Kalshi Authentication
|
|
263
|
+
|
|
264
|
+
Requires **API Key** and **Private Key**.
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
import pmxt from 'pmxtjs';
|
|
268
|
+
|
|
269
|
+
const kalshi = new pmxt.Kalshi({
|
|
270
|
+
apiKey: process.env.KALSHI_API_KEY,
|
|
271
|
+
privateKey: process.env.KALSHI_PRIVATE_KEY
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Account Methods
|
|
278
|
+
|
|
279
|
+
### `fetchBalance()`
|
|
280
|
+
Get your account balance.
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
const balances = await polymarket.fetchBalance();
|
|
284
|
+
console.log(balances);
|
|
285
|
+
// [{ currency: 'USDC', total: 1000, available: 950, locked: 50 }]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Returns**: `Balance[]`
|
|
289
|
+
```typescript
|
|
290
|
+
interface Balance {
|
|
291
|
+
currency: string; // e.g., 'USDC'
|
|
292
|
+
total: number; // Total balance
|
|
293
|
+
available: number; // Available for trading
|
|
294
|
+
locked: number; // Locked in open orders
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### `fetchPositions()`
|
|
299
|
+
Get your current positions across all markets.
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const positions = await kalshi.fetchPositions();
|
|
303
|
+
positions.forEach(pos => {
|
|
304
|
+
console.log(`${pos.outcomeLabel}: ${pos.size} @ $${pos.entryPrice}`);
|
|
305
|
+
console.log(`Unrealized P&L: $${pos.unrealizedPnL}`);
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Returns**: `Position[]`
|
|
310
|
+
```typescript
|
|
311
|
+
interface Position {
|
|
312
|
+
marketId: string;
|
|
313
|
+
outcomeId: string;
|
|
314
|
+
outcomeLabel: string;
|
|
315
|
+
size: number; // Positive for long, negative for short
|
|
316
|
+
entryPrice: number;
|
|
317
|
+
currentPrice: number;
|
|
318
|
+
unrealizedPnL: number;
|
|
319
|
+
realizedPnL?: number;
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Trading Methods
|
|
326
|
+
|
|
327
|
+
### `createOrder(params)`
|
|
328
|
+
Place a new order (market or limit).
|
|
329
|
+
|
|
330
|
+
**Limit Order Example**:
|
|
331
|
+
```typescript
|
|
332
|
+
const order = await polymarket.createOrder({
|
|
333
|
+
marketId: '663583',
|
|
334
|
+
outcomeId: '10991849228756847439673778874175365458450913336396982752046655649803657501964',
|
|
335
|
+
side: 'buy',
|
|
336
|
+
type: 'limit',
|
|
337
|
+
amount: 10, // Number of contracts
|
|
338
|
+
price: 0.55 // Required for limit orders (0.0-1.0)
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
console.log(`Order ${order.id}: ${order.status}`);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**Market Order Example**:
|
|
345
|
+
```typescript
|
|
346
|
+
const order = await kalshi.createOrder({
|
|
347
|
+
marketId: 'FED-25JAN',
|
|
348
|
+
outcomeId: 'FED-25JAN-YES',
|
|
349
|
+
side: 'sell',
|
|
350
|
+
type: 'market',
|
|
351
|
+
amount: 5 // Price not needed for market orders
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Parameters**: `CreateOrderParams`
|
|
356
|
+
```typescript
|
|
357
|
+
interface CreateOrderParams {
|
|
358
|
+
marketId: string;
|
|
359
|
+
outcomeId: string; // Use outcome.id from market data
|
|
360
|
+
side: 'buy' | 'sell';
|
|
361
|
+
type: 'market' | 'limit';
|
|
362
|
+
amount: number; // Number of contracts/shares
|
|
363
|
+
price?: number; // Required for limit orders (0.0-1.0)
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**Returns**: `Order`
|
|
368
|
+
```typescript
|
|
369
|
+
interface Order {
|
|
370
|
+
id: string;
|
|
371
|
+
marketId: string;
|
|
372
|
+
outcomeId: string;
|
|
373
|
+
side: 'buy' | 'sell';
|
|
374
|
+
type: 'market' | 'limit';
|
|
375
|
+
price?: number;
|
|
376
|
+
amount: number;
|
|
377
|
+
status: 'pending' | 'open' | 'filled' | 'cancelled' | 'rejected';
|
|
378
|
+
filled: number; // Amount filled so far
|
|
379
|
+
remaining: number; // Amount remaining
|
|
380
|
+
timestamp: number;
|
|
381
|
+
fee?: number;
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### `cancelOrder(orderId)`
|
|
386
|
+
Cancel an open order.
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
const cancelledOrder = await polymarket.cancelOrder('order-123');
|
|
390
|
+
console.log(cancelledOrder.status); // 'cancelled'
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Returns**: `Order` (with updated status)
|
|
394
|
+
|
|
395
|
+
### `fetchOrder(orderId)`
|
|
396
|
+
Get details of a specific order.
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
const order = await kalshi.fetchOrder('order-456');
|
|
400
|
+
console.log(`Filled: ${order.filled}/${order.amount}`);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Returns**: `Order`
|
|
404
|
+
|
|
405
|
+
### `fetchOpenOrders(marketId?)`
|
|
406
|
+
Get all open orders, optionally filtered by market.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
// All open orders
|
|
410
|
+
const allOrders = await polymarket.fetchOpenOrders();
|
|
411
|
+
|
|
412
|
+
// Open orders for specific market
|
|
413
|
+
const marketOrders = await kalshi.fetchOpenOrders('FED-25JAN');
|
|
414
|
+
|
|
415
|
+
allOrders.forEach(order => {
|
|
416
|
+
console.log(`${order.side} ${order.amount} @ ${order.price}`);
|
|
417
|
+
});
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Returns**: `Order[]`
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Complete Trading Workflow
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
import pmxt from 'pmxtjs';
|
|
428
|
+
|
|
429
|
+
const exchange = new pmxt.Polymarket({
|
|
430
|
+
privateKey: process.env.POLYMARKET_PRIVATE_KEY
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// 1. Check balance
|
|
434
|
+
const [balance] = await exchange.fetchBalance();
|
|
435
|
+
console.log(`Available: $${balance.available}`);
|
|
436
|
+
|
|
437
|
+
// 2. Search for a market
|
|
438
|
+
const markets = await exchange.searchMarkets('Trump');
|
|
439
|
+
const market = markets[0];
|
|
440
|
+
const outcome = market.outcomes[0];
|
|
441
|
+
|
|
442
|
+
// 3. Place a limit order
|
|
443
|
+
const order = await exchange.createOrder({
|
|
444
|
+
marketId: market.id,
|
|
445
|
+
outcomeId: outcome.id,
|
|
446
|
+
side: 'buy',
|
|
447
|
+
type: 'limit',
|
|
448
|
+
amount: 10,
|
|
449
|
+
price: 0.50
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
console.log(`Order placed: ${order.id}`);
|
|
453
|
+
|
|
454
|
+
// 4. Check order status
|
|
455
|
+
const updatedOrder = await exchange.fetchOrder(order.id);
|
|
456
|
+
console.log(`Status: ${updatedOrder.status}`);
|
|
457
|
+
console.log(`Filled: ${updatedOrder.filled}/${updatedOrder.amount}`);
|
|
458
|
+
|
|
459
|
+
// 5. Cancel if needed
|
|
460
|
+
if (updatedOrder.status === 'open') {
|
|
461
|
+
await exchange.cancelOrder(order.id);
|
|
462
|
+
console.log('Order cancelled');
|
|
84
463
|
}
|
|
464
|
+
|
|
465
|
+
// 6. Check positions
|
|
466
|
+
const positions = await exchange.fetchPositions();
|
|
467
|
+
positions.forEach(pos => {
|
|
468
|
+
console.log(`${pos.outcomeLabel}: ${pos.unrealizedPnL > 0 ? '+' : ''}$${pos.unrealizedPnL.toFixed(2)}`);
|
|
469
|
+
});
|
|
85
470
|
```
|
|
86
471
|
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Quick Reference
|
|
475
|
+
|
|
476
|
+
- **Prices**: Always 0.0-1.0 (multiply by 100 for %)
|
|
477
|
+
- **Timestamps**: Unix milliseconds
|
|
478
|
+
- **Volumes**: USD
|
|
479
|
+
- **IDs**: Use `outcome.id` for deep-dive methods, not `market.id`
|
|
480
|
+
- **Authentication**: Required for all trading and account methods
|
|
481
|
+
|
|
482
|
+
For more examples, see [`examples/`](examples/).
|
|
483
|
+
|
package/dist/BaseExchange.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { UnifiedMarket, PriceCandle, CandleInterval, OrderBook, Trade } from './types';
|
|
1
|
+
import { UnifiedMarket, PriceCandle, CandleInterval, OrderBook, Trade, Order, Position, Balance, CreateOrderParams } from './types';
|
|
2
2
|
export interface MarketFilterParams {
|
|
3
3
|
limit?: number;
|
|
4
4
|
offset?: number;
|
|
5
5
|
sort?: 'volume' | 'liquidity' | 'newest';
|
|
6
|
+
searchIn?: 'title' | 'description' | 'both';
|
|
6
7
|
}
|
|
7
8
|
export interface HistoryFilterParams {
|
|
8
9
|
resolution: CandleInterval;
|
|
@@ -10,7 +11,17 @@ export interface HistoryFilterParams {
|
|
|
10
11
|
end?: Date;
|
|
11
12
|
limit?: number;
|
|
12
13
|
}
|
|
14
|
+
export interface ExchangeCredentials {
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
apiSecret?: string;
|
|
17
|
+
passphrase?: string;
|
|
18
|
+
privateKey?: string;
|
|
19
|
+
signatureType?: number;
|
|
20
|
+
funderAddress?: string;
|
|
21
|
+
}
|
|
13
22
|
export declare abstract class PredictionMarketExchange {
|
|
23
|
+
protected credentials?: ExchangeCredentials;
|
|
24
|
+
constructor(credentials?: ExchangeCredentials);
|
|
14
25
|
abstract get name(): string;
|
|
15
26
|
/**
|
|
16
27
|
* Fetch all relevant markets from the source.
|
|
@@ -18,7 +29,7 @@ export declare abstract class PredictionMarketExchange {
|
|
|
18
29
|
abstract fetchMarkets(params?: MarketFilterParams): Promise<UnifiedMarket[]>;
|
|
19
30
|
/**
|
|
20
31
|
* Search for markets matching a keyword query.
|
|
21
|
-
*
|
|
32
|
+
* By default, searches only in market titles. Use params.searchIn to search descriptions or both.
|
|
22
33
|
*/
|
|
23
34
|
abstract searchMarkets(query: string, params?: MarketFilterParams): Promise<UnifiedMarket[]>;
|
|
24
35
|
/**
|
|
@@ -33,7 +44,31 @@ export declare abstract class PredictionMarketExchange {
|
|
|
33
44
|
fetchOrderBook(id: string): Promise<OrderBook>;
|
|
34
45
|
/**
|
|
35
46
|
* Fetch raw trade history.
|
|
36
|
-
* Useful for generating synthetic OHLCV candles if the exchange doesn't provide them natively.
|
|
37
47
|
*/
|
|
38
48
|
fetchTrades(id: string, params: HistoryFilterParams): Promise<Trade[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Place a new order.
|
|
51
|
+
*/
|
|
52
|
+
createOrder(params: CreateOrderParams): Promise<Order>;
|
|
53
|
+
/**
|
|
54
|
+
* Cancel an existing order.
|
|
55
|
+
*/
|
|
56
|
+
cancelOrder(orderId: string): Promise<Order>;
|
|
57
|
+
/**
|
|
58
|
+
* Fetch a specific order by ID.
|
|
59
|
+
*/
|
|
60
|
+
fetchOrder(orderId: string): Promise<Order>;
|
|
61
|
+
/**
|
|
62
|
+
* Fetch all open orders.
|
|
63
|
+
* @param marketId - Optional filter by market.
|
|
64
|
+
*/
|
|
65
|
+
fetchOpenOrders(marketId?: string): Promise<Order[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Fetch current user positions.
|
|
68
|
+
*/
|
|
69
|
+
fetchPositions(): Promise<Position[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Fetch account balances.
|
|
72
|
+
*/
|
|
73
|
+
fetchBalance(): Promise<Balance[]>;
|
|
39
74
|
}
|
package/dist/BaseExchange.js
CHANGED
|
@@ -5,6 +5,9 @@ exports.PredictionMarketExchange = void 0;
|
|
|
5
5
|
// Base Exchange Class
|
|
6
6
|
// ----------------------------------------------------------------------------
|
|
7
7
|
class PredictionMarketExchange {
|
|
8
|
+
constructor(credentials) {
|
|
9
|
+
this.credentials = credentials;
|
|
10
|
+
}
|
|
8
11
|
/**
|
|
9
12
|
* Fetch historical price data for a specific market outcome.
|
|
10
13
|
* @param id - The Outcome ID (MarketOutcome.id). This should be the ID of the specific tradeable asset.
|
|
@@ -21,10 +24,49 @@ class PredictionMarketExchange {
|
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* Fetch raw trade history.
|
|
24
|
-
* Useful for generating synthetic OHLCV candles if the exchange doesn't provide them natively.
|
|
25
27
|
*/
|
|
26
28
|
async fetchTrades(id, params) {
|
|
27
29
|
throw new Error("Method fetchTrades not implemented.");
|
|
28
30
|
}
|
|
31
|
+
// ----------------------------------------------------------------------------
|
|
32
|
+
// Trading Methods
|
|
33
|
+
// ----------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Place a new order.
|
|
36
|
+
*/
|
|
37
|
+
async createOrder(params) {
|
|
38
|
+
throw new Error("Method createOrder not implemented.");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Cancel an existing order.
|
|
42
|
+
*/
|
|
43
|
+
async cancelOrder(orderId) {
|
|
44
|
+
throw new Error("Method cancelOrder not implemented.");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Fetch a specific order by ID.
|
|
48
|
+
*/
|
|
49
|
+
async fetchOrder(orderId) {
|
|
50
|
+
throw new Error("Method fetchOrder not implemented.");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Fetch all open orders.
|
|
54
|
+
* @param marketId - Optional filter by market.
|
|
55
|
+
*/
|
|
56
|
+
async fetchOpenOrders(marketId) {
|
|
57
|
+
throw new Error("Method fetchOpenOrders not implemented.");
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Fetch current user positions.
|
|
61
|
+
*/
|
|
62
|
+
async fetchPositions() {
|
|
63
|
+
throw new Error("Method fetchPositions not implemented.");
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Fetch account balances.
|
|
67
|
+
*/
|
|
68
|
+
async fetchBalance() {
|
|
69
|
+
throw new Error("Method fetchBalance not implemented.");
|
|
70
|
+
}
|
|
29
71
|
}
|
|
30
72
|
exports.PredictionMarketExchange = PredictionMarketExchange;
|
package/dist/exchanges/Kalshi.js
CHANGED
|
@@ -149,8 +149,16 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
149
149
|
try {
|
|
150
150
|
const markets = await this.fetchMarkets({ ...params, limit: fetchLimit });
|
|
151
151
|
const lowerQuery = query.toLowerCase();
|
|
152
|
-
const
|
|
153
|
-
|
|
152
|
+
const searchIn = params?.searchIn || 'title'; // Default to title-only search
|
|
153
|
+
const filtered = markets.filter(market => {
|
|
154
|
+
const titleMatch = (market.title || '').toLowerCase().includes(lowerQuery);
|
|
155
|
+
const descMatch = (market.description || '').toLowerCase().includes(lowerQuery);
|
|
156
|
+
if (searchIn === 'title')
|
|
157
|
+
return titleMatch;
|
|
158
|
+
if (searchIn === 'description')
|
|
159
|
+
return descMatch;
|
|
160
|
+
return titleMatch || descMatch; // 'both'
|
|
161
|
+
});
|
|
154
162
|
const limit = params?.limit || 20;
|
|
155
163
|
return filtered.slice(0, limit);
|
|
156
164
|
}
|