pmxt-core 2.22.1 → 2.23.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/probable/api.d.ts +1 -1
- package/dist/exchanges/probable/api.js +1 -1
- package/dist/exchanges/probable/auth.js +5 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -1
- package/dist/server/app.js +10 -1
- package/package.json +3 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { UnifiedMarket } from "../../types";
|
|
2
|
+
/**
|
|
3
|
+
* Base URL passed to parseOpenApiSpec to override the spec's servers[0].url.
|
|
4
|
+
* The generated api.ts already has "https://www.metaculus.com/api" as its server URL,
|
|
5
|
+
* so this constant must match exactly -- do NOT add a trailing slash or path suffix.
|
|
6
|
+
* Paths in the spec (/posts/, /posts/{postId}/) are appended directly by BaseExchange.
|
|
7
|
+
*/
|
|
8
|
+
export declare const BASE_URL = "https://www.metaculus.com/api";
|
|
9
|
+
/**
|
|
10
|
+
* Map a Metaculus post `status` to pmxt unified status.
|
|
11
|
+
*
|
|
12
|
+
* Metaculus post statuses: "open", "closed", "resolved", "upcoming"
|
|
13
|
+
*/
|
|
14
|
+
export declare function mapStatus(status: string): "active" | "closed";
|
|
15
|
+
/**
|
|
16
|
+
* Convert a raw Metaculus Post (v3 /api/posts/ response item) into a
|
|
17
|
+
* `UnifiedMarket`.
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` for group-of-questions posts -- callers should use
|
|
20
|
+
* {@link expandPost} instead, which handles both single and group posts.
|
|
21
|
+
*
|
|
22
|
+
* @param post Raw post object from the Metaculus API.
|
|
23
|
+
* @param eventId Optional parent event ID (tournament slug) to override
|
|
24
|
+
* the value derived from post.projects.tournament.
|
|
25
|
+
*/
|
|
26
|
+
export declare function mapMarketToUnified(post: any, eventId?: string): UnifiedMarket | null;
|
|
27
|
+
/**
|
|
28
|
+
* Convert a raw Metaculus post into one or more `UnifiedMarket` objects.
|
|
29
|
+
*
|
|
30
|
+
* Handles all post types:
|
|
31
|
+
* - Single-question posts (binary, multiple-choice, continuous) -> 1 market
|
|
32
|
+
* - Group-of-questions posts -> N markets (one per sub-question)
|
|
33
|
+
*
|
|
34
|
+
* Use this instead of calling `mapMarketToUnified` directly when processing
|
|
35
|
+
* feed results, since a single API post can yield multiple tradeable markets.
|
|
36
|
+
*
|
|
37
|
+
* @param post Raw post object from the Metaculus API.
|
|
38
|
+
* @param eventId Optional parent event ID (tournament slug).
|
|
39
|
+
*/
|
|
40
|
+
export declare function expandPost(post: any, eventId?: string): UnifiedMarket[];
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BASE_URL = void 0;
|
|
4
|
+
exports.mapStatus = mapStatus;
|
|
5
|
+
exports.mapMarketToUnified = mapMarketToUnified;
|
|
6
|
+
exports.expandPost = expandPost;
|
|
7
|
+
const market_utils_1 = require("../../utils/market-utils");
|
|
8
|
+
/**
|
|
9
|
+
* Base URL passed to parseOpenApiSpec to override the spec's servers[0].url.
|
|
10
|
+
* The generated api.ts already has "https://www.metaculus.com/api" as its server URL,
|
|
11
|
+
* so this constant must match exactly -- do NOT add a trailing slash or path suffix.
|
|
12
|
+
* Paths in the spec (/posts/, /posts/{postId}/) are appended directly by BaseExchange.
|
|
13
|
+
*/
|
|
14
|
+
exports.BASE_URL = "https://www.metaculus.com/api";
|
|
15
|
+
/**
|
|
16
|
+
* Map a Metaculus post `status` to pmxt unified status.
|
|
17
|
+
*
|
|
18
|
+
* Metaculus post statuses: "open", "closed", "resolved", "upcoming"
|
|
19
|
+
*/
|
|
20
|
+
function mapStatus(status) {
|
|
21
|
+
switch ((status ?? "").toLowerCase()) {
|
|
22
|
+
case "open":
|
|
23
|
+
case "upcoming":
|
|
24
|
+
return "active";
|
|
25
|
+
default:
|
|
26
|
+
return "closed";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Extract the community prediction probability from a question object.
|
|
31
|
+
*
|
|
32
|
+
* For all question types the recency-weighted aggregation exposes a `centers`
|
|
33
|
+
* array where `centers[0]` is the median / central estimate, already normalised
|
|
34
|
+
* to [0, 1] by the API.
|
|
35
|
+
*
|
|
36
|
+
* Accepts either a Post (reads from post.question) or a bare Question object.
|
|
37
|
+
*
|
|
38
|
+
* @returns A number in [0, 1], or 0.5 if no prediction is available.
|
|
39
|
+
*/
|
|
40
|
+
function extractCommunityProbability(questionOrPost) {
|
|
41
|
+
// Support both post.question and bare question objects
|
|
42
|
+
const question = questionOrPost?.question ?? questionOrPost;
|
|
43
|
+
const latest = question?.aggregations?.recency_weighted?.latest;
|
|
44
|
+
if (!latest)
|
|
45
|
+
return 0.5;
|
|
46
|
+
const centers = latest.centers;
|
|
47
|
+
if (Array.isArray(centers) && centers.length > 0 && typeof centers[0] === "number") {
|
|
48
|
+
return Math.max(0, Math.min(1, centers[0]));
|
|
49
|
+
}
|
|
50
|
+
// Fallback: some binary posts expose forecast_values[0] as the Yes probability
|
|
51
|
+
const fv = latest.forecast_values;
|
|
52
|
+
if (Array.isArray(fv) && fv.length > 0 && typeof fv[0] === "number") {
|
|
53
|
+
return Math.max(0, Math.min(1, fv[0]));
|
|
54
|
+
}
|
|
55
|
+
return 0.5;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build the tag list from a Post's project associations.
|
|
59
|
+
* Combines taxonomy tags and categories so consumers can filter by either.
|
|
60
|
+
*/
|
|
61
|
+
function buildTags(post) {
|
|
62
|
+
const tags = [];
|
|
63
|
+
const projects = post?.projects ?? {};
|
|
64
|
+
// Explicit tags
|
|
65
|
+
const tagList = projects.tag ?? [];
|
|
66
|
+
for (const t of tagList) {
|
|
67
|
+
const label = typeof t === "string" ? t : t?.name;
|
|
68
|
+
if (label && !tags.includes(label))
|
|
69
|
+
tags.push(label);
|
|
70
|
+
}
|
|
71
|
+
// Categories (useful for broad filtering)
|
|
72
|
+
const catList = projects.category ?? [];
|
|
73
|
+
for (const c of catList) {
|
|
74
|
+
const label = typeof c === "string" ? c : c?.name;
|
|
75
|
+
if (label && !tags.includes(label))
|
|
76
|
+
tags.push(label);
|
|
77
|
+
}
|
|
78
|
+
// Question type as a tag for easy filtering
|
|
79
|
+
const qType = post?.question?.type;
|
|
80
|
+
if (qType && !tags.includes(qType))
|
|
81
|
+
tags.push(qType);
|
|
82
|
+
return tags;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Build outcomes for a Metaculus question.
|
|
86
|
+
*
|
|
87
|
+
* OutcomeId format uses the **question ID** (not the post ID) so that
|
|
88
|
+
* `createOrder` can extract the correct ID for the forecast API.
|
|
89
|
+
*
|
|
90
|
+
* - Binary: `<questionId>-YES` / `<questionId>-NO`
|
|
91
|
+
* - Multiple-choice: `<questionId>-<categoryIndex>`
|
|
92
|
+
* - Continuous: `<questionId>-HIGHER` / `<questionId>-LOWER` (read-only, not tradeable)
|
|
93
|
+
*
|
|
94
|
+
* Raw aggregation data is exposed in each outcome's `metadata` so consumers
|
|
95
|
+
* can use it directly.
|
|
96
|
+
*
|
|
97
|
+
* @param question The Metaculus Question object (not the Post wrapper).
|
|
98
|
+
* @param postId The parent post ID, used as the marketId on each outcome.
|
|
99
|
+
*/
|
|
100
|
+
function buildOutcomes(question, postId, medianProb) {
|
|
101
|
+
const questionId = String(question?.id ?? postId);
|
|
102
|
+
const type = (question?.type || "binary").toLowerCase();
|
|
103
|
+
const latest = question?.aggregations?.recency_weighted?.latest ?? null;
|
|
104
|
+
const sharedMeta = {
|
|
105
|
+
question_type: type,
|
|
106
|
+
question_id: Number(questionId),
|
|
107
|
+
aggregations: latest,
|
|
108
|
+
resolution: question?.resolution ?? null,
|
|
109
|
+
scaling: question?.scaling ?? null,
|
|
110
|
+
possibilities: question?.possibilities ?? null,
|
|
111
|
+
};
|
|
112
|
+
// Multiple choice: one outcome per option, each independently forecastable
|
|
113
|
+
if (type === "multiple_choice") {
|
|
114
|
+
const options = question?.options ?? [];
|
|
115
|
+
if (options.length > 0) {
|
|
116
|
+
const histogram = latest?.histogram ?? undefined;
|
|
117
|
+
return options.map((opt, idx) => {
|
|
118
|
+
const label = typeof opt === "string"
|
|
119
|
+
? opt
|
|
120
|
+
: opt?.label ?? opt?.value ?? `Option ${idx + 1}`;
|
|
121
|
+
const price = Array.isArray(histogram) && typeof histogram[idx] === "number"
|
|
122
|
+
? Math.max(0, Math.min(1, histogram[idx]))
|
|
123
|
+
: 1 / Math.max(options.length, 1);
|
|
124
|
+
return {
|
|
125
|
+
outcomeId: `${questionId}-${idx}`,
|
|
126
|
+
marketId: postId,
|
|
127
|
+
label,
|
|
128
|
+
price,
|
|
129
|
+
priceChange24h: 0,
|
|
130
|
+
metadata: { ...sharedMeta, choice_index: idx },
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Binary: Yes/No outcomes
|
|
136
|
+
if (type === "binary") {
|
|
137
|
+
return [
|
|
138
|
+
{
|
|
139
|
+
outcomeId: `${questionId}-YES`,
|
|
140
|
+
marketId: postId,
|
|
141
|
+
label: "Yes",
|
|
142
|
+
price: medianProb,
|
|
143
|
+
priceChange24h: 0,
|
|
144
|
+
metadata: sharedMeta,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
outcomeId: `${questionId}-NO`,
|
|
148
|
+
marketId: postId,
|
|
149
|
+
label: "No",
|
|
150
|
+
price: Math.max(0, Math.min(1, 1 - medianProb)),
|
|
151
|
+
priceChange24h: 0,
|
|
152
|
+
metadata: sharedMeta,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
// Continuous / numeric / date -- not tradeable via createOrder.
|
|
157
|
+
// Displayed as synthetic Higher/Lower for read-only price indication.
|
|
158
|
+
return [
|
|
159
|
+
{
|
|
160
|
+
outcomeId: `${questionId}-HIGHER`,
|
|
161
|
+
marketId: postId,
|
|
162
|
+
label: "Higher",
|
|
163
|
+
price: medianProb,
|
|
164
|
+
priceChange24h: 0,
|
|
165
|
+
metadata: sharedMeta,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
outcomeId: `${questionId}-LOWER`,
|
|
169
|
+
marketId: postId,
|
|
170
|
+
label: "Lower",
|
|
171
|
+
price: Math.max(0, Math.min(1, 1 - medianProb)),
|
|
172
|
+
priceChange24h: 0,
|
|
173
|
+
metadata: sharedMeta,
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Convert a raw Metaculus Post (v3 /api/posts/ response item) into a
|
|
179
|
+
* `UnifiedMarket`.
|
|
180
|
+
*
|
|
181
|
+
* Returns `null` for group-of-questions posts -- callers should use
|
|
182
|
+
* {@link expandPost} instead, which handles both single and group posts.
|
|
183
|
+
*
|
|
184
|
+
* @param post Raw post object from the Metaculus API.
|
|
185
|
+
* @param eventId Optional parent event ID (tournament slug) to override
|
|
186
|
+
* the value derived from post.projects.tournament.
|
|
187
|
+
*/
|
|
188
|
+
function mapMarketToUnified(post, eventId) {
|
|
189
|
+
if (!post || !post.id)
|
|
190
|
+
return null;
|
|
191
|
+
// Group-of-questions posts have no top-level question -- they must be
|
|
192
|
+
// expanded into individual sub-question markets via expandPost().
|
|
193
|
+
if (post.group_of_questions && !post.question)
|
|
194
|
+
return null;
|
|
195
|
+
const postId = String(post.id);
|
|
196
|
+
const question = post.question ?? {};
|
|
197
|
+
const medianProb = extractCommunityProbability(post);
|
|
198
|
+
const outcomes = buildOutcomes(question, postId, medianProb);
|
|
199
|
+
// Resolution date -- prefer scheduled_resolve_time, fall back to close time
|
|
200
|
+
const resolveDateStr = post.scheduled_resolve_time ??
|
|
201
|
+
question.scheduled_resolve_time ??
|
|
202
|
+
post.scheduled_close_time ??
|
|
203
|
+
post.actual_close_time;
|
|
204
|
+
const resolutionDate = resolveDateStr
|
|
205
|
+
? new Date(resolveDateStr)
|
|
206
|
+
: new Date("2099-01-01T00:00:00Z");
|
|
207
|
+
const tags = buildTags(post);
|
|
208
|
+
// Primary category label
|
|
209
|
+
const categoryList = post?.projects?.category ?? [];
|
|
210
|
+
const category = categoryList.length > 0
|
|
211
|
+
? typeof categoryList[0] === "string"
|
|
212
|
+
? categoryList[0]
|
|
213
|
+
: categoryList[0]?.name
|
|
214
|
+
: undefined;
|
|
215
|
+
// Forecaster count -- proxy for liquidity (no monetary values on Metaculus)
|
|
216
|
+
const forecastCount = Number(post.nr_forecasters ?? question.nr_forecasters ?? 0);
|
|
217
|
+
// Derive eventId from first tournament slug if not explicitly provided
|
|
218
|
+
const tournamentList = post?.projects?.tournament ?? [];
|
|
219
|
+
const derivedEventId = tournamentList.length > 0
|
|
220
|
+
? typeof tournamentList[0] === "string"
|
|
221
|
+
? tournamentList[0]
|
|
222
|
+
: tournamentList[0]?.slug
|
|
223
|
+
: undefined;
|
|
224
|
+
const resolvedEventId = eventId ?? derivedEventId;
|
|
225
|
+
const um = {
|
|
226
|
+
marketId: postId,
|
|
227
|
+
eventId: resolvedEventId,
|
|
228
|
+
title: post.title ?? question.title ?? "",
|
|
229
|
+
description: question.description ??
|
|
230
|
+
question.resolution_criteria ??
|
|
231
|
+
"",
|
|
232
|
+
slug: post.slug ?? post.url_title ?? undefined,
|
|
233
|
+
outcomes,
|
|
234
|
+
resolutionDate,
|
|
235
|
+
volume24h: 0, // Metaculus has no monetary volume
|
|
236
|
+
volume: 0,
|
|
237
|
+
liquidity: forecastCount, // re-purposed as forecaster count
|
|
238
|
+
openInterest: forecastCount,
|
|
239
|
+
url: `https://www.metaculus.com/questions/${postId}/`,
|
|
240
|
+
image: post.projects?.default_project?.header_image ?? undefined,
|
|
241
|
+
category,
|
|
242
|
+
tags,
|
|
243
|
+
};
|
|
244
|
+
(0, market_utils_1.addBinaryOutcomes)(um);
|
|
245
|
+
return um;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Expand a group-of-questions post into individual sub-question markets.
|
|
249
|
+
*
|
|
250
|
+
* Each sub-question becomes its own `UnifiedMarket` with:
|
|
251
|
+
* - `marketId` = sub-question's post_id (for API lookups via GetPost)
|
|
252
|
+
* - outcomeIds based on the sub-question's question.id (for forecast API)
|
|
253
|
+
* - `eventId` = parent post ID (the group acts as a container)
|
|
254
|
+
* - `metadata.groupPostId` on each outcome for traceability
|
|
255
|
+
*
|
|
256
|
+
* @param post A group-of-questions post (post.group_of_questions.questions[]).
|
|
257
|
+
* @param eventId Optional override for the eventId field.
|
|
258
|
+
*/
|
|
259
|
+
function mapGroupPostToMarkets(post, eventId) {
|
|
260
|
+
const group = post.group_of_questions;
|
|
261
|
+
if (!group?.questions?.length)
|
|
262
|
+
return [];
|
|
263
|
+
const parentPostId = String(post.id);
|
|
264
|
+
const groupEventId = eventId ?? parentPostId;
|
|
265
|
+
const markets = [];
|
|
266
|
+
for (const subQuestion of group.questions) {
|
|
267
|
+
// Build a synthetic post that mapMarketToUnified can process.
|
|
268
|
+
// Use the sub-question's post_id as the post id if available,
|
|
269
|
+
// otherwise fall back to the sub-question's own id.
|
|
270
|
+
const syntheticPost = {
|
|
271
|
+
id: subQuestion.post_id ?? subQuestion.id,
|
|
272
|
+
title: subQuestion.title ?? subQuestion.label ?? post.title,
|
|
273
|
+
question: subQuestion,
|
|
274
|
+
// Inherit metadata from the parent post
|
|
275
|
+
slug: post.slug,
|
|
276
|
+
url_title: post.url_title,
|
|
277
|
+
projects: post.projects,
|
|
278
|
+
nr_forecasters: subQuestion.nr_forecasters ?? post.nr_forecasters,
|
|
279
|
+
scheduled_resolve_time: subQuestion.scheduled_resolve_time ?? post.scheduled_resolve_time,
|
|
280
|
+
scheduled_close_time: subQuestion.scheduled_close_time ?? post.scheduled_close_time,
|
|
281
|
+
actual_close_time: subQuestion.actual_close_time ?? post.actual_close_time,
|
|
282
|
+
status: post.status,
|
|
283
|
+
};
|
|
284
|
+
const market = mapMarketToUnified(syntheticPost, groupEventId);
|
|
285
|
+
if (market) {
|
|
286
|
+
// Tag each outcome with the parent group post ID for traceability
|
|
287
|
+
for (const outcome of market.outcomes) {
|
|
288
|
+
if (outcome.metadata) {
|
|
289
|
+
outcome.metadata.groupPostId = Number(parentPostId);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
markets.push(market);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return markets;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Convert a raw Metaculus post into one or more `UnifiedMarket` objects.
|
|
299
|
+
*
|
|
300
|
+
* Handles all post types:
|
|
301
|
+
* - Single-question posts (binary, multiple-choice, continuous) -> 1 market
|
|
302
|
+
* - Group-of-questions posts -> N markets (one per sub-question)
|
|
303
|
+
*
|
|
304
|
+
* Use this instead of calling `mapMarketToUnified` directly when processing
|
|
305
|
+
* feed results, since a single API post can yield multiple tradeable markets.
|
|
306
|
+
*
|
|
307
|
+
* @param post Raw post object from the Metaculus API.
|
|
308
|
+
* @param eventId Optional parent event ID (tournament slug).
|
|
309
|
+
*/
|
|
310
|
+
function expandPost(post, eventId) {
|
|
311
|
+
if (!post || !post.id)
|
|
312
|
+
return [];
|
|
313
|
+
// Group posts: expand each sub-question into its own market
|
|
314
|
+
if (post.group_of_questions && !post.question) {
|
|
315
|
+
return mapGroupPostToMarkets(post, eventId);
|
|
316
|
+
}
|
|
317
|
+
// Single-question post
|
|
318
|
+
const market = mapMarketToUnified(post, eventId);
|
|
319
|
+
return market ? [market] : [];
|
|
320
|
+
}
|
|
@@ -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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.286Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.286Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.290Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.290Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.235Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.235Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.249Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.249Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.246Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.246Z
|
|
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-
|
|
3
|
+
* Generated at: 2026-04-04T07:52:19.280Z
|
|
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-
|
|
6
|
+
* Generated at: 2026-04-04T07:52:19.280Z
|
|
7
7
|
* Do not edit manually -- run "npm run fetch:openapi" to regenerate.
|
|
8
8
|
*/
|
|
9
9
|
exports.probableApiSpec = {
|
|
@@ -42,10 +42,13 @@ class ProbableAuth {
|
|
|
42
42
|
secret: this.credentials.apiSecret,
|
|
43
43
|
passphrase: this.credentials.passphrase,
|
|
44
44
|
};
|
|
45
|
+
// @prob/clob may resolve a different viem copy than this package; types then
|
|
46
|
+
// disagree on WalletClient. Runtime shape is identical.
|
|
47
|
+
const walletForClob = wallet;
|
|
45
48
|
if (chainId === 56) {
|
|
46
49
|
this.clobClient = (0, clob_1.createClobClient)({
|
|
47
50
|
chainId: 56,
|
|
48
|
-
wallet,
|
|
51
|
+
wallet: walletForClob,
|
|
49
52
|
credential,
|
|
50
53
|
});
|
|
51
54
|
}
|
|
@@ -54,7 +57,7 @@ class ProbableAuth {
|
|
|
54
57
|
this.clobClient = (0, clob_1.createClobClient)({
|
|
55
58
|
chainId,
|
|
56
59
|
baseUrl,
|
|
57
|
-
wallet,
|
|
60
|
+
wallet: walletForClob,
|
|
58
61
|
credential,
|
|
59
62
|
});
|
|
60
63
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ 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';
|
|
14
15
|
export * from './server/app';
|
|
15
16
|
export * from './server/utils/port-manager';
|
|
16
17
|
export * from './server/utils/lock-file';
|
|
@@ -22,6 +23,7 @@ import { ProbableExchange } from './exchanges/probable';
|
|
|
22
23
|
import { BaoziExchange } from './exchanges/baozi';
|
|
23
24
|
import { MyriadExchange } from './exchanges/myriad';
|
|
24
25
|
import { OpinionExchange } from './exchanges/opinion';
|
|
26
|
+
import { MetaculusExchange } from './exchanges/metaculus';
|
|
25
27
|
declare const pmxt: {
|
|
26
28
|
Polymarket: typeof PolymarketExchange;
|
|
27
29
|
Limitless: typeof LimitlessExchange;
|
|
@@ -31,6 +33,7 @@ declare const pmxt: {
|
|
|
31
33
|
Baozi: typeof BaoziExchange;
|
|
32
34
|
Myriad: typeof MyriadExchange;
|
|
33
35
|
Opinion: typeof OpinionExchange;
|
|
36
|
+
Metaculus: typeof MetaculusExchange;
|
|
34
37
|
};
|
|
35
38
|
export declare const Polymarket: typeof PolymarketExchange;
|
|
36
39
|
export declare const Limitless: typeof LimitlessExchange;
|
|
@@ -40,4 +43,5 @@ export declare const Probable: typeof ProbableExchange;
|
|
|
40
43
|
export declare const Baozi: typeof BaoziExchange;
|
|
41
44
|
export declare const Myriad: typeof MyriadExchange;
|
|
42
45
|
export declare const Opinion: typeof OpinionExchange;
|
|
46
|
+
export declare const Metaculus: typeof MetaculusExchange;
|
|
43
47
|
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.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,7 @@ __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);
|
|
32
33
|
__exportStar(require("./server/app"), exports);
|
|
33
34
|
__exportStar(require("./server/utils/port-manager"), exports);
|
|
34
35
|
__exportStar(require("./server/utils/lock-file"), exports);
|
|
@@ -40,6 +41,7 @@ const probable_1 = require("./exchanges/probable");
|
|
|
40
41
|
const baozi_1 = require("./exchanges/baozi");
|
|
41
42
|
const myriad_1 = require("./exchanges/myriad");
|
|
42
43
|
const opinion_1 = require("./exchanges/opinion");
|
|
44
|
+
const metaculus_1 = require("./exchanges/metaculus");
|
|
43
45
|
const pmxt = {
|
|
44
46
|
Polymarket: polymarket_1.PolymarketExchange,
|
|
45
47
|
Limitless: limitless_1.LimitlessExchange,
|
|
@@ -49,6 +51,7 @@ const pmxt = {
|
|
|
49
51
|
Baozi: baozi_1.BaoziExchange,
|
|
50
52
|
Myriad: myriad_1.MyriadExchange,
|
|
51
53
|
Opinion: opinion_1.OpinionExchange,
|
|
54
|
+
Metaculus: metaculus_1.MetaculusExchange,
|
|
52
55
|
};
|
|
53
56
|
exports.Polymarket = polymarket_1.PolymarketExchange;
|
|
54
57
|
exports.Limitless = limitless_1.LimitlessExchange;
|
|
@@ -58,4 +61,5 @@ exports.Probable = probable_1.ProbableExchange;
|
|
|
58
61
|
exports.Baozi = baozi_1.BaoziExchange;
|
|
59
62
|
exports.Myriad = myriad_1.MyriadExchange;
|
|
60
63
|
exports.Opinion = opinion_1.OpinionExchange;
|
|
64
|
+
exports.Metaculus = metaculus_1.MetaculusExchange;
|
|
61
65
|
exports.default = pmxt;
|
package/dist/server/app.js
CHANGED
|
@@ -14,6 +14,7 @@ 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");
|
|
17
18
|
const errors_1 = require("../errors");
|
|
18
19
|
// Singleton instances for local usage (when no credentials provided)
|
|
19
20
|
const defaultExchanges = {
|
|
@@ -25,6 +26,7 @@ const defaultExchanges = {
|
|
|
25
26
|
baozi: null,
|
|
26
27
|
myriad: null,
|
|
27
28
|
opinion: null,
|
|
29
|
+
metaculus: null,
|
|
28
30
|
};
|
|
29
31
|
async function startServer(port, accessToken) {
|
|
30
32
|
const app = (0, express_1.default)();
|
|
@@ -58,7 +60,10 @@ async function startServer(port, accessToken) {
|
|
|
58
60
|
// If credentials are provided, create a new instance for this request
|
|
59
61
|
// Otherwise, use the singleton instance
|
|
60
62
|
let exchange;
|
|
61
|
-
if (credentials &&
|
|
63
|
+
if (credentials &&
|
|
64
|
+
(credentials.privateKey ||
|
|
65
|
+
credentials.apiKey ||
|
|
66
|
+
credentials.apiToken)) {
|
|
62
67
|
exchange = createExchange(exchangeName, credentials);
|
|
63
68
|
}
|
|
64
69
|
else {
|
|
@@ -193,6 +198,10 @@ function createExchange(name, credentials) {
|
|
|
193
198
|
privateKey: credentials?.privateKey || process.env.OPINION_PRIVATE_KEY,
|
|
194
199
|
funderAddress: credentials?.funderAddress,
|
|
195
200
|
});
|
|
201
|
+
case "metaculus":
|
|
202
|
+
return new metaculus_1.MetaculusExchange({
|
|
203
|
+
apiToken: credentials?.apiToken || process.env.METACULUS_API_TOKEN,
|
|
204
|
+
});
|
|
196
205
|
default:
|
|
197
206
|
throw new Error(`Unknown exchange: ${name}`);
|
|
198
207
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmxt-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.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.23.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.23.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",
|