@rhea-finance/cross-chain-aggregation-dex 2.0.5 → 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 +147 -69
- 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 +40 -4
- package/dist/index.d.ts +40 -4
- package/dist/index.js +264 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +263 -16
- package/dist/index.mjs.map +1 -1
- package/dist/{shared-DmMJXknE.d.mts → shared-COkGiqaz.d.mts} +30 -2
- package/dist/{shared-DmMJXknE.d.ts → shared-COkGiqaz.d.ts} +30 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -118,6 +118,22 @@ var ApiClient = class {
|
|
|
118
118
|
body
|
|
119
119
|
});
|
|
120
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 }
|
|
135
|
+
});
|
|
136
|
+
}
|
|
121
137
|
async request(path, stage, options) {
|
|
122
138
|
const url = this.buildUrl(path, options.query);
|
|
123
139
|
const headers = await this.buildHeaders(
|
|
@@ -657,7 +673,7 @@ function normalizeBuild(raw, executionId = createExecutionId(), request) {
|
|
|
657
673
|
const lane = laneFromChainType(common.chainType, fromChain);
|
|
658
674
|
assertLaneMatchesChain(lane, fromChain);
|
|
659
675
|
const execution = normalizeExecution(raw, lane, fromChain);
|
|
660
|
-
const order = normalizeOrder(raw, execution);
|
|
676
|
+
const order = normalizeOrder(raw, execution, request);
|
|
661
677
|
const deposit = normalizeDeposit(raw.deposit);
|
|
662
678
|
return {
|
|
663
679
|
executionId,
|
|
@@ -888,11 +904,12 @@ function assertKind(actual, allowed) {
|
|
|
888
904
|
);
|
|
889
905
|
}
|
|
890
906
|
}
|
|
891
|
-
function normalizeOrder(raw, execution) {
|
|
907
|
+
function normalizeOrder(raw, execution, request) {
|
|
892
908
|
const depositOrderId = readRecordString(raw.deposit, "orderId");
|
|
893
|
-
const orderId = raw.orderId ?? depositOrderId;
|
|
894
|
-
if (!orderId) return void 0;
|
|
895
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;
|
|
896
913
|
const chainId = execution.kind === "evm-signature" ? String(execution.request.chainId) : execution.kind === "evm-transaction" ? String(execution.tx.chainId) : void 0;
|
|
897
914
|
return { orderId, router, ...chainId ? { chainId } : {} };
|
|
898
915
|
}
|
|
@@ -952,6 +969,8 @@ function assertBaseUnitAmount(value) {
|
|
|
952
969
|
|
|
953
970
|
// src/normalizers/quote.ts
|
|
954
971
|
var DEFAULT_QUOTE_WAITING_TIME_MS = 3e3;
|
|
972
|
+
var DEFAULT_SAME_CHAIN_TIMEOUT_MS = 500;
|
|
973
|
+
var DEFAULT_CROSS_CHAIN_TIMEOUT_MS = 3e3;
|
|
955
974
|
function serializeQuoteRequest(request) {
|
|
956
975
|
validateQuoteRequest(request);
|
|
957
976
|
return {
|
|
@@ -963,6 +982,8 @@ function serializeQuoteRequest(request) {
|
|
|
963
982
|
amountIn: request.amountIn,
|
|
964
983
|
slippage: request.slippageBps,
|
|
965
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,
|
|
966
987
|
...request.confidentiality ? { confidentiality: request.confidentiality } : {},
|
|
967
988
|
sender: request.sender.trim(),
|
|
968
989
|
...request.recipient?.trim() ? { recipient: request.recipient.trim() } : {}
|
|
@@ -974,7 +995,11 @@ function normalizeQuote(request, raw, receivedAt = Date.now()) {
|
|
|
974
995
|
throw invalidQuote("Quote response does not contain a valid best route");
|
|
975
996
|
}
|
|
976
997
|
const quoteId = readOptionalString(raw.bestQuote.quoteId);
|
|
977
|
-
const apiRequest =
|
|
998
|
+
const apiRequest = { ...serializeQuoteRequest(request) };
|
|
999
|
+
delete apiRequest.quoteWaitingTimeMs;
|
|
1000
|
+
delete apiRequest.sameChainTimeoutMs;
|
|
1001
|
+
delete apiRequest.crossChainTimeoutMs;
|
|
1002
|
+
Object.freeze(apiRequest);
|
|
978
1003
|
const buildContext = Object.freeze({
|
|
979
1004
|
request: apiRequest,
|
|
980
1005
|
router: bestRoute.router,
|
|
@@ -1042,6 +1067,14 @@ function validateQuoteRequest(request) {
|
|
|
1042
1067
|
"quoteWaitingTimeMs must be a non-negative integer"
|
|
1043
1068
|
);
|
|
1044
1069
|
}
|
|
1070
|
+
validateQuoteTimingParameter(
|
|
1071
|
+
request.sameChainTimeoutMs,
|
|
1072
|
+
"sameChainTimeoutMs"
|
|
1073
|
+
);
|
|
1074
|
+
validateQuoteTimingParameter(
|
|
1075
|
+
request.crossChainTimeoutMs,
|
|
1076
|
+
"crossChainTimeoutMs"
|
|
1077
|
+
);
|
|
1045
1078
|
if (!request.sender.trim()) {
|
|
1046
1079
|
throw new SwapSdkError(
|
|
1047
1080
|
"INVALID_REQUEST",
|
|
@@ -1064,6 +1097,15 @@ function validateQuoteRequest(request) {
|
|
|
1064
1097
|
);
|
|
1065
1098
|
}
|
|
1066
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
|
+
}
|
|
1067
1109
|
function normalizeRoute(raw, required) {
|
|
1068
1110
|
const router = readOptionalString(raw.router);
|
|
1069
1111
|
const amountOutValue = raw.amountOut ?? raw.estimatedOut;
|
|
@@ -1236,6 +1278,137 @@ function normalizeTimestamp(value) {
|
|
|
1236
1278
|
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
1237
1279
|
}
|
|
1238
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
|
+
|
|
1239
1412
|
// src/mca/collateral.ts
|
|
1240
1413
|
function resolveMcaWithdrawPolicy(input) {
|
|
1241
1414
|
const decreaseCollateral = resolveMcaRequiredCollateralDecrease({
|
|
@@ -1399,7 +1572,7 @@ function normalizeMcaQuote(request, signer, quote) {
|
|
|
1399
1572
|
mca: Object.freeze({ ...mca })
|
|
1400
1573
|
};
|
|
1401
1574
|
if (request.flow === "deposit") {
|
|
1402
|
-
if (
|
|
1575
|
+
if (readString2(quote.raw.nearDepositTxError)) {
|
|
1403
1576
|
throw invalidResponse(String(quote.raw.nearDepositTxError));
|
|
1404
1577
|
}
|
|
1405
1578
|
return {
|
|
@@ -1410,7 +1583,7 @@ function normalizeMcaQuote(request, signer, quote) {
|
|
|
1410
1583
|
...quote.raw.nearDepositTx === void 0 ? {} : { nearDepositTx: quote.raw.nearDepositTx }
|
|
1411
1584
|
};
|
|
1412
1585
|
}
|
|
1413
|
-
if (
|
|
1586
|
+
if (readString2(quote.raw.nearMcaWithdrawTxError)) {
|
|
1414
1587
|
throw invalidResponse(String(quote.raw.nearMcaWithdrawTxError));
|
|
1415
1588
|
}
|
|
1416
1589
|
const mode = resolveWithdrawMode(request);
|
|
@@ -1438,7 +1611,7 @@ function resolveWithdrawMode(request) {
|
|
|
1438
1611
|
function isPlainObject(value) {
|
|
1439
1612
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1440
1613
|
}
|
|
1441
|
-
function
|
|
1614
|
+
function readString2(value) {
|
|
1442
1615
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1443
1616
|
}
|
|
1444
1617
|
function invalidRequest(message) {
|
|
@@ -1926,7 +2099,7 @@ var McaSwapService = class {
|
|
|
1926
2099
|
"MCA relayer preview is missing business"
|
|
1927
2100
|
);
|
|
1928
2101
|
}
|
|
1929
|
-
const message =
|
|
2102
|
+
const message = readString3(input.quote.preview.messageToSign);
|
|
1930
2103
|
if (!message) {
|
|
1931
2104
|
throw new SwapSdkError(
|
|
1932
2105
|
"INVALID_API_RESPONSE",
|
|
@@ -1935,7 +2108,7 @@ var McaSwapService = class {
|
|
|
1935
2108
|
);
|
|
1936
2109
|
}
|
|
1937
2110
|
const depositAddress = extractMcaWithdrawDepositAddress({
|
|
1938
|
-
snapshotDepositAddress:
|
|
2111
|
+
snapshotDepositAddress: readString3(input.quote.raw.depositAddress),
|
|
1939
2112
|
preview: input.quote.preview,
|
|
1940
2113
|
bestQuote: input.quote.raw.bestQuote
|
|
1941
2114
|
});
|
|
@@ -2000,8 +2173,8 @@ var McaSwapService = class {
|
|
|
2000
2173
|
signal: input.signal,
|
|
2001
2174
|
idempotencyKey: input.idempotencyKey
|
|
2002
2175
|
});
|
|
2003
|
-
const orderId =
|
|
2004
|
-
const router =
|
|
2176
|
+
const orderId = readString3(raw.orderId) ?? readRecordString2(raw.deposit, "orderId");
|
|
2177
|
+
const router = readString3(raw.router) ?? input.quote.route.router;
|
|
2005
2178
|
const submittedDepositAddress = readRecordString2(raw.deposit, "depositAddress") ?? depositAddress;
|
|
2006
2179
|
if (!orderId || !router) {
|
|
2007
2180
|
throw new SwapSdkError(
|
|
@@ -2134,14 +2307,14 @@ function assertSignerMatchesQuote(signer, expected) {
|
|
|
2134
2307
|
);
|
|
2135
2308
|
}
|
|
2136
2309
|
}
|
|
2137
|
-
function
|
|
2310
|
+
function readString3(value) {
|
|
2138
2311
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2139
2312
|
}
|
|
2140
2313
|
function readRecordString2(value, field) {
|
|
2141
2314
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2142
2315
|
return void 0;
|
|
2143
2316
|
}
|
|
2144
|
-
return
|
|
2317
|
+
return readString3(value[field]);
|
|
2145
2318
|
}
|
|
2146
2319
|
|
|
2147
2320
|
// src/client/SwapClient.ts
|
|
@@ -2149,6 +2322,8 @@ var SwapClient = class {
|
|
|
2149
2322
|
constructor(config) {
|
|
2150
2323
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
2151
2324
|
this.reportRequests = /* @__PURE__ */ new Map();
|
|
2325
|
+
this.tokenListCache = /* @__PURE__ */ new Map();
|
|
2326
|
+
this.tokenListInflight = /* @__PURE__ */ new Map();
|
|
2152
2327
|
this.config = config;
|
|
2153
2328
|
this.api = new ApiClient(config);
|
|
2154
2329
|
this.registry = new ExecutorRegistry(config.executors ?? []);
|
|
@@ -2181,6 +2356,55 @@ var SwapClient = class {
|
|
|
2181
2356
|
buildRaw(request, options = {}) {
|
|
2182
2357
|
return this.api.build(request, options);
|
|
2183
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
|
+
}
|
|
2184
2408
|
async buildSwap(input) {
|
|
2185
2409
|
if (isMcaQuote(input.quote)) {
|
|
2186
2410
|
return this.managedSwapFlow.build({
|
|
@@ -2311,7 +2535,23 @@ var SwapClient = class {
|
|
|
2311
2535
|
emit({ type: "warning", executionId: build.executionId, warning });
|
|
2312
2536
|
}
|
|
2313
2537
|
}
|
|
2314
|
-
|
|
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) {
|
|
2315
2555
|
const status = await this.waitForOrder({
|
|
2316
2556
|
orderId,
|
|
2317
2557
|
router: orderRouter ?? build.router,
|
|
@@ -2546,6 +2786,13 @@ function isMcaQuote(quote) {
|
|
|
2546
2786
|
function readNonEmptyString(value) {
|
|
2547
2787
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2548
2788
|
}
|
|
2789
|
+
function cloneTokenList(tokens) {
|
|
2790
|
+
return tokens.map((token) => ({
|
|
2791
|
+
...token,
|
|
2792
|
+
sources: [...token.sources],
|
|
2793
|
+
raw: { ...token.raw }
|
|
2794
|
+
}));
|
|
2795
|
+
}
|
|
2549
2796
|
function delay(ms, signal) {
|
|
2550
2797
|
return new Promise((resolve, reject) => {
|
|
2551
2798
|
if (signal?.aborted) {
|
|
@@ -2594,6 +2841,8 @@ exports.formatUnits = formatUnits;
|
|
|
2594
2841
|
exports.fromApiChain = fromApiChain;
|
|
2595
2842
|
exports.isSameMcaSignerIdentity = isSameMcaSignerIdentity;
|
|
2596
2843
|
exports.normalizeBuild = normalizeBuild;
|
|
2844
|
+
exports.normalizeCrossChainToTokenList = normalizeCrossChainToTokenList;
|
|
2845
|
+
exports.normalizeFromTokenList = normalizeFromTokenList;
|
|
2597
2846
|
exports.normalizeHistory = normalizeHistory;
|
|
2598
2847
|
exports.normalizeHistoryStatus = normalizeHistoryStatus;
|
|
2599
2848
|
exports.normalizeMcaQuote = normalizeMcaQuote;
|