pmxtjs 2.48.5 → 2.49.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 (79) hide show
  1. package/dist/esm/generated/src/models/OrderLevel.d.ts +6 -0
  2. package/dist/esm/generated/src/models/OrderLevel.js +2 -0
  3. package/dist/esm/generated/src/models/UnifiedMarket.d.ts +2 -2
  4. package/dist/esm/generated/src/models/UnifiedMarket.js +2 -4
  5. package/dist/esm/index.d.ts +2 -0
  6. package/dist/esm/index.js +1 -0
  7. package/dist/esm/pmxt/client.d.ts +106 -5
  8. package/dist/esm/pmxt/client.js +400 -6
  9. package/dist/esm/pmxt/constants.d.ts +11 -0
  10. package/dist/esm/pmxt/constants.js +13 -0
  11. package/dist/esm/pmxt/errors.d.ts +3 -0
  12. package/dist/esm/pmxt/errors.js +9 -0
  13. package/dist/esm/pmxt/escrow.d.ts +39 -0
  14. package/dist/esm/pmxt/escrow.js +78 -0
  15. package/dist/esm/pmxt/feed-client.d.ts +3 -0
  16. package/dist/esm/pmxt/feed-client.js +11 -2
  17. package/dist/esm/pmxt/hosted-errors.d.ts +84 -0
  18. package/dist/esm/pmxt/hosted-errors.js +186 -0
  19. package/dist/esm/pmxt/hosted-mappers.d.ts +45 -0
  20. package/dist/esm/pmxt/hosted-mappers.js +291 -0
  21. package/dist/esm/pmxt/hosted-routing.d.ts +69 -0
  22. package/dist/esm/pmxt/hosted-routing.js +119 -0
  23. package/dist/esm/pmxt/hosted-typed-data.d.ts +36 -0
  24. package/dist/esm/pmxt/hosted-typed-data.js +580 -0
  25. package/dist/esm/pmxt/models.d.ts +46 -8
  26. package/dist/esm/pmxt/server-manager.d.ts +4 -0
  27. package/dist/esm/pmxt/server-manager.js +6 -0
  28. package/dist/esm/pmxt/signers.d.ts +57 -0
  29. package/dist/esm/pmxt/signers.js +50 -0
  30. package/dist/esm/pmxt/ws-client.js +2 -1
  31. package/dist/generated/src/models/OrderLevel.d.ts +6 -0
  32. package/dist/generated/src/models/OrderLevel.js +2 -0
  33. package/dist/generated/src/models/UnifiedMarket.d.ts +2 -2
  34. package/dist/generated/src/models/UnifiedMarket.js +2 -4
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +1 -0
  37. package/dist/pmxt/client.d.ts +106 -5
  38. package/dist/pmxt/client.js +399 -5
  39. package/dist/pmxt/constants.d.ts +11 -0
  40. package/dist/pmxt/constants.js +14 -1
  41. package/dist/pmxt/errors.d.ts +3 -0
  42. package/dist/pmxt/errors.js +11 -1
  43. package/dist/pmxt/escrow.d.ts +39 -0
  44. package/dist/pmxt/escrow.js +82 -0
  45. package/dist/pmxt/feed-client.d.ts +3 -0
  46. package/dist/pmxt/feed-client.js +11 -2
  47. package/dist/pmxt/hosted-errors.d.ts +84 -0
  48. package/dist/pmxt/hosted-errors.js +201 -0
  49. package/dist/pmxt/hosted-mappers.d.ts +45 -0
  50. package/dist/pmxt/hosted-mappers.js +302 -0
  51. package/dist/pmxt/hosted-routing.d.ts +69 -0
  52. package/dist/pmxt/hosted-routing.js +126 -0
  53. package/dist/pmxt/hosted-typed-data.d.ts +36 -0
  54. package/dist/pmxt/hosted-typed-data.js +619 -0
  55. package/dist/pmxt/models.d.ts +46 -8
  56. package/dist/pmxt/server-manager.d.ts +4 -0
  57. package/dist/pmxt/server-manager.js +6 -0
  58. package/dist/pmxt/signers.d.ts +57 -0
  59. package/dist/pmxt/signers.js +55 -0
  60. package/dist/pmxt/ws-client.js +2 -1
  61. package/generated/docs/OrderLevel.md +2 -0
  62. package/generated/package.json +1 -1
  63. package/generated/src/models/OrderLevel.ts +8 -0
  64. package/generated/src/models/UnifiedMarket.ts +4 -5
  65. package/index.ts +1 -0
  66. package/package.json +11 -2
  67. package/pmxt/client.ts +495 -9
  68. package/pmxt/constants.ts +15 -0
  69. package/pmxt/errors.ts +11 -0
  70. package/pmxt/escrow.ts +93 -0
  71. package/pmxt/feed-client.ts +14 -2
  72. package/pmxt/hosted-errors.ts +216 -0
  73. package/pmxt/hosted-mappers.ts +312 -0
  74. package/pmxt/hosted-routing.ts +165 -0
  75. package/pmxt/hosted-typed-data.ts +767 -0
  76. package/pmxt/models.ts +65 -8
  77. package/pmxt/server-manager.ts +7 -0
  78. package/pmxt/signers.ts +86 -0
  79. package/pmxt/ws-client.ts +2 -1
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ /**
3
+ * Hosted trading v0 response mappers.
4
+ *
5
+ * The hosted trading API exposes explicit `/v0/*` JSON shapes. These helpers
6
+ * translate those wire dictionaries to the SDK TypeScript interfaces.
7
+ *
8
+ * Mirrors `sdks/python/pmxt/_hosted_mappers.py`.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.to6dec = to6dec;
12
+ exports.orderFromV0 = orderFromV0;
13
+ exports.orderToV0 = orderToV0;
14
+ exports.userTradeFromV0 = userTradeFromV0;
15
+ exports.userTradeToV0 = userTradeToV0;
16
+ exports.positionFromV0 = positionFromV0;
17
+ exports.positionToV0 = positionToV0;
18
+ exports.balanceFromV0 = balanceFromV0;
19
+ exports.balanceToV0 = balanceToV0;
20
+ const errors_1 = require("./errors");
21
+ // ---------------------------------------------------------------------------
22
+ // Precision helper
23
+ // ---------------------------------------------------------------------------
24
+ const SIX_DEC_SCALE = 1000000n;
25
+ /**
26
+ * Convert a decimal amount to integer micro-units (6-decimal grid).
27
+ *
28
+ * Rejects amounts whose fractional part has more than 6 digits. Pure integer
29
+ * math via BigInt — no float rounding involved.
30
+ */
31
+ function to6dec(amount) {
32
+ const str = typeof amount === "bigint" ? `${amount}` : String(amount);
33
+ const negative = str.startsWith("-");
34
+ const cleaned = negative ? str.slice(1) : str;
35
+ const [intPart, fracPart = ""] = cleaned.split(".");
36
+ if (fracPart.length > 6) {
37
+ throw new errors_1.InvalidOrder(`amount precision exceeds 6 decimals: ${amount}`);
38
+ }
39
+ if (!/^\d*$/.test(intPart) || !/^\d*$/.test(fracPart)) {
40
+ throw new errors_1.InvalidOrder(`invalid amount: ${amount}`);
41
+ }
42
+ const padded = (fracPart + "000000").slice(0, 6);
43
+ const intMag = BigInt(intPart || "0");
44
+ const scaled = intMag * SIX_DEC_SCALE + BigInt(padded);
45
+ return negative ? -scaled : scaled;
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Order mappers
49
+ // ---------------------------------------------------------------------------
50
+ /** Map an `OrderV0` JSON object to {@link Order}. */
51
+ function orderFromV0(payload) {
52
+ const id = strOrEmpty(payload["id"]);
53
+ const marketId = strOrEmpty(payload["market_id"] ?? payload["marketId"]);
54
+ const outcomeId = strOrEmpty(payload["outcome_id"] ?? payload["outcomeId"]);
55
+ const status = strOrEmpty(payload["status"]);
56
+ const sideRaw = payload["side"];
57
+ const side = sideRaw === "sell" ? "sell" : "buy";
58
+ const typeRaw = payload["type"];
59
+ const type = typeRaw === "limit" ? "limit" : "market";
60
+ const order = {
61
+ id,
62
+ marketId,
63
+ outcomeId,
64
+ side,
65
+ type,
66
+ amount: floatOrZero(payload["amount"]),
67
+ status,
68
+ filled: floatOrZero(payload["filled"]),
69
+ remaining: floatOrZero(payload["remaining"]),
70
+ timestamp: timestampToMs(payload["timestamp"]),
71
+ };
72
+ const price = floatOrUndefined(payload["price"]);
73
+ if (price !== undefined)
74
+ order.price = price;
75
+ const fee = floatOrUndefined(payload["fee"]);
76
+ if (fee !== undefined)
77
+ order.fee = fee;
78
+ return order;
79
+ }
80
+ /** Map an {@link Order} back to an `OrderV0` JSON object. */
81
+ function orderToV0(order) {
82
+ const out = {
83
+ id: order.id,
84
+ market_id: order.marketId,
85
+ outcome_id: order.outcomeId,
86
+ side: order.side,
87
+ type: order.type,
88
+ amount: order.amount,
89
+ status: order.status,
90
+ filled: order.filled,
91
+ remaining: order.remaining,
92
+ timestamp: msToTimestamp(order.timestamp),
93
+ };
94
+ if (order.price !== undefined)
95
+ out["price"] = order.price;
96
+ if (order.fee !== undefined)
97
+ out["fee"] = order.fee;
98
+ return out;
99
+ }
100
+ // ---------------------------------------------------------------------------
101
+ // UserTrade mappers
102
+ // ---------------------------------------------------------------------------
103
+ /** Map a `UserTradeV0` JSON object to {@link UserTrade}. */
104
+ function userTradeFromV0(payload) {
105
+ const sideRaw = payload["side"];
106
+ const side = sideRaw === "buy" || sideRaw === "sell" ? sideRaw : "unknown";
107
+ const trade = {
108
+ id: strOrEmpty(payload["id"]),
109
+ price: floatOrZero(payload["price"]),
110
+ amount: floatOrZero(payload["amount"]),
111
+ side,
112
+ timestamp: timestampToMs(payload["timestamp"]),
113
+ };
114
+ const orderId = strOrUndefined(payload["order_id"] ?? payload["orderId"]);
115
+ if (orderId !== undefined)
116
+ trade.orderId = orderId;
117
+ const outcomeId = strOrUndefined(payload["outcome_id"] ?? payload["outcomeId"]);
118
+ if (outcomeId !== undefined)
119
+ trade.outcomeId = outcomeId;
120
+ const marketId = strOrUndefined(payload["market_id"] ?? payload["marketId"]);
121
+ if (marketId !== undefined)
122
+ trade.marketId = marketId;
123
+ return trade;
124
+ }
125
+ /** Map a {@link UserTrade} back to a `UserTradeV0` JSON object. */
126
+ function userTradeToV0(trade) {
127
+ const out = {
128
+ id: trade.id,
129
+ side: trade.side,
130
+ amount: trade.amount,
131
+ price: trade.price,
132
+ timestamp: msToTimestamp(trade.timestamp),
133
+ };
134
+ if (trade.orderId !== undefined)
135
+ out["order_id"] = trade.orderId;
136
+ if (trade.outcomeId !== undefined)
137
+ out["outcome_id"] = trade.outcomeId;
138
+ if (trade.marketId !== undefined)
139
+ out["market_id"] = trade.marketId;
140
+ return out;
141
+ }
142
+ // ---------------------------------------------------------------------------
143
+ // Position mappers
144
+ // ---------------------------------------------------------------------------
145
+ /**
146
+ * Map a `PositionV0` JSON object to {@link Position}.
147
+ *
148
+ * Optional fields (`outcomeLabel`, `entryPrice`, `currentPrice`,
149
+ * `unrealizedPnL`, `realizedPnL`) surface as `undefined` when missing —
150
+ * **never** a fake `0` or `""`. This keeps the SDK honest about which data
151
+ * the server actually provided.
152
+ */
153
+ function positionFromV0(payload) {
154
+ const size = floatOrZero(payload["shares"] ?? payload["size"]);
155
+ const entryPrice = floatOrUndefined(payload["entry_price"] ?? payload["entryPrice"]);
156
+ const currentPrice = floatOrUndefined(payload["current_price"] ?? payload["currentPrice"]);
157
+ let unrealizedPnL = floatOrUndefined(payload["unrealized_pnl"] ?? payload["unrealizedPnl"] ?? payload["unrealizedPnL"]);
158
+ if (unrealizedPnL === undefined &&
159
+ entryPrice !== undefined &&
160
+ currentPrice !== undefined) {
161
+ unrealizedPnL = (currentPrice - entryPrice) * size;
162
+ }
163
+ // Position requires marketId/outcomeId/outcomeLabel/entryPrice/currentPrice/unrealizedPnL
164
+ // in the current interface. We construct with safe defaults and only override
165
+ // when present. Per plan v5: the SDK should NOT fabricate financial data —
166
+ // when the server didn't supply entryPrice/currentPrice/outcomeLabel, we mark
167
+ // them via undefined (cast through a partial since the existing Position type
168
+ // hasn't yet been widened to Optional in this parallel-agent change).
169
+ const position = {
170
+ marketId: strOrEmpty(payload["market_id"] ?? payload["marketId"]),
171
+ outcomeId: strOrEmpty(payload["outcome_id"] ?? payload["outcomeId"]),
172
+ outcomeLabel: strOrUndefined(payload["outcome_label"] ?? payload["outcomeLabel"]),
173
+ size,
174
+ entryPrice: entryPrice,
175
+ currentPrice: currentPrice,
176
+ unrealizedPnL: unrealizedPnL,
177
+ realizedPnL: floatOrUndefined(payload["realized_pnl"] ?? payload["realizedPnl"] ?? payload["realizedPnL"]),
178
+ };
179
+ return position;
180
+ }
181
+ /** Map a {@link Position} back to a `PositionV0` JSON object. */
182
+ function positionToV0(position) {
183
+ const out = {
184
+ market_id: position.marketId,
185
+ outcome_id: position.outcomeId,
186
+ shares: position.size,
187
+ };
188
+ if (position.outcomeLabel !== undefined && position.outcomeLabel !== "") {
189
+ out["outcome_label"] = position.outcomeLabel;
190
+ }
191
+ if (position.entryPrice !== undefined)
192
+ out["entry_price"] = position.entryPrice;
193
+ if (position.currentPrice !== undefined)
194
+ out["current_price"] = position.currentPrice;
195
+ if (position.unrealizedPnL !== undefined)
196
+ out["unrealized_pnl"] = position.unrealizedPnL;
197
+ if (position.realizedPnL !== undefined)
198
+ out["realized_pnl"] = position.realizedPnL;
199
+ return out;
200
+ }
201
+ // ---------------------------------------------------------------------------
202
+ // Balance mappers
203
+ // ---------------------------------------------------------------------------
204
+ /**
205
+ * Map a `BalanceV0` JSON object to {@link Balance}.
206
+ *
207
+ * Hosted-mode semantic: PreFundedEscrow doesn't reserve funds for resting
208
+ * orders, so `available = total` and `locked = 0`. Concurrent limit orders
209
+ * may fail at fill time if cumulative cost exceeds the escrow balance.
210
+ */
211
+ function balanceFromV0(payload) {
212
+ const total = floatOrZero(payload["amount"] ?? payload["total"]);
213
+ const currency = strOrUndefined(payload["currency"]) ?? "USDC";
214
+ return {
215
+ currency,
216
+ total,
217
+ available: total,
218
+ locked: 0,
219
+ };
220
+ }
221
+ /** Map a {@link Balance} back to a `BalanceV0` JSON object. */
222
+ function balanceToV0(balance) {
223
+ return {
224
+ currency: balance.currency,
225
+ amount: balance.total,
226
+ };
227
+ }
228
+ // ---------------------------------------------------------------------------
229
+ // Internal helpers
230
+ // ---------------------------------------------------------------------------
231
+ function strOrUndefined(value) {
232
+ if (value === null || value === undefined)
233
+ return undefined;
234
+ if (typeof value === "string")
235
+ return value || undefined;
236
+ return String(value);
237
+ }
238
+ function strOrEmpty(value) {
239
+ if (value === null || value === undefined)
240
+ return "";
241
+ if (typeof value === "string")
242
+ return value;
243
+ return String(value);
244
+ }
245
+ function floatOrUndefined(value) {
246
+ if (value === null || value === undefined)
247
+ return undefined;
248
+ if (typeof value === "number")
249
+ return Number.isFinite(value) ? value : undefined;
250
+ if (typeof value === "bigint")
251
+ return Number(value);
252
+ if (typeof value === "string") {
253
+ if (!value)
254
+ return undefined;
255
+ const parsed = Number(value);
256
+ return Number.isFinite(parsed) ? parsed : undefined;
257
+ }
258
+ return undefined;
259
+ }
260
+ function floatOrZero(value) {
261
+ const converted = floatOrUndefined(value);
262
+ return converted !== undefined ? converted : 0;
263
+ }
264
+ /**
265
+ * Parse an ISO-8601 string (or numeric) timestamp to milliseconds since epoch.
266
+ * Returns `0` if the input is null/undefined/empty/unparseable.
267
+ */
268
+ function timestampToMs(value) {
269
+ if (value === null || value === undefined)
270
+ return 0;
271
+ if (typeof value === "number") {
272
+ return Number.isFinite(value) ? Math.trunc(value) : 0;
273
+ }
274
+ if (typeof value === "bigint")
275
+ return Number(value);
276
+ if (typeof value === "string") {
277
+ if (!value)
278
+ return 0;
279
+ const normalized = value.endsWith("Z")
280
+ ? value
281
+ : /[+-]\d{2}:?\d{2}$/.test(value)
282
+ ? value
283
+ : value + "Z";
284
+ const ms = Date.parse(normalized);
285
+ return Number.isFinite(ms) ? ms : 0;
286
+ }
287
+ return 0;
288
+ }
289
+ /** Convert milliseconds-since-epoch back to an ISO-8601 string. */
290
+ function msToTimestamp(value) {
291
+ if (value === null || value === undefined)
292
+ return undefined;
293
+ if (typeof value === "string")
294
+ return value;
295
+ if (typeof value === "number" && Number.isFinite(value)) {
296
+ return new Date(value).toISOString();
297
+ }
298
+ if (typeof value === "bigint") {
299
+ return new Date(Number(value)).toISOString();
300
+ }
301
+ return undefined;
302
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Hosted-mode HTTP routing for the pmxt TypeScript SDK.
3
+ *
4
+ * When a client is configured with a `pmxtApiKey`, supported method calls are
5
+ * dispatched to the pmxt-hosted trading API instead of the venue's native
6
+ * client. This module owns:
7
+ *
8
+ * - the static route table mapping SDK method names to hosted endpoints,
9
+ * - the venue allowlist for hosted trading,
10
+ * - wallet address resolution for user-scoped reads/trades, and
11
+ * - the low-level `_tradingRequest` HTTP helper.
12
+ *
13
+ * Mirrors `sdks/python/pmxt/_hosted_routing.py`.
14
+ */
15
+ export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
16
+ export type HostedBase = "catalog" | "trading";
17
+ export declare const HOSTED_CATALOG_BASE_URL = "https://api.pmxt.dev";
18
+ export declare const HOSTED_TRADING_BASE_URL = "https://trade.pmxt.dev";
19
+ export declare const HOSTED_TRADING_VENUES: ReadonlySet<string>;
20
+ export interface HostedRoute {
21
+ method: HttpMethod;
22
+ path: string;
23
+ base: HostedBase;
24
+ requiresWalletAddress?: boolean;
25
+ }
26
+ export declare const HOSTED_METHOD_ROUTES: ReadonlyMap<string, HostedRoute>;
27
+ /**
28
+ * Minimal duck-typed view of a venue client used by hosted-mode helpers.
29
+ *
30
+ * Defining this as a structural interface keeps `hosted-routing` decoupled
31
+ * from the concrete `Exchange` class and makes unit testing trivial.
32
+ */
33
+ export interface HostedClientLike {
34
+ pmxtApiKey?: string;
35
+ exchangeName: string;
36
+ walletAddress?: string;
37
+ }
38
+ /**
39
+ * Throw {@link NotSupported} if the client is in hosted mode (i.e. has a
40
+ * `pmxtApiKey`) but targets a venue outside the hosted trading allowlist.
41
+ * No-op for non-hosted clients.
42
+ */
43
+ export declare function ensureHostedTradingSupported(client: HostedClientLike): void;
44
+ /**
45
+ * Resolve the wallet address to use for a user-scoped hosted call, preferring
46
+ * an explicit per-call override over the client default. Throws
47
+ * {@link MissingWalletAddress} when neither is set.
48
+ */
49
+ export declare function resolveWalletAddress(client: HostedClientLike, override?: string): string;
50
+ /**
51
+ * Substitute `{name}` placeholders in a route path with URL-encoded values
52
+ * from `params`. Throws if a referenced parameter is missing.
53
+ */
54
+ export declare function formatRoutePath(route: HostedRoute, params: Record<string, string | number | undefined>): string;
55
+ export interface TradingRequestOptions {
56
+ method: HttpMethod;
57
+ path: string;
58
+ body?: unknown;
59
+ params?: Record<string, string | number | boolean | undefined>;
60
+ }
61
+ /**
62
+ * Issue a request against the hosted trading API.
63
+ *
64
+ * NOTE: writes (POST/PUT/DELETE) are NEVER retried. `built_order_id` and
65
+ * `cancel_id` are single-use server-side, so replaying a lost response would
66
+ * 404 even though the original write succeeded. Callers needing retry logic
67
+ * must layer it on top with awareness of this invariant.
68
+ */
69
+ export declare function _tradingRequest(client: HostedClientLike, opts: TradingRequestOptions): Promise<unknown>;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * Hosted-mode HTTP routing for the pmxt TypeScript SDK.
4
+ *
5
+ * When a client is configured with a `pmxtApiKey`, supported method calls are
6
+ * dispatched to the pmxt-hosted trading API instead of the venue's native
7
+ * client. This module owns:
8
+ *
9
+ * - the static route table mapping SDK method names to hosted endpoints,
10
+ * - the venue allowlist for hosted trading,
11
+ * - wallet address resolution for user-scoped reads/trades, and
12
+ * - the low-level `_tradingRequest` HTTP helper.
13
+ *
14
+ * Mirrors `sdks/python/pmxt/_hosted_routing.py`.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.HOSTED_METHOD_ROUTES = exports.HOSTED_TRADING_VENUES = exports.HOSTED_TRADING_BASE_URL = exports.HOSTED_CATALOG_BASE_URL = void 0;
18
+ exports.ensureHostedTradingSupported = ensureHostedTradingSupported;
19
+ exports.resolveWalletAddress = resolveWalletAddress;
20
+ exports.formatRoutePath = formatRoutePath;
21
+ exports._tradingRequest = _tradingRequest;
22
+ const errors_1 = require("./errors");
23
+ const hosted_errors_1 = require("./hosted-errors");
24
+ exports.HOSTED_CATALOG_BASE_URL = "https://api.pmxt.dev";
25
+ exports.HOSTED_TRADING_BASE_URL = "https://trade.pmxt.dev";
26
+ exports.HOSTED_TRADING_VENUES = new Set([
27
+ "polymarket",
28
+ "opinion",
29
+ ]);
30
+ exports.HOSTED_METHOD_ROUTES = new Map([
31
+ ["createOrder", { method: "POST", path: "/v0/trade/build-order", base: "trading" }],
32
+ ["buildOrder", { method: "POST", path: "/v0/trade/build-order", base: "trading" }],
33
+ ["submitOrder", { method: "POST", path: "/v0/trade/submit-order", base: "trading" }],
34
+ ["cancelOrderBuild", { method: "POST", path: "/v0/orders/cancel/build", base: "trading" }],
35
+ ["cancelOrder", { method: "POST", path: "/v0/orders/cancel", base: "trading" }],
36
+ ["fetchOrder", { method: "GET", path: "/v0/orders/{order_id}", base: "trading" }],
37
+ ["fetchOpenOrders", { method: "GET", path: "/v0/orders/open", base: "trading", requiresWalletAddress: true }],
38
+ ["fetchMyTrades", { method: "GET", path: "/v0/user/{address}/trades", base: "trading", requiresWalletAddress: true }],
39
+ ["fetchBalance", { method: "GET", path: "/v0/user/{address}/balances", base: "trading", requiresWalletAddress: true }],
40
+ ["fetchPositions", { method: "GET", path: "/v0/user/{address}/positions", base: "trading", requiresWalletAddress: true }],
41
+ ["escrowApproveTx", { method: "POST", path: "/v0/escrow/approve", base: "trading" }],
42
+ ["escrowDepositTx", { method: "POST", path: "/v0/escrow/deposit", base: "trading" }],
43
+ ["escrowWithdrawTx", { method: "POST", path: "/v0/escrow/withdraw", base: "trading" }],
44
+ ["escrowWithdrawals", { method: "GET", path: "/v0/escrow/{address}/withdrawals", base: "trading", requiresWalletAddress: true }],
45
+ ]);
46
+ /**
47
+ * Throw {@link NotSupported} if the client is in hosted mode (i.e. has a
48
+ * `pmxtApiKey`) but targets a venue outside the hosted trading allowlist.
49
+ * No-op for non-hosted clients.
50
+ */
51
+ function ensureHostedTradingSupported(client) {
52
+ if (!client.pmxtApiKey)
53
+ return;
54
+ if (!exports.HOSTED_TRADING_VENUES.has(client.exchangeName)) {
55
+ throw new errors_1.NotSupported(`Hosted trading is only supported for Polymarket and Opinion; ${client.exchangeName} is not supported with pmxtApiKey.`);
56
+ }
57
+ }
58
+ /**
59
+ * Resolve the wallet address to use for a user-scoped hosted call, preferring
60
+ * an explicit per-call override over the client default. Throws
61
+ * {@link MissingWalletAddress} when neither is set.
62
+ */
63
+ function resolveWalletAddress(client, override) {
64
+ if (override)
65
+ return override;
66
+ if (client.walletAddress)
67
+ return client.walletAddress;
68
+ throw new hosted_errors_1.MissingWalletAddress("walletAddress is required for hosted-mode reads and trades; pass it to the exchange constructor or as an override.");
69
+ }
70
+ /**
71
+ * Substitute `{name}` placeholders in a route path with URL-encoded values
72
+ * from `params`. Throws if a referenced parameter is missing.
73
+ */
74
+ function formatRoutePath(route, params) {
75
+ return route.path.replace(/\{(\w+)\}/g, (_, key) => {
76
+ const value = params[key];
77
+ if (value === undefined || value === null) {
78
+ throw new Error(`path parameter cannot be undefined: ${key}`);
79
+ }
80
+ return encodeURIComponent(String(value));
81
+ });
82
+ }
83
+ /**
84
+ * Issue a request against the hosted trading API.
85
+ *
86
+ * NOTE: writes (POST/PUT/DELETE) are NEVER retried. `built_order_id` and
87
+ * `cancel_id` are single-use server-side, so replaying a lost response would
88
+ * 404 even though the original write succeeded. Callers needing retry logic
89
+ * must layer it on top with awareness of this invariant.
90
+ */
91
+ async function _tradingRequest(client, opts) {
92
+ if (!client.pmxtApiKey) {
93
+ throw new Error("hosted request requires pmxtApiKey");
94
+ }
95
+ const base = exports.HOSTED_TRADING_BASE_URL.replace(/\/$/, "");
96
+ const path = opts.path.startsWith("/") ? opts.path : `/${opts.path}`;
97
+ let url = base + path;
98
+ if (opts.params) {
99
+ const qs = new URLSearchParams();
100
+ for (const [k, v] of Object.entries(opts.params)) {
101
+ if (v !== undefined)
102
+ qs.append(k, String(v));
103
+ }
104
+ const q = qs.toString();
105
+ if (q)
106
+ url += `?${q}`;
107
+ }
108
+ const headers = {
109
+ Authorization: `Bearer ${client.pmxtApiKey}`,
110
+ };
111
+ if (opts.body !== undefined) {
112
+ headers["Content-Type"] = "application/json";
113
+ }
114
+ const resp = await fetch(url, {
115
+ method: opts.method,
116
+ headers,
117
+ body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,
118
+ });
119
+ if (!resp.ok) {
120
+ await (0, hosted_errors_1.raiseFromResponse)(resp);
121
+ }
122
+ const text = await resp.text();
123
+ if (!text)
124
+ return null;
125
+ return JSON.parse(text);
126
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Hosted trading EIP-712 validation guardrails.
3
+ *
4
+ * Three layers (mirrors `sdks/python/pmxt/_hosted_typeddata.py`):
5
+ * 1. Schema validation — per-route shape, domain, types, message keys, deadline
6
+ * 2. Economic match — typed_data economics agree with the user's build request
7
+ * 3. Post-sign — exact 65-byte length, low-s canonical, v ∈ {27, 28}, recovery
8
+ *
9
+ * Layer 3 uses the optional `ethers` peer dependency for typed-data verification.
10
+ */
11
+ import { TypedData } from "./signers";
12
+ export type HostedRoute = "polymarket_buy" | "polymarket_sell" | "opinion_buy" | "opinion_sell_polygon" | "opinion_sell_bsc_pull" | "cancel_polymarket" | "cancel_opinion_polygon" | "cancel_opinion_bsc_pull";
13
+ export declare const SECP256K1_HALF_N = 57896044618658097711785492504343953926418782139537452191302581570759080747168n;
14
+ /**
15
+ * Validate the structural shape of a typed-data payload before signing.
16
+ * Throws {@link InvalidSignature} on any mismatch.
17
+ */
18
+ export declare function validateTypedData(typedData: TypedData, route: string, walletAddress: string): void;
19
+ /**
20
+ * Reject typed-data whose economics don't agree with the user's original
21
+ * build request / build response. Guards against a compromised server
22
+ * returning valid-shape typed-data with altered amounts or wrong target.
23
+ */
24
+ export declare function validateEconomics(typedData: TypedData, route: string, buildRequest: any, buildResponse: any): void;
25
+ /**
26
+ * Verify a signature against typed-data and return the normalized signature.
27
+ *
28
+ * Performs:
29
+ * - exact 65-byte length (0x + 130 hex)
30
+ * - low-s canonical check
31
+ * - v ∈ {27, 28} (normalizes {0,1} → {27,28})
32
+ * - typed-data recovery, asserting recovered address === walletAddress
33
+ *
34
+ * Throws {@link InvalidSignature} on any failure.
35
+ */
36
+ export declare function verifySignature(typedData: TypedData, signature: string, walletAddress: string): string;