@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.
Files changed (42) hide show
  1. package/README.md +207 -77
  2. package/dist/executors/aptos.d.mts +1 -1
  3. package/dist/executors/aptos.d.ts +1 -1
  4. package/dist/executors/aptos.js.map +1 -1
  5. package/dist/executors/aptos.mjs.map +1 -1
  6. package/dist/executors/bitcoin.d.mts +1 -1
  7. package/dist/executors/bitcoin.d.ts +1 -1
  8. package/dist/executors/bitcoin.js.map +1 -1
  9. package/dist/executors/bitcoin.mjs.map +1 -1
  10. package/dist/executors/evm.d.mts +1 -1
  11. package/dist/executors/evm.d.ts +1 -1
  12. package/dist/executors/evm.js.map +1 -1
  13. package/dist/executors/evm.mjs.map +1 -1
  14. package/dist/executors/near.d.mts +1 -1
  15. package/dist/executors/near.d.ts +1 -1
  16. package/dist/executors/near.js.map +1 -1
  17. package/dist/executors/near.mjs.map +1 -1
  18. package/dist/executors/solana.d.mts +1 -1
  19. package/dist/executors/solana.d.ts +1 -1
  20. package/dist/executors/solana.js.map +1 -1
  21. package/dist/executors/solana.mjs.map +1 -1
  22. package/dist/executors/sui.d.mts +1 -1
  23. package/dist/executors/sui.d.ts +1 -1
  24. package/dist/executors/sui.js.map +1 -1
  25. package/dist/executors/sui.mjs.map +1 -1
  26. package/dist/executors/tron.d.mts +1 -1
  27. package/dist/executors/tron.d.ts +1 -1
  28. package/dist/executors/tron.js.map +1 -1
  29. package/dist/executors/tron.mjs.map +1 -1
  30. package/dist/executors/zcash.d.mts +1 -1
  31. package/dist/executors/zcash.d.ts +1 -1
  32. package/dist/executors/zcash.js.map +1 -1
  33. package/dist/executors/zcash.mjs.map +1 -1
  34. package/dist/index.d.mts +82 -6
  35. package/dist/index.d.ts +82 -6
  36. package/dist/index.js +454 -71
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +451 -72
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/{shared-D0_DbMT2.d.mts → shared-COkGiqaz.d.mts} +84 -2
  41. package/dist/{shared-D0_DbMT2.d.ts → shared-COkGiqaz.d.ts} +84 -2
  42. 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(options.idempotencyKey);
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 = Object.freeze({ ...serializeQuoteRequest(request) });
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
- if (request.flow === "withdraw" && !/^(?:0|[1-9]\d*)(?:\.\d+)?$/.test(
1234
- request.collateral.decreaseAmountBurrow.trim()
1235
- )) {
1236
- throw invalidRequest(
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: request.collateral.needDecrease,
1249
- decreaseCollateralAmountBurrow: request.collateral.decreaseAmountBurrow,
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 (readString(quote.raw.nearDepositTxError)) {
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 (readString(quote.raw.nearMcaWithdrawTxError)) {
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 readString(value) {
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 = readString2(input.quote.preview.messageToSign);
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: readString2(input.quote.raw.depositAddress),
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 = readString2(raw.orderId) ?? readRecordString2(raw.deposit, "orderId");
1880
- const router = readString2(raw.router) ?? input.quote.route.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 readString2(value) {
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 readString2(value[field]);
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
- if ((input.waitFor ?? "submitted") === "completed" && orderId) {
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;