@rhea-finance/cross-chain-aggregation-dex 2.0.4 → 2.0.6
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/README.md +207 -77
- package/dist/executors/aptos.d.mts +1 -1
- package/dist/executors/aptos.d.ts +1 -1
- package/dist/executors/aptos.js.map +1 -1
- package/dist/executors/aptos.mjs.map +1 -1
- package/dist/executors/bitcoin.d.mts +1 -1
- package/dist/executors/bitcoin.d.ts +1 -1
- package/dist/executors/bitcoin.js.map +1 -1
- package/dist/executors/bitcoin.mjs.map +1 -1
- package/dist/executors/evm.d.mts +1 -1
- package/dist/executors/evm.d.ts +1 -1
- package/dist/executors/evm.js.map +1 -1
- package/dist/executors/evm.mjs.map +1 -1
- package/dist/executors/near.d.mts +1 -1
- package/dist/executors/near.d.ts +1 -1
- package/dist/executors/near.js.map +1 -1
- package/dist/executors/near.mjs.map +1 -1
- package/dist/executors/solana.d.mts +1 -1
- package/dist/executors/solana.d.ts +1 -1
- package/dist/executors/solana.js.map +1 -1
- package/dist/executors/solana.mjs.map +1 -1
- package/dist/executors/sui.d.mts +1 -1
- package/dist/executors/sui.d.ts +1 -1
- package/dist/executors/sui.js.map +1 -1
- package/dist/executors/sui.mjs.map +1 -1
- package/dist/executors/tron.d.mts +1 -1
- package/dist/executors/tron.d.ts +1 -1
- package/dist/executors/tron.js.map +1 -1
- package/dist/executors/tron.mjs.map +1 -1
- package/dist/executors/zcash.d.mts +1 -1
- package/dist/executors/zcash.d.ts +1 -1
- package/dist/executors/zcash.js.map +1 -1
- package/dist/executors/zcash.mjs.map +1 -1
- package/dist/index.d.mts +82 -6
- package/dist/index.d.ts +82 -6
- package/dist/index.js +454 -71
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +451 -72
- package/dist/index.mjs.map +1 -1
- package/dist/{shared-D0_DbMT2.d.mts → shared-COkGiqaz.d.mts} +84 -2
- package/dist/{shared-D0_DbMT2.d.ts → shared-COkGiqaz.d.ts} +84 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -97,14 +97,49 @@ var ApiClient = class {
|
|
|
97
97
|
retryableOperation: true,
|
|
98
98
|
query: {
|
|
99
99
|
sender: params.sender,
|
|
100
|
+
mode: params.mode,
|
|
100
101
|
pageNumber: params.pageNumber,
|
|
101
102
|
pageSize: params.pageSize
|
|
102
|
-
}
|
|
103
|
+
},
|
|
104
|
+
...params.mode === "confidential" && params.walletToken ? { authenticationToken: params.walletToken } : {}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
createHistoryAuthChallenge(body, options = {}) {
|
|
108
|
+
return this.request("/api/swap/history/auth/challenge", "history", {
|
|
109
|
+
...options,
|
|
110
|
+
method: "POST",
|
|
111
|
+
body
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
verifyHistoryAuthChallenge(body, options = {}) {
|
|
115
|
+
return this.request("/api/swap/history/auth/verify", "history", {
|
|
116
|
+
...options,
|
|
117
|
+
method: "POST",
|
|
118
|
+
body
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
getFromTokenRows(chainId, options = {}) {
|
|
122
|
+
return this.request("/get_chain_prices", "tokens", {
|
|
123
|
+
...options,
|
|
124
|
+
method: "GET",
|
|
125
|
+
retryableOperation: true,
|
|
126
|
+
query: { chain: chainId }
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
getCrossChainToTokenRows(chainId, options = {}) {
|
|
130
|
+
return this.request("/api/swap/supported_to_tokens", "tokens", {
|
|
131
|
+
...options,
|
|
132
|
+
method: "GET",
|
|
133
|
+
retryableOperation: true,
|
|
134
|
+
query: { chain: chainId }
|
|
103
135
|
});
|
|
104
136
|
}
|
|
105
137
|
async request(path, stage, options) {
|
|
106
138
|
const url = this.buildUrl(path, options.query);
|
|
107
|
-
const headers = await this.buildHeaders(
|
|
139
|
+
const headers = await this.buildHeaders(
|
|
140
|
+
options.idempotencyKey,
|
|
141
|
+
options.authenticationToken
|
|
142
|
+
);
|
|
108
143
|
const retry = this.retryConfig();
|
|
109
144
|
let attempt = 1;
|
|
110
145
|
for (; ; ) {
|
|
@@ -256,12 +291,13 @@ var ApiClient = class {
|
|
|
256
291
|
const suffix = search.toString();
|
|
257
292
|
return suffix ? `${this.baseUrl}${path}?${suffix}` : `${this.baseUrl}${path}`;
|
|
258
293
|
}
|
|
259
|
-
async buildHeaders(idempotencyKey) {
|
|
294
|
+
async buildHeaders(idempotencyKey, authenticationToken) {
|
|
260
295
|
const configured = typeof this.config.headers === "function" ? await this.config.headers() : this.config.headers ?? {};
|
|
261
296
|
const token = this.config.getAccessToken ? await this.config.getAccessToken() : this.config.apiKey;
|
|
262
297
|
return {
|
|
263
298
|
"Content-Type": "application/json",
|
|
264
299
|
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
300
|
+
...authenticationToken ? { Authentication: `Bearer ${authenticationToken}` } : {},
|
|
265
301
|
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {},
|
|
266
302
|
...configured
|
|
267
303
|
};
|
|
@@ -637,7 +673,7 @@ function normalizeBuild(raw, executionId = createExecutionId(), request) {
|
|
|
637
673
|
const lane = laneFromChainType(common.chainType, fromChain);
|
|
638
674
|
assertLaneMatchesChain(lane, fromChain);
|
|
639
675
|
const execution = normalizeExecution(raw, lane, fromChain);
|
|
640
|
-
const order = normalizeOrder(raw, execution);
|
|
676
|
+
const order = normalizeOrder(raw, execution, request);
|
|
641
677
|
const deposit = normalizeDeposit(raw.deposit);
|
|
642
678
|
return {
|
|
643
679
|
executionId,
|
|
@@ -868,11 +904,12 @@ function assertKind(actual, allowed) {
|
|
|
868
904
|
);
|
|
869
905
|
}
|
|
870
906
|
}
|
|
871
|
-
function normalizeOrder(raw, execution) {
|
|
907
|
+
function normalizeOrder(raw, execution, request) {
|
|
872
908
|
const depositOrderId = readRecordString(raw.deposit, "orderId");
|
|
873
|
-
const orderId = raw.orderId ?? depositOrderId;
|
|
874
|
-
if (!orderId) return void 0;
|
|
875
909
|
const router = raw.statusRouter ?? (execution.kind === "evm-signature" ? execution.request.router : void 0) ?? raw.router;
|
|
910
|
+
const confidentialNearIntentsStatusKey = request?.confidentiality === "basic" && router.toLowerCase().includes("nearintents") ? readRecordString(raw.deposit, "depositAddress") : void 0;
|
|
911
|
+
const orderId = raw.orderId ?? depositOrderId ?? confidentialNearIntentsStatusKey;
|
|
912
|
+
if (!orderId) return void 0;
|
|
876
913
|
const chainId = execution.kind === "evm-signature" ? String(execution.request.chainId) : execution.kind === "evm-transaction" ? String(execution.tx.chainId) : void 0;
|
|
877
914
|
return { orderId, router, ...chainId ? { chainId } : {} };
|
|
878
915
|
}
|
|
@@ -932,6 +969,8 @@ function assertBaseUnitAmount(value) {
|
|
|
932
969
|
|
|
933
970
|
// src/normalizers/quote.ts
|
|
934
971
|
var DEFAULT_QUOTE_WAITING_TIME_MS = 3e3;
|
|
972
|
+
var DEFAULT_SAME_CHAIN_TIMEOUT_MS = 500;
|
|
973
|
+
var DEFAULT_CROSS_CHAIN_TIMEOUT_MS = 3e3;
|
|
935
974
|
function serializeQuoteRequest(request) {
|
|
936
975
|
validateQuoteRequest(request);
|
|
937
976
|
return {
|
|
@@ -943,6 +982,9 @@ function serializeQuoteRequest(request) {
|
|
|
943
982
|
amountIn: request.amountIn,
|
|
944
983
|
slippage: request.slippageBps,
|
|
945
984
|
quoteWaitingTimeMs: request.quoteWaitingTimeMs ?? DEFAULT_QUOTE_WAITING_TIME_MS,
|
|
985
|
+
sameChainTimeoutMs: request.sameChainTimeoutMs ?? DEFAULT_SAME_CHAIN_TIMEOUT_MS,
|
|
986
|
+
crossChainTimeoutMs: request.crossChainTimeoutMs ?? DEFAULT_CROSS_CHAIN_TIMEOUT_MS,
|
|
987
|
+
...request.confidentiality ? { confidentiality: request.confidentiality } : {},
|
|
946
988
|
sender: request.sender.trim(),
|
|
947
989
|
...request.recipient?.trim() ? { recipient: request.recipient.trim() } : {}
|
|
948
990
|
};
|
|
@@ -953,7 +995,11 @@ function normalizeQuote(request, raw, receivedAt = Date.now()) {
|
|
|
953
995
|
throw invalidQuote("Quote response does not contain a valid best route");
|
|
954
996
|
}
|
|
955
997
|
const quoteId = readOptionalString(raw.bestQuote.quoteId);
|
|
956
|
-
const apiRequest =
|
|
998
|
+
const apiRequest = { ...serializeQuoteRequest(request) };
|
|
999
|
+
delete apiRequest.quoteWaitingTimeMs;
|
|
1000
|
+
delete apiRequest.sameChainTimeoutMs;
|
|
1001
|
+
delete apiRequest.crossChainTimeoutMs;
|
|
1002
|
+
Object.freeze(apiRequest);
|
|
957
1003
|
const buildContext = Object.freeze({
|
|
958
1004
|
request: apiRequest,
|
|
959
1005
|
router: bestRoute.router,
|
|
@@ -1021,6 +1067,14 @@ function validateQuoteRequest(request) {
|
|
|
1021
1067
|
"quoteWaitingTimeMs must be a non-negative integer"
|
|
1022
1068
|
);
|
|
1023
1069
|
}
|
|
1070
|
+
validateQuoteTimingParameter(
|
|
1071
|
+
request.sameChainTimeoutMs,
|
|
1072
|
+
"sameChainTimeoutMs"
|
|
1073
|
+
);
|
|
1074
|
+
validateQuoteTimingParameter(
|
|
1075
|
+
request.crossChainTimeoutMs,
|
|
1076
|
+
"crossChainTimeoutMs"
|
|
1077
|
+
);
|
|
1024
1078
|
if (!request.sender.trim()) {
|
|
1025
1079
|
throw new SwapSdkError(
|
|
1026
1080
|
"INVALID_REQUEST",
|
|
@@ -1043,6 +1097,15 @@ function validateQuoteRequest(request) {
|
|
|
1043
1097
|
);
|
|
1044
1098
|
}
|
|
1045
1099
|
}
|
|
1100
|
+
function validateQuoteTimingParameter(value, field) {
|
|
1101
|
+
if (value !== void 0 && (!Number.isFinite(value) || !Number.isInteger(value) || value < 0)) {
|
|
1102
|
+
throw new SwapSdkError(
|
|
1103
|
+
"INVALID_REQUEST",
|
|
1104
|
+
"quote",
|
|
1105
|
+
`${field} must be a non-negative integer`
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1046
1109
|
function normalizeRoute(raw, required) {
|
|
1047
1110
|
const router = readOptionalString(raw.router);
|
|
1048
1111
|
const amountOutValue = raw.amountOut ?? raw.estimatedOut;
|
|
@@ -1215,6 +1278,243 @@ function normalizeTimestamp(value) {
|
|
|
1215
1278
|
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
1216
1279
|
}
|
|
1217
1280
|
|
|
1281
|
+
// src/normalizers/tokens.ts
|
|
1282
|
+
var TOKEN_LIST_CHAIN_METADATA = /* @__PURE__ */ new Map([
|
|
1283
|
+
[1, { chain: "1", blockchain: "eth" }],
|
|
1284
|
+
[10, { chain: "10", blockchain: "op" }],
|
|
1285
|
+
[43114, { chain: "43114", blockchain: "avax" }],
|
|
1286
|
+
[4663, { chain: "4663", blockchain: "robinhood" }],
|
|
1287
|
+
[747474, { chain: "747474", blockchain: "katana" }],
|
|
1288
|
+
[146, { chain: "146", blockchain: "sonic" }],
|
|
1289
|
+
[130, { chain: "130", blockchain: "unichain" }],
|
|
1290
|
+
[1672, { chain: "1672", blockchain: "pharos" }],
|
|
1291
|
+
[4217, { chain: "4217", blockchain: "tempo" }],
|
|
1292
|
+
[56, { chain: "56", blockchain: "bsc" }],
|
|
1293
|
+
[100, { chain: "100", blockchain: "gnosis" }],
|
|
1294
|
+
[137, { chain: "137", blockchain: "pol" }],
|
|
1295
|
+
[143, { chain: "143", blockchain: "monad" }],
|
|
1296
|
+
[196, { chain: "196", blockchain: "xlayer" }],
|
|
1297
|
+
[8453, { chain: "8453", blockchain: "base" }],
|
|
1298
|
+
[9745, { chain: "9745", blockchain: "plasma" }],
|
|
1299
|
+
[42161, { chain: "42161", blockchain: "arb" }],
|
|
1300
|
+
[80094, { chain: "80094", blockchain: "bera" }],
|
|
1301
|
+
[195, { chain: "tron", blockchain: "tron" }],
|
|
1302
|
+
[501, { chain: "solana", blockchain: "sol" }],
|
|
1303
|
+
[784, { chain: "sui", blockchain: "sui" }],
|
|
1304
|
+
[900001, { chain: "near", blockchain: "near" }],
|
|
1305
|
+
[900002, { chain: "btc", blockchain: "btc" }],
|
|
1306
|
+
[900010, { chain: "zcash", blockchain: "zec" }],
|
|
1307
|
+
[900012, { chain: "aptos", blockchain: "aptos" }]
|
|
1308
|
+
]);
|
|
1309
|
+
function normalizeFromTokenList(raw, chainId) {
|
|
1310
|
+
if (!isRecord2(raw) || Array.isArray(raw)) {
|
|
1311
|
+
throw invalidTokenList("From-token response data must be an object");
|
|
1312
|
+
}
|
|
1313
|
+
return normalizeRows(Object.values(raw), chainId);
|
|
1314
|
+
}
|
|
1315
|
+
function normalizeCrossChainToTokenList(raw, chainId) {
|
|
1316
|
+
if (!isRecord2(raw) || !Array.isArray(raw.tokens)) {
|
|
1317
|
+
throw invalidTokenList(
|
|
1318
|
+
"Cross-chain to-token response data must contain a tokens array"
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
return normalizeRows(raw.tokens, chainId);
|
|
1322
|
+
}
|
|
1323
|
+
function normalizeRows(rows, chainId) {
|
|
1324
|
+
const tokens = rows.map((row) => normalizeRow(row, chainId)).filter((token) => token !== void 0);
|
|
1325
|
+
if (rows.length > 0 && tokens.length === 0) {
|
|
1326
|
+
throw invalidTokenList("Token-list response contains no valid token rows");
|
|
1327
|
+
}
|
|
1328
|
+
return tokens;
|
|
1329
|
+
}
|
|
1330
|
+
function normalizeRow(value, chainId) {
|
|
1331
|
+
if (!isRecord2(value)) return void 0;
|
|
1332
|
+
const row = value;
|
|
1333
|
+
const assetId = readString(row.assetId) ?? readString(row.address) ?? readString(row.contractAddress) ?? readString(row.coinType);
|
|
1334
|
+
const symbol = readString(row.symbol);
|
|
1335
|
+
const decimals = readDecimals(row.decimals);
|
|
1336
|
+
if (!assetId || !symbol || decimals === void 0) return void 0;
|
|
1337
|
+
const metadata = TOKEN_LIST_CHAIN_METADATA.get(chainId);
|
|
1338
|
+
const chain = metadata?.chain ?? String(chainId);
|
|
1339
|
+
const blockchain = readString(row.blockchain)?.toLowerCase() ?? metadata?.blockchain ?? String(chainId);
|
|
1340
|
+
const rawAddress = readString(row.contractAddress) ?? readString(row.address) ?? readString(row.coinType);
|
|
1341
|
+
const isNative = isNativeToken({
|
|
1342
|
+
row,
|
|
1343
|
+
chain,
|
|
1344
|
+
blockchain,
|
|
1345
|
+
assetId,
|
|
1346
|
+
rawAddress,
|
|
1347
|
+
symbol
|
|
1348
|
+
});
|
|
1349
|
+
const sources = Array.isArray(row.sources) ? row.sources.filter(
|
|
1350
|
+
(source) => typeof source === "string" && source.trim().length > 0
|
|
1351
|
+
) : readString(row.platform) ? [readString(row.platform)] : [];
|
|
1352
|
+
const price = typeof row.price === "string" || typeof row.price === "number" ? row.price : null;
|
|
1353
|
+
const priceUpdatedAt = typeof row.updated_at === "number" && Number.isFinite(row.updated_at) ? row.updated_at : null;
|
|
1354
|
+
return {
|
|
1355
|
+
chain,
|
|
1356
|
+
address: assetId,
|
|
1357
|
+
symbol,
|
|
1358
|
+
decimals,
|
|
1359
|
+
isNative,
|
|
1360
|
+
tokenListChainId: chainId,
|
|
1361
|
+
blockchain,
|
|
1362
|
+
assetId,
|
|
1363
|
+
contractAddress: isNative ? null : rawAddress ?? null,
|
|
1364
|
+
coinType: readString(row.coinType) ?? null,
|
|
1365
|
+
name: readString(row.name) ?? null,
|
|
1366
|
+
logoURI: readString(row.logoURI) ?? null,
|
|
1367
|
+
price,
|
|
1368
|
+
priceUpdatedAt,
|
|
1369
|
+
sources,
|
|
1370
|
+
raw: { ...row }
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
function isNativeToken(input) {
|
|
1374
|
+
if (input.row.isNative === true) return true;
|
|
1375
|
+
const address = (input.rawAddress ?? "").toLowerCase();
|
|
1376
|
+
const assetId = input.assetId.toLowerCase();
|
|
1377
|
+
const coinType = readString(input.row.coinType)?.toLowerCase() ?? "";
|
|
1378
|
+
if (/^[1-9]\d*$/.test(input.chain)) {
|
|
1379
|
+
return address === "0x0000000000000000000000000000000000000000" || address === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" || (input.blockchain === "pol" || input.blockchain === "polygon") && address === "0x0000000000000000000000000000000000001010";
|
|
1380
|
+
}
|
|
1381
|
+
if (input.chain === "solana") {
|
|
1382
|
+
return address === "11111111111111111111111111111111" || assetId === "nep141:sol.omft.near";
|
|
1383
|
+
}
|
|
1384
|
+
if (input.chain === "tron") {
|
|
1385
|
+
return input.symbol.toUpperCase() === "TRX";
|
|
1386
|
+
}
|
|
1387
|
+
if (input.chain === "sui") {
|
|
1388
|
+
return address.endsWith("::sui::sui");
|
|
1389
|
+
}
|
|
1390
|
+
if (input.chain === "aptos") {
|
|
1391
|
+
if (coinType === "0x1::aptos_coin::aptoscoin") return true;
|
|
1392
|
+
if (!/^0x[0-9a-f]+$/.test(address)) return false;
|
|
1393
|
+
const compactAddress = address.slice(2).replace(/^0+/, "") || "0";
|
|
1394
|
+
return compactAddress === "a";
|
|
1395
|
+
}
|
|
1396
|
+
return false;
|
|
1397
|
+
}
|
|
1398
|
+
function readString(value) {
|
|
1399
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1400
|
+
}
|
|
1401
|
+
function readDecimals(value) {
|
|
1402
|
+
const decimals = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number(value) : Number.NaN;
|
|
1403
|
+
return Number.isInteger(decimals) && decimals >= 0 ? decimals : void 0;
|
|
1404
|
+
}
|
|
1405
|
+
function isRecord2(value) {
|
|
1406
|
+
return typeof value === "object" && value !== null;
|
|
1407
|
+
}
|
|
1408
|
+
function invalidTokenList(message) {
|
|
1409
|
+
return new SwapSdkError("INVALID_API_RESPONSE", "tokens", message);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
// src/mca/collateral.ts
|
|
1413
|
+
function resolveMcaWithdrawPolicy(input) {
|
|
1414
|
+
const decreaseCollateral = resolveMcaRequiredCollateralDecrease({
|
|
1415
|
+
amountBurrow: input.amountBurrow,
|
|
1416
|
+
suppliedBalance: input.suppliedBalance
|
|
1417
|
+
});
|
|
1418
|
+
const available = parseDecimal(input.availableBalance, "availableBalance");
|
|
1419
|
+
const amount = parseDecimal(input.amountIn, "amountIn");
|
|
1420
|
+
return {
|
|
1421
|
+
...decreaseCollateral,
|
|
1422
|
+
withdrawAll: input.isMax || available.digits > 0n && isAtLeastWithdrawAllThreshold(amount, available)
|
|
1423
|
+
};
|
|
1424
|
+
}
|
|
1425
|
+
function resolveMcaRequiredCollateralDecrease(input) {
|
|
1426
|
+
const amount = parseBurrowDecimal(input.amountBurrow, "amountBurrow");
|
|
1427
|
+
const supplied = parseBurrowDecimal(
|
|
1428
|
+
input.suppliedBalance,
|
|
1429
|
+
"suppliedBalance"
|
|
1430
|
+
);
|
|
1431
|
+
const [amountScaled, suppliedScaled] = alignScale(amount, supplied);
|
|
1432
|
+
const decreaseScaled = amountScaled > suppliedScaled ? amountScaled - suppliedScaled : 0n;
|
|
1433
|
+
return resolveParsedMcaDecreaseCollateral({
|
|
1434
|
+
digits: decreaseScaled,
|
|
1435
|
+
scale: Math.max(amount.scale, supplied.scale)
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
function resolveMcaDecreaseCollateral(decreaseAmountBurrow, field = "decreaseAmountBurrow") {
|
|
1439
|
+
const parsed = parseBurrowDecimal(decreaseAmountBurrow, field);
|
|
1440
|
+
return resolveParsedMcaDecreaseCollateral(parsed);
|
|
1441
|
+
}
|
|
1442
|
+
function resolveParsedMcaDecreaseCollateral(parsed) {
|
|
1443
|
+
const needDecrease = parsed.digits > 0n;
|
|
1444
|
+
return {
|
|
1445
|
+
needDecrease,
|
|
1446
|
+
decreaseAmountBurrow: needDecrease ? formatDecimal(parsed) : "0"
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
function isAtLeastWithdrawAllThreshold(amount, available) {
|
|
1450
|
+
const [amountScaled, availableScaled] = alignScale(amount, available);
|
|
1451
|
+
return amountScaled * 1000000n >= availableScaled * 999999n;
|
|
1452
|
+
}
|
|
1453
|
+
function alignScale(a, b) {
|
|
1454
|
+
const scale = Math.max(a.scale, b.scale);
|
|
1455
|
+
return [
|
|
1456
|
+
a.digits * pow10(scale - a.scale),
|
|
1457
|
+
b.digits * pow10(scale - b.scale)
|
|
1458
|
+
];
|
|
1459
|
+
}
|
|
1460
|
+
function parseDecimal(value, field) {
|
|
1461
|
+
const trimmed = value.trim();
|
|
1462
|
+
if (!/^(?:0|[1-9]\d*)(?:\.\d+)?$/.test(trimmed)) {
|
|
1463
|
+
throw new SwapSdkError(
|
|
1464
|
+
"INVALID_REQUEST",
|
|
1465
|
+
"quote",
|
|
1466
|
+
`${field} must be a non-negative decimal string`
|
|
1467
|
+
);
|
|
1468
|
+
}
|
|
1469
|
+
const [integer = "0", fraction = ""] = trimmed.split(".");
|
|
1470
|
+
return {
|
|
1471
|
+
digits: BigInt(`${integer}${fraction}`),
|
|
1472
|
+
scale: fraction.length
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function parseBurrowDecimal(value, field) {
|
|
1476
|
+
const trimmed = value.trim();
|
|
1477
|
+
const match = /^(?:([0-9]+)(?:\.([0-9]*))?|\.([0-9]+))(?:[eE]([+-]?[0-9]+))?$/.exec(
|
|
1478
|
+
trimmed
|
|
1479
|
+
);
|
|
1480
|
+
if (!match) {
|
|
1481
|
+
throw new SwapSdkError(
|
|
1482
|
+
"INVALID_REQUEST",
|
|
1483
|
+
"quote",
|
|
1484
|
+
`${field} must be a non-negative decimal string`
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
const integer = match[1] ?? "0";
|
|
1488
|
+
const fraction = match[2] ?? match[3] ?? "";
|
|
1489
|
+
const exponent = Number(match[4] ?? "0");
|
|
1490
|
+
if (!Number.isSafeInteger(exponent) || Math.abs(exponent) > 1e5) {
|
|
1491
|
+
throw new SwapSdkError(
|
|
1492
|
+
"INVALID_REQUEST",
|
|
1493
|
+
"quote",
|
|
1494
|
+
`${field} exponent is out of range`
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1497
|
+
let digits = BigInt(`${integer}${fraction}` || "0");
|
|
1498
|
+
let scale = fraction.length - exponent;
|
|
1499
|
+
if (scale < 0) {
|
|
1500
|
+
digits *= pow10(-scale);
|
|
1501
|
+
scale = 0;
|
|
1502
|
+
}
|
|
1503
|
+
return { digits, scale };
|
|
1504
|
+
}
|
|
1505
|
+
function formatDecimal(value) {
|
|
1506
|
+
if (value.digits === 0n) return "0";
|
|
1507
|
+
if (value.scale === 0) return value.digits.toString();
|
|
1508
|
+
const padded = value.digits.toString().padStart(value.scale + 1, "0");
|
|
1509
|
+
const splitAt = padded.length - value.scale;
|
|
1510
|
+
const integer = padded.slice(0, splitAt);
|
|
1511
|
+
const fraction = padded.slice(splitAt).replace(/0+$/, "");
|
|
1512
|
+
return fraction ? `${integer}.${fraction}` : integer;
|
|
1513
|
+
}
|
|
1514
|
+
function pow10(exponent) {
|
|
1515
|
+
return 10n ** BigInt(exponent);
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1218
1518
|
// src/mca/quote.ts
|
|
1219
1519
|
function serializeMcaQuoteRequest(request, signer) {
|
|
1220
1520
|
const mcaAccountId = request.mcaAccountId.trim();
|
|
@@ -1230,13 +1530,10 @@ function serializeMcaQuoteRequest(request, signer) {
|
|
|
1230
1530
|
if (!identityKey) {
|
|
1231
1531
|
throw invalidRequest("signer identityKey is required");
|
|
1232
1532
|
}
|
|
1233
|
-
|
|
1234
|
-
request.collateral.decreaseAmountBurrow
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
"collateral.decreaseAmountBurrow must be a non-negative decimal string"
|
|
1238
|
-
);
|
|
1239
|
-
}
|
|
1533
|
+
const decreaseCollateral = request.flow === "withdraw" ? resolveMcaDecreaseCollateral(
|
|
1534
|
+
request.collateral.decreaseAmountBurrow,
|
|
1535
|
+
"collateral.decreaseAmountBurrow"
|
|
1536
|
+
) : void 0;
|
|
1240
1537
|
const mca = {
|
|
1241
1538
|
flow: request.flow,
|
|
1242
1539
|
mcaAccountId,
|
|
@@ -1245,8 +1542,8 @@ function serializeMcaQuoteRequest(request, signer) {
|
|
|
1245
1542
|
identityKey
|
|
1246
1543
|
},
|
|
1247
1544
|
...request.flow === "deposit" ? { useAsCollateral: request.collateral.useAsCollateral } : {
|
|
1248
|
-
needDecreaseCollateral:
|
|
1249
|
-
decreaseCollateralAmountBurrow:
|
|
1545
|
+
needDecreaseCollateral: decreaseCollateral.needDecrease,
|
|
1546
|
+
decreaseCollateralAmountBurrow: decreaseCollateral.decreaseAmountBurrow,
|
|
1250
1547
|
...request.collateral.withdrawAll ? { withdrawAll: true } : {}
|
|
1251
1548
|
},
|
|
1252
1549
|
...request.recipientMsgSignatures ? { recipientMsgSignatures: [...request.recipientMsgSignatures] } : {},
|
|
@@ -1275,7 +1572,7 @@ function normalizeMcaQuote(request, signer, quote) {
|
|
|
1275
1572
|
mca: Object.freeze({ ...mca })
|
|
1276
1573
|
};
|
|
1277
1574
|
if (request.flow === "deposit") {
|
|
1278
|
-
if (
|
|
1575
|
+
if (readString2(quote.raw.nearDepositTxError)) {
|
|
1279
1576
|
throw invalidResponse(String(quote.raw.nearDepositTxError));
|
|
1280
1577
|
}
|
|
1281
1578
|
return {
|
|
@@ -1286,7 +1583,7 @@ function normalizeMcaQuote(request, signer, quote) {
|
|
|
1286
1583
|
...quote.raw.nearDepositTx === void 0 ? {} : { nearDepositTx: quote.raw.nearDepositTx }
|
|
1287
1584
|
};
|
|
1288
1585
|
}
|
|
1289
|
-
if (
|
|
1586
|
+
if (readString2(quote.raw.nearMcaWithdrawTxError)) {
|
|
1290
1587
|
throw invalidResponse(String(quote.raw.nearMcaWithdrawTxError));
|
|
1291
1588
|
}
|
|
1292
1589
|
const mode = resolveWithdrawMode(request);
|
|
@@ -1314,7 +1611,7 @@ function resolveWithdrawMode(request) {
|
|
|
1314
1611
|
function isPlainObject(value) {
|
|
1315
1612
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1316
1613
|
}
|
|
1317
|
-
function
|
|
1614
|
+
function readString2(value) {
|
|
1318
1615
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1319
1616
|
}
|
|
1320
1617
|
function invalidRequest(message) {
|
|
@@ -1802,7 +2099,7 @@ var McaSwapService = class {
|
|
|
1802
2099
|
"MCA relayer preview is missing business"
|
|
1803
2100
|
);
|
|
1804
2101
|
}
|
|
1805
|
-
const message =
|
|
2102
|
+
const message = readString3(input.quote.preview.messageToSign);
|
|
1806
2103
|
if (!message) {
|
|
1807
2104
|
throw new SwapSdkError(
|
|
1808
2105
|
"INVALID_API_RESPONSE",
|
|
@@ -1811,7 +2108,7 @@ var McaSwapService = class {
|
|
|
1811
2108
|
);
|
|
1812
2109
|
}
|
|
1813
2110
|
const depositAddress = extractMcaWithdrawDepositAddress({
|
|
1814
|
-
snapshotDepositAddress:
|
|
2111
|
+
snapshotDepositAddress: readString3(input.quote.raw.depositAddress),
|
|
1815
2112
|
preview: input.quote.preview,
|
|
1816
2113
|
bestQuote: input.quote.raw.bestQuote
|
|
1817
2114
|
});
|
|
@@ -1876,8 +2173,8 @@ var McaSwapService = class {
|
|
|
1876
2173
|
signal: input.signal,
|
|
1877
2174
|
idempotencyKey: input.idempotencyKey
|
|
1878
2175
|
});
|
|
1879
|
-
const orderId =
|
|
1880
|
-
const router =
|
|
2176
|
+
const orderId = readString3(raw.orderId) ?? readRecordString2(raw.deposit, "orderId");
|
|
2177
|
+
const router = readString3(raw.router) ?? input.quote.route.router;
|
|
1881
2178
|
const submittedDepositAddress = readRecordString2(raw.deposit, "depositAddress") ?? depositAddress;
|
|
1882
2179
|
if (!orderId || !router) {
|
|
1883
2180
|
throw new SwapSdkError(
|
|
@@ -1901,7 +2198,8 @@ var McaSwapService = class {
|
|
|
1901
2198
|
is_cross_chain: true,
|
|
1902
2199
|
tx_type: "mca-withdraw-relayer",
|
|
1903
2200
|
multi_addr: input.quote.mcaAccountId,
|
|
1904
|
-
swapId: orderId
|
|
2201
|
+
swapId: orderId,
|
|
2202
|
+
...request.confidentiality ? { confidentiality: request.confidentiality } : {}
|
|
1905
2203
|
};
|
|
1906
2204
|
this.relayerReports.set(executionId, reportRequest);
|
|
1907
2205
|
const result = {
|
|
@@ -2009,14 +2307,14 @@ function assertSignerMatchesQuote(signer, expected) {
|
|
|
2009
2307
|
);
|
|
2010
2308
|
}
|
|
2011
2309
|
}
|
|
2012
|
-
function
|
|
2310
|
+
function readString3(value) {
|
|
2013
2311
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2014
2312
|
}
|
|
2015
2313
|
function readRecordString2(value, field) {
|
|
2016
2314
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2017
2315
|
return void 0;
|
|
2018
2316
|
}
|
|
2019
|
-
return
|
|
2317
|
+
return readString3(value[field]);
|
|
2020
2318
|
}
|
|
2021
2319
|
|
|
2022
2320
|
// src/client/SwapClient.ts
|
|
@@ -2024,6 +2322,8 @@ var SwapClient = class {
|
|
|
2024
2322
|
constructor(config) {
|
|
2025
2323
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
2026
2324
|
this.reportRequests = /* @__PURE__ */ new Map();
|
|
2325
|
+
this.tokenListCache = /* @__PURE__ */ new Map();
|
|
2326
|
+
this.tokenListInflight = /* @__PURE__ */ new Map();
|
|
2027
2327
|
this.config = config;
|
|
2028
2328
|
this.api = new ApiClient(config);
|
|
2029
2329
|
this.registry = new ExecutorRegistry(config.executors ?? []);
|
|
@@ -2056,6 +2356,55 @@ var SwapClient = class {
|
|
|
2056
2356
|
buildRaw(request, options = {}) {
|
|
2057
2357
|
return this.api.build(request, options);
|
|
2058
2358
|
}
|
|
2359
|
+
async getFromTokens(request, options = {}) {
|
|
2360
|
+
return this.loadTokenList("from", request, options, async () => {
|
|
2361
|
+
const raw = await this.api.getFromTokenRows(request.chainId, options);
|
|
2362
|
+
return normalizeFromTokenList(raw, request.chainId);
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
async getCrossChainToTokens(request, options = {}) {
|
|
2366
|
+
return this.loadTokenList("cross-chain-to", request, options, async () => {
|
|
2367
|
+
const raw = await this.api.getCrossChainToTokenRows(
|
|
2368
|
+
request.chainId,
|
|
2369
|
+
options
|
|
2370
|
+
);
|
|
2371
|
+
return normalizeCrossChainToTokenList(raw, request.chainId);
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
async loadTokenList(direction, request, options, load) {
|
|
2375
|
+
if (!Number.isSafeInteger(request.chainId) || request.chainId <= 0) {
|
|
2376
|
+
throw new SwapSdkError(
|
|
2377
|
+
"INVALID_REQUEST",
|
|
2378
|
+
"tokens",
|
|
2379
|
+
`Token-list chainId must be a positive safe integer: ${String(
|
|
2380
|
+
request.chainId
|
|
2381
|
+
)}`
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2384
|
+
const ttlMs = Math.max(0, this.config.tokenListCacheTtlMs ?? 6e5);
|
|
2385
|
+
const key = `${direction}:${request.chainId}`;
|
|
2386
|
+
const cached = this.tokenListCache.get(key);
|
|
2387
|
+
if (ttlMs > 0 && cached && cached.expiresAt > this.now()) {
|
|
2388
|
+
return cloneTokenList(cached.tokens);
|
|
2389
|
+
}
|
|
2390
|
+
const existing = options.signal ? void 0 : this.tokenListInflight.get(key);
|
|
2391
|
+
if (existing) return cloneTokenList(await existing);
|
|
2392
|
+
const pending = load().then((tokens) => {
|
|
2393
|
+
if (ttlMs > 0) {
|
|
2394
|
+
this.tokenListCache.set(key, {
|
|
2395
|
+
expiresAt: this.now() + ttlMs,
|
|
2396
|
+
tokens: cloneTokenList(tokens)
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
return tokens;
|
|
2400
|
+
}).finally(() => {
|
|
2401
|
+
if (this.tokenListInflight.get(key) === pending) {
|
|
2402
|
+
this.tokenListInflight.delete(key);
|
|
2403
|
+
}
|
|
2404
|
+
});
|
|
2405
|
+
if (!options.signal) this.tokenListInflight.set(key, pending);
|
|
2406
|
+
return cloneTokenList(await pending);
|
|
2407
|
+
}
|
|
2059
2408
|
async buildSwap(input) {
|
|
2060
2409
|
if (isMcaQuote(input.quote)) {
|
|
2061
2410
|
return this.managedSwapFlow.build({
|
|
@@ -2186,7 +2535,23 @@ var SwapClient = class {
|
|
|
2186
2535
|
emit({ type: "warning", executionId: build.executionId, warning });
|
|
2187
2536
|
}
|
|
2188
2537
|
}
|
|
2189
|
-
|
|
2538
|
+
const waitsForCompletion = (input.waitFor ?? "submitted") === "completed";
|
|
2539
|
+
const requiresOrderStatus = build.isCrossChain || build.request?.confidentiality === "basic";
|
|
2540
|
+
if (waitsForCompletion && requiresOrderStatus && !orderId) {
|
|
2541
|
+
throw new SwapSdkError(
|
|
2542
|
+
"INVALID_API_RESPONSE",
|
|
2543
|
+
"status",
|
|
2544
|
+
"Swap submitted, but the API did not provide a status key",
|
|
2545
|
+
{
|
|
2546
|
+
details: {
|
|
2547
|
+
executionId: build.executionId,
|
|
2548
|
+
...result.txHash ? { txHash: result.txHash } : {},
|
|
2549
|
+
router: orderRouter ?? build.router
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
if (waitsForCompletion && orderId) {
|
|
2190
2555
|
const status = await this.waitForOrder({
|
|
2191
2556
|
orderId,
|
|
2192
2557
|
router: orderRouter ?? build.router,
|
|
@@ -2298,10 +2663,30 @@ var SwapClient = class {
|
|
|
2298
2663
|
getHistoryRaw(params, options = {}) {
|
|
2299
2664
|
return this.api.getHistory(params, options);
|
|
2300
2665
|
}
|
|
2666
|
+
createHistoryAuthChallenge(request, options = {}) {
|
|
2667
|
+
return this.api.createHistoryAuthChallenge(request, options);
|
|
2668
|
+
}
|
|
2669
|
+
verifyHistoryAuthChallenge(request, options = {}) {
|
|
2670
|
+
return this.api.verifyHistoryAuthChallenge(request, options);
|
|
2671
|
+
}
|
|
2672
|
+
async authorizeConfidentialHistory(request, signChallenge, options = {}) {
|
|
2673
|
+
const challenge = await this.createHistoryAuthChallenge(request, options);
|
|
2674
|
+
assertHistoryChallengeMatchesRequest(challenge, request);
|
|
2675
|
+
const proof = await signChallenge(challenge);
|
|
2676
|
+
const verifyRequest = {
|
|
2677
|
+
challengeId: challenge.challengeId,
|
|
2678
|
+
proof
|
|
2679
|
+
};
|
|
2680
|
+
const token = await this.verifyHistoryAuthChallenge(verifyRequest, options);
|
|
2681
|
+
assertHistoryTokenMatchesChallenge(token, challenge);
|
|
2682
|
+
return token;
|
|
2683
|
+
}
|
|
2301
2684
|
async getHistory(request, options = {}) {
|
|
2302
2685
|
const raw = await this.api.getHistory(
|
|
2303
2686
|
{
|
|
2304
2687
|
sender: request.sender,
|
|
2688
|
+
...request.mode ? { mode: request.mode } : {},
|
|
2689
|
+
...request.walletToken ? { walletToken: request.walletToken } : {},
|
|
2305
2690
|
...request.page !== void 0 ? { pageNumber: request.page } : {},
|
|
2306
2691
|
...request.pageSize !== void 0 ? { pageSize: request.pageSize } : {}
|
|
2307
2692
|
},
|
|
@@ -2352,10 +2737,39 @@ var SwapClient = class {
|
|
|
2352
2737
|
router: build.router,
|
|
2353
2738
|
tx_type: reportContext?.txType ?? (build.isCrossChain ? "cross-chain" : "same-chain"),
|
|
2354
2739
|
...reportContext?.multiAddr ? { multi_addr: reportContext.multiAddr } : {},
|
|
2355
|
-
...reportContext?.swapId ?? result.orderId ? { swapId: reportContext?.swapId ?? result.orderId } : {}
|
|
2740
|
+
...reportContext?.swapId ?? result.orderId ? { swapId: reportContext?.swapId ?? result.orderId } : {},
|
|
2741
|
+
...request.confidentiality ? { confidentiality: request.confidentiality } : {}
|
|
2356
2742
|
};
|
|
2357
2743
|
}
|
|
2358
2744
|
};
|
|
2745
|
+
function assertHistoryChallengeMatchesRequest(challenge, request) {
|
|
2746
|
+
const expectedMca = request.mcaAccountId?.trim();
|
|
2747
|
+
const principalMatches = expectedMca ? challenge.principalType === "mca" && challenge.mcaAccountId?.toLowerCase() === expectedMca.toLowerCase() : challenge.principalType === "wallet" && !challenge.mcaAccountId;
|
|
2748
|
+
const identityMatches = request.identityKey ? normalizeHistoryIdentity(challenge.chainFamily, challenge.identityKey) === normalizeHistoryIdentity(challenge.chainFamily, request.identityKey) : true;
|
|
2749
|
+
if (challenge.chainFamily !== request.chainFamily || challenge.chainId !== request.chainId || normalizeHistoryAddress(challenge.chainFamily, challenge.walletAddress) !== normalizeHistoryAddress(request.chainFamily, request.walletAddress) || !identityMatches || !principalMatches || !challenge.queryAddress) {
|
|
2750
|
+
throw new SwapSdkError(
|
|
2751
|
+
"INVALID_API_RESPONSE",
|
|
2752
|
+
"history",
|
|
2753
|
+
"Confidential history challenge does not match the requested wallet or MCA"
|
|
2754
|
+
);
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
function assertHistoryTokenMatchesChallenge(token, challenge) {
|
|
2758
|
+
const principalMatches = token.principalType === challenge.principalType && (challenge.principalType === "mca" ? token.mcaAccountId?.toLowerCase() === challenge.mcaAccountId?.toLowerCase() : !token.mcaAccountId);
|
|
2759
|
+
if (!principalMatches || token.queryAddress !== challenge.queryAddress) {
|
|
2760
|
+
throw new SwapSdkError(
|
|
2761
|
+
"INVALID_API_RESPONSE",
|
|
2762
|
+
"history",
|
|
2763
|
+
"Confidential history authorization returned a different principal"
|
|
2764
|
+
);
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
function normalizeHistoryAddress(chain, value) {
|
|
2768
|
+
return chain === "evm" || chain === "aptos" || chain === "sui" ? value.toLowerCase() : value;
|
|
2769
|
+
}
|
|
2770
|
+
function normalizeHistoryIdentity(chain, value) {
|
|
2771
|
+
return chain === "evm" || chain === "aptos" || chain === "sui" || chain === "btc" || chain === "zcash" ? value.toLowerCase().replace(/^0x/, "") : value;
|
|
2772
|
+
}
|
|
2359
2773
|
function isMcaQuoteRequest(request) {
|
|
2360
2774
|
if (!("flow" in request) || !("mcaAccountId" in request)) return false;
|
|
2361
2775
|
const flow = Reflect.get(request, "flow");
|
|
@@ -2372,6 +2786,13 @@ function isMcaQuote(quote) {
|
|
|
2372
2786
|
function readNonEmptyString(value) {
|
|
2373
2787
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2374
2788
|
}
|
|
2789
|
+
function cloneTokenList(tokens) {
|
|
2790
|
+
return tokens.map((token) => ({
|
|
2791
|
+
...token,
|
|
2792
|
+
sources: [...token.sources],
|
|
2793
|
+
raw: { ...token.raw }
|
|
2794
|
+
}));
|
|
2795
|
+
}
|
|
2375
2796
|
function delay(ms, signal) {
|
|
2376
2797
|
return new Promise((resolve, reject) => {
|
|
2377
2798
|
if (signal?.aborted) {
|
|
@@ -2402,48 +2823,6 @@ function delay(ms, signal) {
|
|
|
2402
2823
|
});
|
|
2403
2824
|
}
|
|
2404
2825
|
|
|
2405
|
-
// src/mca/collateral.ts
|
|
2406
|
-
function resolveMcaWithdrawPolicy(input) {
|
|
2407
|
-
const collateral = parseDecimal(input.collateralBalance, "collateralBalance");
|
|
2408
|
-
const available = parseDecimal(input.availableBalance, "availableBalance");
|
|
2409
|
-
const amount = parseDecimal(input.amountIn, "amountIn");
|
|
2410
|
-
const needDecrease = collateral.digits > 0n;
|
|
2411
|
-
return {
|
|
2412
|
-
needDecrease,
|
|
2413
|
-
decreaseAmountBurrow: needDecrease ? input.collateralBalance.trim() : "0",
|
|
2414
|
-
withdrawAll: input.isMax || available.digits > 0n && isAtLeastWithdrawAllThreshold(amount, available)
|
|
2415
|
-
};
|
|
2416
|
-
}
|
|
2417
|
-
function isAtLeastWithdrawAllThreshold(amount, available) {
|
|
2418
|
-
const [amountScaled, availableScaled] = alignScale(amount, available);
|
|
2419
|
-
return amountScaled * 1000000n >= availableScaled * 999999n;
|
|
2420
|
-
}
|
|
2421
|
-
function alignScale(a, b) {
|
|
2422
|
-
const scale = Math.max(a.scale, b.scale);
|
|
2423
|
-
return [
|
|
2424
|
-
a.digits * pow10(scale - a.scale),
|
|
2425
|
-
b.digits * pow10(scale - b.scale)
|
|
2426
|
-
];
|
|
2427
|
-
}
|
|
2428
|
-
function parseDecimal(value, field) {
|
|
2429
|
-
const trimmed = value.trim();
|
|
2430
|
-
if (!/^(?:0|[1-9]\d*)(?:\.\d+)?$/.test(trimmed)) {
|
|
2431
|
-
throw new SwapSdkError(
|
|
2432
|
-
"INVALID_REQUEST",
|
|
2433
|
-
"quote",
|
|
2434
|
-
`${field} must be a non-negative decimal string`
|
|
2435
|
-
);
|
|
2436
|
-
}
|
|
2437
|
-
const [integer = "0", fraction = ""] = trimmed.split(".");
|
|
2438
|
-
return {
|
|
2439
|
-
digits: BigInt(`${integer}${fraction}`),
|
|
2440
|
-
scale: fraction.length
|
|
2441
|
-
};
|
|
2442
|
-
}
|
|
2443
|
-
function pow10(exponent) {
|
|
2444
|
-
return 10n ** BigInt(exponent);
|
|
2445
|
-
}
|
|
2446
|
-
|
|
2447
2826
|
exports.ApiClient = ApiClient;
|
|
2448
2827
|
exports.DEFAULT_MCA_SIGNER_PRIORITY = DEFAULT_MCA_SIGNER_PRIORITY;
|
|
2449
2828
|
exports.ExecutorRegistry = ExecutorRegistry;
|
|
@@ -2462,12 +2841,16 @@ exports.formatUnits = formatUnits;
|
|
|
2462
2841
|
exports.fromApiChain = fromApiChain;
|
|
2463
2842
|
exports.isSameMcaSignerIdentity = isSameMcaSignerIdentity;
|
|
2464
2843
|
exports.normalizeBuild = normalizeBuild;
|
|
2844
|
+
exports.normalizeCrossChainToTokenList = normalizeCrossChainToTokenList;
|
|
2845
|
+
exports.normalizeFromTokenList = normalizeFromTokenList;
|
|
2465
2846
|
exports.normalizeHistory = normalizeHistory;
|
|
2466
2847
|
exports.normalizeHistoryStatus = normalizeHistoryStatus;
|
|
2467
2848
|
exports.normalizeMcaQuote = normalizeMcaQuote;
|
|
2468
2849
|
exports.normalizeOrderStatus = normalizeOrderStatus;
|
|
2469
2850
|
exports.normalizeQuote = normalizeQuote;
|
|
2470
2851
|
exports.parseUnits = parseUnits;
|
|
2852
|
+
exports.resolveMcaDecreaseCollateral = resolveMcaDecreaseCollateral;
|
|
2853
|
+
exports.resolveMcaRequiredCollateralDecrease = resolveMcaRequiredCollateralDecrease;
|
|
2471
2854
|
exports.resolveMcaWithdrawPolicy = resolveMcaWithdrawPolicy;
|
|
2472
2855
|
exports.selectMcaSigner = selectMcaSigner;
|
|
2473
2856
|
exports.serializeMcaQuoteRequest = serializeMcaQuoteRequest;
|