pmxt-core 2.20.1 → 2.20.2
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/baozi/fetcher.d.ts +40 -0
- package/dist/exchanges/baozi/fetcher.js +155 -0
- package/dist/exchanges/baozi/index.d.ts +2 -0
- package/dist/exchanges/baozi/index.js +60 -131
- package/dist/exchanges/baozi/normalizer.d.ts +14 -0
- package/dist/exchanges/baozi/normalizer.js +208 -0
- package/dist/exchanges/interfaces.d.ts +28 -0
- package/dist/exchanges/interfaces.js +2 -0
- package/dist/exchanges/kalshi/api.d.ts +1 -1
- package/dist/exchanges/kalshi/api.js +1 -1
- package/dist/exchanges/kalshi/fetcher.d.ts +126 -0
- package/dist/exchanges/kalshi/fetcher.js +313 -0
- package/dist/exchanges/kalshi/index.d.ts +6 -6
- package/dist/exchanges/kalshi/index.js +119 -202
- package/dist/exchanges/kalshi/normalizer.d.ts +25 -0
- package/dist/exchanges/kalshi/normalizer.js +294 -0
- package/dist/exchanges/limitless/api.d.ts +1 -1
- package/dist/exchanges/limitless/api.js +1 -1
- package/dist/exchanges/limitless/fetcher.d.ts +81 -0
- package/dist/exchanges/limitless/fetcher.js +238 -0
- package/dist/exchanges/limitless/index.d.ts +6 -9
- package/dist/exchanges/limitless/index.js +81 -79
- package/dist/exchanges/limitless/normalizer.d.ts +14 -0
- package/dist/exchanges/limitless/normalizer.js +117 -0
- package/dist/exchanges/limitless/websocket.d.ts +3 -0
- package/dist/exchanges/limitless/websocket.js +5 -4
- package/dist/exchanges/myriad/api.d.ts +1 -1
- package/dist/exchanges/myriad/api.js +1 -1
- package/dist/exchanges/myriad/fetcher.d.ts +73 -0
- package/dist/exchanges/myriad/fetcher.js +217 -0
- package/dist/exchanges/myriad/index.d.ts +2 -0
- package/dist/exchanges/myriad/index.js +40 -97
- package/dist/exchanges/myriad/normalizer.d.ts +14 -0
- package/dist/exchanges/myriad/normalizer.js +167 -0
- package/dist/exchanges/myriad/websocket.d.ts +3 -1
- package/dist/exchanges/myriad/websocket.js +4 -3
- 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/fetcher.d.ts +99 -0
- package/dist/exchanges/polymarket/fetcher.js +335 -0
- package/dist/exchanges/polymarket/index.d.ts +2 -0
- package/dist/exchanges/polymarket/index.js +80 -66
- package/dist/exchanges/polymarket/normalizer.d.ts +18 -0
- package/dist/exchanges/polymarket/normalizer.js +126 -0
- package/dist/exchanges/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/fetcher.d.ts +106 -0
- package/dist/exchanges/probable/fetcher.js +357 -0
- package/dist/exchanges/probable/index.d.ts +3 -1
- package/dist/exchanges/probable/index.js +73 -105
- package/dist/exchanges/probable/normalizer.d.ts +14 -0
- package/dist/exchanges/probable/normalizer.js +109 -0
- package/package.json +3 -3
- package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
- package/dist/exchanges/baozi/fetchEvents.js +0 -39
- package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
- package/dist/exchanges/baozi/fetchMarkets.js +0 -160
- package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
- package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
- package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
- package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
- package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
- package/dist/exchanges/baozi/fetchTrades.js +0 -10
- package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
- package/dist/exchanges/kalshi/fetchEvents.js +0 -196
- package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
- package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
- package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
- package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
- package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
- package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
- package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
- package/dist/exchanges/kalshi/fetchTrades.js +0 -33
- package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
- package/dist/exchanges/limitless/fetchEvents.js +0 -173
- package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
- package/dist/exchanges/limitless/fetchMarkets.js +0 -152
- package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
- package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
- package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
- package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
- package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
- package/dist/exchanges/limitless/fetchTrades.js +0 -27
- package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
- package/dist/exchanges/myriad/fetchEvents.js +0 -48
- package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/myriad/fetchMarkets.js +0 -102
- package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
- package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
- package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
- package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
- package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
- package/dist/exchanges/polymarket/fetchEvents.js +0 -135
- package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
- package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
- package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
- package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
- package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
- package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
- package/dist/exchanges/polymarket/fetchTrades.js +0 -43
- package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
- package/dist/exchanges/probable/fetchEvents.js +0 -151
- package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
- package/dist/exchanges/probable/fetchMarkets.js +0 -239
- package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
- package/dist/exchanges/probable/fetchTrades.js +0 -40
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resetCache = resetCache;
|
|
4
|
-
exports.fetchMarkets = fetchMarkets;
|
|
5
|
-
const utils_1 = require("./utils");
|
|
6
|
-
const errors_1 = require("./errors");
|
|
7
|
-
async function fetchActiveEvents(callApi, targetMarketCount, status = "open") {
|
|
8
|
-
let allEvents = [];
|
|
9
|
-
let totalMarketCount = 0;
|
|
10
|
-
let cursor = null;
|
|
11
|
-
let page = 0;
|
|
12
|
-
// Note: Kalshi API uses cursor-based pagination which requires sequential fetching.
|
|
13
|
-
// We cannot parallelize requests for a single list because we need the cursor from page N to fetch page N+1.
|
|
14
|
-
// To optimize, we use the maximum allowed limit (200) and fetch until exhaustion.
|
|
15
|
-
const MAX_PAGES = 1000; // Safety cap against infinite loops
|
|
16
|
-
const BATCH_SIZE = 200; // Max limit per Kalshi API docs
|
|
17
|
-
do {
|
|
18
|
-
try {
|
|
19
|
-
const queryParams = {
|
|
20
|
-
limit: BATCH_SIZE,
|
|
21
|
-
with_nested_markets: true,
|
|
22
|
-
status: status, // Filter by status (default 'open')
|
|
23
|
-
};
|
|
24
|
-
if (cursor)
|
|
25
|
-
queryParams.cursor = cursor;
|
|
26
|
-
const data = await callApi("GetEvents", queryParams);
|
|
27
|
-
const events = data.events || [];
|
|
28
|
-
if (events.length === 0)
|
|
29
|
-
break;
|
|
30
|
-
allEvents = allEvents.concat(events);
|
|
31
|
-
// Count markets in this batch for early termination
|
|
32
|
-
if (targetMarketCount) {
|
|
33
|
-
for (const event of events) {
|
|
34
|
-
totalMarketCount += (event.markets || []).length;
|
|
35
|
-
}
|
|
36
|
-
// Early termination: if we have enough markets, stop fetching
|
|
37
|
-
// Use 1.5x multiplier to ensure we have enough for sorting/filtering
|
|
38
|
-
if (totalMarketCount >= targetMarketCount * 1.5) {
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
cursor = data.cursor;
|
|
43
|
-
page++;
|
|
44
|
-
// Additional safety: if no target specified, limit to reasonable number of pages
|
|
45
|
-
if (!targetMarketCount && page >= 10) {
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
throw errors_1.kalshiErrorMapper.mapError(e);
|
|
51
|
-
}
|
|
52
|
-
} while (cursor && page < MAX_PAGES);
|
|
53
|
-
return allEvents;
|
|
54
|
-
}
|
|
55
|
-
async function fetchSeriesMap(callApi) {
|
|
56
|
-
try {
|
|
57
|
-
const data = await callApi("GetSeriesList");
|
|
58
|
-
const seriesList = data.series || [];
|
|
59
|
-
const map = new Map();
|
|
60
|
-
for (const series of seriesList) {
|
|
61
|
-
if (series.tags && series.tags.length > 0) {
|
|
62
|
-
map.set(series.ticker, series.tags);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return map;
|
|
66
|
-
}
|
|
67
|
-
catch (e) {
|
|
68
|
-
throw errors_1.kalshiErrorMapper.mapError(e);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// Simple in-memory cache to avoid redundant API calls within a short period
|
|
72
|
-
let cachedEvents = null;
|
|
73
|
-
let cachedSeriesMap = null;
|
|
74
|
-
let lastCacheTime = 0;
|
|
75
|
-
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
76
|
-
// Export a function to reset the cache (useful for testing)
|
|
77
|
-
function resetCache() {
|
|
78
|
-
cachedEvents = null;
|
|
79
|
-
cachedSeriesMap = null;
|
|
80
|
-
lastCacheTime = 0;
|
|
81
|
-
}
|
|
82
|
-
async function fetchMarkets(params, callApi) {
|
|
83
|
-
try {
|
|
84
|
-
// Handle marketId lookup (Kalshi marketId is the ticker)
|
|
85
|
-
if (params?.marketId) {
|
|
86
|
-
return await fetchMarketsBySlug(params.marketId, callApi);
|
|
87
|
-
}
|
|
88
|
-
// Handle slug-based lookup (event ticker)
|
|
89
|
-
if (params?.slug) {
|
|
90
|
-
return await fetchMarketsBySlug(params.slug, callApi);
|
|
91
|
-
}
|
|
92
|
-
// Handle outcomeId lookup (strip -NO suffix, use as ticker)
|
|
93
|
-
if (params?.outcomeId) {
|
|
94
|
-
const ticker = params.outcomeId.replace(/-NO$/, "");
|
|
95
|
-
return await fetchMarketsBySlug(ticker, callApi);
|
|
96
|
-
}
|
|
97
|
-
// Handle eventId lookup (event ticker works the same way)
|
|
98
|
-
if (params?.eventId) {
|
|
99
|
-
return await fetchMarketsBySlug(params.eventId, callApi);
|
|
100
|
-
}
|
|
101
|
-
// Handle query-based search
|
|
102
|
-
if (params?.query) {
|
|
103
|
-
return await searchMarkets(params.query, params, callApi);
|
|
104
|
-
}
|
|
105
|
-
// Default: fetch markets
|
|
106
|
-
return await fetchMarketsDefault(params, callApi);
|
|
107
|
-
}
|
|
108
|
-
catch (error) {
|
|
109
|
-
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async function fetchMarketsBySlug(eventTicker, callApi) {
|
|
113
|
-
// Kalshi API expects uppercase tickers, but URLs use lowercase
|
|
114
|
-
const normalizedTicker = eventTicker.toUpperCase();
|
|
115
|
-
const data = await callApi("GetEvent", {
|
|
116
|
-
event_ticker: normalizedTicker,
|
|
117
|
-
with_nested_markets: true,
|
|
118
|
-
});
|
|
119
|
-
const event = data.event;
|
|
120
|
-
if (!event)
|
|
121
|
-
return [];
|
|
122
|
-
// Enrichment: Fetch series tags if they exist
|
|
123
|
-
if (event.series_ticker) {
|
|
124
|
-
try {
|
|
125
|
-
const seriesData = await callApi("GetSeries", {
|
|
126
|
-
series_ticker: event.series_ticker,
|
|
127
|
-
});
|
|
128
|
-
const series = seriesData.series;
|
|
129
|
-
if (series && series.tags && series.tags.length > 0) {
|
|
130
|
-
if (!event.tags || event.tags.length === 0) {
|
|
131
|
-
event.tags = series.tags;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch (e) {
|
|
136
|
-
// Ignore errors fetching series info - non-critical
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const unifiedMarkets = [];
|
|
140
|
-
const markets = event.markets || [];
|
|
141
|
-
for (const market of markets) {
|
|
142
|
-
const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market);
|
|
143
|
-
if (unifiedMarket) {
|
|
144
|
-
unifiedMarkets.push(unifiedMarket);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return unifiedMarkets;
|
|
148
|
-
}
|
|
149
|
-
async function searchMarkets(query, params, callApi) {
|
|
150
|
-
// We must fetch ALL markets to search them locally since we don't have server-side search
|
|
151
|
-
const searchLimit = 250000;
|
|
152
|
-
const markets = await fetchMarketsDefault({ ...params, limit: searchLimit }, callApi);
|
|
153
|
-
const lowerQuery = query.toLowerCase();
|
|
154
|
-
const searchIn = params?.searchIn || "title"; // Default to title-only search
|
|
155
|
-
const filtered = markets.filter((market) => {
|
|
156
|
-
const titleMatch = (market.title || "").toLowerCase().includes(lowerQuery);
|
|
157
|
-
const descMatch = (market.description || "")
|
|
158
|
-
.toLowerCase()
|
|
159
|
-
.includes(lowerQuery);
|
|
160
|
-
if (searchIn === "title")
|
|
161
|
-
return titleMatch;
|
|
162
|
-
if (searchIn === "description")
|
|
163
|
-
return descMatch;
|
|
164
|
-
return titleMatch || descMatch; // 'both'
|
|
165
|
-
});
|
|
166
|
-
const limit = params?.limit || 250000;
|
|
167
|
-
return filtered.slice(0, limit);
|
|
168
|
-
}
|
|
169
|
-
async function fetchMarketsDefault(params, callApi) {
|
|
170
|
-
const limit = params?.limit || 250000;
|
|
171
|
-
const offset = params?.offset || 0;
|
|
172
|
-
const now = Date.now();
|
|
173
|
-
const status = params?.status || "active"; // Default to 'active'
|
|
174
|
-
// Map 'active' -> 'open', 'closed' -> 'closed'
|
|
175
|
-
// Kalshi statuses: 'open', 'closed', 'settled'
|
|
176
|
-
let apiStatus = "open";
|
|
177
|
-
if (status === "closed" || status === "inactive")
|
|
178
|
-
apiStatus = "closed";
|
|
179
|
-
else if (status === "all")
|
|
180
|
-
apiStatus = "open"; // Fallback for all? Or loop? For now default to open.
|
|
181
|
-
try {
|
|
182
|
-
let events;
|
|
183
|
-
let seriesMap;
|
|
184
|
-
// Check if we have valid cached data
|
|
185
|
-
// Only use global cache for the default 'active'/'open' case
|
|
186
|
-
const useCache = status === "active" || !params?.status;
|
|
187
|
-
if (useCache &&
|
|
188
|
-
cachedEvents &&
|
|
189
|
-
cachedSeriesMap &&
|
|
190
|
-
now - lastCacheTime < CACHE_TTL) {
|
|
191
|
-
events = cachedEvents;
|
|
192
|
-
seriesMap = cachedSeriesMap;
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
// Optimize fetch limit based on request parameters
|
|
196
|
-
// If sorting is required (e.g. by volume), we need to fetch a larger set (or all) to sort correctly.
|
|
197
|
-
// If no sorting is requested, we only need to fetch enough to satisfy the limit.
|
|
198
|
-
const isSorted = params?.sort &&
|
|
199
|
-
(params.sort === "volume" || params.sort === "liquidity");
|
|
200
|
-
const fetchLimit = isSorted ? 1000 : limit;
|
|
201
|
-
const [allEvents, fetchedSeriesMap] = await Promise.all([
|
|
202
|
-
fetchActiveEvents(callApi, fetchLimit, apiStatus),
|
|
203
|
-
fetchSeriesMap(callApi),
|
|
204
|
-
]);
|
|
205
|
-
events = allEvents;
|
|
206
|
-
seriesMap = fetchedSeriesMap;
|
|
207
|
-
// Cache the dataset ONLY if:
|
|
208
|
-
// 1. We fetched a comprehensive set (>= 1000)
|
|
209
|
-
// 2. It's the standard 'open' status query
|
|
210
|
-
if (fetchLimit >= 1000 && useCache) {
|
|
211
|
-
cachedEvents = allEvents;
|
|
212
|
-
cachedSeriesMap = fetchedSeriesMap;
|
|
213
|
-
lastCacheTime = now;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// Extract ALL markets from all events
|
|
217
|
-
const allMarkets = [];
|
|
218
|
-
// ... rest of the logic
|
|
219
|
-
for (const event of events) {
|
|
220
|
-
// Enrich event with tags from Series
|
|
221
|
-
if (event.series_ticker && seriesMap.has(event.series_ticker)) {
|
|
222
|
-
// If event has no tags or empty tags, use series tags
|
|
223
|
-
if (!event.tags || event.tags.length === 0) {
|
|
224
|
-
event.tags = seriesMap.get(event.series_ticker);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
const markets = event.markets || [];
|
|
228
|
-
for (const market of markets) {
|
|
229
|
-
const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market);
|
|
230
|
-
if (unifiedMarket) {
|
|
231
|
-
allMarkets.push(unifiedMarket);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Sort by 24h volume
|
|
236
|
-
if (params?.sort === "volume") {
|
|
237
|
-
allMarkets.sort((a, b) => b.volume24h - a.volume24h);
|
|
238
|
-
}
|
|
239
|
-
else if (params?.sort === "liquidity") {
|
|
240
|
-
allMarkets.sort((a, b) => b.liquidity - a.liquidity);
|
|
241
|
-
}
|
|
242
|
-
return allMarkets.slice(offset, offset + limit);
|
|
243
|
-
}
|
|
244
|
-
catch (error) {
|
|
245
|
-
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchOHLCV = fetchOHLCV;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
5
|
-
const validation_1 = require("../../utils/validation");
|
|
6
|
-
const errors_1 = require("./errors");
|
|
7
|
-
const price_1 = require("./price");
|
|
8
|
-
async function fetchOHLCV(id, params, callApi) {
|
|
9
|
-
(0, validation_1.validateIdFormat)(id, "OHLCV");
|
|
10
|
-
// Validate resolution is provided
|
|
11
|
-
if (!params.resolution) {
|
|
12
|
-
throw new Error("fetchOHLCV requires a resolution parameter. Use OHLCVParams with resolution specified.");
|
|
13
|
-
}
|
|
14
|
-
try {
|
|
15
|
-
// Kalshi API expects uppercase tickers
|
|
16
|
-
// Handle virtual "-NO" suffix by stripping it (fetching the underlying market history)
|
|
17
|
-
const cleanedId = id.replace(/-NO$/, "");
|
|
18
|
-
const normalizedId = cleanedId.toUpperCase();
|
|
19
|
-
const interval = (0, utils_1.mapIntervalToKalshi)(params.resolution);
|
|
20
|
-
// Heuristic for series_ticker
|
|
21
|
-
const parts = normalizedId.split("-");
|
|
22
|
-
if (parts.length < 2) {
|
|
23
|
-
throw new Error(`Invalid Kalshi Ticker format: "${id}". Expected format like "FED-25JAN29-B4.75".`);
|
|
24
|
-
}
|
|
25
|
-
const seriesTicker = parts.slice(0, -1).join("-");
|
|
26
|
-
const now = Math.floor(Date.now() / 1000);
|
|
27
|
-
let startTs = now - 24 * 60 * 60;
|
|
28
|
-
let endTs = now;
|
|
29
|
-
// Helper to handle string dates (from JSON)
|
|
30
|
-
// IMPORTANT: Python sends naive datetimes as ISO strings without 'Z' suffix.
|
|
31
|
-
// We must treat these as UTC, not local time.
|
|
32
|
-
const ensureDate = (d) => {
|
|
33
|
-
if (typeof d === "string") {
|
|
34
|
-
// If string doesn't end with 'Z' and doesn't have timezone offset, append 'Z'
|
|
35
|
-
if (!d.endsWith("Z") && !d.match(/[+-]\d{2}:\d{2}$/)) {
|
|
36
|
-
return new Date(d + "Z");
|
|
37
|
-
}
|
|
38
|
-
return new Date(d);
|
|
39
|
-
}
|
|
40
|
-
return d;
|
|
41
|
-
};
|
|
42
|
-
const pStart = params.start ? ensureDate(params.start) : undefined;
|
|
43
|
-
const pEnd = params.end ? ensureDate(params.end) : undefined;
|
|
44
|
-
if (pStart) {
|
|
45
|
-
startTs = Math.floor(pStart.getTime() / 1000);
|
|
46
|
-
}
|
|
47
|
-
if (pEnd) {
|
|
48
|
-
endTs = Math.floor(pEnd.getTime() / 1000);
|
|
49
|
-
if (!pStart) {
|
|
50
|
-
startTs = endTs - 24 * 60 * 60;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const data = await callApi("GetMarketCandlesticks", {
|
|
54
|
-
series_ticker: seriesTicker,
|
|
55
|
-
ticker: normalizedId,
|
|
56
|
-
period_interval: interval,
|
|
57
|
-
start_ts: startTs,
|
|
58
|
-
end_ts: endTs,
|
|
59
|
-
});
|
|
60
|
-
const candles = data.candlesticks || [];
|
|
61
|
-
const mappedCandles = candles.map((c) => {
|
|
62
|
-
// Priority:
|
|
63
|
-
// 1. Transaction price (close)
|
|
64
|
-
// 2. Mid price (average of yes_ask and yes_bid close)
|
|
65
|
-
// 3. Fallback to 0 if everything is missing
|
|
66
|
-
const p = c.price || {};
|
|
67
|
-
const ask = c.yes_ask || {};
|
|
68
|
-
const bid = c.yes_bid || {};
|
|
69
|
-
const getVal = (field) => {
|
|
70
|
-
if (p[field] !== null && p[field] !== undefined)
|
|
71
|
-
return p[field];
|
|
72
|
-
if (ask[field] !== null &&
|
|
73
|
-
bid[field] !== null &&
|
|
74
|
-
ask[field] !== undefined &&
|
|
75
|
-
bid[field] !== undefined) {
|
|
76
|
-
return (ask[field] + bid[field]) / 2;
|
|
77
|
-
}
|
|
78
|
-
return p.previous || 0;
|
|
79
|
-
};
|
|
80
|
-
return {
|
|
81
|
-
timestamp: c.end_period_ts * 1000,
|
|
82
|
-
open: (0, price_1.fromKalshiCents)(getVal("open")),
|
|
83
|
-
high: (0, price_1.fromKalshiCents)(getVal("high")),
|
|
84
|
-
low: (0, price_1.fromKalshiCents)(getVal("low")),
|
|
85
|
-
close: (0, price_1.fromKalshiCents)(getVal("close")),
|
|
86
|
-
volume: c.volume || 0,
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
if (params.limit && mappedCandles.length > params.limit) {
|
|
90
|
-
return mappedCandles.slice(-params.limit);
|
|
91
|
-
}
|
|
92
|
-
return mappedCandles;
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchOrderBook = fetchOrderBook;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const validation_1 = require("../../utils/validation");
|
|
9
|
-
const errors_1 = require("./errors");
|
|
10
|
-
const config_1 = require("./config");
|
|
11
|
-
async function fetchOrderBook(baseUrl, id) {
|
|
12
|
-
(0, validation_1.validateIdFormat)(id, "OrderBook");
|
|
13
|
-
try {
|
|
14
|
-
// Check if this is a NO outcome request
|
|
15
|
-
const isNoOutcome = id.endsWith("-NO");
|
|
16
|
-
const ticker = id.replace(/-NO$/, "");
|
|
17
|
-
const url = (0, config_1.getMarketsUrl)(baseUrl, ticker, ["orderbook"]);
|
|
18
|
-
const response = await axios_1.default.get(url);
|
|
19
|
-
const data = response.data.orderbook_fp;
|
|
20
|
-
// Structure: { yes_dollars: [["price", "qty"], ...], no_dollars: [["price", "qty"], ...] }
|
|
21
|
-
// Prices are dollar strings (e.g. "0.15"), quantities are fixed-point strings (e.g. "100.00")
|
|
22
|
-
// - yes_dollars: bids for buying YES at price X
|
|
23
|
-
// - no_dollars: bids for buying NO at price X
|
|
24
|
-
let bids;
|
|
25
|
-
let asks;
|
|
26
|
-
if (isNoOutcome) {
|
|
27
|
-
// NO outcome order book:
|
|
28
|
-
// - Bids: people buying NO (use data.no_dollars directly)
|
|
29
|
-
// - Asks: people selling NO = people buying YES (invert data.yes_dollars)
|
|
30
|
-
bids = (data.no_dollars || []).map((level) => ({
|
|
31
|
-
price: parseFloat(level[0]),
|
|
32
|
-
size: parseFloat(level[1]),
|
|
33
|
-
}));
|
|
34
|
-
asks = (data.yes_dollars || []).map((level) => ({
|
|
35
|
-
price: Math.round((1 - parseFloat(level[0])) * 10000) / 10000,
|
|
36
|
-
size: parseFloat(level[1]),
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
// YES outcome order book:
|
|
41
|
-
// - Bids: people buying YES (use data.yes_dollars directly)
|
|
42
|
-
// - Asks: people selling YES = people buying NO (invert data.no_dollars)
|
|
43
|
-
bids = (data.yes_dollars || []).map((level) => ({
|
|
44
|
-
price: parseFloat(level[0]),
|
|
45
|
-
size: parseFloat(level[1]),
|
|
46
|
-
}));
|
|
47
|
-
asks = (data.no_dollars || []).map((level) => ({
|
|
48
|
-
price: Math.round((1 - parseFloat(level[0])) * 10000) / 10000,
|
|
49
|
-
size: parseFloat(level[1]),
|
|
50
|
-
}));
|
|
51
|
-
}
|
|
52
|
-
// Sort bids desc, asks asc
|
|
53
|
-
bids.sort((a, b) => b.price - a.price);
|
|
54
|
-
asks.sort((a, b) => a.price - b.price);
|
|
55
|
-
return { bids, asks, timestamp: Date.now() };
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fetchTrades = fetchTrades;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const errors_1 = require("./errors");
|
|
9
|
-
const config_1 = require("./config");
|
|
10
|
-
const price_1 = require("./price");
|
|
11
|
-
async function fetchTrades(baseUrl, id, params) {
|
|
12
|
-
try {
|
|
13
|
-
const ticker = id.replace(/-NO$/, "");
|
|
14
|
-
const url = (0, config_1.getMarketsUrl)(baseUrl, undefined, ["trades"]);
|
|
15
|
-
const response = await axios_1.default.get(url, {
|
|
16
|
-
params: {
|
|
17
|
-
ticker: ticker,
|
|
18
|
-
limit: params.limit || 100,
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
const trades = response.data.trades || [];
|
|
22
|
-
return trades.map((t) => ({
|
|
23
|
-
id: t.trade_id,
|
|
24
|
-
timestamp: new Date(t.created_time).getTime(),
|
|
25
|
-
price: (0, price_1.fromKalshiCents)(t.yes_price),
|
|
26
|
-
amount: t.count,
|
|
27
|
-
side: t.taker_side === "yes" ? "buy" : "sell",
|
|
28
|
-
}));
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
throw errors_1.kalshiErrorMapper.mapError(error);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { EventFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedEvent } from '../../types';
|
|
3
|
-
import { AxiosInstance } from 'axios';
|
|
4
|
-
export declare function fetchEvents(params: EventFetchParams, callApi: (operationId: string, params?: Record<string, any>) => Promise<any>, http?: AxiosInstance): Promise<UnifiedEvent[]>;
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.fetchEvents = fetchEvents;
|
|
40
|
-
const utils_1 = require("./utils");
|
|
41
|
-
const errors_1 = require("./errors");
|
|
42
|
-
const axios_1 = __importDefault(require("axios"));
|
|
43
|
-
async function fetchEventBySlug(slug, http = axios_1.default) {
|
|
44
|
-
const { HttpClient, MarketFetcher } = await Promise.resolve().then(() => __importStar(require('@limitless-exchange/sdk')));
|
|
45
|
-
const httpClient = new HttpClient({ baseURL: utils_1.LIMITLESS_API_URL });
|
|
46
|
-
const marketFetcher = new MarketFetcher(httpClient);
|
|
47
|
-
const market = await marketFetcher.getMarket(slug);
|
|
48
|
-
if (!market)
|
|
49
|
-
return null;
|
|
50
|
-
let marketsList = [];
|
|
51
|
-
if (market.markets && Array.isArray(market.markets)) {
|
|
52
|
-
marketsList = market.markets
|
|
53
|
-
.map((child) => (0, utils_1.mapMarketToUnified)(child))
|
|
54
|
-
.filter((m) => m !== null);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
const unifiedMarket = (0, utils_1.mapMarketToUnified)(market);
|
|
58
|
-
if (unifiedMarket)
|
|
59
|
-
marketsList = [unifiedMarket];
|
|
60
|
-
}
|
|
61
|
-
const unifiedEvent = {
|
|
62
|
-
id: market.slug,
|
|
63
|
-
title: market.title || market.question,
|
|
64
|
-
description: market.description || '',
|
|
65
|
-
slug: market.slug,
|
|
66
|
-
markets: marketsList,
|
|
67
|
-
volume24h: marketsList.reduce((sum, m) => sum + m.volume24h, 0),
|
|
68
|
-
volume: marketsList.some(m => m.volume !== undefined) ? marketsList.reduce((sum, m) => sum + (m.volume ?? 0), 0) : undefined,
|
|
69
|
-
url: `https://limitless.exchange/markets/${market.slug}`,
|
|
70
|
-
image: market.logo || `https://limitless.exchange/api/og?slug=${market.slug}`,
|
|
71
|
-
category: market.categories?.[0],
|
|
72
|
-
tags: market.tags || []
|
|
73
|
-
};
|
|
74
|
-
return unifiedEvent;
|
|
75
|
-
}
|
|
76
|
-
function rawMarketToEvent(market) {
|
|
77
|
-
let marketsList = [];
|
|
78
|
-
if (market.markets && Array.isArray(market.markets)) {
|
|
79
|
-
marketsList = market.markets
|
|
80
|
-
.map((child) => (0, utils_1.mapMarketToUnified)(child))
|
|
81
|
-
.filter((m) => m !== null);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
const unifiedMarket = (0, utils_1.mapMarketToUnified)(market);
|
|
85
|
-
if (unifiedMarket)
|
|
86
|
-
marketsList = [unifiedMarket];
|
|
87
|
-
}
|
|
88
|
-
const unifiedEvent = {
|
|
89
|
-
id: market.slug,
|
|
90
|
-
title: market.title || market.question,
|
|
91
|
-
description: market.description || '',
|
|
92
|
-
slug: market.slug,
|
|
93
|
-
markets: marketsList,
|
|
94
|
-
volume24h: marketsList.reduce((sum, m) => sum + m.volume24h, 0),
|
|
95
|
-
volume: marketsList.some(m => m.volume !== undefined) ? marketsList.reduce((sum, m) => sum + (m.volume ?? 0), 0) : undefined,
|
|
96
|
-
url: `https://limitless.exchange/markets/${market.slug}`,
|
|
97
|
-
image: market.logo || `https://limitless.exchange/api/og?slug=${market.slug}`,
|
|
98
|
-
category: market.categories?.[0],
|
|
99
|
-
tags: market.tags || []
|
|
100
|
-
};
|
|
101
|
-
return unifiedEvent;
|
|
102
|
-
}
|
|
103
|
-
async function fetchEvents(params, callApi, http = axios_1.default) {
|
|
104
|
-
try {
|
|
105
|
-
// Handle eventId/slug lookup (same thing for Limitless)
|
|
106
|
-
if (params.eventId || params.slug) {
|
|
107
|
-
const slug = params.eventId || params.slug;
|
|
108
|
-
const event = await fetchEventBySlug(slug, http);
|
|
109
|
-
return event ? [event] : [];
|
|
110
|
-
}
|
|
111
|
-
// Query-based search: use the /markets/search endpoint
|
|
112
|
-
if (params.query) {
|
|
113
|
-
return await searchEvents(params, callApi);
|
|
114
|
-
}
|
|
115
|
-
// Default: fetch active group markets from /markets/active
|
|
116
|
-
// On Limitless, "events" = group markets (tradeType === 'group')
|
|
117
|
-
return await fetchEventsDefault(params, http);
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
throw errors_1.limitlessErrorMapper.mapError(error);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
async function searchEvents(params, callApi) {
|
|
124
|
-
// NOTE: The Limitless /markets/search endpoint currently only returns active/funded markets.
|
|
125
|
-
const data = await callApi('MarketSearchController_search', {
|
|
126
|
-
query: params.query,
|
|
127
|
-
limit: params?.limit || 10000,
|
|
128
|
-
similarityThreshold: 0.5,
|
|
129
|
-
});
|
|
130
|
-
let markets = data?.markets || [];
|
|
131
|
-
const status = params?.status || 'active';
|
|
132
|
-
if (status === 'active') {
|
|
133
|
-
markets = markets.filter((m) => !m.expired && m.winningOutcomeIndex === null);
|
|
134
|
-
}
|
|
135
|
-
else if (status === 'inactive' || status === 'closed') {
|
|
136
|
-
markets = markets.filter((m) => m.expired === true || m.winningOutcomeIndex !== null);
|
|
137
|
-
}
|
|
138
|
-
return markets.map(rawMarketToEvent);
|
|
139
|
-
}
|
|
140
|
-
async function fetchEventsDefault(params, http = axios_1.default) {
|
|
141
|
-
// Limitless has no dedicated /events endpoint.
|
|
142
|
-
// Group markets (tradeType === 'group') are the semantic equivalent of events.
|
|
143
|
-
// We use GET /markets/active and filter for groups only.
|
|
144
|
-
const limit = params?.limit || 10000;
|
|
145
|
-
let page = 1;
|
|
146
|
-
const pageSize = 25; // Limitless API hard limit
|
|
147
|
-
const MAX_PAGES = 40; // Safety cap
|
|
148
|
-
const allGroups = [];
|
|
149
|
-
while (allGroups.length < limit && page <= MAX_PAGES) {
|
|
150
|
-
const response = await http.get(`${utils_1.LIMITLESS_API_URL}/markets/active`, {
|
|
151
|
-
params: {
|
|
152
|
-
page,
|
|
153
|
-
limit: pageSize,
|
|
154
|
-
tradeType: 'group',
|
|
155
|
-
sortBy: params?.sort === 'newest' ? 'newest' : params?.sort === 'liquidity' ? 'lp_rewards' : 'high_value',
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
const items = response.data?.data || response.data || [];
|
|
159
|
-
if (items.length === 0)
|
|
160
|
-
break;
|
|
161
|
-
for (const item of items) {
|
|
162
|
-
if (allGroups.length >= limit)
|
|
163
|
-
break;
|
|
164
|
-
const event = rawMarketToEvent(item);
|
|
165
|
-
allGroups.push(event);
|
|
166
|
-
}
|
|
167
|
-
// If the page returned fewer items than the page size, we've reached the end
|
|
168
|
-
if (items.length < pageSize)
|
|
169
|
-
break;
|
|
170
|
-
page++;
|
|
171
|
-
}
|
|
172
|
-
return allGroups;
|
|
173
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { MarketFetchParams } from '../../BaseExchange';
|
|
2
|
-
import { UnifiedMarket } from '../../types';
|
|
3
|
-
export declare function fetchMarkets(params?: MarketFetchParams, apiKey?: string, callApi?: (operationId: string, params?: Record<string, any>) => Promise<any>): Promise<UnifiedMarket[]>;
|