pmxt-core 2.22.2 → 2.24.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 +2 -0
- 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/metaculus/api.d.ts +212 -0
- package/dist/exchanges/metaculus/api.js +418 -0
- package/dist/exchanges/metaculus/cancelOrder.d.ts +38 -0
- package/dist/exchanges/metaculus/cancelOrder.js +74 -0
- package/dist/exchanges/metaculus/createOrder.d.ts +107 -0
- package/dist/exchanges/metaculus/createOrder.js +272 -0
- package/dist/exchanges/metaculus/errors.d.ts +21 -0
- package/dist/exchanges/metaculus/errors.js +59 -0
- package/dist/exchanges/metaculus/fetchEvents.d.ts +5 -0
- package/dist/exchanges/metaculus/fetchEvents.js +187 -0
- package/dist/exchanges/metaculus/fetchMarkets.d.ts +6 -0
- package/dist/exchanges/metaculus/fetchMarkets.js +198 -0
- package/dist/exchanges/metaculus/index.d.ts +105 -0
- package/dist/exchanges/metaculus/index.js +166 -0
- package/dist/exchanges/metaculus/utils.d.ts +40 -0
- package/dist/exchanges/metaculus/utils.js +320 -0
- 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/polymarket/auth.js +42 -8
- package/dist/exchanges/polymarket/index.js +56 -19
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/auth.js +5 -2
- package/dist/exchanges/smarkets/api.d.ts +8067 -0
- package/dist/exchanges/smarkets/api.js +10698 -0
- package/dist/exchanges/smarkets/auth.d.ts +56 -0
- package/dist/exchanges/smarkets/auth.js +105 -0
- package/dist/exchanges/smarkets/config.d.ts +41 -0
- package/dist/exchanges/smarkets/config.js +47 -0
- package/dist/exchanges/smarkets/errors.d.ts +31 -0
- package/dist/exchanges/smarkets/errors.js +186 -0
- package/dist/exchanges/smarkets/fetcher.d.ts +177 -0
- package/dist/exchanges/smarkets/fetcher.js +342 -0
- package/dist/exchanges/smarkets/index.d.ts +54 -0
- package/dist/exchanges/smarkets/index.js +285 -0
- package/dist/exchanges/smarkets/normalizer.d.ts +18 -0
- package/dist/exchanges/smarkets/normalizer.js +267 -0
- package/dist/exchanges/smarkets/price.d.ts +26 -0
- package/dist/exchanges/smarkets/price.js +44 -0
- package/dist/exchanges/smarkets/price.test.d.ts +1 -0
- package/dist/exchanges/smarkets/price.test.js +50 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -1
- package/dist/server/app.js +22 -3
- package/package.json +3 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { UnifiedMarket, UnifiedEvent, OrderBook, Trade, UserTrade, Position, Balance, Order } from '../../types';
|
|
2
|
+
import { IExchangeNormalizer } from '../interfaces';
|
|
3
|
+
import { SmarketsRawEventWithMarkets, SmarketsRawEvent, SmarketsRawMarket, SmarketsRawContract, SmarketsRawQuote, SmarketsRawActivityRow, SmarketsRawOrder, SmarketsRawVolume, SmarketsRawBalance } from './fetcher';
|
|
4
|
+
export declare class SmarketsNormalizer implements IExchangeNormalizer<SmarketsRawEventWithMarkets, SmarketsRawEventWithMarkets> {
|
|
5
|
+
normalizeMarket(raw: SmarketsRawEventWithMarkets): UnifiedMarket | null;
|
|
6
|
+
normalizeMarketsFromEvent(raw: SmarketsRawEventWithMarkets): UnifiedMarket[];
|
|
7
|
+
normalizeRawMarket(event: SmarketsRawEvent, market: SmarketsRawMarket, contracts: SmarketsRawContract[], volumes: SmarketsRawVolume[]): UnifiedMarket | null;
|
|
8
|
+
normalizeEvent(raw: SmarketsRawEventWithMarkets): UnifiedEvent | null;
|
|
9
|
+
normalizeOrderBook(raw: Record<string, SmarketsRawQuote>, _id: string): OrderBook;
|
|
10
|
+
normalizeActivityTrade(raw: SmarketsRawActivityRow, index: number): Trade;
|
|
11
|
+
normalizeActivityUserTrade(raw: SmarketsRawActivityRow, index: number): UserTrade;
|
|
12
|
+
normalizeOrder(raw: SmarketsRawOrder): Order;
|
|
13
|
+
normalizeCreateOrderResponse(raw: Record<string, any>): Order;
|
|
14
|
+
normalizePosition(raw: SmarketsRawOrder): Position;
|
|
15
|
+
normalizeBalance(raw: SmarketsRawBalance): Balance[];
|
|
16
|
+
private mapOrderStatus;
|
|
17
|
+
private mapOrderType;
|
|
18
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SmarketsNormalizer = void 0;
|
|
4
|
+
const market_utils_1 = require("../../utils/market-utils");
|
|
5
|
+
const price_1 = require("./price");
|
|
6
|
+
// ----------------------------------------------------------------------------
|
|
7
|
+
// Helpers
|
|
8
|
+
// ----------------------------------------------------------------------------
|
|
9
|
+
function extractEventCategory(event) {
|
|
10
|
+
const eventType = event.type;
|
|
11
|
+
if (typeof eventType === 'object' && eventType !== null) {
|
|
12
|
+
return eventType.domain;
|
|
13
|
+
}
|
|
14
|
+
if (typeof eventType === 'string') {
|
|
15
|
+
// e.g. "football_match" -> "football"
|
|
16
|
+
const parts = eventType.split('_');
|
|
17
|
+
if (parts.length >= 2) {
|
|
18
|
+
return parts.slice(0, -1).join('_');
|
|
19
|
+
}
|
|
20
|
+
return eventType;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
function buildEventUrl(event) {
|
|
25
|
+
if (event.full_slug) {
|
|
26
|
+
return `https://smarkets.com${event.full_slug}`;
|
|
27
|
+
}
|
|
28
|
+
return `https://smarkets.com/event/${event.id}/${event.slug}`;
|
|
29
|
+
}
|
|
30
|
+
function buildContractOutcome(contract, marketId) {
|
|
31
|
+
return {
|
|
32
|
+
outcomeId: contract.id,
|
|
33
|
+
marketId,
|
|
34
|
+
label: contract.name,
|
|
35
|
+
price: 0,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// ----------------------------------------------------------------------------
|
|
39
|
+
// Normalizer
|
|
40
|
+
// ----------------------------------------------------------------------------
|
|
41
|
+
class SmarketsNormalizer {
|
|
42
|
+
normalizeMarket(raw) {
|
|
43
|
+
if (!raw || !raw.markets || raw.markets.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
return this.normalizeRawMarket(raw.event, raw.markets[0], raw.contracts, raw.volumes);
|
|
46
|
+
}
|
|
47
|
+
normalizeMarketsFromEvent(raw) {
|
|
48
|
+
const results = [];
|
|
49
|
+
for (const market of raw.markets) {
|
|
50
|
+
const marketContracts = raw.contracts.filter(c => c.market_id === market.id);
|
|
51
|
+
const marketVolumes = raw.volumes.filter(v => v.market_id === market.id);
|
|
52
|
+
const um = this.normalizeRawMarket(raw.event, market, marketContracts, marketVolumes);
|
|
53
|
+
if (um)
|
|
54
|
+
results.push(um);
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
normalizeRawMarket(event, market, contracts, volumes) {
|
|
59
|
+
if (!market)
|
|
60
|
+
return null;
|
|
61
|
+
const marketContracts = contracts.filter(c => c.market_id === market.id);
|
|
62
|
+
const volume = volumes.find(v => v.market_id === market.id);
|
|
63
|
+
const outcomes = marketContracts.map(contract => buildContractOutcome(contract, market.id));
|
|
64
|
+
const category = extractEventCategory(event);
|
|
65
|
+
const tags = [];
|
|
66
|
+
if (category)
|
|
67
|
+
tags.push(category);
|
|
68
|
+
if (market.category && !tags.includes(market.category)) {
|
|
69
|
+
tags.push(market.category);
|
|
70
|
+
}
|
|
71
|
+
if (market.categories) {
|
|
72
|
+
for (const cat of market.categories) {
|
|
73
|
+
if (!tags.includes(cat))
|
|
74
|
+
tags.push(cat);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Derive resolution date from event end_date or start_datetime
|
|
78
|
+
const resolutionDate = event.end_date
|
|
79
|
+
? new Date(event.end_date)
|
|
80
|
+
: event.start_datetime
|
|
81
|
+
? new Date(event.start_datetime)
|
|
82
|
+
: new Date();
|
|
83
|
+
const um = {
|
|
84
|
+
marketId: market.id,
|
|
85
|
+
eventId: event.id,
|
|
86
|
+
title: event.name,
|
|
87
|
+
description: market.description || market.name || '',
|
|
88
|
+
slug: market.slug,
|
|
89
|
+
outcomes,
|
|
90
|
+
resolutionDate,
|
|
91
|
+
volume24h: 0, // Smarkets does not provide 24h volume separately
|
|
92
|
+
volume: volume ? (0, price_1.fromQuantityUnits)(volume.volume) : undefined,
|
|
93
|
+
liquidity: 0,
|
|
94
|
+
url: buildEventUrl(event),
|
|
95
|
+
category,
|
|
96
|
+
tags,
|
|
97
|
+
};
|
|
98
|
+
(0, market_utils_1.addBinaryOutcomes)(um);
|
|
99
|
+
return um;
|
|
100
|
+
}
|
|
101
|
+
normalizeEvent(raw) {
|
|
102
|
+
if (!raw || !raw.event)
|
|
103
|
+
return null;
|
|
104
|
+
const markets = this.normalizeMarketsFromEvent(raw);
|
|
105
|
+
const category = extractEventCategory(raw.event);
|
|
106
|
+
return {
|
|
107
|
+
id: raw.event.id,
|
|
108
|
+
title: raw.event.name,
|
|
109
|
+
description: raw.event.description || '',
|
|
110
|
+
slug: raw.event.slug,
|
|
111
|
+
markets,
|
|
112
|
+
volume24h: markets.reduce((sum, m) => sum + m.volume24h, 0),
|
|
113
|
+
volume: markets.some(m => m.volume !== undefined)
|
|
114
|
+
? markets.reduce((sum, m) => sum + (m.volume ?? 0), 0)
|
|
115
|
+
: undefined,
|
|
116
|
+
url: buildEventUrl(raw.event),
|
|
117
|
+
category,
|
|
118
|
+
tags: category ? [category] : [],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
normalizeOrderBook(raw, _id) {
|
|
122
|
+
const allBids = [];
|
|
123
|
+
const allAsks = [];
|
|
124
|
+
for (const contractId of Object.keys(raw)) {
|
|
125
|
+
const quote = raw[contractId];
|
|
126
|
+
if (!quote)
|
|
127
|
+
continue;
|
|
128
|
+
for (const bid of (quote.bids || [])) {
|
|
129
|
+
allBids.push({
|
|
130
|
+
price: (0, price_1.fromBasisPoints)(bid.price),
|
|
131
|
+
size: (0, price_1.fromQuantityUnits)(bid.quantity),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
for (const offer of (quote.offers || [])) {
|
|
135
|
+
allAsks.push({
|
|
136
|
+
price: (0, price_1.fromBasisPoints)(offer.price),
|
|
137
|
+
size: (0, price_1.fromQuantityUnits)(offer.quantity),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const sortedBids = [...allBids].sort((a, b) => b.price - a.price);
|
|
142
|
+
const sortedAsks = [...allAsks].sort((a, b) => a.price - b.price);
|
|
143
|
+
return {
|
|
144
|
+
bids: sortedBids,
|
|
145
|
+
asks: sortedAsks,
|
|
146
|
+
timestamp: Date.now(),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
normalizeActivityTrade(raw, index) {
|
|
150
|
+
const price = raw.price !== null ? (0, price_1.fromBasisPoints)(raw.price) : 0;
|
|
151
|
+
const amount = raw.quantity !== null ? (0, price_1.fromQuantityUnits)(raw.quantity) : 0;
|
|
152
|
+
let side = 'unknown';
|
|
153
|
+
if (raw.side === 'buy')
|
|
154
|
+
side = 'buy';
|
|
155
|
+
else if (raw.side === 'sell')
|
|
156
|
+
side = 'sell';
|
|
157
|
+
return {
|
|
158
|
+
id: `${raw.seq}-${raw.subseq}`,
|
|
159
|
+
timestamp: new Date(raw.timestamp).getTime(),
|
|
160
|
+
price,
|
|
161
|
+
amount,
|
|
162
|
+
side,
|
|
163
|
+
outcomeId: raw.contract_id || undefined,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
normalizeActivityUserTrade(raw, index) {
|
|
167
|
+
const trade = this.normalizeActivityTrade(raw, index);
|
|
168
|
+
return {
|
|
169
|
+
...trade,
|
|
170
|
+
orderId: raw.order_id || undefined,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
normalizeOrder(raw) {
|
|
174
|
+
return {
|
|
175
|
+
id: raw.id,
|
|
176
|
+
marketId: raw.market_id,
|
|
177
|
+
outcomeId: raw.contract_id,
|
|
178
|
+
side: raw.side === 'buy' ? 'buy' : 'sell',
|
|
179
|
+
type: this.mapOrderType(raw.type),
|
|
180
|
+
price: (0, price_1.fromBasisPoints)(raw.price),
|
|
181
|
+
amount: (0, price_1.fromQuantityUnits)(raw.quantity),
|
|
182
|
+
status: this.mapOrderStatus(raw.state),
|
|
183
|
+
filled: (0, price_1.fromQuantityUnits)(raw.quantity_filled),
|
|
184
|
+
remaining: (0, price_1.fromQuantityUnits)(raw.quantity_unfilled),
|
|
185
|
+
timestamp: new Date(raw.created_datetime).getTime(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
normalizeCreateOrderResponse(raw) {
|
|
189
|
+
const totalExecuted = raw.total_executed_quantity || 0;
|
|
190
|
+
const availableQty = raw.available_quantity || 0;
|
|
191
|
+
const quantity = raw.quantity || (totalExecuted + availableQty);
|
|
192
|
+
let status = 'open';
|
|
193
|
+
if (totalExecuted > 0 && availableQty === 0) {
|
|
194
|
+
status = 'filled';
|
|
195
|
+
}
|
|
196
|
+
else if (totalExecuted > 0) {
|
|
197
|
+
status = 'open';
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
status = 'pending';
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
id: raw.order_id,
|
|
204
|
+
marketId: raw.market_id,
|
|
205
|
+
outcomeId: raw.contract_id,
|
|
206
|
+
side: raw.side === 'buy' ? 'buy' : 'sell',
|
|
207
|
+
type: 'limit',
|
|
208
|
+
price: (0, price_1.fromBasisPoints)(raw.price),
|
|
209
|
+
amount: (0, price_1.fromQuantityUnits)(quantity),
|
|
210
|
+
status,
|
|
211
|
+
filled: (0, price_1.fromQuantityUnits)(totalExecuted),
|
|
212
|
+
remaining: (0, price_1.fromQuantityUnits)(availableQty),
|
|
213
|
+
timestamp: Date.now(),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
normalizePosition(raw) {
|
|
217
|
+
const size = (0, price_1.fromQuantityUnits)(raw.quantity_filled);
|
|
218
|
+
const entryPrice = raw.average_price_matched
|
|
219
|
+
? (0, price_1.fromBasisPoints)(raw.average_price_matched)
|
|
220
|
+
: (0, price_1.fromBasisPoints)(raw.price);
|
|
221
|
+
return {
|
|
222
|
+
marketId: raw.market_id,
|
|
223
|
+
outcomeId: raw.contract_id,
|
|
224
|
+
outcomeLabel: raw.contract_id,
|
|
225
|
+
size: raw.side === 'buy' ? size : -size,
|
|
226
|
+
entryPrice,
|
|
227
|
+
currentPrice: entryPrice,
|
|
228
|
+
unrealizedPnL: 0,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
normalizeBalance(raw) {
|
|
232
|
+
const balance = parseFloat(raw.balance || '0');
|
|
233
|
+
const available = parseFloat(raw.available_balance || '0');
|
|
234
|
+
return [{
|
|
235
|
+
currency: raw.currency || 'GBP',
|
|
236
|
+
total: balance,
|
|
237
|
+
available,
|
|
238
|
+
locked: balance - available,
|
|
239
|
+
}];
|
|
240
|
+
}
|
|
241
|
+
// -- Private helpers ------------------------------------------------------
|
|
242
|
+
mapOrderStatus(state) {
|
|
243
|
+
switch (state) {
|
|
244
|
+
case 'created':
|
|
245
|
+
return 'pending';
|
|
246
|
+
case 'partial':
|
|
247
|
+
return 'open';
|
|
248
|
+
case 'filled':
|
|
249
|
+
case 'settled':
|
|
250
|
+
return 'filled';
|
|
251
|
+
default:
|
|
252
|
+
return 'open';
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
mapOrderType(type) {
|
|
256
|
+
switch (type) {
|
|
257
|
+
case 'immediate_or_cancel':
|
|
258
|
+
return 'market';
|
|
259
|
+
case 'good_til_cancelled':
|
|
260
|
+
case 'good_til_halted':
|
|
261
|
+
case 'keep_in_play':
|
|
262
|
+
default:
|
|
263
|
+
return 'limit';
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.SmarketsNormalizer = SmarketsNormalizer;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smarkets price and quantity conversion utilities.
|
|
3
|
+
*
|
|
4
|
+
* Smarkets uses percentage basis points (0-10000) for prices
|
|
5
|
+
* and 1/10000 GBP units for quantities.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Convert Smarkets basis points (0-10000) to probability (0.0-1.0).
|
|
9
|
+
*/
|
|
10
|
+
export declare function fromBasisPoints(basisPoints: number): number;
|
|
11
|
+
/**
|
|
12
|
+
* Convert probability (0.0-1.0) to Smarkets basis points (0-10000).
|
|
13
|
+
*/
|
|
14
|
+
export declare function toBasisPoints(probability: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* Convert Smarkets quantity units (1/10000 GBP) to GBP.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fromQuantityUnits(units: number): number;
|
|
19
|
+
/**
|
|
20
|
+
* Convert GBP to Smarkets quantity units (1/10000 GBP).
|
|
21
|
+
*/
|
|
22
|
+
export declare function toQuantityUnits(gbp: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Get the complement probability (for binary markets: No = 1 - Yes).
|
|
25
|
+
*/
|
|
26
|
+
export declare function invertProbability(price: number): number;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Smarkets price and quantity conversion utilities.
|
|
4
|
+
*
|
|
5
|
+
* Smarkets uses percentage basis points (0-10000) for prices
|
|
6
|
+
* and 1/10000 GBP units for quantities.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.fromBasisPoints = fromBasisPoints;
|
|
10
|
+
exports.toBasisPoints = toBasisPoints;
|
|
11
|
+
exports.fromQuantityUnits = fromQuantityUnits;
|
|
12
|
+
exports.toQuantityUnits = toQuantityUnits;
|
|
13
|
+
exports.invertProbability = invertProbability;
|
|
14
|
+
const BASIS_POINTS_SCALE = 10000;
|
|
15
|
+
/**
|
|
16
|
+
* Convert Smarkets basis points (0-10000) to probability (0.0-1.0).
|
|
17
|
+
*/
|
|
18
|
+
function fromBasisPoints(basisPoints) {
|
|
19
|
+
return basisPoints / BASIS_POINTS_SCALE;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Convert probability (0.0-1.0) to Smarkets basis points (0-10000).
|
|
23
|
+
*/
|
|
24
|
+
function toBasisPoints(probability) {
|
|
25
|
+
return Math.round(probability * BASIS_POINTS_SCALE);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert Smarkets quantity units (1/10000 GBP) to GBP.
|
|
29
|
+
*/
|
|
30
|
+
function fromQuantityUnits(units) {
|
|
31
|
+
return units / BASIS_POINTS_SCALE;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Convert GBP to Smarkets quantity units (1/10000 GBP).
|
|
35
|
+
*/
|
|
36
|
+
function toQuantityUnits(gbp) {
|
|
37
|
+
return Math.round(gbp * BASIS_POINTS_SCALE);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the complement probability (for binary markets: No = 1 - Yes).
|
|
41
|
+
*/
|
|
42
|
+
function invertProbability(price) {
|
|
43
|
+
return 1 - price;
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const price_1 = require("./price");
|
|
4
|
+
describe('Smarkets price conversions', () => {
|
|
5
|
+
describe('fromBasisPoints', () => {
|
|
6
|
+
test('converts basis points to a probability', () => {
|
|
7
|
+
expect((0, price_1.fromBasisPoints)(0)).toBe(0);
|
|
8
|
+
expect((0, price_1.fromBasisPoints)(5500)).toBe(0.55);
|
|
9
|
+
expect((0, price_1.fromBasisPoints)(10000)).toBe(1);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
describe('toBasisPoints', () => {
|
|
13
|
+
test('converts a probability to basis points', () => {
|
|
14
|
+
expect((0, price_1.toBasisPoints)(0)).toBe(0);
|
|
15
|
+
expect((0, price_1.toBasisPoints)(0.55)).toBe(5500);
|
|
16
|
+
expect((0, price_1.toBasisPoints)(1)).toBe(10000);
|
|
17
|
+
});
|
|
18
|
+
test('rounds non-integer results', () => {
|
|
19
|
+
expect((0, price_1.toBasisPoints)(0.12345)).toBe(1235);
|
|
20
|
+
});
|
|
21
|
+
test('round-trips with fromBasisPoints', () => {
|
|
22
|
+
const bp = (0, price_1.toBasisPoints)(0.42);
|
|
23
|
+
expect((0, price_1.fromBasisPoints)(bp)).toBeCloseTo(0.42);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe('fromQuantityUnits', () => {
|
|
27
|
+
test('converts quantity units to GBP', () => {
|
|
28
|
+
expect((0, price_1.fromQuantityUnits)(0)).toBe(0);
|
|
29
|
+
expect((0, price_1.fromQuantityUnits)(10000)).toBe(1);
|
|
30
|
+
expect((0, price_1.fromQuantityUnits)(25000)).toBe(2.5);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('toQuantityUnits', () => {
|
|
34
|
+
test('converts GBP to quantity units', () => {
|
|
35
|
+
expect((0, price_1.toQuantityUnits)(0)).toBe(0);
|
|
36
|
+
expect((0, price_1.toQuantityUnits)(1)).toBe(10000);
|
|
37
|
+
expect((0, price_1.toQuantityUnits)(2.5)).toBe(25000);
|
|
38
|
+
});
|
|
39
|
+
test('rounds fractional units', () => {
|
|
40
|
+
expect((0, price_1.toQuantityUnits)(0.123456)).toBe(1235);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('invertProbability', () => {
|
|
44
|
+
test('returns the complement of a probability', () => {
|
|
45
|
+
expect((0, price_1.invertProbability)(0)).toBe(1);
|
|
46
|
+
expect((0, price_1.invertProbability)(1)).toBe(0);
|
|
47
|
+
expect((0, price_1.invertProbability)(0.3)).toBeCloseTo(0.7);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export * from './exchanges/probable';
|
|
|
11
11
|
export * from './exchanges/baozi';
|
|
12
12
|
export * from './exchanges/myriad';
|
|
13
13
|
export * from './exchanges/opinion';
|
|
14
|
+
export * from './exchanges/metaculus';
|
|
15
|
+
export * from './exchanges/smarkets';
|
|
14
16
|
export * from './server/app';
|
|
15
17
|
export * from './server/utils/port-manager';
|
|
16
18
|
export * from './server/utils/lock-file';
|
|
@@ -22,6 +24,8 @@ import { ProbableExchange } from './exchanges/probable';
|
|
|
22
24
|
import { BaoziExchange } from './exchanges/baozi';
|
|
23
25
|
import { MyriadExchange } from './exchanges/myriad';
|
|
24
26
|
import { OpinionExchange } from './exchanges/opinion';
|
|
27
|
+
import { MetaculusExchange } from './exchanges/metaculus';
|
|
28
|
+
import { SmarketsExchange } from './exchanges/smarkets';
|
|
25
29
|
declare const pmxt: {
|
|
26
30
|
Polymarket: typeof PolymarketExchange;
|
|
27
31
|
Limitless: typeof LimitlessExchange;
|
|
@@ -31,6 +35,8 @@ declare const pmxt: {
|
|
|
31
35
|
Baozi: typeof BaoziExchange;
|
|
32
36
|
Myriad: typeof MyriadExchange;
|
|
33
37
|
Opinion: typeof OpinionExchange;
|
|
38
|
+
Metaculus: typeof MetaculusExchange;
|
|
39
|
+
Smarkets: typeof SmarketsExchange;
|
|
34
40
|
};
|
|
35
41
|
export declare const Polymarket: typeof PolymarketExchange;
|
|
36
42
|
export declare const Limitless: typeof LimitlessExchange;
|
|
@@ -40,4 +46,6 @@ export declare const Probable: typeof ProbableExchange;
|
|
|
40
46
|
export declare const Baozi: typeof BaoziExchange;
|
|
41
47
|
export declare const Myriad: typeof MyriadExchange;
|
|
42
48
|
export declare const Opinion: typeof OpinionExchange;
|
|
49
|
+
export declare const Metaculus: typeof MetaculusExchange;
|
|
50
|
+
export declare const Smarkets: typeof SmarketsExchange;
|
|
43
51
|
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.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.parseOpenApiSpec = void 0;
|
|
17
|
+
exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.parseOpenApiSpec = void 0;
|
|
18
18
|
__exportStar(require("./BaseExchange"), exports);
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
__exportStar(require("./utils/math"), exports);
|
|
@@ -29,6 +29,8 @@ __exportStar(require("./exchanges/probable"), exports);
|
|
|
29
29
|
__exportStar(require("./exchanges/baozi"), exports);
|
|
30
30
|
__exportStar(require("./exchanges/myriad"), exports);
|
|
31
31
|
__exportStar(require("./exchanges/opinion"), exports);
|
|
32
|
+
__exportStar(require("./exchanges/metaculus"), exports);
|
|
33
|
+
__exportStar(require("./exchanges/smarkets"), exports);
|
|
32
34
|
__exportStar(require("./server/app"), exports);
|
|
33
35
|
__exportStar(require("./server/utils/port-manager"), exports);
|
|
34
36
|
__exportStar(require("./server/utils/lock-file"), exports);
|
|
@@ -40,6 +42,8 @@ const probable_1 = require("./exchanges/probable");
|
|
|
40
42
|
const baozi_1 = require("./exchanges/baozi");
|
|
41
43
|
const myriad_1 = require("./exchanges/myriad");
|
|
42
44
|
const opinion_1 = require("./exchanges/opinion");
|
|
45
|
+
const metaculus_1 = require("./exchanges/metaculus");
|
|
46
|
+
const smarkets_1 = require("./exchanges/smarkets");
|
|
43
47
|
const pmxt = {
|
|
44
48
|
Polymarket: polymarket_1.PolymarketExchange,
|
|
45
49
|
Limitless: limitless_1.LimitlessExchange,
|
|
@@ -49,6 +53,8 @@ const pmxt = {
|
|
|
49
53
|
Baozi: baozi_1.BaoziExchange,
|
|
50
54
|
Myriad: myriad_1.MyriadExchange,
|
|
51
55
|
Opinion: opinion_1.OpinionExchange,
|
|
56
|
+
Metaculus: metaculus_1.MetaculusExchange,
|
|
57
|
+
Smarkets: smarkets_1.SmarketsExchange,
|
|
52
58
|
};
|
|
53
59
|
exports.Polymarket = polymarket_1.PolymarketExchange;
|
|
54
60
|
exports.Limitless = limitless_1.LimitlessExchange;
|
|
@@ -58,4 +64,6 @@ exports.Probable = probable_1.ProbableExchange;
|
|
|
58
64
|
exports.Baozi = baozi_1.BaoziExchange;
|
|
59
65
|
exports.Myriad = myriad_1.MyriadExchange;
|
|
60
66
|
exports.Opinion = opinion_1.OpinionExchange;
|
|
67
|
+
exports.Metaculus = metaculus_1.MetaculusExchange;
|
|
68
|
+
exports.Smarkets = smarkets_1.SmarketsExchange;
|
|
61
69
|
exports.default = pmxt;
|
package/dist/server/app.js
CHANGED
|
@@ -14,6 +14,8 @@ const probable_1 = require("../exchanges/probable");
|
|
|
14
14
|
const baozi_1 = require("../exchanges/baozi");
|
|
15
15
|
const myriad_1 = require("../exchanges/myriad");
|
|
16
16
|
const opinion_1 = require("../exchanges/opinion");
|
|
17
|
+
const metaculus_1 = require("../exchanges/metaculus");
|
|
18
|
+
const smarkets_1 = require("../exchanges/smarkets");
|
|
17
19
|
const errors_1 = require("../errors");
|
|
18
20
|
// Singleton instances for local usage (when no credentials provided)
|
|
19
21
|
const defaultExchanges = {
|
|
@@ -25,6 +27,8 @@ const defaultExchanges = {
|
|
|
25
27
|
baozi: null,
|
|
26
28
|
myriad: null,
|
|
27
29
|
opinion: null,
|
|
30
|
+
metaculus: null,
|
|
31
|
+
smarkets: null,
|
|
28
32
|
};
|
|
29
33
|
async function startServer(port, accessToken) {
|
|
30
34
|
const app = (0, express_1.default)();
|
|
@@ -58,7 +62,10 @@ async function startServer(port, accessToken) {
|
|
|
58
62
|
// If credentials are provided, create a new instance for this request
|
|
59
63
|
// Otherwise, use the singleton instance
|
|
60
64
|
let exchange;
|
|
61
|
-
if (credentials &&
|
|
65
|
+
if (credentials &&
|
|
66
|
+
(credentials.privateKey ||
|
|
67
|
+
credentials.apiKey ||
|
|
68
|
+
credentials.apiToken)) {
|
|
62
69
|
exchange = createExchange(exchangeName, credentials);
|
|
63
70
|
}
|
|
64
71
|
else {
|
|
@@ -143,8 +150,11 @@ function createExchange(name, credentials) {
|
|
|
143
150
|
apiKey: credentials?.apiKey || process.env.POLYMARKET_API_KEY,
|
|
144
151
|
apiSecret: credentials?.apiSecret || process.env.POLYMARKET_API_SECRET,
|
|
145
152
|
passphrase: credentials?.passphrase || process.env.POLYMARKET_PASSPHRASE,
|
|
146
|
-
funderAddress: credentials?.funderAddress
|
|
147
|
-
|
|
153
|
+
funderAddress: credentials?.funderAddress ||
|
|
154
|
+
process.env.POLYMARKET_FUNDER_ADDRESS ||
|
|
155
|
+
process.env.POLYMARKET_PROXY_ADDRESS,
|
|
156
|
+
signatureType: credentials?.signatureType ||
|
|
157
|
+
process.env.POLYMARKET_SIGNATURE_TYPE,
|
|
148
158
|
});
|
|
149
159
|
case "limitless":
|
|
150
160
|
return new limitless_1.LimitlessExchange({
|
|
@@ -193,6 +203,15 @@ function createExchange(name, credentials) {
|
|
|
193
203
|
privateKey: credentials?.privateKey || process.env.OPINION_PRIVATE_KEY,
|
|
194
204
|
funderAddress: credentials?.funderAddress,
|
|
195
205
|
});
|
|
206
|
+
case "metaculus":
|
|
207
|
+
return new metaculus_1.MetaculusExchange({
|
|
208
|
+
apiToken: credentials?.apiToken || process.env.METACULUS_API_TOKEN,
|
|
209
|
+
});
|
|
210
|
+
case "smarkets":
|
|
211
|
+
return new smarkets_1.SmarketsExchange({
|
|
212
|
+
apiKey: credentials?.apiKey || process.env.SMARKETS_EMAIL,
|
|
213
|
+
privateKey: credentials?.privateKey || process.env.SMARKETS_PASSWORD,
|
|
214
|
+
});
|
|
196
215
|
default:
|
|
197
216
|
throw new Error(`Unknown exchange: ${name}`);
|
|
198
217
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.24.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.24.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.24.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",
|