pmxt-core 2.50.16 → 2.51.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/hunch/api.d.ts +736 -0
- package/dist/exchanges/hunch/api.js +820 -0
- package/dist/exchanges/hunch/auth.d.ts +36 -0
- package/dist/exchanges/hunch/auth.js +63 -0
- package/dist/exchanges/hunch/errors.d.ts +26 -0
- package/dist/exchanges/hunch/errors.js +94 -0
- package/dist/exchanges/hunch/fetcher.d.ts +204 -0
- package/dist/exchanges/hunch/fetcher.js +130 -0
- package/dist/exchanges/hunch/index.d.ts +51 -0
- package/dist/exchanges/hunch/index.js +330 -0
- package/dist/exchanges/hunch/normalizer.d.ts +56 -0
- package/dist/exchanges/hunch/normalizer.js +180 -0
- package/dist/exchanges/hunch/price.d.ts +5 -0
- package/dist/exchanges/hunch/price.js +12 -0
- package/dist/exchanges/hunch/utils.d.ts +79 -0
- package/dist/exchanges/hunch/utils.js +182 -0
- package/dist/exchanges/hunch/websocket.d.ts +25 -0
- package/dist/exchanges/hunch/websocket.js +137 -0
- package/dist/exchanges/hyperliquid/auth.js +15 -2
- package/dist/exchanges/hyperliquid/fetcher.d.ts +26 -1
- package/dist/exchanges/hyperliquid/fetcher.js +66 -4
- package/dist/exchanges/hyperliquid/index.d.ts +4 -1
- package/dist/exchanges/hyperliquid/index.js +84 -20
- package/dist/exchanges/hyperliquid/normalizer.d.ts +4 -3
- package/dist/exchanges/hyperliquid/normalizer.js +69 -11
- package/dist/exchanges/hyperliquid/utils.d.ts +7 -1
- package/dist/exchanges/hyperliquid/utils.js +16 -4
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- 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/opinion/api.d.ts +1 -1
- package/dist/exchanges/opinion/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 +1 -0
- package/dist/server/exchange-factory.js +8 -0
- package/dist/server/openapi.yaml +17 -0
- package/dist/types.d.ts +4 -0
- package/package.json +3 -3
|
@@ -8,6 +8,7 @@ const fetcher_1 = require("./fetcher");
|
|
|
8
8
|
const normalizer_1 = require("./normalizer");
|
|
9
9
|
const auth_1 = require("./auth");
|
|
10
10
|
const errors_2 = require("./errors");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
11
12
|
class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
12
13
|
capabilityOverrides = {
|
|
13
14
|
fetchSeries: false,
|
|
@@ -76,13 +77,14 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
76
77
|
if (params.series !== undefined) {
|
|
77
78
|
return [];
|
|
78
79
|
}
|
|
79
|
-
const [rawQuestions, meta, mids] = await Promise.all([
|
|
80
|
+
const [rawQuestions, meta, mids, volumeMap] = await Promise.all([
|
|
80
81
|
this.fetcher.fetchRawEvents(params),
|
|
81
82
|
this.fetcher.fetchOutcomeMeta(),
|
|
82
83
|
this.fetcher.fetchAllMids(),
|
|
84
|
+
this.fetcher.fetchOutcomeVolumeMap(),
|
|
83
85
|
]);
|
|
84
86
|
return rawQuestions
|
|
85
|
-
.map(q => this.normalizer.normalizeEventWithMarkets(q, meta, mids))
|
|
87
|
+
.map(q => this.normalizer.normalizeEventWithMarkets(q, meta, mids, volumeMap))
|
|
86
88
|
.filter((e) => e !== null);
|
|
87
89
|
}
|
|
88
90
|
async fetchOrderBook(outcomeId, _limit, _params) {
|
|
@@ -92,7 +94,13 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
92
94
|
const raw = await this.fetcher.fetchRawOrderBook(outcomeId);
|
|
93
95
|
return this.normalizer.normalizeOrderBook(raw, outcomeId);
|
|
94
96
|
}
|
|
95
|
-
|
|
97
|
+
// ponytail: Hyperliquid has no native batch order-book endpoint; loop client-side.
|
|
98
|
+
// Add a concurrency cap if rate limits start biting in practice.
|
|
99
|
+
async fetchOrderBooks(outcomeIds) {
|
|
100
|
+
const entries = await Promise.all(outcomeIds.map(async (id) => [id, await this.fetchOrderBook(id)]));
|
|
101
|
+
return Object.fromEntries(entries);
|
|
102
|
+
}
|
|
103
|
+
async fetchOHLCV(outcomeId, params = { resolution: '1h' }) {
|
|
96
104
|
const raw = await this.fetcher.fetchRawOHLCV(outcomeId, params);
|
|
97
105
|
return this.normalizer.normalizeOHLCV(raw, params);
|
|
98
106
|
}
|
|
@@ -105,8 +113,11 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
105
113
|
// -------------------------------------------------------------------------
|
|
106
114
|
async fetchBalance() {
|
|
107
115
|
const wallet = this.requireWallet();
|
|
108
|
-
const
|
|
109
|
-
|
|
116
|
+
const [perp, spot] = await Promise.all([
|
|
117
|
+
this.fetcher.fetchRawUserState(wallet),
|
|
118
|
+
this.fetcher.fetchRawSpotState(wallet),
|
|
119
|
+
]);
|
|
120
|
+
return this.normalizer.normalizeBalance(perp, spot);
|
|
110
121
|
}
|
|
111
122
|
async fetchPositions() {
|
|
112
123
|
const wallet = this.requireWallet();
|
|
@@ -129,6 +140,35 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
129
140
|
.filter(f => f.coin.startsWith('#'))
|
|
130
141
|
.map((f, i) => this.normalizer.normalizeUserTrade(f, i));
|
|
131
142
|
}
|
|
143
|
+
// ponytail: HL exposes no "closed orders" endpoint, only userFills + openOrders.
|
|
144
|
+
// Synthesize closed orders as: oids seen in fills that are not currently open.
|
|
145
|
+
// Caveat — this surfaces *filled* orders, not *cancelled-with-no-fills* (HL drops those from public history).
|
|
146
|
+
async fetchClosedOrders() {
|
|
147
|
+
const wallet = this.requireWallet();
|
|
148
|
+
const [rawFills, rawOpen] = await Promise.all([
|
|
149
|
+
this.fetcher.fetchRawUserFills(wallet),
|
|
150
|
+
this.fetcher.fetchRawOpenOrders(wallet),
|
|
151
|
+
]);
|
|
152
|
+
const openOids = new Set(rawOpen.map(o => o.oid));
|
|
153
|
+
const byOid = new Map();
|
|
154
|
+
for (const f of rawFills) {
|
|
155
|
+
if (!f.coin.startsWith('#'))
|
|
156
|
+
continue;
|
|
157
|
+
if (openOids.has(f.oid))
|
|
158
|
+
continue;
|
|
159
|
+
const list = byOid.get(f.oid) ?? [];
|
|
160
|
+
list.push(f);
|
|
161
|
+
byOid.set(f.oid, list);
|
|
162
|
+
}
|
|
163
|
+
return [...byOid.values()].map(fills => this.normalizer.synthesizeClosedOrder(fills));
|
|
164
|
+
}
|
|
165
|
+
async fetchAllOrders() {
|
|
166
|
+
const [open, closed] = await Promise.all([
|
|
167
|
+
this.fetchOpenOrders(),
|
|
168
|
+
this.fetchClosedOrders(),
|
|
169
|
+
]);
|
|
170
|
+
return [...open, ...closed];
|
|
171
|
+
}
|
|
132
172
|
// -------------------------------------------------------------------------
|
|
133
173
|
// Trading (EIP-712 signing required)
|
|
134
174
|
// -------------------------------------------------------------------------
|
|
@@ -167,18 +207,24 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
167
207
|
if (data.status === 'err') {
|
|
168
208
|
throw errors_2.hyperliquidErrorMapper.mapError(new Error(data.response || 'Order submission failed'));
|
|
169
209
|
}
|
|
170
|
-
const
|
|
210
|
+
const status0 = data.response?.data?.statuses?.[0];
|
|
211
|
+
// HL returns one of: { resting: { oid } } | { filled: { oid, totalSz, avgPx } } | { error: string }
|
|
212
|
+
if (status0?.error) {
|
|
213
|
+
throw errors_2.hyperliquidErrorMapper.mapError(new Error(status0.error));
|
|
214
|
+
}
|
|
215
|
+
const oid = status0?.resting?.oid ?? status0?.filled?.oid;
|
|
216
|
+
const filledSz = status0?.filled?.totalSz ? parseFloat(status0.filled.totalSz) : 0;
|
|
171
217
|
return {
|
|
172
|
-
id:
|
|
218
|
+
id: oid !== undefined ? String(oid) : 'unknown',
|
|
173
219
|
marketId: built.params.marketId,
|
|
174
220
|
outcomeId: built.params.outcomeId,
|
|
175
221
|
side: built.params.side,
|
|
176
222
|
type: built.params.type,
|
|
177
|
-
price: built.params.price,
|
|
223
|
+
price: status0?.filled?.avgPx ? parseFloat(status0.filled.avgPx) : built.params.price,
|
|
178
224
|
amount: built.params.amount,
|
|
179
|
-
status:
|
|
180
|
-
filled:
|
|
181
|
-
remaining: built.params.amount -
|
|
225
|
+
status: status0?.resting ? 'open' : (status0?.filled ? 'filled' : 'pending'),
|
|
226
|
+
filled: filledSz,
|
|
227
|
+
remaining: built.params.amount - filledSz,
|
|
182
228
|
timestamp: Date.now(),
|
|
183
229
|
};
|
|
184
230
|
}
|
|
@@ -192,11 +238,24 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
192
238
|
}
|
|
193
239
|
async cancelOrder(orderId) {
|
|
194
240
|
const auth = this.requireAuth();
|
|
195
|
-
|
|
196
|
-
//
|
|
241
|
+
const wallet = this.requireWallet();
|
|
242
|
+
// HL needs the asset id of the order being cancelled, not just the oid.
|
|
243
|
+
// ponytail: look it up from openOrders. One extra HTTP call per cancel,
|
|
244
|
+
// and gives us a typed OrderNotFound when the caller's id is stale.
|
|
245
|
+
const oidNum = parseInt(orderId, 10);
|
|
246
|
+
if (!Number.isFinite(oidNum)) {
|
|
247
|
+
throw new Error(`Invalid Hyperliquid order id: ${orderId}`);
|
|
248
|
+
}
|
|
249
|
+
const open = await this.fetcher.fetchRawOpenOrders(wallet);
|
|
250
|
+
const target = open.find(o => o.oid === oidNum);
|
|
251
|
+
if (!target) {
|
|
252
|
+
throw errors_2.hyperliquidErrorMapper.mapError(new Error(`Order not found: ${orderId}`));
|
|
253
|
+
}
|
|
254
|
+
const decoded = (0, utils_1.fromCoinEncoding)(parseInt(target.coin.slice(1), 10));
|
|
255
|
+
const assetId = (0, utils_1.encodeAssetId)(decoded.outcomeId, decoded.side);
|
|
197
256
|
const action = {
|
|
198
257
|
type: 'cancel',
|
|
199
|
-
cancels: [{ a:
|
|
258
|
+
cancels: [{ a: assetId, o: oidNum }],
|
|
200
259
|
};
|
|
201
260
|
try {
|
|
202
261
|
const requestBody = await auth.signExchangeRequest(action);
|
|
@@ -205,17 +264,22 @@ class HyperliquidExchange extends BaseExchange_1.PredictionMarketExchange {
|
|
|
205
264
|
if (data.status === 'err') {
|
|
206
265
|
throw new Error(data.response || 'Cancel failed');
|
|
207
266
|
}
|
|
267
|
+
const status0 = data.response?.data?.statuses?.[0];
|
|
268
|
+
if (status0?.error) {
|
|
269
|
+
throw errors_2.hyperliquidErrorMapper.mapError(new Error(status0.error));
|
|
270
|
+
}
|
|
208
271
|
return {
|
|
209
272
|
id: orderId,
|
|
210
|
-
marketId: '',
|
|
211
|
-
outcomeId: '',
|
|
212
|
-
side: 'buy',
|
|
273
|
+
marketId: this.normalizer['coinToMarketId'](target.coin),
|
|
274
|
+
outcomeId: this.normalizer['coinToOutcomeId'](target.coin),
|
|
275
|
+
side: target.side === 'B' ? 'buy' : 'sell',
|
|
213
276
|
type: 'limit',
|
|
214
|
-
|
|
277
|
+
price: parseFloat(target.limitPx),
|
|
278
|
+
amount: parseFloat(target.sz),
|
|
215
279
|
status: 'canceled',
|
|
216
280
|
filled: 0,
|
|
217
|
-
remaining:
|
|
218
|
-
timestamp:
|
|
281
|
+
remaining: parseFloat(target.sz),
|
|
282
|
+
timestamp: target.timestamp,
|
|
219
283
|
};
|
|
220
284
|
}
|
|
221
285
|
catch (error) {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { UnifiedMarket, UnifiedEvent, OrderBook, PriceCandle, Trade, UserTrade, Position, Balance, Order } from '../../types';
|
|
2
2
|
import { IExchangeNormalizer } from '../interfaces';
|
|
3
3
|
import { OHLCVParams } from '../../BaseExchange';
|
|
4
|
-
import { HyperliquidRawOutcomeWithQuestion, HyperliquidRawQuestion, HyperliquidRawL2Book, HyperliquidRawCandle, HyperliquidRawTrade, HyperliquidRawFill, HyperliquidRawOpenOrder, HyperliquidRawPosition, HyperliquidRawUserState, HyperliquidRawOutcomeMeta, HyperliquidRawMid } from './fetcher';
|
|
4
|
+
import { HyperliquidRawOutcomeWithQuestion, HyperliquidRawQuestion, HyperliquidRawL2Book, HyperliquidRawCandle, HyperliquidRawTrade, HyperliquidRawFill, HyperliquidRawOpenOrder, HyperliquidRawPosition, HyperliquidRawUserState, HyperliquidRawSpotState, HyperliquidRawOutcomeMeta, HyperliquidRawMid } from './fetcher';
|
|
5
5
|
export declare class HyperliquidNormalizer implements IExchangeNormalizer<HyperliquidRawOutcomeWithQuestion, HyperliquidRawQuestion> {
|
|
6
6
|
normalizeMarket(raw: HyperliquidRawOutcomeWithQuestion): UnifiedMarket | null;
|
|
7
7
|
normalizeEvent(raw: HyperliquidRawQuestion): UnifiedEvent | null;
|
|
8
|
-
normalizeEventWithMarkets(raw: HyperliquidRawQuestion, outcomeMeta: HyperliquidRawOutcomeMeta, mids: HyperliquidRawMid): UnifiedEvent | null;
|
|
8
|
+
normalizeEventWithMarkets(raw: HyperliquidRawQuestion, outcomeMeta: HyperliquidRawOutcomeMeta, mids: HyperliquidRawMid, volumeMap?: Map<number, number>): UnifiedEvent | null;
|
|
9
9
|
normalizeOrderBook(raw: HyperliquidRawL2Book, _id: string): OrderBook;
|
|
10
10
|
normalizeOHLCV(raw: HyperliquidRawCandle[], _params: OHLCVParams): PriceCandle[];
|
|
11
11
|
normalizeTrade(raw: HyperliquidRawTrade, _index: number): Trade;
|
|
12
12
|
normalizeUserTrade(raw: HyperliquidRawFill, _index: number): UserTrade;
|
|
13
|
+
synthesizeClosedOrder(fills: HyperliquidRawFill[]): Order;
|
|
13
14
|
normalizeOpenOrder(raw: HyperliquidRawOpenOrder): Order;
|
|
14
15
|
normalizePosition(raw: HyperliquidRawPosition): Position;
|
|
15
|
-
normalizeBalance(raw: HyperliquidRawUserState): Balance[];
|
|
16
|
+
normalizeBalance(raw: HyperliquidRawUserState, spot?: HyperliquidRawSpotState): Balance[];
|
|
16
17
|
private coinToMarketId;
|
|
17
18
|
private coinToOutcomeId;
|
|
18
19
|
}
|
|
@@ -176,7 +176,7 @@ class HyperliquidNormalizer {
|
|
|
176
176
|
slug: `hl-${outcomeId}`,
|
|
177
177
|
outcomes,
|
|
178
178
|
resolutionDate: expiryDate ?? new Date(0),
|
|
179
|
-
volume24h: 0,
|
|
179
|
+
volume24h: raw.volume24h ?? 0,
|
|
180
180
|
liquidity: 0,
|
|
181
181
|
url: buildMarketUrl(outcomeId),
|
|
182
182
|
category,
|
|
@@ -218,7 +218,7 @@ class HyperliquidNormalizer {
|
|
|
218
218
|
sourceMetadata: (0, metadata_1.buildSourceMetadata)(raw, HL_PROMOTED_EVENT_KEYS),
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
|
-
normalizeEventWithMarkets(raw, outcomeMeta, mids) {
|
|
221
|
+
normalizeEventWithMarkets(raw, outcomeMeta, mids, volumeMap) {
|
|
222
222
|
const event = this.normalizeEvent(raw);
|
|
223
223
|
if (!event)
|
|
224
224
|
return null;
|
|
@@ -235,6 +235,7 @@ class HyperliquidNormalizer {
|
|
|
235
235
|
outcome,
|
|
236
236
|
question: raw,
|
|
237
237
|
midPrice,
|
|
238
|
+
volume24h: volumeMap?.get(outcomeId),
|
|
238
239
|
});
|
|
239
240
|
if (market) {
|
|
240
241
|
markets.push(market);
|
|
@@ -284,6 +285,7 @@ class HyperliquidNormalizer {
|
|
|
284
285
|
};
|
|
285
286
|
}
|
|
286
287
|
normalizeUserTrade(raw, _index) {
|
|
288
|
+
const fee = parseFloat(raw.fee);
|
|
287
289
|
return {
|
|
288
290
|
id: String(raw.tid),
|
|
289
291
|
timestamp: raw.time,
|
|
@@ -291,6 +293,44 @@ class HyperliquidNormalizer {
|
|
|
291
293
|
amount: parseFloat(raw.sz),
|
|
292
294
|
side: raw.side === 'B' ? 'buy' : raw.side === 'A' ? 'sell' : 'unknown',
|
|
293
295
|
orderId: String(raw.oid),
|
|
296
|
+
marketId: this.coinToMarketId(raw.coin),
|
|
297
|
+
outcomeId: this.coinToOutcomeId(raw.coin),
|
|
298
|
+
fee: Number.isFinite(fee) ? fee : undefined,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
// ponytail: HL has no closed-orders endpoint; we reconstruct from the fills of one oid.
|
|
302
|
+
// amount = filled (we cannot recover the unfilled-then-cancelled portion); price = VWAP across fills.
|
|
303
|
+
synthesizeClosedOrder(fills) {
|
|
304
|
+
const first = fills[0];
|
|
305
|
+
let totalSz = 0;
|
|
306
|
+
let totalNotional = 0;
|
|
307
|
+
let totalFee = 0;
|
|
308
|
+
let earliest = first.time;
|
|
309
|
+
for (const f of fills) {
|
|
310
|
+
const sz = parseFloat(f.sz);
|
|
311
|
+
const px = parseFloat(f.px);
|
|
312
|
+
const fee = parseFloat(f.fee);
|
|
313
|
+
totalSz += sz;
|
|
314
|
+
totalNotional += sz * px;
|
|
315
|
+
if (Number.isFinite(fee))
|
|
316
|
+
totalFee += fee;
|
|
317
|
+
if (f.time < earliest)
|
|
318
|
+
earliest = f.time;
|
|
319
|
+
}
|
|
320
|
+
const vwap = totalSz > 0 ? totalNotional / totalSz : parseFloat(first.px);
|
|
321
|
+
return {
|
|
322
|
+
id: String(first.oid),
|
|
323
|
+
marketId: this.coinToMarketId(first.coin),
|
|
324
|
+
outcomeId: this.coinToOutcomeId(first.coin),
|
|
325
|
+
side: first.side === 'B' ? 'buy' : 'sell',
|
|
326
|
+
type: 'limit',
|
|
327
|
+
price: vwap,
|
|
328
|
+
amount: totalSz,
|
|
329
|
+
status: 'filled',
|
|
330
|
+
filled: totalSz,
|
|
331
|
+
remaining: 0,
|
|
332
|
+
timestamp: earliest,
|
|
333
|
+
fee: totalFee,
|
|
294
334
|
};
|
|
295
335
|
}
|
|
296
336
|
normalizeOpenOrder(raw) {
|
|
@@ -333,16 +373,34 @@ class HyperliquidNormalizer {
|
|
|
333
373
|
unrealizedPnL: parseFloat(raw.unrealizedPnl),
|
|
334
374
|
};
|
|
335
375
|
}
|
|
336
|
-
normalizeBalance(raw) {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
376
|
+
normalizeBalance(raw, spot) {
|
|
377
|
+
const result = [];
|
|
378
|
+
// Spot balances: outcome markets quote against these (USDC, USDH, etc.).
|
|
379
|
+
for (const b of spot?.balances ?? []) {
|
|
380
|
+
const total = parseFloat(b.total);
|
|
381
|
+
const hold = parseFloat(b.hold);
|
|
382
|
+
if (!Number.isFinite(total) || total === 0)
|
|
383
|
+
continue;
|
|
384
|
+
result.push({
|
|
385
|
+
currency: b.coin,
|
|
342
386
|
total,
|
|
343
|
-
available: total -
|
|
344
|
-
locked,
|
|
345
|
-
}
|
|
387
|
+
available: total - (Number.isFinite(hold) ? hold : 0),
|
|
388
|
+
locked: Number.isFinite(hold) ? hold : 0,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
// Perp cross-margin account, labelled as such so consumers don't conflate it with spot.
|
|
392
|
+
const summary = raw.crossMarginSummary;
|
|
393
|
+
const perpTotal = parseFloat(summary.accountValue);
|
|
394
|
+
const perpLocked = parseFloat(summary.totalMarginUsed);
|
|
395
|
+
if (Number.isFinite(perpTotal) && perpTotal > 0) {
|
|
396
|
+
result.push({
|
|
397
|
+
currency: 'USDC_PERP',
|
|
398
|
+
total: perpTotal,
|
|
399
|
+
available: perpTotal - perpLocked,
|
|
400
|
+
locked: perpLocked,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
return result;
|
|
346
404
|
}
|
|
347
405
|
// -- Private helpers -------------------------------------------------------
|
|
348
406
|
coinToMarketId(coin) {
|
|
@@ -39,7 +39,13 @@ export declare function toMidKey(outcomeId: number): string;
|
|
|
39
39
|
*/
|
|
40
40
|
export declare function toMarketId(outcomeId: number): string;
|
|
41
41
|
/**
|
|
42
|
-
* Extract the numeric outcome ID from
|
|
42
|
+
* Extract the numeric outcome ID from a Hyperliquid identifier.
|
|
43
|
+
*
|
|
44
|
+
* Accepts either:
|
|
45
|
+
* - our canonical market ID, "hl-outcome-{N}"
|
|
46
|
+
* - a raw encoded asset token (numeric string >= OUTCOME_ASSET_BASE),
|
|
47
|
+
* as returned in UnifiedMarket.outcomes[].outcomeId. Decoded via
|
|
48
|
+
* decodeAssetId so callers can pass an outcome token directly.
|
|
43
49
|
*/
|
|
44
50
|
export declare function fromMarketId(marketId: string): number;
|
|
45
51
|
/**
|
|
@@ -69,14 +69,26 @@ function toMarketId(outcomeId) {
|
|
|
69
69
|
return `hl-outcome-${outcomeId}`;
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
|
-
* Extract the numeric outcome ID from
|
|
72
|
+
* Extract the numeric outcome ID from a Hyperliquid identifier.
|
|
73
|
+
*
|
|
74
|
+
* Accepts either:
|
|
75
|
+
* - our canonical market ID, "hl-outcome-{N}"
|
|
76
|
+
* - a raw encoded asset token (numeric string >= OUTCOME_ASSET_BASE),
|
|
77
|
+
* as returned in UnifiedMarket.outcomes[].outcomeId. Decoded via
|
|
78
|
+
* decodeAssetId so callers can pass an outcome token directly.
|
|
73
79
|
*/
|
|
74
80
|
function fromMarketId(marketId) {
|
|
75
81
|
const match = marketId.match(/^hl-outcome-(\d+)$/);
|
|
76
|
-
if (
|
|
77
|
-
|
|
82
|
+
if (match) {
|
|
83
|
+
return parseInt(match[1], 10);
|
|
84
|
+
}
|
|
85
|
+
if (/^\d+$/.test(marketId)) {
|
|
86
|
+
const assetId = parseInt(marketId, 10);
|
|
87
|
+
if (assetId >= config_1.OUTCOME_ASSET_BASE) {
|
|
88
|
+
return decodeAssetId(assetId).outcomeId;
|
|
89
|
+
}
|
|
78
90
|
}
|
|
79
|
-
|
|
91
|
+
throw new Error(`Invalid Hyperliquid market ID: ${marketId}`);
|
|
80
92
|
}
|
|
81
93
|
/**
|
|
82
94
|
* Build an outcome ID string for the unified type.
|
|
@@ -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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.874Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.874Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.kalshiApiSpec = {
|
|
@@ -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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.913Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.913Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.limitlessApiSpec = {
|
|
@@ -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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.925Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.925Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.myriadApiSpec = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
|
|
3
|
-
* Generated at: 2026-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.930Z
|
|
4
4
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
5
5
|
*/
|
|
6
6
|
export declare const opinionApiSpec: {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.opinionApiSpec = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/opinion/opinion-openapi.yaml
|
|
6
|
-
* Generated at: 2026-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.930Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.opinionApiSpec = {
|
|
@@ -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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.882Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.882Z
|
|
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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.896Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.896Z
|
|
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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.893Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.893Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.polymarketGammaSpec = {
|
|
@@ -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-06-
|
|
3
|
+
* Generated at: 2026-06-22T13:10:46.919Z
|
|
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-06-
|
|
6
|
+
* Generated at: 2026-06-22T13:10:46.919Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export * from './exchanges/hyperliquid';
|
|
|
19
19
|
export * from './exchanges/gemini-titan';
|
|
20
20
|
export * from './exchanges/suibets';
|
|
21
21
|
export * from './exchanges/rain';
|
|
22
|
+
export * from './exchanges/hunch';
|
|
22
23
|
export * from './router';
|
|
23
24
|
export * from './feeds';
|
|
24
25
|
export * from './server/app';
|
|
@@ -40,6 +41,7 @@ import { HyperliquidExchange } from './exchanges/hyperliquid';
|
|
|
40
41
|
import { GeminiTitanExchange } from './exchanges/gemini-titan';
|
|
41
42
|
import { SuiBetsExchange } from './exchanges/suibets';
|
|
42
43
|
import { RainExchange } from './exchanges/rain';
|
|
44
|
+
import { HunchExchange } from './exchanges/hunch';
|
|
43
45
|
import { Router } from './router';
|
|
44
46
|
declare const pmxt: {
|
|
45
47
|
Mock: typeof MockExchange;
|
|
@@ -58,6 +60,7 @@ declare const pmxt: {
|
|
|
58
60
|
GeminiTitan: typeof GeminiTitanExchange;
|
|
59
61
|
SuiBets: typeof SuiBetsExchange;
|
|
60
62
|
Rain: typeof RainExchange;
|
|
63
|
+
Hunch: typeof HunchExchange;
|
|
61
64
|
Router: typeof Router;
|
|
62
65
|
};
|
|
63
66
|
export declare const Mock: typeof MockExchange;
|
|
@@ -76,4 +79,5 @@ export declare const Hyperliquid: typeof HyperliquidExchange;
|
|
|
76
79
|
export declare const GeminiTitan: typeof GeminiTitanExchange;
|
|
77
80
|
export declare const SuiBets: typeof SuiBetsExchange;
|
|
78
81
|
export declare const Rain: typeof RainExchange;
|
|
82
|
+
export declare const Hunch: typeof HunchExchange;
|
|
79
83
|
export default pmxt;
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.Rain = exports.SuiBets = exports.GeminiTitan = exports.Hyperliquid = exports.PolymarketUS = exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.Mock = exports.parseOpenApiSpec = void 0;
|
|
17
|
+
exports.Hunch = exports.Rain = exports.SuiBets = exports.GeminiTitan = exports.Hyperliquid = exports.PolymarketUS = exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.Mock = exports.parseOpenApiSpec = void 0;
|
|
18
18
|
__exportStar(require("./BaseExchange"), exports);
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
__exportStar(require("./utils/math"), exports);
|
|
@@ -37,6 +37,7 @@ __exportStar(require("./exchanges/hyperliquid"), exports);
|
|
|
37
37
|
__exportStar(require("./exchanges/gemini-titan"), exports);
|
|
38
38
|
__exportStar(require("./exchanges/suibets"), exports);
|
|
39
39
|
__exportStar(require("./exchanges/rain"), exports);
|
|
40
|
+
__exportStar(require("./exchanges/hunch"), exports);
|
|
40
41
|
__exportStar(require("./router"), exports);
|
|
41
42
|
__exportStar(require("./feeds"), exports);
|
|
42
43
|
__exportStar(require("./server/app"), exports);
|
|
@@ -58,6 +59,7 @@ const hyperliquid_1 = require("./exchanges/hyperliquid");
|
|
|
58
59
|
const gemini_titan_1 = require("./exchanges/gemini-titan");
|
|
59
60
|
const suibets_1 = require("./exchanges/suibets");
|
|
60
61
|
const rain_1 = require("./exchanges/rain");
|
|
62
|
+
const hunch_1 = require("./exchanges/hunch");
|
|
61
63
|
const router_1 = require("./router");
|
|
62
64
|
const pmxt = {
|
|
63
65
|
Mock: mock_1.MockExchange,
|
|
@@ -76,6 +78,7 @@ const pmxt = {
|
|
|
76
78
|
GeminiTitan: gemini_titan_1.GeminiTitanExchange,
|
|
77
79
|
SuiBets: suibets_1.SuiBetsExchange,
|
|
78
80
|
Rain: rain_1.RainExchange,
|
|
81
|
+
Hunch: hunch_1.HunchExchange,
|
|
79
82
|
Router: router_1.Router,
|
|
80
83
|
};
|
|
81
84
|
exports.Mock = mock_1.MockExchange;
|
|
@@ -94,4 +97,5 @@ exports.Hyperliquid = hyperliquid_1.HyperliquidExchange;
|
|
|
94
97
|
exports.GeminiTitan = gemini_titan_1.GeminiTitanExchange;
|
|
95
98
|
exports.SuiBets = suibets_1.SuiBetsExchange;
|
|
96
99
|
exports.Rain = rain_1.RainExchange;
|
|
100
|
+
exports.Hunch = hunch_1.HunchExchange;
|
|
97
101
|
exports.default = pmxt;
|
package/dist/server/app.js
CHANGED
|
@@ -16,6 +16,7 @@ const hyperliquid_1 = require("../exchanges/hyperliquid");
|
|
|
16
16
|
const gemini_titan_1 = require("../exchanges/gemini-titan");
|
|
17
17
|
const suibets_1 = require("../exchanges/suibets");
|
|
18
18
|
const rain_1 = require("../exchanges/rain");
|
|
19
|
+
const hunch_1 = require("../exchanges/hunch");
|
|
19
20
|
const mock_1 = require("../exchanges/mock");
|
|
20
21
|
const router_1 = require("../router");
|
|
21
22
|
function createExchange(name, credentials, bearerToken) {
|
|
@@ -124,6 +125,13 @@ function createExchange(name, credentials, bearerToken) {
|
|
|
124
125
|
environment: (credentials?.environment ||
|
|
125
126
|
process.env.RAIN_ENVIRONMENT),
|
|
126
127
|
});
|
|
128
|
+
case "hunch":
|
|
129
|
+
return new hunch_1.HunchExchange({
|
|
130
|
+
privateKey: credentials?.privateKey || process.env.HUNCH_PRIVATE_KEY,
|
|
131
|
+
walletAddress: credentials?.walletAddress ||
|
|
132
|
+
process.env.HUNCH_WALLET_ADDRESS,
|
|
133
|
+
baseUrl: credentials?.baseUrl || process.env.HUNCH_BASE_URL,
|
|
134
|
+
});
|
|
127
135
|
case "mock":
|
|
128
136
|
return new mock_1.MockExchange();
|
|
129
137
|
case "router":
|