pmxtjs 2.1.3 → 2.3.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.
Files changed (85) hide show
  1. package/README.md +2 -2
  2. package/dist/esm/generated/src/models/MarketOutcome.d.ts +6 -0
  3. package/dist/esm/generated/src/models/MarketOutcome.js +2 -0
  4. package/dist/esm/index.d.ts +3 -0
  5. package/dist/esm/index.js +1 -0
  6. package/dist/esm/pmxt/client.js +20 -3
  7. package/dist/esm/pmxt/models.d.ts +18 -1
  8. package/dist/esm/pmxt/models.js +56 -1
  9. package/dist/generated/src/models/MarketOutcome.d.ts +6 -0
  10. package/dist/generated/src/models/MarketOutcome.js +2 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.js +3 -1
  13. package/dist/pmxt/client.js +20 -3
  14. package/dist/pmxt/models.d.ts +18 -1
  15. package/dist/pmxt/models.js +58 -0
  16. package/generated/docs/MarketOutcome.md +2 -0
  17. package/generated/package.json +1 -1
  18. package/generated/src/apis/DefaultApi.js +812 -0
  19. package/generated/src/apis/index.js +19 -0
  20. package/generated/src/index.js +21 -0
  21. package/generated/src/models/Balance.js +54 -0
  22. package/generated/src/models/BaseRequest.js +49 -0
  23. package/generated/src/models/BaseResponse.js +51 -0
  24. package/generated/src/models/CancelOrderRequest.js +53 -0
  25. package/generated/src/models/CreateOrder200Response.js +54 -0
  26. package/generated/src/models/CreateOrderParams.js +85 -0
  27. package/generated/src/models/CreateOrderRequest.js +54 -0
  28. package/generated/src/models/ErrorDetail.js +48 -0
  29. package/generated/src/models/ErrorResponse.js +51 -0
  30. package/generated/src/models/EventFetchParams.js +63 -0
  31. package/generated/src/models/ExchangeCredentials.js +59 -0
  32. package/generated/src/models/ExchangeCredentialsSignatureType.js +49 -0
  33. package/generated/src/models/ExecutionPriceResult.js +52 -0
  34. package/generated/src/models/FetchBalance200Response.js +54 -0
  35. package/generated/src/models/FetchEvents200Response.js +54 -0
  36. package/generated/src/models/FetchEventsRequest.js +52 -0
  37. package/generated/src/models/FetchMarkets200Response.js +54 -0
  38. package/generated/src/models/FetchMarketsRequest.js +52 -0
  39. package/generated/src/models/FetchOHLCV200Response.js +54 -0
  40. package/generated/src/models/FetchOHLCVRequest.js +54 -0
  41. package/generated/src/models/FetchOHLCVRequestArgsInner.js +56 -0
  42. package/generated/src/models/FetchOpenOrders200Response.js +54 -0
  43. package/generated/src/models/FetchOpenOrdersRequest.js +51 -0
  44. package/generated/src/models/FetchOrderBook200Response.js +54 -0
  45. package/generated/src/models/FetchOrderBookRequest.js +53 -0
  46. package/generated/src/models/FetchPositions200Response.js +54 -0
  47. package/generated/src/models/FetchPositionsRequest.js +51 -0
  48. package/generated/src/models/FetchTrades200Response.js +54 -0
  49. package/generated/src/models/FetchTradesRequest.js +54 -0
  50. package/generated/src/models/FilterEventsRequest.js +54 -0
  51. package/generated/src/models/FilterEventsRequestArgsInner.js +67 -0
  52. package/generated/src/models/FilterMarketsRequest.js +54 -0
  53. package/generated/src/models/FilterMarketsRequestArgsInner.js +67 -0
  54. package/generated/src/models/FilterMarketsRequestArgsInnerOneOf.js +47 -0
  55. package/generated/src/models/GetExecutionPrice200Response.js +53 -0
  56. package/generated/src/models/GetExecutionPriceDetailed200Response.js +54 -0
  57. package/generated/src/models/GetExecutionPriceRequest.js +54 -0
  58. package/generated/src/models/GetExecutionPriceRequestArgsInner.js +62 -0
  59. package/generated/src/models/HealthCheck200Response.js +50 -0
  60. package/generated/src/models/HistoryFilterParams.js +68 -0
  61. package/generated/src/models/MarketFilterParams.js +79 -0
  62. package/generated/src/models/MarketOutcome.js +56 -0
  63. package/generated/src/models/MarketOutcome.ts +8 -0
  64. package/generated/src/models/Order.js +95 -0
  65. package/generated/src/models/OrderBook.js +53 -0
  66. package/generated/src/models/OrderLevel.js +50 -0
  67. package/generated/src/models/Position.js +62 -0
  68. package/generated/src/models/PriceCandle.js +58 -0
  69. package/generated/src/models/Trade.js +65 -0
  70. package/generated/src/models/UnifiedEvent.js +65 -0
  71. package/generated/src/models/UnifiedMarket.js +81 -0
  72. package/generated/src/models/WatchOrderBookRequest.js +54 -0
  73. package/generated/src/models/WatchOrderBookRequestArgsInner.js +49 -0
  74. package/generated/src/models/WatchPricesRequest.js +53 -0
  75. package/generated/src/models/WatchTradesRequest.js +54 -0
  76. package/generated/src/models/WatchUserPositionsRequest.js +49 -0
  77. package/generated/src/models/index.js +73 -0
  78. package/generated/src/runtime.js +338 -0
  79. package/index.ts +1 -0
  80. package/package.json +2 -2
  81. package/pmxt/client.js +957 -0
  82. package/pmxt/client.ts +26 -3
  83. package/pmxt/models.js +60 -0
  84. package/pmxt/models.ts +63 -1
  85. package/pmxt/server-manager.js +204 -0
package/pmxt/client.ts CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  import {
23
23
  UnifiedMarket,
24
24
  MarketOutcome,
25
+ MarketList,
25
26
  PriceCandle,
26
27
  OrderBook,
27
28
  OrderLevel,
@@ -44,6 +45,7 @@ import { ServerManager } from "./server-manager.js";
44
45
  function convertMarket(raw: any): UnifiedMarket {
45
46
  const outcomes: MarketOutcome[] = (raw.outcomes || []).map((o: any) => ({
46
47
  outcomeId: o.outcomeId,
48
+ marketId: o.marketId,
47
49
  label: o.label,
48
50
  price: o.price,
49
51
  priceChange24h: o.priceChange24h,
@@ -52,6 +54,7 @@ function convertMarket(raw: any): UnifiedMarket {
52
54
 
53
55
  const convertOutcome = (o: any) => o ? ({
54
56
  outcomeId: o.outcomeId,
57
+ marketId: o.marketId,
55
58
  label: o.label,
56
59
  price: o.price,
57
60
  priceChange24h: o.priceChange24h,
@@ -159,7 +162,7 @@ function convertBalance(raw: any): Balance {
159
162
  }
160
163
 
161
164
  function convertEvent(raw: any): UnifiedEvent {
162
- const markets = (raw.markets || []).map(convertMarket);
165
+ const markets = MarketList.from((raw.markets || []).map(convertMarket)) as MarketList;
163
166
 
164
167
  return {
165
168
  id: raw.id,
@@ -570,9 +573,29 @@ export abstract class Exchange {
570
573
  async createOrder(params: any): Promise<Order> {
571
574
  await this.initPromise;
572
575
  try {
576
+ // Resolve outcome shorthand: extract marketId/outcomeId from outcome object
577
+ let marketId = params.marketId;
578
+ let outcomeId = params.outcomeId;
579
+
580
+ if (params.outcome) {
581
+ if (marketId !== undefined || outcomeId !== undefined) {
582
+ throw new Error(
583
+ "Cannot specify both 'outcome' and 'marketId'/'outcomeId'. Use one or the other."
584
+ );
585
+ }
586
+ const outcome: MarketOutcome = params.outcome;
587
+ if (!outcome.marketId) {
588
+ throw new Error(
589
+ "outcome.marketId is not set. Ensure the outcome comes from a fetched market."
590
+ );
591
+ }
592
+ marketId = outcome.marketId;
593
+ outcomeId = outcome.outcomeId;
594
+ }
595
+
573
596
  const paramsDict: any = {
574
- marketId: params.marketId,
575
- outcomeId: params.outcomeId,
597
+ marketId,
598
+ outcomeId,
576
599
  side: params.side,
577
600
  type: params.type,
578
601
  amount: params.amount,
package/pmxt/models.js ADDED
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * Data models for PMXT TypeScript SDK.
4
+ *
5
+ * These are clean TypeScript interfaces that provide a user-friendly API.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.MarketList = void 0;
9
+ /**
10
+ * A list of UnifiedMarket objects with a convenience match() method.
11
+ * Extends Array so all standard array operations work unchanged.
12
+ */
13
+ class MarketList extends Array {
14
+ /**
15
+ * Find a single market by case-insensitive substring match.
16
+ *
17
+ * @param query - Substring to search for
18
+ * @param searchIn - Fields to search in (default: ['title'])
19
+ * @returns The matching UnifiedMarket
20
+ * @throws Error if zero or multiple markets match
21
+ */
22
+ match(query, searchIn) {
23
+ const fields = searchIn || ['title'];
24
+ const lowerQuery = query.toLowerCase();
25
+ const matches = [];
26
+ for (const m of this) {
27
+ for (const field of fields) {
28
+ if (field === 'title' && m.title?.toLowerCase().includes(lowerQuery)) {
29
+ matches.push(m);
30
+ break;
31
+ }
32
+ if (field === 'description' && m.description?.toLowerCase().includes(lowerQuery)) {
33
+ matches.push(m);
34
+ break;
35
+ }
36
+ if (field === 'category' && m.category?.toLowerCase().includes(lowerQuery)) {
37
+ matches.push(m);
38
+ break;
39
+ }
40
+ if (field === 'tags' && m.tags?.some(t => t.toLowerCase().includes(lowerQuery))) {
41
+ matches.push(m);
42
+ break;
43
+ }
44
+ if (field === 'outcomes' && m.outcomes?.some(o => o.label.toLowerCase().includes(lowerQuery))) {
45
+ matches.push(m);
46
+ break;
47
+ }
48
+ }
49
+ }
50
+ if (matches.length === 0) {
51
+ throw new Error(`No markets matching '${query}'`);
52
+ }
53
+ if (matches.length > 1) {
54
+ const titles = matches.map(m => m.title);
55
+ throw new Error(`Multiple markets matching '${query}': ${JSON.stringify(titles)}`);
56
+ }
57
+ return matches[0];
58
+ }
59
+ }
60
+ exports.MarketList = MarketList;
package/pmxt/models.ts CHANGED
@@ -15,6 +15,9 @@ export interface MarketOutcome {
15
15
  */
16
16
  outcomeId: string;
17
17
 
18
+ /** The market this outcome belongs to (set automatically). */
19
+ marketId?: string;
20
+
18
21
  /** Human-readable label (e.g., "Trump", "Yes") */
19
22
  label: string;
20
23
 
@@ -319,6 +322,65 @@ export interface CreateOrderParams {
319
322
  /** Optional fee rate (e.g., 1000 for 0.1%) */
320
323
  fee?: number;
321
324
  }
325
+ /**
326
+ * A list of UnifiedMarket objects with a convenience match() method.
327
+ * Extends Array so all standard array operations work unchanged.
328
+ */
329
+ export class MarketList extends Array<UnifiedMarket> {
330
+ /**
331
+ * Find a single market by case-insensitive substring match.
332
+ *
333
+ * @param query - Substring to search for
334
+ * @param searchIn - Fields to search in (default: ['title'])
335
+ * @returns The matching UnifiedMarket
336
+ * @throws Error if zero or multiple markets match
337
+ */
338
+ match(query: string, searchIn?: ('title' | 'description' | 'category' | 'tags' | 'outcomes')[]): UnifiedMarket {
339
+ const fields = searchIn || ['title'];
340
+ const lowerQuery = query.toLowerCase();
341
+ const matches: UnifiedMarket[] = [];
342
+
343
+ for (const m of this) {
344
+ for (const field of fields) {
345
+ if (field === 'title' && m.title?.toLowerCase().includes(lowerQuery)) {
346
+ matches.push(m);
347
+ break;
348
+ }
349
+ if (field === 'description' && m.description?.toLowerCase().includes(lowerQuery)) {
350
+ matches.push(m);
351
+ break;
352
+ }
353
+ if (field === 'category' && m.category?.toLowerCase().includes(lowerQuery)) {
354
+ matches.push(m);
355
+ break;
356
+ }
357
+ if (field === 'tags' && m.tags?.some(t => t.toLowerCase().includes(lowerQuery))) {
358
+ matches.push(m);
359
+ break;
360
+ }
361
+ if (field === 'outcomes' && m.outcomes?.some(o => o.label.toLowerCase().includes(lowerQuery))) {
362
+ matches.push(m);
363
+ break;
364
+ }
365
+ }
366
+ }
367
+
368
+ if (matches.length === 0) {
369
+ throw new Error(`No markets matching '${query}'`);
370
+ }
371
+ if (matches.length > 1) {
372
+ const titlesStr = matches
373
+ .map((m, i) => {
374
+ const truncated = m.title.length > 70 ? m.title.substring(0, 70) + '...' : m.title;
375
+ return `${i + 1}. ${truncated}`;
376
+ })
377
+ .join('\n ');
378
+ throw new Error(`Multiple markets matching '${query}' (${matches.length} matches):\n ${titlesStr}\n\nPlease refine your search.`);
379
+ }
380
+ return matches[0];
381
+ }
382
+ }
383
+
322
384
  /**
323
385
  * A grouped collection of related markets (e.g., "Who will be Fed Chair?" contains multiple candidate markets)
324
386
  */
@@ -336,7 +398,7 @@ export interface UnifiedEvent {
336
398
  slug: string;
337
399
 
338
400
  /** Related markets in this event */
339
- markets: UnifiedMarket[];
401
+ markets: MarketList;
340
402
 
341
403
  /** Event URL */
342
404
  url: string;
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * Server manager for PMXT TypeScript SDK.
4
+ *
5
+ * Handles automatic server startup and health checks.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.ServerManager = void 0;
9
+ const index_js_1 = require("../generated/src/index.js");
10
+ const fs_1 = require("fs");
11
+ const os_1 = require("os");
12
+ const path_1 = require("path");
13
+ class ServerManager {
14
+ constructor(options = {}) {
15
+ this.baseUrl = options.baseUrl || `http://localhost:${ServerManager.DEFAULT_PORT}`;
16
+ this.maxRetries = options.maxRetries || 30;
17
+ this.retryDelayMs = options.retryDelayMs || 1000;
18
+ this.lockPath = (0, path_1.join)((0, os_1.homedir)(), '.pmxt', 'server.lock');
19
+ const config = new index_js_1.Configuration({ basePath: this.baseUrl });
20
+ this.api = new index_js_1.DefaultApi(config);
21
+ }
22
+ /**
23
+ * Read server information from lock file.
24
+ */
25
+ getServerInfo() {
26
+ try {
27
+ if (!(0, fs_1.existsSync)(this.lockPath)) {
28
+ return null;
29
+ }
30
+ const content = (0, fs_1.readFileSync)(this.lockPath, 'utf-8');
31
+ return JSON.parse(content);
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ /**
38
+ * Get the actual port the server is running on.
39
+ *
40
+ * This reads the lock file to determine the actual port,
41
+ * which may differ from the default if the default port was busy.
42
+ */
43
+ getRunningPort() {
44
+ const info = this.getServerInfo();
45
+ return info?.port || ServerManager.DEFAULT_PORT;
46
+ }
47
+ /**
48
+ * Get the access token from the lock file.
49
+ */
50
+ getAccessToken() {
51
+ const info = this.getServerInfo();
52
+ return info?.accessToken;
53
+ }
54
+ /**
55
+ * Check if the server is running.
56
+ */
57
+ async isServerRunning() {
58
+ // Read lock file to get current port
59
+ const port = this.getRunningPort();
60
+ try {
61
+ // Use native fetch to check health on the actual running port
62
+ // This avoids issues where this.api is configured with the wrong port
63
+ const response = await fetch(`http://localhost:${port}/health`);
64
+ if (response.ok) {
65
+ const data = await response.json();
66
+ return data.status === "ok";
67
+ }
68
+ return false;
69
+ }
70
+ catch (error) {
71
+ return false;
72
+ }
73
+ }
74
+ /**
75
+ * Wait for the server to be ready.
76
+ */
77
+ async waitForServer() {
78
+ for (let i = 0; i < this.maxRetries; i++) {
79
+ if (await this.isServerRunning()) {
80
+ return;
81
+ }
82
+ await new Promise((resolve) => setTimeout(resolve, this.retryDelayMs));
83
+ }
84
+ throw new Error(`Server did not start within ${(this.maxRetries * this.retryDelayMs) / 1000}s`);
85
+ }
86
+ /**
87
+ * Ensure the server is running, starting it if necessary.
88
+ */
89
+ async ensureServerRunning() {
90
+ // Check for force restart
91
+ if (process.env.PMXT_ALWAYS_RESTART === '1') {
92
+ await this.killOldServer();
93
+ }
94
+ // Check if already running and version matches
95
+ if (await this.isServerRunning()) {
96
+ if (await this.isVersionMismatch()) {
97
+ await this.killOldServer();
98
+ }
99
+ else {
100
+ return;
101
+ }
102
+ }
103
+ // Locate pmxt-ensure-server
104
+ let launcherPath = 'pmxt-ensure-server'; // Default to PATH
105
+ try {
106
+ // Try to resolve from pmxt-core dependency
107
+ // For CommonJS build (which is primary), we can use require directly
108
+ // For ESM build, this will be transpiled appropriately
109
+ const corePackageJson = require.resolve('pmxt-core/package.json');
110
+ const coreDir = (0, path_1.dirname)(corePackageJson);
111
+ const binPath = (0, path_1.join)(coreDir, 'bin', 'pmxt-ensure-server');
112
+ if ((0, fs_1.existsSync)(binPath)) {
113
+ launcherPath = binPath;
114
+ }
115
+ }
116
+ catch (error) {
117
+ // If resolution fails, fall back to PATH
118
+ // This could happen in dev environments where pmxt-core is globally installed
119
+ }
120
+ // Try to start the server using pmxt-ensure-server
121
+ const { spawn } = await Promise.resolve().then(() => require("child_process"));
122
+ try {
123
+ const proc = spawn(launcherPath, [], {
124
+ detached: true,
125
+ stdio: "ignore",
126
+ });
127
+ proc.unref();
128
+ // Wait for server to be ready
129
+ await this.waitForServer();
130
+ }
131
+ catch (error) {
132
+ throw new Error(`Failed to start PMXT server: ${error}\n\n` +
133
+ `Please ensure 'pmxt-core' is installed: npm install -g pmxt-core\n` +
134
+ `Or start the server manually: pmxt-server`);
135
+ }
136
+ }
137
+ async isVersionMismatch() {
138
+ const info = this.getServerInfo();
139
+ if (!info || !info.version) {
140
+ return true; // Old server without version
141
+ }
142
+ try {
143
+ // 1. Try to find package.json relative to the installed location (Production)
144
+ let corePackageJsonPath;
145
+ try {
146
+ corePackageJsonPath = require.resolve('pmxt-core/package.json');
147
+ }
148
+ catch {
149
+ // 2. Try dev path (Monorepo)
150
+ const devPath = (0, path_1.join)((0, path_1.dirname)(__dirname), '../../core/package.json');
151
+ if ((0, fs_1.existsSync)(devPath)) {
152
+ corePackageJsonPath = devPath;
153
+ }
154
+ }
155
+ if (corePackageJsonPath && (0, fs_1.existsSync)(corePackageJsonPath)) {
156
+ const content = (0, fs_1.readFileSync)(corePackageJsonPath, 'utf-8');
157
+ const pkg = JSON.parse(content);
158
+ // Check if running version starts with package version
159
+ // (Server version might have extra hash in dev mode)
160
+ if (pkg.version && !info.version.startsWith(pkg.version)) {
161
+ return true;
162
+ }
163
+ }
164
+ }
165
+ catch {
166
+ // Ignore errors
167
+ }
168
+ return false;
169
+ }
170
+ /**
171
+ * Stop the currently running server.
172
+ */
173
+ async stop() {
174
+ await this.killOldServer();
175
+ }
176
+ /**
177
+ * Restart the server.
178
+ */
179
+ async restart() {
180
+ await this.stop();
181
+ await this.ensureServerRunning();
182
+ }
183
+ async killOldServer() {
184
+ const info = this.getServerInfo();
185
+ if (info && info.pid) {
186
+ try {
187
+ process.kill(info.pid, 'SIGTERM');
188
+ // Brief wait
189
+ await new Promise(resolve => setTimeout(resolve, 500));
190
+ }
191
+ catch {
192
+ // Ignore
193
+ }
194
+ }
195
+ // Remove lock file (best effort)
196
+ try {
197
+ const { unlinkSync } = await Promise.resolve().then(() => require('fs'));
198
+ unlinkSync(this.lockPath);
199
+ }
200
+ catch { }
201
+ }
202
+ }
203
+ exports.ServerManager = ServerManager;
204
+ ServerManager.DEFAULT_PORT = 3847;