@rhea-finance/cross-chain-aggregation-dex 2.0.5 → 2.0.7
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 +148 -71
- 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 -6
- package/dist/index.d.ts +40 -6
- package/dist/index.js +266 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +265 -48
- 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
|
@@ -50,7 +50,7 @@ var ApiClient = class {
|
|
|
50
50
|
this.fetchImpl = fetchImpl.bind(globalThis);
|
|
51
51
|
}
|
|
52
52
|
quote(body, options = {}) {
|
|
53
|
-
return this.request("/api/swap/quote", "quote", {
|
|
53
|
+
return this.request("/api/v2/swap/quote", "quote", {
|
|
54
54
|
...options,
|
|
55
55
|
method: "POST",
|
|
56
56
|
body,
|
|
@@ -58,7 +58,7 @@ var ApiClient = class {
|
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
60
|
build(body, options = {}) {
|
|
61
|
-
return this.request("/api/swap/swap", "build", {
|
|
61
|
+
return this.request("/api/v2/swap/swap", "build", {
|
|
62
62
|
...options,
|
|
63
63
|
method: "POST",
|
|
64
64
|
body
|
|
@@ -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) {
|
|
@@ -1740,7 +1913,6 @@ var McaSwapService = class {
|
|
|
1740
1913
|
this.client = client;
|
|
1741
1914
|
this.relayerReports = /* @__PURE__ */ new Map();
|
|
1742
1915
|
this.now = config.now ?? Date.now;
|
|
1743
|
-
this.maxQuoteAgeMs = config.maxQuoteAgeMs === void 0 ? 3e4 : config.maxQuoteAgeMs;
|
|
1744
1916
|
this.reportMode = config.reportMode ?? "auto";
|
|
1745
1917
|
this.onEvent = config.onEvent;
|
|
1746
1918
|
this.resolveSignerIdentity = config.resolveSignerIdentity;
|
|
@@ -1762,7 +1934,6 @@ var McaSwapService = class {
|
|
|
1762
1934
|
return normalizeMcaQuote(request, signer, quote);
|
|
1763
1935
|
}
|
|
1764
1936
|
async build(input) {
|
|
1765
|
-
this.assertQuoteFresh(input.quote);
|
|
1766
1937
|
if (input.quote.executionMode === "withdraw-relayer") {
|
|
1767
1938
|
throw new SwapSdkError(
|
|
1768
1939
|
"INVALID_REQUEST",
|
|
@@ -1783,7 +1954,6 @@ var McaSwapService = class {
|
|
|
1783
1954
|
};
|
|
1784
1955
|
}
|
|
1785
1956
|
async swap(input) {
|
|
1786
|
-
this.assertQuoteFresh(input.quote);
|
|
1787
1957
|
if (input.quote.executionMode === "withdraw-relayer") {
|
|
1788
1958
|
return this.executeRelayerWithdraw({ ...input, quote: input.quote });
|
|
1789
1959
|
}
|
|
@@ -1926,7 +2096,7 @@ var McaSwapService = class {
|
|
|
1926
2096
|
"MCA relayer preview is missing business"
|
|
1927
2097
|
);
|
|
1928
2098
|
}
|
|
1929
|
-
const message =
|
|
2099
|
+
const message = readString3(input.quote.preview.messageToSign);
|
|
1930
2100
|
if (!message) {
|
|
1931
2101
|
throw new SwapSdkError(
|
|
1932
2102
|
"INVALID_API_RESPONSE",
|
|
@@ -1935,7 +2105,7 @@ var McaSwapService = class {
|
|
|
1935
2105
|
);
|
|
1936
2106
|
}
|
|
1937
2107
|
const depositAddress = extractMcaWithdrawDepositAddress({
|
|
1938
|
-
snapshotDepositAddress:
|
|
2108
|
+
snapshotDepositAddress: readString3(input.quote.raw.depositAddress),
|
|
1939
2109
|
preview: input.quote.preview,
|
|
1940
2110
|
bestQuote: input.quote.raw.bestQuote
|
|
1941
2111
|
});
|
|
@@ -2000,8 +2170,8 @@ var McaSwapService = class {
|
|
|
2000
2170
|
signal: input.signal,
|
|
2001
2171
|
idempotencyKey: input.idempotencyKey
|
|
2002
2172
|
});
|
|
2003
|
-
const orderId =
|
|
2004
|
-
const router =
|
|
2173
|
+
const orderId = readString3(raw.orderId) ?? readRecordString2(raw.deposit, "orderId");
|
|
2174
|
+
const router = readString3(raw.router) ?? input.quote.route.router;
|
|
2005
2175
|
const submittedDepositAddress = readRecordString2(raw.deposit, "depositAddress") ?? depositAddress;
|
|
2006
2176
|
if (!orderId || !router) {
|
|
2007
2177
|
throw new SwapSdkError(
|
|
@@ -2099,18 +2269,6 @@ var McaSwapService = class {
|
|
|
2099
2269
|
this.onEvent?.(event);
|
|
2100
2270
|
if (local !== this.onEvent) local?.(event);
|
|
2101
2271
|
}
|
|
2102
|
-
assertQuoteFresh(quote) {
|
|
2103
|
-
const now = this.now();
|
|
2104
|
-
const expiredByApi = quote.expiresAt !== void 0 && now > quote.expiresAt;
|
|
2105
|
-
const expiredByAge = this.maxQuoteAgeMs !== null && now - quote.receivedAt > Math.max(0, this.maxQuoteAgeMs);
|
|
2106
|
-
if (expiredByApi || expiredByAge) {
|
|
2107
|
-
throw new SwapSdkError(
|
|
2108
|
-
"QUOTE_EXPIRED",
|
|
2109
|
-
"build",
|
|
2110
|
-
"Quote has expired; request a fresh quote"
|
|
2111
|
-
);
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
2272
|
};
|
|
2115
2273
|
function buildRequestFromQuote(quote) {
|
|
2116
2274
|
const context = quote.buildContext;
|
|
@@ -2134,14 +2292,14 @@ function assertSignerMatchesQuote(signer, expected) {
|
|
|
2134
2292
|
);
|
|
2135
2293
|
}
|
|
2136
2294
|
}
|
|
2137
|
-
function
|
|
2295
|
+
function readString3(value) {
|
|
2138
2296
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2139
2297
|
}
|
|
2140
2298
|
function readRecordString2(value, field) {
|
|
2141
2299
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
2142
2300
|
return void 0;
|
|
2143
2301
|
}
|
|
2144
|
-
return
|
|
2302
|
+
return readString3(value[field]);
|
|
2145
2303
|
}
|
|
2146
2304
|
|
|
2147
2305
|
// src/client/SwapClient.ts
|
|
@@ -2149,6 +2307,8 @@ var SwapClient = class {
|
|
|
2149
2307
|
constructor(config) {
|
|
2150
2308
|
this.inFlight = /* @__PURE__ */ new Set();
|
|
2151
2309
|
this.reportRequests = /* @__PURE__ */ new Map();
|
|
2310
|
+
this.tokenListCache = /* @__PURE__ */ new Map();
|
|
2311
|
+
this.tokenListInflight = /* @__PURE__ */ new Map();
|
|
2152
2312
|
this.config = config;
|
|
2153
2313
|
this.api = new ApiClient(config);
|
|
2154
2314
|
this.registry = new ExecutorRegistry(config.executors ?? []);
|
|
@@ -2156,7 +2316,6 @@ var SwapClient = class {
|
|
|
2156
2316
|
this.now = config.now ?? Date.now;
|
|
2157
2317
|
this.managedSwapFlow = new McaSwapService(this, {
|
|
2158
2318
|
now: this.now,
|
|
2159
|
-
maxQuoteAgeMs: config.maxQuoteAgeMs,
|
|
2160
2319
|
reportMode: this.reportMode,
|
|
2161
2320
|
resolveSignerIdentity: (chain) => this.registry.getSigner(chain),
|
|
2162
2321
|
resolveMessageSigner: (chain) => this.registry.getSigner(chain, true),
|
|
@@ -2181,6 +2340,55 @@ var SwapClient = class {
|
|
|
2181
2340
|
buildRaw(request, options = {}) {
|
|
2182
2341
|
return this.api.build(request, options);
|
|
2183
2342
|
}
|
|
2343
|
+
async getFromTokens(request, options = {}) {
|
|
2344
|
+
return this.loadTokenList("from", request, options, async () => {
|
|
2345
|
+
const raw = await this.api.getFromTokenRows(request.chainId, options);
|
|
2346
|
+
return normalizeFromTokenList(raw, request.chainId);
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
async getCrossChainToTokens(request, options = {}) {
|
|
2350
|
+
return this.loadTokenList("cross-chain-to", request, options, async () => {
|
|
2351
|
+
const raw = await this.api.getCrossChainToTokenRows(
|
|
2352
|
+
request.chainId,
|
|
2353
|
+
options
|
|
2354
|
+
);
|
|
2355
|
+
return normalizeCrossChainToTokenList(raw, request.chainId);
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
async loadTokenList(direction, request, options, load) {
|
|
2359
|
+
if (!Number.isSafeInteger(request.chainId) || request.chainId <= 0) {
|
|
2360
|
+
throw new SwapSdkError(
|
|
2361
|
+
"INVALID_REQUEST",
|
|
2362
|
+
"tokens",
|
|
2363
|
+
`Token-list chainId must be a positive safe integer: ${String(
|
|
2364
|
+
request.chainId
|
|
2365
|
+
)}`
|
|
2366
|
+
);
|
|
2367
|
+
}
|
|
2368
|
+
const ttlMs = Math.max(0, this.config.tokenListCacheTtlMs ?? 6e5);
|
|
2369
|
+
const key = `${direction}:${request.chainId}`;
|
|
2370
|
+
const cached = this.tokenListCache.get(key);
|
|
2371
|
+
if (ttlMs > 0 && cached && cached.expiresAt > this.now()) {
|
|
2372
|
+
return cloneTokenList(cached.tokens);
|
|
2373
|
+
}
|
|
2374
|
+
const existing = options.signal ? void 0 : this.tokenListInflight.get(key);
|
|
2375
|
+
if (existing) return cloneTokenList(await existing);
|
|
2376
|
+
const pending = load().then((tokens) => {
|
|
2377
|
+
if (ttlMs > 0) {
|
|
2378
|
+
this.tokenListCache.set(key, {
|
|
2379
|
+
expiresAt: this.now() + ttlMs,
|
|
2380
|
+
tokens: cloneTokenList(tokens)
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
return tokens;
|
|
2384
|
+
}).finally(() => {
|
|
2385
|
+
if (this.tokenListInflight.get(key) === pending) {
|
|
2386
|
+
this.tokenListInflight.delete(key);
|
|
2387
|
+
}
|
|
2388
|
+
});
|
|
2389
|
+
if (!options.signal) this.tokenListInflight.set(key, pending);
|
|
2390
|
+
return cloneTokenList(await pending);
|
|
2391
|
+
}
|
|
2184
2392
|
async buildSwap(input) {
|
|
2185
2393
|
if (isMcaQuote(input.quote)) {
|
|
2186
2394
|
return this.managedSwapFlow.build({
|
|
@@ -2192,7 +2400,6 @@ var SwapClient = class {
|
|
|
2192
2400
|
return this.buildStandardSwap(input);
|
|
2193
2401
|
}
|
|
2194
2402
|
async buildStandardSwap(input) {
|
|
2195
|
-
this.assertQuoteFresh(input.quote);
|
|
2196
2403
|
const executionId = createExecutionId();
|
|
2197
2404
|
this.emit({ type: "build-started", executionId });
|
|
2198
2405
|
const context = input.quote.buildContext;
|
|
@@ -2311,7 +2518,23 @@ var SwapClient = class {
|
|
|
2311
2518
|
emit({ type: "warning", executionId: build.executionId, warning });
|
|
2312
2519
|
}
|
|
2313
2520
|
}
|
|
2314
|
-
|
|
2521
|
+
const waitsForCompletion = (input.waitFor ?? "submitted") === "completed";
|
|
2522
|
+
const requiresOrderStatus = build.isCrossChain || build.request?.confidentiality === "basic";
|
|
2523
|
+
if (waitsForCompletion && requiresOrderStatus && !orderId) {
|
|
2524
|
+
throw new SwapSdkError(
|
|
2525
|
+
"INVALID_API_RESPONSE",
|
|
2526
|
+
"status",
|
|
2527
|
+
"Swap submitted, but the API did not provide a status key",
|
|
2528
|
+
{
|
|
2529
|
+
details: {
|
|
2530
|
+
executionId: build.executionId,
|
|
2531
|
+
...result.txHash ? { txHash: result.txHash } : {},
|
|
2532
|
+
router: orderRouter ?? build.router
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
);
|
|
2536
|
+
}
|
|
2537
|
+
if (waitsForCompletion && orderId) {
|
|
2315
2538
|
const status = await this.waitForOrder({
|
|
2316
2539
|
orderId,
|
|
2317
2540
|
router: orderRouter ?? build.router,
|
|
@@ -2464,19 +2687,6 @@ var SwapClient = class {
|
|
|
2464
2687
|
emit(event) {
|
|
2465
2688
|
this.config.onEvent?.(event);
|
|
2466
2689
|
}
|
|
2467
|
-
assertQuoteFresh(quote) {
|
|
2468
|
-
const now = this.now();
|
|
2469
|
-
const maxAge = this.config.maxQuoteAgeMs === void 0 ? 3e4 : this.config.maxQuoteAgeMs;
|
|
2470
|
-
const expiredByApi = quote.expiresAt !== void 0 && now > quote.expiresAt;
|
|
2471
|
-
const expiredByAge = maxAge !== null && now - quote.receivedAt > Math.max(0, maxAge);
|
|
2472
|
-
if (expiredByApi || expiredByAge) {
|
|
2473
|
-
throw new SwapSdkError(
|
|
2474
|
-
"QUOTE_EXPIRED",
|
|
2475
|
-
"build",
|
|
2476
|
-
"Quote has expired; request a fresh quote"
|
|
2477
|
-
);
|
|
2478
|
-
}
|
|
2479
|
-
}
|
|
2480
2690
|
createReportRequest(build, result) {
|
|
2481
2691
|
const request = build.request;
|
|
2482
2692
|
const reportContext = build.reportContext;
|
|
@@ -2546,6 +2756,13 @@ function isMcaQuote(quote) {
|
|
|
2546
2756
|
function readNonEmptyString(value) {
|
|
2547
2757
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2548
2758
|
}
|
|
2759
|
+
function cloneTokenList(tokens) {
|
|
2760
|
+
return tokens.map((token) => ({
|
|
2761
|
+
...token,
|
|
2762
|
+
sources: [...token.sources],
|
|
2763
|
+
raw: { ...token.raw }
|
|
2764
|
+
}));
|
|
2765
|
+
}
|
|
2549
2766
|
function delay(ms, signal) {
|
|
2550
2767
|
return new Promise((resolve, reject) => {
|
|
2551
2768
|
if (signal?.aborted) {
|
|
@@ -2594,6 +2811,8 @@ exports.formatUnits = formatUnits;
|
|
|
2594
2811
|
exports.fromApiChain = fromApiChain;
|
|
2595
2812
|
exports.isSameMcaSignerIdentity = isSameMcaSignerIdentity;
|
|
2596
2813
|
exports.normalizeBuild = normalizeBuild;
|
|
2814
|
+
exports.normalizeCrossChainToTokenList = normalizeCrossChainToTokenList;
|
|
2815
|
+
exports.normalizeFromTokenList = normalizeFromTokenList;
|
|
2597
2816
|
exports.normalizeHistory = normalizeHistory;
|
|
2598
2817
|
exports.normalizeHistoryStatus = normalizeHistoryStatus;
|
|
2599
2818
|
exports.normalizeMcaQuote = normalizeMcaQuote;
|