pmxt-core 2.18.1 → 2.19.3

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.
@@ -1,4 +1,4 @@
1
- import { UnifiedMarket, UnifiedEvent, PriceCandle, CandleInterval, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from './types';
1
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, CandleInterval, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams, BuiltOrder } from './types';
2
2
  import { ExecutionPriceResult } from './utils/math';
3
3
  import { AxiosInstance } from 'axios';
4
4
  export interface ApiEndpoint {
@@ -145,6 +145,8 @@ export interface ExchangeHas {
145
145
  fetchMyTrades: ExchangeCapability;
146
146
  fetchClosedOrders: ExchangeCapability;
147
147
  fetchAllOrders: ExchangeCapability;
148
+ buildOrder: ExchangeCapability;
149
+ submitOrder: ExchangeCapability;
148
150
  }
149
151
  export interface ExchangeCredentials {
150
152
  apiKey?: string;
@@ -450,6 +452,56 @@ export declare abstract class PredictionMarketExchange {
450
452
  * )
451
453
  */
452
454
  createOrder(params: CreateOrderParams): Promise<Order>;
455
+ /**
456
+ * Build an order payload without submitting it to the exchange.
457
+ * Returns the exchange-native signed order or request body for inspection,
458
+ * forwarding through a middleware layer, or deferred submission via submitOrder().
459
+ *
460
+ * @param params - Order parameters (same as createOrder)
461
+ * @returns A BuiltOrder containing the exchange-native payload
462
+ *
463
+ * @example-ts Build then inspect a Polymarket order
464
+ * const built = await exchange.buildOrder({
465
+ * marketId: market.marketId,
466
+ * outcomeId: market.yes.outcomeId,
467
+ * side: 'buy',
468
+ * type: 'limit',
469
+ * amount: 10,
470
+ * price: 0.55
471
+ * });
472
+ * console.log(built.signedOrder); // EIP-712 signed order struct
473
+ * const order = await exchange.submitOrder(built);
474
+ *
475
+ * @example-python Build then submit a Polymarket order
476
+ * built = exchange.build_order(
477
+ * market_id=market.market_id,
478
+ * outcome_id=market.yes.outcome_id,
479
+ * side='buy',
480
+ * type='limit',
481
+ * amount=10,
482
+ * price=0.55
483
+ * )
484
+ * print(built.signed_order)
485
+ * order = exchange.submit_order(built)
486
+ */
487
+ buildOrder(params: CreateOrderParams): Promise<BuiltOrder>;
488
+ /**
489
+ * Submit a pre-built order returned by buildOrder().
490
+ *
491
+ * @param built - A BuiltOrder from buildOrder()
492
+ * @returns The submitted order
493
+ *
494
+ * @example-ts Submit a pre-built order
495
+ * const built = await exchange.buildOrder(params);
496
+ * const order = await exchange.submitOrder(built);
497
+ * console.log(`Order ${order.id}: ${order.status}`);
498
+ *
499
+ * @example-python Submit a pre-built order
500
+ * built = exchange.build_order(params)
501
+ * order = exchange.submit_order(built)
502
+ * print(f"Order {order.id}: {order.status}")
503
+ */
504
+ submitOrder(built: BuiltOrder): Promise<Order>;
453
505
  /**
454
506
  * Cancel an existing open order.
455
507
  *
@@ -56,6 +56,8 @@ class PredictionMarketExchange {
56
56
  fetchMyTrades: false,
57
57
  fetchClosedOrders: false,
58
58
  fetchAllOrders: false,
59
+ buildOrder: false,
60
+ submitOrder: false,
59
61
  };
60
62
  constructor(credentials, options) {
61
63
  this.credentials = credentials;
@@ -472,6 +474,60 @@ class PredictionMarketExchange {
472
474
  async createOrder(params) {
473
475
  throw new Error("Method createOrder not implemented.");
474
476
  }
477
+ /**
478
+ * Build an order payload without submitting it to the exchange.
479
+ * Returns the exchange-native signed order or request body for inspection,
480
+ * forwarding through a middleware layer, or deferred submission via submitOrder().
481
+ *
482
+ * @param params - Order parameters (same as createOrder)
483
+ * @returns A BuiltOrder containing the exchange-native payload
484
+ *
485
+ * @example-ts Build then inspect a Polymarket order
486
+ * const built = await exchange.buildOrder({
487
+ * marketId: market.marketId,
488
+ * outcomeId: market.yes.outcomeId,
489
+ * side: 'buy',
490
+ * type: 'limit',
491
+ * amount: 10,
492
+ * price: 0.55
493
+ * });
494
+ * console.log(built.signedOrder); // EIP-712 signed order struct
495
+ * const order = await exchange.submitOrder(built);
496
+ *
497
+ * @example-python Build then submit a Polymarket order
498
+ * built = exchange.build_order(
499
+ * market_id=market.market_id,
500
+ * outcome_id=market.yes.outcome_id,
501
+ * side='buy',
502
+ * type='limit',
503
+ * amount=10,
504
+ * price=0.55
505
+ * )
506
+ * print(built.signed_order)
507
+ * order = exchange.submit_order(built)
508
+ */
509
+ async buildOrder(params) {
510
+ throw new Error("Method buildOrder not implemented.");
511
+ }
512
+ /**
513
+ * Submit a pre-built order returned by buildOrder().
514
+ *
515
+ * @param built - A BuiltOrder from buildOrder()
516
+ * @returns The submitted order
517
+ *
518
+ * @example-ts Submit a pre-built order
519
+ * const built = await exchange.buildOrder(params);
520
+ * const order = await exchange.submitOrder(built);
521
+ * console.log(`Order ${order.id}: ${order.status}`);
522
+ *
523
+ * @example-python Submit a pre-built order
524
+ * built = exchange.build_order(params)
525
+ * order = exchange.submit_order(built)
526
+ * print(f"Order {order.id}: {order.status}")
527
+ */
528
+ async submitOrder(built) {
529
+ throw new Error("Method submitOrder not implemented.");
530
+ }
475
531
  /**
476
532
  * Cancel an existing open order.
477
533
  *
@@ -22,6 +22,8 @@ export declare class BaoziExchange extends PredictionMarketExchange {
22
22
  fetchMyTrades: false;
23
23
  fetchClosedOrders: false;
24
24
  fetchAllOrders: false;
25
+ buildOrder: false;
26
+ submitOrder: false;
25
27
  };
26
28
  private auth?;
27
29
  private connection;
@@ -31,6 +31,8 @@ class BaoziExchange extends BaseExchange_1.PredictionMarketExchange {
31
31
  fetchMyTrades: false,
32
32
  fetchClosedOrders: false,
33
33
  fetchAllOrders: false,
34
+ buildOrder: false,
35
+ submitOrder: false,
34
36
  };
35
37
  auth;
36
38
  connection;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
3
- * Generated at: 2026-02-28T16:13:08.794Z
3
+ * Generated at: 2026-03-04T18:08:33.100Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const kalshiApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.kalshiApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/kalshi/Kalshi.yaml
6
- * Generated at: 2026-02-28T16:13:08.794Z
6
+ * Generated at: 2026-03-04T18:08:33.100Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.kalshiApiSpec = {
@@ -1,5 +1,5 @@
1
1
  import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams, OrderHistoryParams } from "../../BaseExchange";
2
- import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Balance, Order, Position, CreateOrderParams } from "../../types";
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Balance, Order, Position, CreateOrderParams, BuiltOrder } from "../../types";
3
3
  import { KalshiWebSocketConfig } from "./websocket";
4
4
  export type { KalshiWebSocketConfig };
5
5
  export interface KalshiExchangeOptions {
@@ -28,6 +28,8 @@ export declare class KalshiExchange extends PredictionMarketExchange {
28
28
  fetchMyTrades: true;
29
29
  fetchClosedOrders: true;
30
30
  fetchAllOrders: true;
31
+ buildOrder: true;
32
+ submitOrder: true;
31
33
  };
32
34
  private auth?;
33
35
  private wsConfig?;
@@ -43,6 +45,8 @@ export declare class KalshiExchange extends PredictionMarketExchange {
43
45
  fetchOrderBook(id: string): Promise<OrderBook>;
44
46
  fetchTrades(id: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
45
47
  fetchBalance(): Promise<Balance[]>;
48
+ buildOrder(params: CreateOrderParams): Promise<BuiltOrder>;
49
+ submitOrder(built: BuiltOrder): Promise<Order>;
46
50
  createOrder(params: CreateOrderParams): Promise<Order>;
47
51
  cancelOrder(orderId: string): Promise<Order>;
48
52
  fetchOrder(orderId: string): Promise<Order>;
@@ -31,6 +31,8 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
31
31
  fetchMyTrades: true,
32
32
  fetchClosedOrders: true,
33
33
  fetchAllOrders: true,
34
+ buildOrder: true,
35
+ submitOrder: true,
34
36
  };
35
37
  auth;
36
38
  wsConfig;
@@ -167,9 +169,9 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
167
169
  // ----------------------------------------------------------------------------
168
170
  // Trading Methods
169
171
  // ----------------------------------------------------------------------------
170
- async createOrder(params) {
172
+ async buildOrder(params) {
171
173
  const isYesSide = params.side === "buy";
172
- const kalshiOrder = {
174
+ const body = {
173
175
  ticker: params.marketId,
174
176
  client_order_id: `pmxt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
175
177
  side: isYesSide ? "yes" : "no",
@@ -180,15 +182,25 @@ class KalshiExchange extends BaseExchange_1.PredictionMarketExchange {
180
182
  if (params.price) {
181
183
  const priceInCents = Math.round(params.price * 100);
182
184
  if (isYesSide) {
183
- kalshiOrder.yes_price = priceInCents;
185
+ body.yes_price = priceInCents;
184
186
  }
185
187
  else {
186
- kalshiOrder.no_price = priceInCents;
188
+ body.no_price = priceInCents;
187
189
  }
188
190
  }
189
- const data = await this.callApi("CreateOrder", kalshiOrder);
190
- const order = data.order;
191
- return this.mapKalshiOrder(order);
191
+ return {
192
+ exchange: this.name,
193
+ params,
194
+ raw: body,
195
+ };
196
+ }
197
+ async submitOrder(built) {
198
+ const data = await this.callApi("CreateOrder", built.raw);
199
+ return this.mapKalshiOrder(data.order);
200
+ }
201
+ async createOrder(params) {
202
+ const built = await this.buildOrder(params);
203
+ return this.submitOrder(built);
192
204
  }
193
205
  async cancelOrder(orderId) {
194
206
  const data = await this.callApi("CancelOrder", { order_id: orderId });
@@ -499,6 +499,107 @@ describe("KalshiExchange", () => {
499
499
  });
500
500
  });
501
501
  });
502
+ describe("buildOrder", () => {
503
+ it("should return correct raw body for a buy limit order without making HTTP call", async () => {
504
+ const params = {
505
+ marketId: "TEST-MARKET",
506
+ outcomeId: "yes",
507
+ side: "buy",
508
+ type: "limit",
509
+ amount: 10,
510
+ price: 0.55,
511
+ };
512
+ const built = await exchange.buildOrder(params);
513
+ expect(mockAxiosInstance.request).not.toHaveBeenCalled();
514
+ expect(built.exchange).toBe("Kalshi");
515
+ expect(built.params).toBe(params);
516
+ expect(built.raw).toEqual(expect.objectContaining({
517
+ ticker: "TEST-MARKET",
518
+ side: "yes",
519
+ action: "buy",
520
+ count: 10,
521
+ type: "limit",
522
+ yes_price: 55,
523
+ }));
524
+ });
525
+ it("should return correct raw body for a sell limit order", async () => {
526
+ const params = {
527
+ marketId: "TEST-MARKET",
528
+ outcomeId: "no",
529
+ side: "sell",
530
+ type: "limit",
531
+ amount: 5,
532
+ price: 0.45,
533
+ };
534
+ const built = await exchange.buildOrder(params);
535
+ expect(mockAxiosInstance.request).not.toHaveBeenCalled();
536
+ expect(built.exchange).toBe("Kalshi");
537
+ expect(built.raw).toEqual(expect.objectContaining({
538
+ ticker: "TEST-MARKET",
539
+ side: "no",
540
+ action: "sell",
541
+ count: 5,
542
+ type: "limit",
543
+ no_price: 45,
544
+ }));
545
+ });
546
+ it("should mirror input params in built.params", async () => {
547
+ const params = {
548
+ marketId: "SOME-MARKET",
549
+ outcomeId: "yes",
550
+ side: "buy",
551
+ type: "market",
552
+ amount: 3,
553
+ };
554
+ const built = await exchange.buildOrder(params);
555
+ expect(built.params).toBe(params);
556
+ });
557
+ });
558
+ describe("submitOrder", () => {
559
+ it("should POST built.raw to CreateOrder and return mapped order", async () => {
560
+ const params = {
561
+ marketId: "TEST-MARKET",
562
+ outcomeId: "yes",
563
+ side: "buy",
564
+ type: "limit",
565
+ amount: 10,
566
+ price: 0.55,
567
+ };
568
+ const built = await exchange.buildOrder(params);
569
+ const mockResponse = {
570
+ data: {
571
+ order: {
572
+ order_id: "order-789",
573
+ ticker: "TEST-MARKET",
574
+ side: "yes",
575
+ type: "limit",
576
+ yes_price: 55,
577
+ count: 10,
578
+ remaining_count: 10,
579
+ status: "resting",
580
+ created_time: "2026-01-13T12:00:00Z",
581
+ },
582
+ },
583
+ };
584
+ mockAxiosInstance.request.mockResolvedValue(mockResponse);
585
+ const order = await exchange.submitOrder(built);
586
+ expect(mockAxiosInstance.request).toHaveBeenCalledWith(expect.objectContaining({
587
+ method: "POST",
588
+ url: "https://api.elections.kalshi.com/trade-api/v2/portfolio/orders",
589
+ data: expect.objectContaining({
590
+ ticker: "TEST-MARKET",
591
+ side: "yes",
592
+ action: "buy",
593
+ count: 10,
594
+ type: "limit",
595
+ yes_price: 55,
596
+ }),
597
+ }));
598
+ expect(order.id).toBe("order-789");
599
+ expect(order.status).toBe("open");
600
+ expect(order.price).toBe(0.55);
601
+ });
602
+ });
502
603
  describe("Order Status Mapping", () => {
503
604
  beforeEach(() => {
504
605
  exchange = new kalshi_1.KalshiExchange(mockCredentials);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
3
- * Generated at: 2026-02-28T16:13:08.839Z
3
+ * Generated at: 2026-03-04T18:08:33.145Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const limitlessApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.limitlessApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/limitless/Limitless.yaml
6
- * Generated at: 2026-02-28T16:13:08.839Z
6
+ * Generated at: 2026-03-04T18:08:33.145Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.limitlessApiSpec = {
@@ -24,6 +24,8 @@ export declare class LimitlessExchange extends PredictionMarketExchange {
24
24
  fetchMyTrades: true;
25
25
  fetchClosedOrders: true;
26
26
  fetchAllOrders: true;
27
+ buildOrder: false;
28
+ submitOrder: false;
27
29
  };
28
30
  private auth?;
29
31
  private client?;
@@ -34,6 +34,8 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
34
34
  fetchMyTrades: true,
35
35
  fetchClosedOrders: true,
36
36
  fetchAllOrders: true,
37
+ buildOrder: false,
38
+ submitOrder: false,
37
39
  };
38
40
  auth;
39
41
  client;
@@ -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-02-28T16:13:08.854Z
3
+ * Generated at: 2026-03-04T18:08:33.158Z
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-02-28T16:13:08.854Z
6
+ * Generated at: 2026-03-04T18:08:33.158Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.myriadApiSpec = {
@@ -18,6 +18,8 @@ export declare class MyriadExchange extends PredictionMarketExchange {
18
18
  fetchMyTrades: true;
19
19
  fetchClosedOrders: false;
20
20
  fetchAllOrders: false;
21
+ buildOrder: false;
22
+ submitOrder: false;
21
23
  };
22
24
  private auth?;
23
25
  private ws?;
@@ -31,6 +31,8 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
31
31
  fetchMyTrades: true,
32
32
  fetchClosedOrders: false,
33
33
  fetchAllOrders: false,
34
+ buildOrder: false,
35
+ submitOrder: false,
34
36
  };
35
37
  auth;
36
38
  ws;
@@ -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-02-28T16:13:08.804Z
3
+ * Generated at: 2026-03-04T18:08:33.110Z
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-02-28T16:13:08.804Z
6
+ * Generated at: 2026-03-04T18:08:33.110Z
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-02-28T16:13:08.818Z
3
+ * Generated at: 2026-03-04T18:08:33.124Z
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-02-28T16:13:08.818Z
6
+ * Generated at: 2026-03-04T18:08:33.124Z
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-02-28T16:13:08.816Z
3
+ * Generated at: 2026-03-04T18:08:33.121Z
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-02-28T16:13:08.816Z
6
+ * Generated at: 2026-03-04T18:08:33.121Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.polymarketGammaSpec = {
@@ -1,5 +1,5 @@
1
1
  import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams, MyTradesParams } from '../../BaseExchange';
2
- import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams } from '../../types';
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Order, Position, Balance, CreateOrderParams, BuiltOrder } from '../../types';
3
3
  import { PolymarketWebSocketConfig } from './websocket';
4
4
  export type { PolymarketWebSocketConfig };
5
5
  export interface PolymarketExchangeOptions {
@@ -24,6 +24,8 @@ export declare class PolymarketExchange extends PredictionMarketExchange {
24
24
  fetchMyTrades: true;
25
25
  fetchClosedOrders: false;
26
26
  fetchAllOrders: false;
27
+ buildOrder: true;
28
+ submitOrder: true;
27
29
  };
28
30
  private auth?;
29
31
  private wsConfig?;
@@ -70,6 +72,8 @@ export declare class PolymarketExchange extends PredictionMarketExchange {
70
72
  * # Subsequent create_order calls are faster
71
73
  */
72
74
  preWarmMarket(outcomeId: string): Promise<void>;
75
+ buildOrder(params: CreateOrderParams): Promise<BuiltOrder>;
76
+ submitOrder(built: BuiltOrder): Promise<Order>;
73
77
  createOrder(params: CreateOrderParams): Promise<Order>;
74
78
  cancelOrder(orderId: string): Promise<Order>;
75
79
  fetchOrder(orderId: string): Promise<Order>;
@@ -36,6 +36,8 @@ class PolymarketExchange extends BaseExchange_1.PredictionMarketExchange {
36
36
  fetchMyTrades: true,
37
37
  fetchClosedOrders: false,
38
38
  fetchAllOrders: false,
39
+ buildOrder: true,
40
+ submitOrder: true,
39
41
  };
40
42
  auth;
41
43
  wsConfig;
@@ -231,59 +233,71 @@ class PolymarketExchange extends BaseExchange_1.PredictionMarketExchange {
231
233
  client.getNegRisk(outcomeId),
232
234
  ]);
233
235
  }
234
- async createOrder(params) {
236
+ async buildOrder(params) {
235
237
  try {
236
238
  const auth = this.ensureAuth();
237
239
  const client = await auth.getClobClient();
238
- // Map side to Polymarket enum
239
240
  const side = params.side.toUpperCase() === 'BUY' ? clob_client_1.Side.BUY : clob_client_1.Side.SELL;
240
- // For limit orders, price is required
241
- if (params.type === 'limit' && !params.price) {
242
- throw new Error('Price is required for limit orders');
243
- }
244
- // For market orders, use max slippage: 0.99 for BUY (willing to pay up to 99%), 0.01 for SELL (willing to accept down to 1%)
245
241
  const price = params.price || (side === clob_client_1.Side.BUY ? 0.99 : 0.01);
246
- // Use provided tickSize, or let the SDK resolve it from its own cache / API
247
242
  const tickSize = params.tickSize ? params.tickSize.toString() : undefined;
248
243
  const orderArgs = {
249
244
  tokenID: params.outcomeId,
250
- price: price,
251
- side: side,
245
+ price,
246
+ side,
252
247
  size: params.amount,
253
248
  };
254
- if (params.fee !== undefined && params.fee !== null) {
249
+ if (params.fee != null)
255
250
  orderArgs.feeRateBps = params.fee;
256
- }
257
251
  const options = {};
258
- if (tickSize) {
252
+ if (tickSize)
259
253
  options.tickSize = tickSize;
260
- }
261
- if (params.negRisk !== undefined) {
254
+ if (params.negRisk !== undefined)
262
255
  options.negRisk = params.negRisk;
263
- }
264
- const response = await client.createAndPostOrder(orderArgs, options);
256
+ const signedOrder = await client.createOrder(orderArgs, options);
257
+ return {
258
+ exchange: this.name,
259
+ params,
260
+ signedOrder: signedOrder,
261
+ raw: signedOrder,
262
+ };
263
+ }
264
+ catch (error) {
265
+ throw errors_1.polymarketErrorMapper.mapError(error);
266
+ }
267
+ }
268
+ async submitOrder(built) {
269
+ try {
270
+ const auth = this.ensureAuth();
271
+ const client = await auth.getClobClient();
272
+ const response = await client.postOrder(built.raw);
265
273
  if (!response || !response.success) {
266
- throw new Error(`${response?.errorMsg || 'Order placement failed'} (Response: ${JSON.stringify(response)})`);
274
+ throw new Error(`${response?.errorMsg || 'Order submission failed'} (Response: ${JSON.stringify(response)})`);
267
275
  }
276
+ const side = built.params.side.toUpperCase() === 'BUY' ? clob_client_1.Side.BUY : clob_client_1.Side.SELL;
277
+ const price = built.params.price || (side === clob_client_1.Side.BUY ? 0.99 : 0.01);
268
278
  return {
269
279
  id: response.orderID,
270
- marketId: params.marketId,
271
- outcomeId: params.outcomeId,
272
- side: params.side,
273
- type: params.type,
274
- price: price,
275
- amount: params.amount,
280
+ marketId: built.params.marketId,
281
+ outcomeId: built.params.outcomeId,
282
+ side: built.params.side,
283
+ type: built.params.type,
284
+ price,
285
+ amount: built.params.amount,
276
286
  status: 'open',
277
287
  filled: 0,
278
- remaining: params.amount,
279
- fee: params.fee,
280
- timestamp: Date.now()
288
+ remaining: built.params.amount,
289
+ fee: built.params.fee,
290
+ timestamp: Date.now(),
281
291
  };
282
292
  }
283
293
  catch (error) {
284
294
  throw errors_1.polymarketErrorMapper.mapError(error);
285
295
  }
286
296
  }
297
+ async createOrder(params) {
298
+ const built = await this.buildOrder(params);
299
+ return this.submitOrder(built);
300
+ }
287
301
  async cancelOrder(orderId) {
288
302
  try {
289
303
  const auth = this.ensureAuth();
@@ -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-02-28T16:13:08.846Z
3
+ * Generated at: 2026-03-04T18:08:33.151Z
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-02-28T16:13:08.846Z
6
+ * Generated at: 2026-03-04T18:08:33.151Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.probableApiSpec = {
@@ -19,6 +19,8 @@ export declare class ProbableExchange extends PredictionMarketExchange {
19
19
  fetchMyTrades: true;
20
20
  fetchClosedOrders: false;
21
21
  fetchAllOrders: false;
22
+ buildOrder: false;
23
+ submitOrder: false;
22
24
  };
23
25
  private auth?;
24
26
  private ws?;
@@ -50,6 +50,8 @@ class ProbableExchange extends BaseExchange_1.PredictionMarketExchange {
50
50
  fetchMyTrades: true,
51
51
  fetchClosedOrders: false,
52
52
  fetchAllOrders: false,
53
+ buildOrder: false,
54
+ submitOrder: false,
53
55
  };
54
56
  auth;
55
57
  ws;
package/dist/types.d.ts CHANGED
@@ -113,3 +113,26 @@ export interface CreateOrderParams {
113
113
  tickSize?: number;
114
114
  negRisk?: boolean;
115
115
  }
116
+ export interface BuiltOrder {
117
+ /** The exchange name this order was built for. */
118
+ exchange: string;
119
+ /** The original params used to build this order. */
120
+ params: CreateOrderParams;
121
+ /**
122
+ * For CLOB exchanges (Polymarket): the EIP-712 signed order
123
+ * ready to POST to the exchange's order endpoint.
124
+ */
125
+ signedOrder?: Record<string, unknown>;
126
+ /**
127
+ * For on-chain AMM exchanges: the EVM transaction payload.
128
+ * Reserved for future exchanges; no current exchange populates this.
129
+ */
130
+ tx?: {
131
+ to: string;
132
+ data: string;
133
+ value: string;
134
+ chainId: number;
135
+ };
136
+ /** The raw, exchange-native payload. Always present. */
137
+ raw: unknown;
138
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmxt-core",
3
- "version": "2.18.1",
3
+ "version": "2.19.3",
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.18.1,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.18.1,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.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.19.3,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.19.3,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",