pmxtjs 2.49.10 → 2.50.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/generated/src/apis/DefaultApi.d.ts +28 -0
- package/dist/esm/generated/src/apis/DefaultApi.js +28 -0
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.js +4 -3
- package/dist/esm/pmxt/client.d.ts +37 -25
- package/dist/esm/pmxt/client.js +117 -202
- package/dist/esm/pmxt/constants.d.ts +4 -0
- package/dist/esm/pmxt/constants.js +6 -0
- package/dist/esm/pmxt/hosted-routing.js +1 -0
- package/dist/esm/pmxt/hosted-typed-data.d.ts +1 -1
- package/dist/esm/pmxt/hosted-typed-data.js +53 -12
- package/dist/esm/pmxt/models.d.ts +1 -0
- package/dist/esm/pmxt/router.js +12 -3
- package/dist/esm/pmxt/signers.d.ts +7 -0
- package/dist/esm/pmxt/signers.js +30 -8
- package/dist/generated/src/apis/DefaultApi.d.ts +28 -0
- package/dist/generated/src/apis/DefaultApi.js +28 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +6 -1
- package/dist/pmxt/client.d.ts +37 -25
- package/dist/pmxt/client.js +116 -200
- package/dist/pmxt/constants.d.ts +4 -0
- package/dist/pmxt/constants.js +7 -1
- package/dist/pmxt/hosted-routing.js +1 -0
- package/dist/pmxt/hosted-typed-data.d.ts +1 -1
- package/dist/pmxt/hosted-typed-data.js +53 -12
- package/dist/pmxt/models.d.ts +1 -0
- package/dist/pmxt/router.js +12 -3
- package/dist/pmxt/signers.d.ts +7 -0
- package/dist/pmxt/signers.js +31 -8
- package/generated/docs/DefaultApi.md +56 -56
- package/generated/package.json +1 -1
- package/generated/src/apis/DefaultApi.ts +28 -0
- package/index.ts +12 -3
- package/package.json +2 -2
- package/pmxt/client.ts +123 -219
- package/pmxt/constants.ts +7 -0
- package/pmxt/hosted-routing.ts +1 -0
- package/pmxt/hosted-typed-data.ts +67 -17
- package/pmxt/models.ts +3 -0
- package/pmxt/router.ts +14 -3
- package/pmxt/signers.ts +28 -7
package/dist/pmxt/client.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* OpenAPI client, matching the Python API exactly.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.Mock = exports.Suibets = exports.SuiBets = exports.Hyperliquid = exports.GeminiTitan = exports.PolymarketUS = exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Baozi = exports.Probable = exports.Myriad = exports.KalshiDemo = exports.Limitless = exports.Kalshi = exports.Polymarket = exports.Exchange = void 0;
|
|
9
|
+
exports.Mock = exports.Rain = exports.Suibets = exports.SuiBets = exports.Hyperliquid = exports.GeminiTitan = exports.PolymarketUS = exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Baozi = exports.Probable = exports.Myriad = exports.KalshiDemo = exports.Limitless = exports.Kalshi = exports.Polymarket = exports.Exchange = void 0;
|
|
10
10
|
const index_js_1 = require("../generated/src/index.js");
|
|
11
11
|
const models_js_1 = require("./models.js");
|
|
12
12
|
const server_manager_js_1 = require("./server-manager.js");
|
|
@@ -924,9 +924,6 @@ class Exchange {
|
|
|
924
924
|
}
|
|
925
925
|
}
|
|
926
926
|
async submitOrder(built) {
|
|
927
|
-
if (this.isHostedTradingMode()) {
|
|
928
|
-
return this._hostedSubmitOrder(built);
|
|
929
|
-
}
|
|
930
927
|
await this.initPromise;
|
|
931
928
|
if (this.isHosted) {
|
|
932
929
|
throw new errors_js_1.PmxtError("submitOrder is not available in hosted mode. Use createOrder instead.");
|
|
@@ -956,80 +953,7 @@ class Exchange {
|
|
|
956
953
|
throw new errors_js_1.PmxtError(`Failed to submitOrder: ${error}`);
|
|
957
954
|
}
|
|
958
955
|
}
|
|
959
|
-
/**
|
|
960
|
-
* Hosted-mode submitOrder: validate the stored build response, sign the
|
|
961
|
-
* typed_data (and pull_typed_data for Opinion cross-chain sells), then
|
|
962
|
-
* POST to `/v0/trade/submit-order`.
|
|
963
|
-
*/
|
|
964
|
-
async _hostedSubmitOrder(built) {
|
|
965
|
-
const signer = this.requireHostedSigner();
|
|
966
|
-
if (!this.walletAddress) {
|
|
967
|
-
throw new hosted_errors_js_1.MissingWalletAddress("hosted submitOrder requires walletAddress");
|
|
968
|
-
}
|
|
969
|
-
// BuiltOrder is the SDK-side wrapper around the build response —
|
|
970
|
-
// expect typed_data, optional pull_typed_data, built_order_id, and
|
|
971
|
-
// the originating build_request to be present.
|
|
972
|
-
const payload = built;
|
|
973
|
-
const typedData = payload["typed_data"];
|
|
974
|
-
if (!typedData) {
|
|
975
|
-
throw new hosted_errors_js_1.InvalidSignature(0, "typed_data missing from built order");
|
|
976
|
-
}
|
|
977
|
-
const buildRequest = payload["build_request"]
|
|
978
|
-
?? payload["params"]?.["build_request"];
|
|
979
|
-
const side = String(buildRequest?.["side"] ?? "buy");
|
|
980
|
-
const primaryRoute = this._hostedTypedDataRoute(side, false);
|
|
981
|
-
// Layer 1: schema, Layer 2: economics.
|
|
982
|
-
(0, hosted_typed_data_js_1.validateTypedData)(typedData, primaryRoute, this.walletAddress);
|
|
983
|
-
if (buildRequest) {
|
|
984
|
-
(0, hosted_typed_data_js_1.validateEconomics)(typedData, primaryRoute, buildRequest, payload);
|
|
985
|
-
}
|
|
986
|
-
const signature = await signer.signTypedData(typedData);
|
|
987
|
-
// Layer 3: post-sign recovery + canonical check.
|
|
988
|
-
(0, hosted_typed_data_js_1.verifySignature)(typedData, signature, signer.address);
|
|
989
|
-
const body = {
|
|
990
|
-
built_order_id: payload["built_order_id"],
|
|
991
|
-
signature,
|
|
992
|
-
};
|
|
993
|
-
const pullTypedData = payload["pull_typed_data"];
|
|
994
|
-
if (pullTypedData) {
|
|
995
|
-
const pullRoute = this._hostedTypedDataRoute(side, true);
|
|
996
|
-
if (pullRoute) {
|
|
997
|
-
(0, hosted_typed_data_js_1.validateTypedData)(pullTypedData, pullRoute, this.walletAddress);
|
|
998
|
-
}
|
|
999
|
-
const pullSig = await signer.signTypedData(pullTypedData);
|
|
1000
|
-
(0, hosted_typed_data_js_1.verifySignature)(pullTypedData, pullSig, signer.address);
|
|
1001
|
-
body["pull_signature"] = pullSig;
|
|
1002
|
-
}
|
|
1003
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("submitOrder");
|
|
1004
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path: route.path, body });
|
|
1005
|
-
return (0, hosted_mappers_js_1.orderFromV0)(data);
|
|
1006
|
-
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Resolve the per-(venue, side, pull) typed-data schema route used by
|
|
1009
|
-
* `validateTypedData` / `validateEconomics`. Returns undefined for the
|
|
1010
|
-
* pull leg when a venue/side combo doesn't have one.
|
|
1011
|
-
*/
|
|
1012
|
-
_hostedTypedDataRoute(side, isPull) {
|
|
1013
|
-
const venue = this.exchangeName;
|
|
1014
|
-
const sideLower = side.toLowerCase();
|
|
1015
|
-
if (venue === "polymarket") {
|
|
1016
|
-
return sideLower === "sell" ? "polymarket_sell" : "polymarket_buy";
|
|
1017
|
-
}
|
|
1018
|
-
// opinion
|
|
1019
|
-
if (sideLower === "buy")
|
|
1020
|
-
return "opinion_buy";
|
|
1021
|
-
// sell — polygon, or BSC pull leg for cross-chain
|
|
1022
|
-
return isPull ? "opinion_sell_bsc_pull" : "opinion_sell_polygon";
|
|
1023
|
-
}
|
|
1024
|
-
_hostedCancelTypedDataRoute(isPull) {
|
|
1025
|
-
if (this.exchangeName === "polymarket")
|
|
1026
|
-
return "cancel_polymarket";
|
|
1027
|
-
return isPull ? "cancel_opinion_bsc_pull" : "cancel_opinion_polygon";
|
|
1028
|
-
}
|
|
1029
956
|
async cancelOrder(orderId) {
|
|
1030
|
-
if (this.isHostedTradingMode()) {
|
|
1031
|
-
return this._hostedCancelOrder(orderId);
|
|
1032
|
-
}
|
|
1033
957
|
await this.initPromise;
|
|
1034
958
|
try {
|
|
1035
959
|
const args = [];
|
|
@@ -1056,47 +980,7 @@ class Exchange {
|
|
|
1056
980
|
throw new errors_js_1.PmxtError(`Failed to cancelOrder: ${error}`);
|
|
1057
981
|
}
|
|
1058
982
|
}
|
|
1059
|
-
/**
|
|
1060
|
-
* Hosted-mode cancelOrder: build the cancel typed_data on the server,
|
|
1061
|
-
* validate + sign (dual-sign for Opinion cross-chain), then submit.
|
|
1062
|
-
*/
|
|
1063
|
-
async _hostedCancelOrder(orderId) {
|
|
1064
|
-
const signer = this.requireHostedSigner();
|
|
1065
|
-
if (!this.walletAddress) {
|
|
1066
|
-
throw new hosted_errors_js_1.MissingWalletAddress("hosted cancelOrder requires walletAddress");
|
|
1067
|
-
}
|
|
1068
|
-
const buildRoute = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("cancelOrderBuild");
|
|
1069
|
-
const buildResp = await (0, hosted_routing_js_1._tradingRequest)(this, {
|
|
1070
|
-
method: buildRoute.method,
|
|
1071
|
-
path: buildRoute.path,
|
|
1072
|
-
body: { order_id: orderId },
|
|
1073
|
-
});
|
|
1074
|
-
const typedData = buildResp["typed_data"];
|
|
1075
|
-
if (!typedData) {
|
|
1076
|
-
throw new hosted_errors_js_1.InvalidSignature(0, "typed_data missing from cancel build response");
|
|
1077
|
-
}
|
|
1078
|
-
(0, hosted_typed_data_js_1.validateTypedData)(typedData, this._hostedCancelTypedDataRoute(false), this.walletAddress);
|
|
1079
|
-
const signature = await signer.signTypedData(typedData);
|
|
1080
|
-
(0, hosted_typed_data_js_1.verifySignature)(typedData, signature, signer.address);
|
|
1081
|
-
const body = {
|
|
1082
|
-
cancel_id: buildResp["cancel_id"],
|
|
1083
|
-
signature,
|
|
1084
|
-
};
|
|
1085
|
-
const pullTypedData = buildResp["pull_typed_data"];
|
|
1086
|
-
if (pullTypedData) {
|
|
1087
|
-
(0, hosted_typed_data_js_1.validateTypedData)(pullTypedData, this._hostedCancelTypedDataRoute(true), this.walletAddress);
|
|
1088
|
-
const pullSig = await signer.signTypedData(pullTypedData);
|
|
1089
|
-
(0, hosted_typed_data_js_1.verifySignature)(pullTypedData, pullSig, signer.address);
|
|
1090
|
-
body["pull_signature"] = pullSig;
|
|
1091
|
-
}
|
|
1092
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("cancelOrder");
|
|
1093
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path: route.path, body });
|
|
1094
|
-
return (0, hosted_mappers_js_1.orderFromV0)(data);
|
|
1095
|
-
}
|
|
1096
983
|
async fetchOrder(orderId) {
|
|
1097
|
-
if (this.isHostedTradingMode()) {
|
|
1098
|
-
return this._hostedFetchOrder(orderId);
|
|
1099
|
-
}
|
|
1100
984
|
await this.initPromise;
|
|
1101
985
|
try {
|
|
1102
986
|
const args = [];
|
|
@@ -1123,16 +1007,7 @@ class Exchange {
|
|
|
1123
1007
|
throw new errors_js_1.PmxtError(`Failed to fetchOrder: ${error}`);
|
|
1124
1008
|
}
|
|
1125
1009
|
}
|
|
1126
|
-
async _hostedFetchOrder(orderId) {
|
|
1127
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("fetchOrder");
|
|
1128
|
-
const path = (0, hosted_routing_js_1.formatRoutePath)(route, { order_id: orderId });
|
|
1129
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path });
|
|
1130
|
-
return (0, hosted_mappers_js_1.orderFromV0)(data);
|
|
1131
|
-
}
|
|
1132
1010
|
async fetchOpenOrders(marketId) {
|
|
1133
|
-
if (this.isHostedTradingMode()) {
|
|
1134
|
-
return this._hostedFetchOpenOrders(marketId);
|
|
1135
|
-
}
|
|
1136
1011
|
await this.initPromise;
|
|
1137
1012
|
try {
|
|
1138
1013
|
const args = [];
|
|
@@ -1160,24 +1035,7 @@ class Exchange {
|
|
|
1160
1035
|
throw new errors_js_1.PmxtError(`Failed to fetchOpenOrders: ${error}`);
|
|
1161
1036
|
}
|
|
1162
1037
|
}
|
|
1163
|
-
async _hostedFetchOpenOrders(marketId) {
|
|
1164
|
-
const address = (0, hosted_routing_js_1.resolveWalletAddress)(this, undefined);
|
|
1165
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("fetchOpenOrders");
|
|
1166
|
-
const params = { address };
|
|
1167
|
-
if (marketId !== undefined)
|
|
1168
|
-
params["market_id"] = marketId;
|
|
1169
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, {
|
|
1170
|
-
method: route.method,
|
|
1171
|
-
path: route.path,
|
|
1172
|
-
params,
|
|
1173
|
-
});
|
|
1174
|
-
const items = (Array.isArray(data) ? data : data?.["orders"] ?? []);
|
|
1175
|
-
return items.map(hosted_mappers_js_1.orderFromV0);
|
|
1176
|
-
}
|
|
1177
1038
|
async fetchMyTrades(params) {
|
|
1178
|
-
if (this.isHostedTradingMode()) {
|
|
1179
|
-
return this._hostedFetchMyTrades(params);
|
|
1180
|
-
}
|
|
1181
1039
|
await this.initPromise;
|
|
1182
1040
|
try {
|
|
1183
1041
|
const args = [];
|
|
@@ -1205,35 +1063,7 @@ class Exchange {
|
|
|
1205
1063
|
throw new errors_js_1.PmxtError(`Failed to fetchMyTrades: ${error}`);
|
|
1206
1064
|
}
|
|
1207
1065
|
}
|
|
1208
|
-
async _hostedFetchMyTrades(params) {
|
|
1209
|
-
const address = (0, hosted_routing_js_1.resolveWalletAddress)(this, undefined);
|
|
1210
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("fetchMyTrades");
|
|
1211
|
-
const path = (0, hosted_routing_js_1.formatRoutePath)(route, { address });
|
|
1212
|
-
const q = {};
|
|
1213
|
-
if (params?.marketId)
|
|
1214
|
-
q["market_id"] = params.marketId;
|
|
1215
|
-
if (params?.outcomeId)
|
|
1216
|
-
q["outcome_id"] = params.outcomeId;
|
|
1217
|
-
if (params?.limit !== undefined)
|
|
1218
|
-
q["limit"] = String(params.limit);
|
|
1219
|
-
if (params?.cursor)
|
|
1220
|
-
q["cursor"] = params.cursor;
|
|
1221
|
-
if (params?.since)
|
|
1222
|
-
q["since"] = String(params.since.getTime());
|
|
1223
|
-
if (params?.until)
|
|
1224
|
-
q["until"] = String(params.until.getTime());
|
|
1225
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, {
|
|
1226
|
-
method: route.method,
|
|
1227
|
-
path,
|
|
1228
|
-
params: Object.keys(q).length ? q : undefined,
|
|
1229
|
-
});
|
|
1230
|
-
const items = (Array.isArray(data) ? data : data?.["trades"] ?? []);
|
|
1231
|
-
return items.map(hosted_mappers_js_1.userTradeFromV0);
|
|
1232
|
-
}
|
|
1233
1066
|
async fetchClosedOrders(params) {
|
|
1234
|
-
if (this.isHostedTradingMode()) {
|
|
1235
|
-
throw new errors_js_1.NotSupported("Settled orders are modeled as trades — use fetchMyTrades().");
|
|
1236
|
-
}
|
|
1237
1067
|
await this.initPromise;
|
|
1238
1068
|
try {
|
|
1239
1069
|
const args = [];
|
|
@@ -1262,9 +1092,6 @@ class Exchange {
|
|
|
1262
1092
|
}
|
|
1263
1093
|
}
|
|
1264
1094
|
async fetchAllOrders(params) {
|
|
1265
|
-
if (this.isHostedTradingMode()) {
|
|
1266
|
-
throw new errors_js_1.NotSupported("Use fetchOpenOrders() and fetchMyTrades() separately.");
|
|
1267
|
-
}
|
|
1268
1095
|
await this.initPromise;
|
|
1269
1096
|
try {
|
|
1270
1097
|
const args = [];
|
|
@@ -1293,9 +1120,6 @@ class Exchange {
|
|
|
1293
1120
|
}
|
|
1294
1121
|
}
|
|
1295
1122
|
async fetchPositions(address) {
|
|
1296
|
-
if (this.isHostedTradingMode()) {
|
|
1297
|
-
return this._hostedFetchPositions(address);
|
|
1298
|
-
}
|
|
1299
1123
|
await this.initPromise;
|
|
1300
1124
|
try {
|
|
1301
1125
|
const args = [];
|
|
@@ -1323,18 +1147,7 @@ class Exchange {
|
|
|
1323
1147
|
throw new errors_js_1.PmxtError(`Failed to fetchPositions: ${error}`);
|
|
1324
1148
|
}
|
|
1325
1149
|
}
|
|
1326
|
-
async _hostedFetchPositions(address) {
|
|
1327
|
-
const resolvedAddr = (0, hosted_routing_js_1.resolveWalletAddress)(this, address);
|
|
1328
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("fetchPositions");
|
|
1329
|
-
const path = (0, hosted_routing_js_1.formatRoutePath)(route, { address: resolvedAddr });
|
|
1330
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path });
|
|
1331
|
-
const items = (Array.isArray(data) ? data : data?.["positions"] ?? []);
|
|
1332
|
-
return items.map(hosted_mappers_js_1.positionFromV0);
|
|
1333
|
-
}
|
|
1334
1150
|
async fetchBalance(address) {
|
|
1335
|
-
if (this.isHostedTradingMode()) {
|
|
1336
|
-
return this._hostedFetchBalance(address);
|
|
1337
|
-
}
|
|
1338
1151
|
await this.initPromise;
|
|
1339
1152
|
try {
|
|
1340
1153
|
const args = [];
|
|
@@ -1362,18 +1175,6 @@ class Exchange {
|
|
|
1362
1175
|
throw new errors_js_1.PmxtError(`Failed to fetchBalance: ${error}`);
|
|
1363
1176
|
}
|
|
1364
1177
|
}
|
|
1365
|
-
async _hostedFetchBalance(address) {
|
|
1366
|
-
const resolvedAddr = (0, hosted_routing_js_1.resolveWalletAddress)(this, address);
|
|
1367
|
-
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("fetchBalance");
|
|
1368
|
-
const path = (0, hosted_routing_js_1.formatRoutePath)(route, { address: resolvedAddr });
|
|
1369
|
-
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path });
|
|
1370
|
-
// Hosted balance is a single USDC escrow record; wrap in an array
|
|
1371
|
-
// to match the existing Balance[] return shape.
|
|
1372
|
-
if (Array.isArray(data)) {
|
|
1373
|
-
return data.map(hosted_mappers_js_1.balanceFromV0);
|
|
1374
|
-
}
|
|
1375
|
-
return [(0, hosted_mappers_js_1.balanceFromV0)(data)];
|
|
1376
|
-
}
|
|
1377
1178
|
async unwatchOrderBook(outcomeId) {
|
|
1378
1179
|
await this.initPromise;
|
|
1379
1180
|
try {
|
|
@@ -2082,6 +1883,15 @@ class Exchange {
|
|
|
2082
1883
|
if (params.fee !== undefined) {
|
|
2083
1884
|
paramsDict.fee = params.fee;
|
|
2084
1885
|
}
|
|
1886
|
+
if (params.tickSize !== undefined) {
|
|
1887
|
+
paramsDict.tickSize = params.tickSize;
|
|
1888
|
+
}
|
|
1889
|
+
if (params.negRisk !== undefined) {
|
|
1890
|
+
paramsDict.negRisk = params.negRisk;
|
|
1891
|
+
}
|
|
1892
|
+
if (params.onBehalfOf !== undefined) {
|
|
1893
|
+
paramsDict.onBehalfOf = params.onBehalfOf;
|
|
1894
|
+
}
|
|
2085
1895
|
const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/buildOrder`, {
|
|
2086
1896
|
method: 'POST',
|
|
2087
1897
|
headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
|
|
@@ -2206,6 +2016,81 @@ class Exchange {
|
|
|
2206
2016
|
const built = await this._hostedBuildOrder(params);
|
|
2207
2017
|
return this._hostedSubmitOrder(built);
|
|
2208
2018
|
}
|
|
2019
|
+
/**
|
|
2020
|
+
* Hosted-mode submitOrder: validate the stored build response, sign the
|
|
2021
|
+
* typed_data (and pull_typed_data for cross-chain venue sells), then
|
|
2022
|
+
* POST to `/v0/trade/submit-order`.
|
|
2023
|
+
*
|
|
2024
|
+
* Restored after PR #1058 (Limitless hosted wire-up) accidentally
|
|
2025
|
+
* removed it but left the call site + signing imports intact.
|
|
2026
|
+
*/
|
|
2027
|
+
async _hostedSubmitOrder(built) {
|
|
2028
|
+
const signer = this.requireHostedSigner();
|
|
2029
|
+
if (!this.walletAddress) {
|
|
2030
|
+
throw new hosted_errors_js_1.MissingWalletAddress("hosted submitOrder requires walletAddress");
|
|
2031
|
+
}
|
|
2032
|
+
const payload = built;
|
|
2033
|
+
const typedData = payload["typed_data"];
|
|
2034
|
+
if (!typedData) {
|
|
2035
|
+
throw new hosted_errors_js_1.InvalidSignature(0, "typed_data missing from built order");
|
|
2036
|
+
}
|
|
2037
|
+
const buildRequest = payload["build_request"]
|
|
2038
|
+
?? payload["params"]?.["build_request"];
|
|
2039
|
+
const side = String(buildRequest?.["side"] ?? "buy");
|
|
2040
|
+
const primaryRoute = this._hostedTypedDataRoute(side, false);
|
|
2041
|
+
(0, hosted_typed_data_js_1.validateTypedData)(typedData, primaryRoute, this.walletAddress);
|
|
2042
|
+
if (buildRequest) {
|
|
2043
|
+
(0, hosted_typed_data_js_1.validateEconomics)(typedData, primaryRoute, buildRequest, payload);
|
|
2044
|
+
}
|
|
2045
|
+
const signature = await signer.signTypedData(typedData);
|
|
2046
|
+
(0, hosted_typed_data_js_1.verifySignature)(typedData, signature, signer.address);
|
|
2047
|
+
const body = {
|
|
2048
|
+
built_order_id: payload["built_order_id"],
|
|
2049
|
+
signature,
|
|
2050
|
+
};
|
|
2051
|
+
const pullTypedData = payload["pull_typed_data"];
|
|
2052
|
+
if (pullTypedData) {
|
|
2053
|
+
const pullRoute = this._hostedTypedDataRoute(side, true);
|
|
2054
|
+
if (pullRoute) {
|
|
2055
|
+
(0, hosted_typed_data_js_1.validateTypedData)(pullTypedData, pullRoute, this.walletAddress);
|
|
2056
|
+
}
|
|
2057
|
+
const pullSig = await signer.signTypedData(pullTypedData);
|
|
2058
|
+
(0, hosted_typed_data_js_1.verifySignature)(pullTypedData, pullSig, signer.address);
|
|
2059
|
+
body["pull_signature"] = pullSig;
|
|
2060
|
+
}
|
|
2061
|
+
const route = hosted_routing_js_1.HOSTED_METHOD_ROUTES.get("submitOrder");
|
|
2062
|
+
const data = await (0, hosted_routing_js_1._tradingRequest)(this, { method: route.method, path: route.path, body });
|
|
2063
|
+
return (0, hosted_mappers_js_1.orderFromV0)(data);
|
|
2064
|
+
}
|
|
2065
|
+
/**
|
|
2066
|
+
* Resolve the per-(venue, side, pull) typed-data schema route used by
|
|
2067
|
+
* `validateTypedData` / `validateEconomics`. Returns the cross-chain
|
|
2068
|
+
* pull-leg route name for Opinion sells and Limitless cross-chain orders.
|
|
2069
|
+
*/
|
|
2070
|
+
_hostedTypedDataRoute(side, isPull) {
|
|
2071
|
+
const venue = this.exchangeName;
|
|
2072
|
+
const sideLower = side.toLowerCase();
|
|
2073
|
+
if (venue === "polymarket") {
|
|
2074
|
+
return sideLower === "sell" ? "polymarket_sell" : "polymarket_buy";
|
|
2075
|
+
}
|
|
2076
|
+
if (venue === "limitless") {
|
|
2077
|
+
if (sideLower === "buy")
|
|
2078
|
+
return "limitless_buy";
|
|
2079
|
+
return isPull ? "limitless_sell_base_pull" : "limitless_sell_polygon";
|
|
2080
|
+
}
|
|
2081
|
+
// opinion
|
|
2082
|
+
if (sideLower === "buy")
|
|
2083
|
+
return "opinion_buy";
|
|
2084
|
+
return isPull ? "opinion_sell_bsc_pull" : "opinion_sell_polygon";
|
|
2085
|
+
}
|
|
2086
|
+
_hostedCancelTypedDataRoute(isPull) {
|
|
2087
|
+
const venue = this.exchangeName;
|
|
2088
|
+
if (venue === "polymarket")
|
|
2089
|
+
return "cancel_polymarket";
|
|
2090
|
+
if (venue === "limitless")
|
|
2091
|
+
return isPull ? "cancel_limitless_base_pull" : "cancel_limitless_polygon";
|
|
2092
|
+
return isPull ? "cancel_opinion_bsc_pull" : "cancel_opinion_polygon";
|
|
2093
|
+
}
|
|
2209
2094
|
/**
|
|
2210
2095
|
* Construct the hosted build-order request body and validate inputs
|
|
2211
2096
|
* locally per the v0 contract (denom/side compatibility, > 6-decimal
|
|
@@ -2363,6 +2248,15 @@ class Exchange {
|
|
|
2363
2248
|
if (params.fee !== undefined) {
|
|
2364
2249
|
paramsDict.fee = params.fee;
|
|
2365
2250
|
}
|
|
2251
|
+
if (params.tickSize !== undefined) {
|
|
2252
|
+
paramsDict.tickSize = params.tickSize;
|
|
2253
|
+
}
|
|
2254
|
+
if (params.negRisk !== undefined) {
|
|
2255
|
+
paramsDict.negRisk = params.negRisk;
|
|
2256
|
+
}
|
|
2257
|
+
if (params.onBehalfOf !== undefined) {
|
|
2258
|
+
paramsDict.onBehalfOf = params.onBehalfOf;
|
|
2259
|
+
}
|
|
2366
2260
|
const response = await this.fetchWithRetry(`${this.resolveBaseUrl()}/api/${this.exchangeName}/createOrder`, {
|
|
2367
2261
|
method: 'POST',
|
|
2368
2262
|
headers: { 'Content-Type': 'application/json', ...this.getAuthHeaders() },
|
|
@@ -3014,6 +2908,28 @@ class SuiBets extends Exchange {
|
|
|
3014
2908
|
exports.SuiBets = SuiBets;
|
|
3015
2909
|
// Backwards-compatible casing alias matching the Python SDK export.
|
|
3016
2910
|
exports.Suibets = SuiBets;
|
|
2911
|
+
/**
|
|
2912
|
+
* Rain exchange client.
|
|
2913
|
+
*
|
|
2914
|
+
* Rain is a permissionless AMM-plus-orderbook prediction market on Arbitrum One.
|
|
2915
|
+
* Reads are unauthenticated; trading requires an EVM privateKey.
|
|
2916
|
+
*
|
|
2917
|
+
* @example
|
|
2918
|
+
* ```typescript
|
|
2919
|
+
* const rain = new Rain();
|
|
2920
|
+
* const markets = await rain.fetchMarkets({ limit: 20 });
|
|
2921
|
+
*
|
|
2922
|
+
* // With wallet for trading
|
|
2923
|
+
* const me = new Rain({ privateKey: '0x...' });
|
|
2924
|
+
* await me.createOrder({ marketId, outcomeId, side: 'buy', type: 'market', amount: 10 });
|
|
2925
|
+
* ```
|
|
2926
|
+
*/
|
|
2927
|
+
class Rain extends Exchange {
|
|
2928
|
+
constructor(options = {}) {
|
|
2929
|
+
super("rain", options);
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
exports.Rain = Rain;
|
|
3017
2933
|
/**
|
|
3018
2934
|
* Mock exchange client.
|
|
3019
2935
|
*
|
package/dist/pmxt/constants.d.ts
CHANGED
|
@@ -62,3 +62,7 @@ export declare const PREFUNDED_ESCROW_ADDRESSES: ReadonlySet<string>;
|
|
|
62
62
|
* as venue-owned escrows. Currently empty; populated as venues onboard.
|
|
63
63
|
*/
|
|
64
64
|
export declare const VENUE_ESCROW_ADDRESSES: ReadonlySet<string>;
|
|
65
|
+
/**
|
|
66
|
+
* Limitless VenueEscrow contract addresses on Base (chain 8453).
|
|
67
|
+
*/
|
|
68
|
+
export declare const LIMITLESS_VENUE_ESCROW_ADDRESSES: ReadonlySet<string>;
|
package/dist/pmxt/constants.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* can be imported from any module without creating import cycles.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.VENUE_ESCROW_ADDRESSES = exports.PREFUNDED_ESCROW_ADDRESSES = exports.ENV = exports.LOCAL_URL = exports.HOSTED_URL = void 0;
|
|
9
|
+
exports.LIMITLESS_VENUE_ESCROW_ADDRESSES = exports.VENUE_ESCROW_ADDRESSES = exports.PREFUNDED_ESCROW_ADDRESSES = exports.ENV = exports.LOCAL_URL = exports.HOSTED_URL = void 0;
|
|
10
10
|
exports.resolvePmxtBaseUrl = resolvePmxtBaseUrl;
|
|
11
11
|
/**
|
|
12
12
|
* The hosted pmxt production endpoint.
|
|
@@ -75,3 +75,9 @@ exports.PREFUNDED_ESCROW_ADDRESSES = new Set([
|
|
|
75
75
|
* as venue-owned escrows. Currently empty; populated as venues onboard.
|
|
76
76
|
*/
|
|
77
77
|
exports.VENUE_ESCROW_ADDRESSES = new Set();
|
|
78
|
+
/**
|
|
79
|
+
* Limitless VenueEscrow contract addresses on Base (chain 8453).
|
|
80
|
+
*/
|
|
81
|
+
exports.LIMITLESS_VENUE_ESCROW_ADDRESSES = new Set([
|
|
82
|
+
"0x34c42d01aad6ded00f1a6830d90b0e9204db7855",
|
|
83
|
+
]);
|
|
@@ -26,6 +26,7 @@ exports.HOSTED_TRADING_BASE_URL = "https://trade.pmxt.dev";
|
|
|
26
26
|
exports.HOSTED_TRADING_VENUES = new Set([
|
|
27
27
|
"polymarket",
|
|
28
28
|
"opinion",
|
|
29
|
+
"limitless",
|
|
29
30
|
]);
|
|
30
31
|
exports.HOSTED_METHOD_ROUTES = new Map([
|
|
31
32
|
["createOrder", { method: "POST", path: "/v0/trade/build-order", base: "trading" }],
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Layer 3 uses the optional `ethers` peer dependency for typed-data verification.
|
|
10
10
|
*/
|
|
11
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";
|
|
12
|
+
export type HostedRoute = "polymarket_buy" | "polymarket_sell" | "limitless_buy" | "limitless_sell_polygon" | "limitless_sell_base_pull" | "opinion_buy" | "opinion_sell_polygon" | "opinion_sell_bsc_pull" | "cancel_polymarket" | "cancel_opinion_polygon" | "cancel_opinion_bsc_pull";
|
|
13
13
|
export declare const SECP256K1_HALF_N = 57896044618658097711785492504343953926418782139537452191302581570759080747168n;
|
|
14
14
|
/**
|
|
15
15
|
* Validate the structural shape of a typed-data payload before signing.
|
|
@@ -49,6 +49,7 @@ exports.validateEconomics = validateEconomics;
|
|
|
49
49
|
exports.verifySignature = verifySignature;
|
|
50
50
|
const hosted_errors_1 = require("./hosted-errors");
|
|
51
51
|
const hosted_mappers_1 = require("./hosted-mappers");
|
|
52
|
+
const signers_1 = require("./signers");
|
|
52
53
|
// The constants module is updated in a parallel-agent change to add these
|
|
53
54
|
// allowlists. We import them at runtime so we don't hard-fail if the change
|
|
54
55
|
// hasn't landed yet (the imports are typed below).
|
|
@@ -126,6 +127,12 @@ const VENUE_DOMAIN = {
|
|
|
126
127
|
chainId: 56,
|
|
127
128
|
allowlistKey: "venue",
|
|
128
129
|
};
|
|
130
|
+
const LIMITLESS_VENUE_DOMAIN = {
|
|
131
|
+
name: "VenueEscrow",
|
|
132
|
+
version: "1",
|
|
133
|
+
chainId: 8453,
|
|
134
|
+
allowlistKey: "venue",
|
|
135
|
+
};
|
|
129
136
|
const SCHEMAS = {
|
|
130
137
|
polymarket_buy: {
|
|
131
138
|
primaryType: "OrderParams",
|
|
@@ -134,6 +141,27 @@ const SCHEMAS = {
|
|
|
134
141
|
messageKeys: messageKeysFromFields(ORDER_PARAMS_FIELDS),
|
|
135
142
|
walletField: "user",
|
|
136
143
|
},
|
|
144
|
+
limitless_buy: {
|
|
145
|
+
primaryType: "CrossChainOrderParams",
|
|
146
|
+
domain: PREFUNDED_DOMAIN,
|
|
147
|
+
fields: CROSS_CHAIN_ORDER_PARAMS_FIELDS,
|
|
148
|
+
messageKeys: messageKeysFromFields(CROSS_CHAIN_ORDER_PARAMS_FIELDS),
|
|
149
|
+
walletField: "user",
|
|
150
|
+
},
|
|
151
|
+
limitless_sell_polygon: {
|
|
152
|
+
primaryType: "CrossChainSellPayParams",
|
|
153
|
+
domain: PREFUNDED_DOMAIN,
|
|
154
|
+
fields: CROSS_CHAIN_SELL_PAY_PARAMS_FIELDS,
|
|
155
|
+
messageKeys: messageKeysFromFields(CROSS_CHAIN_SELL_PAY_PARAMS_FIELDS),
|
|
156
|
+
walletField: "user",
|
|
157
|
+
},
|
|
158
|
+
limitless_sell_base_pull: {
|
|
159
|
+
primaryType: "CrossChainSellPullParams",
|
|
160
|
+
domain: LIMITLESS_VENUE_DOMAIN,
|
|
161
|
+
fields: CROSS_CHAIN_SELL_PULL_PARAMS_FIELDS,
|
|
162
|
+
messageKeys: messageKeysFromFields(CROSS_CHAIN_SELL_PULL_PARAMS_FIELDS),
|
|
163
|
+
walletField: "user",
|
|
164
|
+
},
|
|
137
165
|
polymarket_sell: {
|
|
138
166
|
primaryType: "SellOrderParams",
|
|
139
167
|
domain: PREFUNDED_DOMAIN,
|
|
@@ -382,14 +410,26 @@ function validateWorstPrice(message, route, buildRequest, buildResponse) {
|
|
|
382
410
|
}
|
|
383
411
|
}
|
|
384
412
|
function validateOpinionMarketId(message, buildResponse) {
|
|
385
|
-
|
|
386
|
-
|
|
413
|
+
// The current trading-API Opinion message schema does not embed
|
|
414
|
+
// opinion_market_id — the signed economic identity is the outcome
|
|
415
|
+
// tokenId. Validate that against the build response's resolved token.
|
|
416
|
+
// The legacy opinion_market_id check only applies when the message
|
|
417
|
+
// actually carries the field (older API versions).
|
|
418
|
+
const expectedToken = firstPresent(getPath(buildResponse, "resolved", "token_id"), getPath(buildResponse, "resolved", "tokenId"), getField(buildResponse, "token_id"), getField(buildResponse, "tokenId"));
|
|
419
|
+
const actualToken = firstPresent(getField(message, "tokenId"), getField(message, "token_id"));
|
|
420
|
+
if (actualToken === MISSING)
|
|
421
|
+
economicFail("message.tokenId missing");
|
|
422
|
+
if (expectedToken !== MISSING && idValue(actualToken) !== idValue(expectedToken)) {
|
|
423
|
+
economicFail(`tokenId expected ${expectedToken} got ${actualToken}`);
|
|
424
|
+
}
|
|
425
|
+
const actualMarketId = firstPresent(getField(message, "opinion_market_id"), getField(message, "opinionMarketId"));
|
|
426
|
+
if (actualMarketId === MISSING)
|
|
427
|
+
return; // current schema: tokenId-only message
|
|
428
|
+
const expectedMarketId = firstPresent(getPath(buildResponse, "resolved", "opinion_market_id"), getPath(buildResponse, "resolved", "opinionMarketId"), getField(buildResponse, "opinion_market_id"), getField(buildResponse, "opinionMarketId"), getPath(buildResponse, "params", "opinion_market_id"), getPath(buildResponse, "params", "opinionMarketId"));
|
|
429
|
+
if (expectedMarketId === MISSING)
|
|
387
430
|
economicFail("resolved.opinion_market_id missing");
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
economicFail("message.opinion_market_id missing");
|
|
391
|
-
if (idValue(actual) !== idValue(expected)) {
|
|
392
|
-
economicFail(`opinion_market_id expected ${expected} got ${actual}`);
|
|
431
|
+
if (idValue(actualMarketId) !== idValue(expectedMarketId)) {
|
|
432
|
+
economicFail(`opinion_market_id expected ${expectedMarketId} got ${actualMarketId}`);
|
|
393
433
|
}
|
|
394
434
|
}
|
|
395
435
|
// ---------------------------------------------------------------------------
|
|
@@ -427,11 +467,10 @@ function verifySignature(typedData, signature, walletAddress) {
|
|
|
427
467
|
}
|
|
428
468
|
let ethers;
|
|
429
469
|
try {
|
|
430
|
-
|
|
431
|
-
ethers = require("ethers");
|
|
470
|
+
ethers = (0, signers_1.loadEthers)("ethers is required for hosted signature verification");
|
|
432
471
|
}
|
|
433
|
-
catch {
|
|
434
|
-
throw new hosted_errors_1.InvalidSignature(0, "ethers is required for hosted signature verification");
|
|
472
|
+
catch (err) {
|
|
473
|
+
throw new hosted_errors_1.InvalidSignature(0, err instanceof Error ? err.message : "ethers is required for hosted signature verification");
|
|
435
474
|
}
|
|
436
475
|
let recovered;
|
|
437
476
|
try {
|
|
@@ -514,7 +553,9 @@ function addressesEqual(left, right) {
|
|
|
514
553
|
function allowedAddresses(key, chainId) {
|
|
515
554
|
const raw = key === "prefunded"
|
|
516
555
|
? constants.PREFUNDED_ESCROW_ADDRESSES
|
|
517
|
-
:
|
|
556
|
+
: chainId === 8453
|
|
557
|
+
? constants.LIMITLESS_VENUE_ESCROW_ADDRESSES
|
|
558
|
+
: constants.VENUE_ESCROW_ADDRESSES;
|
|
518
559
|
const list = [];
|
|
519
560
|
if (raw == null) {
|
|
520
561
|
// empty
|
package/dist/pmxt/models.d.ts
CHANGED
|
@@ -773,6 +773,7 @@ export interface FetchMatchedMarketClustersParams extends MatchedClusterFilterPa
|
|
|
773
773
|
/** Anchor the response to a specific market URL. */
|
|
774
774
|
url?: string;
|
|
775
775
|
}
|
|
776
|
+
export type MatchedMarketClusterParams = FetchMatchedMarketClustersParams;
|
|
776
777
|
/** Parameters for fetching matched event clusters. */
|
|
777
778
|
export interface FetchMatchedEventClustersParams extends MatchedClusterFilterParams {
|
|
778
779
|
/** Pass a UnifiedEvent directly instead of eventId/slug/url. */
|
package/dist/pmxt/router.js
CHANGED
|
@@ -42,6 +42,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
42
42
|
exports.Router = void 0;
|
|
43
43
|
const client_js_1 = require("./client.js");
|
|
44
44
|
const logger_js_1 = require("./logger.js");
|
|
45
|
+
function withQuestionAlias(market) {
|
|
46
|
+
Object.defineProperty(market, 'question', {
|
|
47
|
+
get() { return this.title; },
|
|
48
|
+
enumerable: false,
|
|
49
|
+
configurable: true,
|
|
50
|
+
});
|
|
51
|
+
return market;
|
|
52
|
+
}
|
|
45
53
|
function convertMarket(raw) {
|
|
46
54
|
const outcomes = (raw.outcomes || []).map((o) => ({
|
|
47
55
|
outcomeId: o.outcomeId,
|
|
@@ -63,7 +71,7 @@ function convertMarket(raw) {
|
|
|
63
71
|
bestAsk: o.bestAsk,
|
|
64
72
|
metadata: o.metadata,
|
|
65
73
|
}) : undefined;
|
|
66
|
-
return {
|
|
74
|
+
return withQuestionAlias({
|
|
67
75
|
marketId: raw.marketId,
|
|
68
76
|
title: raw.title,
|
|
69
77
|
slug: raw.slug,
|
|
@@ -87,7 +95,7 @@ function convertMarket(raw) {
|
|
|
87
95
|
no: convertOutcome(raw.no),
|
|
88
96
|
up: convertOutcome(raw.up),
|
|
89
97
|
down: convertOutcome(raw.down),
|
|
90
|
-
};
|
|
98
|
+
});
|
|
91
99
|
}
|
|
92
100
|
function convertEvent(raw) {
|
|
93
101
|
return {
|
|
@@ -108,7 +116,7 @@ function convertEvent(raw) {
|
|
|
108
116
|
function parseMatchResult(raw) {
|
|
109
117
|
const marketData = raw.market || {};
|
|
110
118
|
const market = convertMarket(marketData);
|
|
111
|
-
|
|
119
|
+
const result = {
|
|
112
120
|
...market,
|
|
113
121
|
market,
|
|
114
122
|
relation: raw.relation || 'identity',
|
|
@@ -118,6 +126,7 @@ function parseMatchResult(raw) {
|
|
|
118
126
|
bestAsk: raw.bestAsk ?? marketData.bestAsk,
|
|
119
127
|
sourceMarket: raw.sourceMarket ? convertMarket(raw.sourceMarket) : undefined,
|
|
120
128
|
};
|
|
129
|
+
return withQuestionAlias(result);
|
|
121
130
|
}
|
|
122
131
|
function normalizeQueryValue(value) {
|
|
123
132
|
if (value instanceof Date)
|
package/dist/pmxt/signers.d.ts
CHANGED
|
@@ -35,6 +35,13 @@ export interface Signer {
|
|
|
35
35
|
readonly address: string;
|
|
36
36
|
signTypedData(typedData: TypedData): Promise<string>;
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Load ethers lazily in BOTH module systems. The CJS build has native
|
|
40
|
+
* `require`; the ESM build does not — bare `require("ethers")` there threw
|
|
41
|
+
* ReferenceError, which callers swallowed, silently dropping the signer and
|
|
42
|
+
* killing every hosted write with "hosted write requires a signer".
|
|
43
|
+
*/
|
|
44
|
+
export declare function loadEthers(installHint?: string): any;
|
|
38
45
|
/**
|
|
39
46
|
* Built-in signer backed by an ethers `Wallet`.
|
|
40
47
|
*
|