@rhea-finance/cross-chain-aggregation-dex 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js +179 -87
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,6 +15,76 @@ function requiresRecipientInExecute(params) {
|
|
|
15
15
|
return "sender" in params && "receiveUser" in params;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// src/utils/errorMessages.ts
|
|
19
|
+
var ErrorMessages = {
|
|
20
|
+
// Parameter validation errors
|
|
21
|
+
MISSING_PARAMS: "Required parameters missing",
|
|
22
|
+
MISSING_TOKEN_ADDRESS: "Token address required",
|
|
23
|
+
INVALID_TOKEN_ADDRESS: "Invalid token address",
|
|
24
|
+
MISSING_USER_ADDRESS: "User address required",
|
|
25
|
+
INVALID_USER_ADDRESS: "Invalid user address",
|
|
26
|
+
// Quote errors
|
|
27
|
+
QUOTE_FAILED: "Failed to get quote",
|
|
28
|
+
QUOTE_INVALID: "Invalid quote",
|
|
29
|
+
QUOTE_NO_ROUTE: "No route found",
|
|
30
|
+
QUOTE_EXPIRED: "Quote expired, please refresh",
|
|
31
|
+
// Execution errors
|
|
32
|
+
EXECUTE_FAILED: "Transaction failed",
|
|
33
|
+
EXECUTE_INVALID_QUOTE: "Invalid quote, please refresh",
|
|
34
|
+
EXECUTE_INSUFFICIENT_BALANCE: "Insufficient balance",
|
|
35
|
+
EXECUTE_INSUFFICIENT_LIQUIDITY: "Insufficient liquidity",
|
|
36
|
+
EXECUTE_SLIPPAGE_TOO_HIGH: "Price changed, please refresh",
|
|
37
|
+
// Network/API errors
|
|
38
|
+
NETWORK_ERROR: "Network error, please try again",
|
|
39
|
+
API_ERROR: "Service temporarily unavailable",
|
|
40
|
+
// Gas/Transaction errors
|
|
41
|
+
GAS_ESTIMATE_FAILED: "Unable to estimate transaction fee",
|
|
42
|
+
GAS_PRICE_FAILED: "Failed to get transaction fee",
|
|
43
|
+
TRANSACTION_REVERTED: "Transaction would fail, please refresh"
|
|
44
|
+
};
|
|
45
|
+
function getErrorMessage(error, fallback = ErrorMessages.EXECUTE_FAILED) {
|
|
46
|
+
if (!error) return fallback;
|
|
47
|
+
if (error && error.length > 0) {
|
|
48
|
+
return error;
|
|
49
|
+
}
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
function normalizeError(error) {
|
|
53
|
+
if (!error) return ErrorMessages.EXECUTE_FAILED;
|
|
54
|
+
const errorLower = error.toLowerCase();
|
|
55
|
+
if (errorLower.includes("missing") || errorLower.includes("required")) {
|
|
56
|
+
if (errorLower.includes("token")) return ErrorMessages.MISSING_TOKEN_ADDRESS;
|
|
57
|
+
if (errorLower.includes("address") || errorLower.includes("user") || errorLower.includes("sender") || errorLower.includes("recipient")) {
|
|
58
|
+
return ErrorMessages.MISSING_USER_ADDRESS;
|
|
59
|
+
}
|
|
60
|
+
return ErrorMessages.MISSING_PARAMS;
|
|
61
|
+
}
|
|
62
|
+
if (errorLower.includes("invalid")) {
|
|
63
|
+
if (errorLower.includes("token")) return ErrorMessages.INVALID_TOKEN_ADDRESS;
|
|
64
|
+
if (errorLower.includes("address") || errorLower.includes("user")) {
|
|
65
|
+
return ErrorMessages.INVALID_USER_ADDRESS;
|
|
66
|
+
}
|
|
67
|
+
if (errorLower.includes("quote")) return ErrorMessages.QUOTE_INVALID;
|
|
68
|
+
}
|
|
69
|
+
if (errorLower.includes("quote") && (errorLower.includes("fail") || errorLower.includes("error"))) {
|
|
70
|
+
return ErrorMessages.QUOTE_FAILED;
|
|
71
|
+
}
|
|
72
|
+
if (errorLower.includes("route") || errorLower.includes("no path")) {
|
|
73
|
+
return ErrorMessages.QUOTE_NO_ROUTE;
|
|
74
|
+
}
|
|
75
|
+
if (errorLower.includes("balance") && errorLower.includes("insufficient")) {
|
|
76
|
+
return ErrorMessages.EXECUTE_INSUFFICIENT_BALANCE;
|
|
77
|
+
}
|
|
78
|
+
if (errorLower.includes("liquidity") || errorLower.includes("slippage")) {
|
|
79
|
+
return ErrorMessages.EXECUTE_SLIPPAGE_TOO_HIGH;
|
|
80
|
+
}
|
|
81
|
+
if (errorLower.includes("gas")) {
|
|
82
|
+
if (errorLower.includes("price")) return ErrorMessages.GAS_PRICE_FAILED;
|
|
83
|
+
return ErrorMessages.GAS_ESTIMATE_FAILED;
|
|
84
|
+
}
|
|
85
|
+
return error;
|
|
86
|
+
}
|
|
87
|
+
|
|
18
88
|
// src/utils/logger.ts
|
|
19
89
|
var LOG_LEVELS = {
|
|
20
90
|
silent: 0,
|
|
@@ -155,7 +225,7 @@ function findBestEvmBluechipToken(bluechipTokens, nativeTokenAddress) {
|
|
|
155
225
|
};
|
|
156
226
|
}
|
|
157
227
|
if (preferredTokens.length === 0) {
|
|
158
|
-
throw new Error(
|
|
228
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
159
229
|
}
|
|
160
230
|
return preferredTokens[0];
|
|
161
231
|
}
|
|
@@ -336,7 +406,7 @@ var NearSmartRouter = class {
|
|
|
336
406
|
amountOut: "0",
|
|
337
407
|
minAmountOut: "0",
|
|
338
408
|
routes: [],
|
|
339
|
-
error:
|
|
409
|
+
error: ErrorMessages.MISSING_TOKEN_ADDRESS
|
|
340
410
|
};
|
|
341
411
|
}
|
|
342
412
|
const normalizedTokenIn = normalizeTokenId(
|
|
@@ -356,7 +426,7 @@ var NearSmartRouter = class {
|
|
|
356
426
|
amountOut: "0",
|
|
357
427
|
minAmountOut: "0",
|
|
358
428
|
routes: [],
|
|
359
|
-
error:
|
|
429
|
+
error: ErrorMessages.INVALID_TOKEN_ADDRESS
|
|
360
430
|
};
|
|
361
431
|
}
|
|
362
432
|
const slippageBps = convertSlippageToBasisPoints(slippage);
|
|
@@ -377,7 +447,7 @@ var NearSmartRouter = class {
|
|
|
377
447
|
amountOut: "0",
|
|
378
448
|
minAmountOut: "0",
|
|
379
449
|
routes: [],
|
|
380
|
-
error: response?.result_msg || response?.result_message ||
|
|
450
|
+
error: normalizeError(response?.result_msg || response?.result_message) || ErrorMessages.QUOTE_NO_ROUTE
|
|
381
451
|
};
|
|
382
452
|
}
|
|
383
453
|
const { routes: serverRoutes, amount_out } = response.result_data;
|
|
@@ -416,7 +486,7 @@ var NearSmartRouter = class {
|
|
|
416
486
|
amountOut: "0",
|
|
417
487
|
minAmountOut: "0",
|
|
418
488
|
routes: [],
|
|
419
|
-
error: error?.message ||
|
|
489
|
+
error: normalizeError(error?.message) || ErrorMessages.QUOTE_FAILED
|
|
420
490
|
};
|
|
421
491
|
}
|
|
422
492
|
}
|
|
@@ -429,7 +499,7 @@ var NearSmartRouter = class {
|
|
|
429
499
|
if (!quote.success || !quote.routes.length) {
|
|
430
500
|
return {
|
|
431
501
|
success: false,
|
|
432
|
-
error:
|
|
502
|
+
error: ErrorMessages.EXECUTE_INVALID_QUOTE
|
|
433
503
|
};
|
|
434
504
|
}
|
|
435
505
|
const swapActions = [];
|
|
@@ -448,7 +518,7 @@ var NearSmartRouter = class {
|
|
|
448
518
|
if (!swapActions.length) {
|
|
449
519
|
return {
|
|
450
520
|
success: false,
|
|
451
|
-
error:
|
|
521
|
+
error: ErrorMessages.QUOTE_INVALID
|
|
452
522
|
};
|
|
453
523
|
}
|
|
454
524
|
const finalRecipient = depositAddress || recipient;
|
|
@@ -549,13 +619,13 @@ var NearSmartRouter = class {
|
|
|
549
619
|
} else {
|
|
550
620
|
return {
|
|
551
621
|
success: false,
|
|
552
|
-
error: result.message ||
|
|
622
|
+
error: normalizeError(result.message) || ErrorMessages.EXECUTE_FAILED
|
|
553
623
|
};
|
|
554
624
|
}
|
|
555
625
|
} catch (error) {
|
|
556
626
|
return {
|
|
557
627
|
success: false,
|
|
558
|
-
error: error?.message ||
|
|
628
|
+
error: normalizeError(error?.message) || ErrorMessages.EXECUTE_FAILED
|
|
559
629
|
};
|
|
560
630
|
}
|
|
561
631
|
}
|
|
@@ -617,7 +687,7 @@ var AggregateDexRouter = class {
|
|
|
617
687
|
amountOut: "0",
|
|
618
688
|
minAmountOut: "0",
|
|
619
689
|
routes: [],
|
|
620
|
-
error:
|
|
690
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
621
691
|
};
|
|
622
692
|
}
|
|
623
693
|
const { tokenIn, tokenOut, amountIn, slippage, sender, recipient } = params;
|
|
@@ -630,7 +700,7 @@ var AggregateDexRouter = class {
|
|
|
630
700
|
amountOut: "0",
|
|
631
701
|
minAmountOut: "0",
|
|
632
702
|
routes: [],
|
|
633
|
-
error:
|
|
703
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
634
704
|
};
|
|
635
705
|
}
|
|
636
706
|
if (!tokenIn?.address || !tokenOut?.address) {
|
|
@@ -642,7 +712,7 @@ var AggregateDexRouter = class {
|
|
|
642
712
|
amountOut: "0",
|
|
643
713
|
minAmountOut: "0",
|
|
644
714
|
routes: [],
|
|
645
|
-
error:
|
|
715
|
+
error: ErrorMessages.MISSING_TOKEN_ADDRESS
|
|
646
716
|
};
|
|
647
717
|
}
|
|
648
718
|
const normalizedTokenIn = normalizeTokenId(
|
|
@@ -662,7 +732,7 @@ var AggregateDexRouter = class {
|
|
|
662
732
|
amountOut: "0",
|
|
663
733
|
minAmountOut: "0",
|
|
664
734
|
routes: [],
|
|
665
|
-
error:
|
|
735
|
+
error: ErrorMessages.INVALID_TOKEN_ADDRESS
|
|
666
736
|
};
|
|
667
737
|
}
|
|
668
738
|
const slippageBps = convertSlippageToBasisPoints(slippage);
|
|
@@ -685,7 +755,7 @@ var AggregateDexRouter = class {
|
|
|
685
755
|
amountOut: "0",
|
|
686
756
|
minAmountOut: "0",
|
|
687
757
|
routes: [],
|
|
688
|
-
error:
|
|
758
|
+
error: ErrorMessages.QUOTE_FAILED
|
|
689
759
|
};
|
|
690
760
|
}
|
|
691
761
|
const {
|
|
@@ -721,7 +791,7 @@ var AggregateDexRouter = class {
|
|
|
721
791
|
amountOut: "0",
|
|
722
792
|
minAmountOut: "0",
|
|
723
793
|
routes: [],
|
|
724
|
-
error:
|
|
794
|
+
error: normalizeError(error?.message) || ErrorMessages.QUOTE_FAILED
|
|
725
795
|
};
|
|
726
796
|
}
|
|
727
797
|
}
|
|
@@ -730,7 +800,7 @@ var AggregateDexRouter = class {
|
|
|
730
800
|
*/
|
|
731
801
|
async finalizeQuote(params, depositAddress) {
|
|
732
802
|
if (!requiresRecipient(params)) {
|
|
733
|
-
throw new Error(
|
|
803
|
+
throw new Error(ErrorMessages.MISSING_USER_ADDRESS);
|
|
734
804
|
}
|
|
735
805
|
return await this.quote({
|
|
736
806
|
...params,
|
|
@@ -747,7 +817,7 @@ var AggregateDexRouter = class {
|
|
|
747
817
|
if (adjustedQuote.success && adjustedQuote.routerMsg && adjustedQuote.signature) {
|
|
748
818
|
return adjustedQuote;
|
|
749
819
|
} else {
|
|
750
|
-
throw new Error(
|
|
820
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
751
821
|
}
|
|
752
822
|
}
|
|
753
823
|
async ensureQuoteAmountWithinBalance(quoteParams, actualBalance, context) {
|
|
@@ -779,7 +849,7 @@ var AggregateDexRouter = class {
|
|
|
779
849
|
}
|
|
780
850
|
const quote = await this.quote(quoteParams);
|
|
781
851
|
if (!quote.success) {
|
|
782
|
-
throw new Error(
|
|
852
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
783
853
|
}
|
|
784
854
|
if (quote.amountIn !== quoteParams.amountIn) {
|
|
785
855
|
const apiAmountBig = new Big3__default.default(quote.amountIn);
|
|
@@ -802,26 +872,26 @@ var AggregateDexRouter = class {
|
|
|
802
872
|
if (!requiresRecipientInExecute(params)) {
|
|
803
873
|
return {
|
|
804
874
|
success: false,
|
|
805
|
-
error:
|
|
875
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
806
876
|
};
|
|
807
877
|
}
|
|
808
878
|
const { quote, sender, receiveUser } = params;
|
|
809
879
|
if (!quote.success) {
|
|
810
880
|
return {
|
|
811
881
|
success: false,
|
|
812
|
-
error:
|
|
882
|
+
error: ErrorMessages.EXECUTE_INVALID_QUOTE
|
|
813
883
|
};
|
|
814
884
|
}
|
|
815
885
|
if (!receiveUser || receiveUser.trim() === "") {
|
|
816
886
|
return {
|
|
817
887
|
success: false,
|
|
818
|
-
error:
|
|
888
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
819
889
|
};
|
|
820
890
|
}
|
|
821
891
|
if (receiveUser.startsWith("0x") && receiveUser.length === 42) {
|
|
822
892
|
return {
|
|
823
893
|
success: false,
|
|
824
|
-
error:
|
|
894
|
+
error: ErrorMessages.INVALID_USER_ADDRESS
|
|
825
895
|
};
|
|
826
896
|
}
|
|
827
897
|
const slippage = quote.slippage || 5e-3;
|
|
@@ -853,7 +923,7 @@ var AggregateDexRouter = class {
|
|
|
853
923
|
} catch (error) {
|
|
854
924
|
return {
|
|
855
925
|
success: false,
|
|
856
|
-
error:
|
|
926
|
+
error: normalizeError(error?.message) || ErrorMessages.QUOTE_FAILED
|
|
857
927
|
};
|
|
858
928
|
}
|
|
859
929
|
const routerMsg = finalQuote.routerMsg;
|
|
@@ -861,7 +931,7 @@ var AggregateDexRouter = class {
|
|
|
861
931
|
if (!routerMsg || !signature) {
|
|
862
932
|
return {
|
|
863
933
|
success: false,
|
|
864
|
-
error:
|
|
934
|
+
error: ErrorMessages.QUOTE_FAILED
|
|
865
935
|
};
|
|
866
936
|
}
|
|
867
937
|
const tokens = finalQuote.tokens || [];
|
|
@@ -1056,7 +1126,7 @@ var AggregateDexRouter = class {
|
|
|
1056
1126
|
} catch (error) {
|
|
1057
1127
|
return {
|
|
1058
1128
|
success: false,
|
|
1059
|
-
error:
|
|
1129
|
+
error: normalizeError(error?.message) || ErrorMessages.QUOTE_FAILED
|
|
1060
1130
|
};
|
|
1061
1131
|
}
|
|
1062
1132
|
const finalAmountToTransfer = finalQuoteForExecution.amountIn;
|
|
@@ -1087,13 +1157,13 @@ var AggregateDexRouter = class {
|
|
|
1087
1157
|
} else {
|
|
1088
1158
|
return {
|
|
1089
1159
|
success: false,
|
|
1090
|
-
error:
|
|
1160
|
+
error: normalizeError(result.message) || ErrorMessages.EXECUTE_FAILED
|
|
1091
1161
|
};
|
|
1092
1162
|
}
|
|
1093
1163
|
} catch (error) {
|
|
1094
1164
|
return {
|
|
1095
1165
|
success: false,
|
|
1096
|
-
error:
|
|
1166
|
+
error: normalizeError(error?.message) || ErrorMessages.EXECUTE_FAILED
|
|
1097
1167
|
};
|
|
1098
1168
|
}
|
|
1099
1169
|
}
|
|
@@ -1190,6 +1260,7 @@ async function estimateGasLimit(gas, to, transactionData, value, sender, chainId
|
|
|
1190
1260
|
const bufferPercent = getGasBuffer(chainId);
|
|
1191
1261
|
let estimatedGasLimit;
|
|
1192
1262
|
let hasReliableEstimate = false;
|
|
1263
|
+
let rpcEstimateError = null;
|
|
1193
1264
|
if (gas) {
|
|
1194
1265
|
try {
|
|
1195
1266
|
const gasBN = ethers.ethers.BigNumber.from(gas);
|
|
@@ -1218,6 +1289,11 @@ async function estimateGasLimit(gas, to, transactionData, value, sender, chainId
|
|
|
1218
1289
|
hasReliableEstimate = true;
|
|
1219
1290
|
}
|
|
1220
1291
|
} catch (estimateError) {
|
|
1292
|
+
rpcEstimateError = {
|
|
1293
|
+
code: estimateError?.code,
|
|
1294
|
+
reason: estimateError?.reason,
|
|
1295
|
+
message: estimateError?.message || String(estimateError)
|
|
1296
|
+
};
|
|
1221
1297
|
console.warn("RPC gas estimate failed:", {
|
|
1222
1298
|
error: estimateError?.message || String(estimateError),
|
|
1223
1299
|
code: estimateError?.code,
|
|
@@ -1231,12 +1307,12 @@ async function estimateGasLimit(gas, to, transactionData, value, sender, chainId
|
|
|
1231
1307
|
});
|
|
1232
1308
|
}
|
|
1233
1309
|
if (estimatedGasLimit && estimatedGasLimit.gt(0) && hasReliableEstimate) {
|
|
1234
|
-
return [estimatedGasLimit, true];
|
|
1310
|
+
return [estimatedGasLimit, true, rpcEstimateError];
|
|
1235
1311
|
}
|
|
1236
1312
|
if (estimatedGasLimit && estimatedGasLimit.gt(0)) {
|
|
1237
|
-
return [estimatedGasLimit, false];
|
|
1313
|
+
return [estimatedGasLimit, false, rpcEstimateError];
|
|
1238
1314
|
}
|
|
1239
|
-
return [ethers.ethers.BigNumber.from(CONSERVATIVE_GAS_LIMIT), false];
|
|
1315
|
+
return [ethers.ethers.BigNumber.from(CONSERVATIVE_GAS_LIMIT), false, rpcEstimateError];
|
|
1240
1316
|
}
|
|
1241
1317
|
async function getEip1559FeeData(chainId, evmChainAdapter) {
|
|
1242
1318
|
const feeData = {};
|
|
@@ -1314,7 +1390,7 @@ var BitgetRouter = class {
|
|
|
1314
1390
|
amountOut: "0",
|
|
1315
1391
|
minAmountOut: "0",
|
|
1316
1392
|
routes: [],
|
|
1317
|
-
error:
|
|
1393
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
1318
1394
|
};
|
|
1319
1395
|
}
|
|
1320
1396
|
const { tokenIn, tokenOut, amountIn, slippage, sender, recipient } = params;
|
|
@@ -1327,7 +1403,7 @@ var BitgetRouter = class {
|
|
|
1327
1403
|
amountOut: "0",
|
|
1328
1404
|
minAmountOut: "0",
|
|
1329
1405
|
routes: [],
|
|
1330
|
-
error:
|
|
1406
|
+
error: ErrorMessages.MISSING_USER_ADDRESS
|
|
1331
1407
|
};
|
|
1332
1408
|
}
|
|
1333
1409
|
if (tokenIn?.address === void 0 || tokenOut?.address === void 0) {
|
|
@@ -1339,7 +1415,7 @@ var BitgetRouter = class {
|
|
|
1339
1415
|
amountOut: "0",
|
|
1340
1416
|
minAmountOut: "0",
|
|
1341
1417
|
routes: [],
|
|
1342
|
-
error:
|
|
1418
|
+
error: ErrorMessages.MISSING_TOKEN_ADDRESS
|
|
1343
1419
|
};
|
|
1344
1420
|
}
|
|
1345
1421
|
const normalizedTokenIn = tokenIn.address === "" ? "" : this.normalizeEvmAddress(tokenIn.address);
|
|
@@ -1361,7 +1437,7 @@ var BitgetRouter = class {
|
|
|
1361
1437
|
if (!isBitgetResponseSuccess(response) || !response.data) {
|
|
1362
1438
|
return createQuoteError(
|
|
1363
1439
|
params,
|
|
1364
|
-
response.msg ||
|
|
1440
|
+
normalizeError(response.msg) || ErrorMessages.QUOTE_FAILED
|
|
1365
1441
|
);
|
|
1366
1442
|
}
|
|
1367
1443
|
const {
|
|
@@ -1427,21 +1503,21 @@ var BitgetRouter = class {
|
|
|
1427
1503
|
} catch (error) {
|
|
1428
1504
|
return createQuoteError(
|
|
1429
1505
|
params,
|
|
1430
|
-
error?.message ||
|
|
1506
|
+
normalizeError(error?.message) || ErrorMessages.QUOTE_FAILED
|
|
1431
1507
|
);
|
|
1432
1508
|
}
|
|
1433
1509
|
}
|
|
1434
1510
|
async executeSwap(params) {
|
|
1435
1511
|
try {
|
|
1436
1512
|
if (!requiresRecipientInExecute(params)) {
|
|
1437
|
-
return createExecuteError(
|
|
1513
|
+
return createExecuteError(ErrorMessages.MISSING_USER_ADDRESS);
|
|
1438
1514
|
}
|
|
1439
1515
|
const { quote, sender, receiveUser } = params;
|
|
1440
1516
|
if (!quote.success) {
|
|
1441
|
-
return createExecuteError(
|
|
1517
|
+
return createExecuteError(ErrorMessages.EXECUTE_INVALID_QUOTE);
|
|
1442
1518
|
}
|
|
1443
1519
|
if (!receiveUser || receiveUser.trim() === "") {
|
|
1444
|
-
return createExecuteError(
|
|
1520
|
+
return createExecuteError(ErrorMessages.MISSING_USER_ADDRESS);
|
|
1445
1521
|
}
|
|
1446
1522
|
let market;
|
|
1447
1523
|
try {
|
|
@@ -1449,13 +1525,13 @@ var BitgetRouter = class {
|
|
|
1449
1525
|
const routerMsg = JSON.parse(quote.routerMsg);
|
|
1450
1526
|
market = routerMsg.market || "";
|
|
1451
1527
|
} else {
|
|
1452
|
-
return createExecuteError(
|
|
1528
|
+
return createExecuteError(ErrorMessages.QUOTE_EXPIRED);
|
|
1453
1529
|
}
|
|
1454
1530
|
} catch (error) {
|
|
1455
|
-
return createExecuteError(
|
|
1531
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1456
1532
|
}
|
|
1457
1533
|
if (!market) {
|
|
1458
|
-
return createExecuteError(
|
|
1534
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1459
1535
|
}
|
|
1460
1536
|
const normalizedTokenIn = this.normalizeEvmAddress(
|
|
1461
1537
|
quote.tokenIn.address
|
|
@@ -1479,7 +1555,7 @@ var BitgetRouter = class {
|
|
|
1479
1555
|
});
|
|
1480
1556
|
if (!isBitgetResponseSuccess(reQuoteResponse) || !reQuoteResponse.data) {
|
|
1481
1557
|
return createExecuteError(
|
|
1482
|
-
|
|
1558
|
+
normalizeError(reQuoteResponse.msg) || ErrorMessages.QUOTE_EXPIRED
|
|
1483
1559
|
);
|
|
1484
1560
|
}
|
|
1485
1561
|
market = reQuoteResponse.data?.market || market;
|
|
@@ -1499,13 +1575,11 @@ var BitgetRouter = class {
|
|
|
1499
1575
|
});
|
|
1500
1576
|
if (!isBitgetResponseSuccess(swapResponse) || !swapResponse.data) {
|
|
1501
1577
|
return createExecuteError(
|
|
1502
|
-
swapResponse.msg ||
|
|
1578
|
+
normalizeError(swapResponse.msg) || ErrorMessages.QUOTE_FAILED
|
|
1503
1579
|
);
|
|
1504
1580
|
}
|
|
1505
1581
|
if (swapResponse.data?.estimateRevert === true) {
|
|
1506
|
-
return createExecuteError(
|
|
1507
|
-
"Transaction will fail on-chain (slippage too high or price changed). Please refresh quote."
|
|
1508
|
-
);
|
|
1582
|
+
return createExecuteError(ErrorMessages.EXECUTE_SLIPPAGE_TOO_HIGH);
|
|
1509
1583
|
}
|
|
1510
1584
|
let transactionData = swapResponse.data?.calldata || swapResponse.data?.data;
|
|
1511
1585
|
const to = swapResponse.data?.contract || swapResponse.data?.to;
|
|
@@ -1519,14 +1593,14 @@ var BitgetRouter = class {
|
|
|
1519
1593
|
}
|
|
1520
1594
|
const gas = swapResponse.data?.gas || (swapResponse.data?.computeUnits !== void 0 ? String(swapResponse.data.computeUnits) : void 0);
|
|
1521
1595
|
if (!to || !transactionData) {
|
|
1522
|
-
return createExecuteError(
|
|
1596
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1523
1597
|
}
|
|
1524
1598
|
if (transactionData.length < 10 || !/^0x[0-9a-fA-F]+$/.test(transactionData)) {
|
|
1525
|
-
return createExecuteError(
|
|
1599
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1526
1600
|
}
|
|
1527
1601
|
if (normalizedTokenIn && normalizedTokenIn !== "") {
|
|
1528
1602
|
if (!this.evmChainAdapter.getBalance) {
|
|
1529
|
-
return createExecuteError(
|
|
1603
|
+
return createExecuteError(ErrorMessages.NETWORK_ERROR);
|
|
1530
1604
|
}
|
|
1531
1605
|
const tokenBalanceFormatted = await this.evmChainAdapter.getBalance({
|
|
1532
1606
|
address: sender,
|
|
@@ -1536,9 +1610,7 @@ var BitgetRouter = class {
|
|
|
1536
1610
|
const balanceBN = ethers.ethers.utils.parseUnits(tokenBalanceFormatted || "0", tokenDecimals);
|
|
1537
1611
|
const amountInBN = ethers.ethers.BigNumber.from(quote.amountIn);
|
|
1538
1612
|
if (balanceBN.lt(amountInBN)) {
|
|
1539
|
-
return createExecuteError(
|
|
1540
|
-
`Insufficient token balance: have ${tokenBalanceFormatted}, need ${ethers.ethers.utils.formatUnits(amountInBN, tokenDecimals)}`
|
|
1541
|
-
);
|
|
1613
|
+
return createExecuteError(ErrorMessages.EXECUTE_INSUFFICIENT_BALANCE);
|
|
1542
1614
|
}
|
|
1543
1615
|
const currentAllowance = await this.evmChainAdapter.getAllowance({
|
|
1544
1616
|
tokenAddress: normalizedTokenIn,
|
|
@@ -1548,7 +1620,7 @@ var BitgetRouter = class {
|
|
|
1548
1620
|
const allowanceBN = ethers.ethers.BigNumber.from(currentAllowance);
|
|
1549
1621
|
if (allowanceBN.lt(amountInBN)) {
|
|
1550
1622
|
try {
|
|
1551
|
-
|
|
1623
|
+
await this.evmChainAdapter.approve({
|
|
1552
1624
|
tokenAddress: normalizedTokenIn,
|
|
1553
1625
|
spender: to,
|
|
1554
1626
|
amount: ethers.ethers.constants.MaxUint256.toString()
|
|
@@ -1571,19 +1643,17 @@ var BitgetRouter = class {
|
|
|
1571
1643
|
retryCount++;
|
|
1572
1644
|
}
|
|
1573
1645
|
if (newAllowanceBN.lt(amountInBN)) {
|
|
1574
|
-
return createExecuteError(
|
|
1575
|
-
`Token approval insufficient after ${MAX_APPROVAL_RETRIES} retries. Approval tx: ${approveResult.txHash}`
|
|
1576
|
-
);
|
|
1646
|
+
return createExecuteError(ErrorMessages.NETWORK_ERROR);
|
|
1577
1647
|
}
|
|
1578
1648
|
} catch (error) {
|
|
1579
1649
|
return createExecuteError(
|
|
1580
|
-
|
|
1650
|
+
normalizeError(error?.message) || ErrorMessages.NETWORK_ERROR
|
|
1581
1651
|
);
|
|
1582
1652
|
}
|
|
1583
1653
|
}
|
|
1584
1654
|
} else {
|
|
1585
1655
|
if (!this.evmChainAdapter.getBalance) {
|
|
1586
|
-
return createExecuteError(
|
|
1656
|
+
return createExecuteError(ErrorMessages.NETWORK_ERROR);
|
|
1587
1657
|
}
|
|
1588
1658
|
const nativeBalanceFormatted = await this.evmChainAdapter.getBalance({
|
|
1589
1659
|
address: sender,
|
|
@@ -1607,9 +1677,7 @@ var BitgetRouter = class {
|
|
|
1607
1677
|
const gasCostEstimate = estimatedGasLimitForBalance.mul(gasPriceEstimate2);
|
|
1608
1678
|
const totalRequired = amountInBN.add(gasCostEstimate);
|
|
1609
1679
|
if (balanceBN.lt(totalRequired)) {
|
|
1610
|
-
return createExecuteError(
|
|
1611
|
-
`Insufficient native token balance: have ${nativeBalanceFormatted} ETH, need ${ethers.ethers.utils.formatEther(totalRequired)} ETH`
|
|
1612
|
-
);
|
|
1680
|
+
return createExecuteError(ErrorMessages.EXECUTE_INSUFFICIENT_BALANCE);
|
|
1613
1681
|
}
|
|
1614
1682
|
}
|
|
1615
1683
|
if (normalizedTokenIn && normalizedTokenIn !== "") {
|
|
@@ -1621,12 +1689,10 @@ var BitgetRouter = class {
|
|
|
1621
1689
|
const finalAllowanceBN = ethers.ethers.BigNumber.from(finalAllowanceCheck);
|
|
1622
1690
|
const amountInBN = ethers.ethers.BigNumber.from(quote.amountIn);
|
|
1623
1691
|
if (finalAllowanceBN.lt(amountInBN)) {
|
|
1624
|
-
return createExecuteError(
|
|
1625
|
-
`Insufficient allowance: current ${finalAllowanceBN.toString()}, required ${amountInBN.toString()}`
|
|
1626
|
-
);
|
|
1692
|
+
return createExecuteError(ErrorMessages.NETWORK_ERROR);
|
|
1627
1693
|
}
|
|
1628
1694
|
}
|
|
1629
|
-
const [estimatedGasLimit, hasReliableEstimate] = await estimateGasLimit(
|
|
1695
|
+
const [estimatedGasLimit, hasReliableEstimate, rpcEstimateError] = await estimateGasLimit(
|
|
1630
1696
|
gas,
|
|
1631
1697
|
to,
|
|
1632
1698
|
transactionData,
|
|
@@ -1635,7 +1701,29 @@ var BitgetRouter = class {
|
|
|
1635
1701
|
this.chainId,
|
|
1636
1702
|
this.evmChainAdapter
|
|
1637
1703
|
);
|
|
1638
|
-
if (
|
|
1704
|
+
if (rpcEstimateError) {
|
|
1705
|
+
const isUnpredictableGasLimit = rpcEstimateError.code === "UNPREDICTABLE_GAS_LIMIT" || rpcEstimateError.message && rpcEstimateError.message.includes("UNPREDICTABLE_GAS_LIMIT") || rpcEstimateError.reason && rpcEstimateError.reason.includes("execution reverted");
|
|
1706
|
+
if (isUnpredictableGasLimit) {
|
|
1707
|
+
logger.warn("Blocking transaction due to RPC gas estimation failure", {
|
|
1708
|
+
chainId: this.chainId,
|
|
1709
|
+
tokenIn: quote.tokenIn.symbol,
|
|
1710
|
+
tokenOut: quote.tokenOut.symbol,
|
|
1711
|
+
rpcError: rpcEstimateError
|
|
1712
|
+
});
|
|
1713
|
+
return createExecuteError(ErrorMessages.EXECUTE_INSUFFICIENT_LIQUIDITY);
|
|
1714
|
+
}
|
|
1715
|
+
if (!gas || gas === "0") {
|
|
1716
|
+
return createExecuteError(ErrorMessages.GAS_ESTIMATE_FAILED);
|
|
1717
|
+
}
|
|
1718
|
+
logger.warn("RPC gas estimation failed, using Bitget estimate", {
|
|
1719
|
+
chainId: this.chainId,
|
|
1720
|
+
tokenIn: quote.tokenIn.symbol,
|
|
1721
|
+
tokenOut: quote.tokenOut.symbol,
|
|
1722
|
+
estimatedGasLimit: estimatedGasLimit.toString(),
|
|
1723
|
+
bitgetGas: gas || "not provided",
|
|
1724
|
+
rpcError: rpcEstimateError
|
|
1725
|
+
});
|
|
1726
|
+
} else if (!hasReliableEstimate) {
|
|
1639
1727
|
logger.warn("Gas estimation unreliable, using conservative default", {
|
|
1640
1728
|
chainId: this.chainId,
|
|
1641
1729
|
tokenIn: quote.tokenIn.symbol,
|
|
@@ -1658,7 +1746,7 @@ var BitgetRouter = class {
|
|
|
1658
1746
|
if (!feeData.maxFeePerGas || !feeData.maxPriorityFeePerGas || feeData.maxFeePerGas.lte(0) || feeData.maxPriorityFeePerGas.lte(0)) {
|
|
1659
1747
|
const cachedGasPrice = await getCachedGasPrice();
|
|
1660
1748
|
if (!cachedGasPrice || cachedGasPrice.lte(0)) {
|
|
1661
|
-
return createExecuteError(
|
|
1749
|
+
return createExecuteError(ErrorMessages.GAS_PRICE_FAILED);
|
|
1662
1750
|
}
|
|
1663
1751
|
feeData.maxFeePerGas = cachedGasPrice;
|
|
1664
1752
|
feeData.maxPriorityFeePerGas = cachedGasPrice.div(10);
|
|
@@ -1691,27 +1779,27 @@ var BitgetRouter = class {
|
|
|
1691
1779
|
} catch (error) {
|
|
1692
1780
|
const cachedGasPrice = await getCachedGasPrice();
|
|
1693
1781
|
if (!cachedGasPrice || cachedGasPrice.lte(0)) {
|
|
1694
|
-
return createExecuteError(
|
|
1782
|
+
return createExecuteError(ErrorMessages.GAS_PRICE_FAILED);
|
|
1695
1783
|
}
|
|
1696
1784
|
feeData.gasPrice = cachedGasPrice;
|
|
1697
1785
|
}
|
|
1698
1786
|
}
|
|
1699
1787
|
if (!to || !ethers.ethers.utils.isAddress(to)) {
|
|
1700
|
-
return createExecuteError(
|
|
1788
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1701
1789
|
}
|
|
1702
1790
|
if (!transactionData || transactionData.length < 10) {
|
|
1703
|
-
return createExecuteError(
|
|
1791
|
+
return createExecuteError(ErrorMessages.QUOTE_INVALID);
|
|
1704
1792
|
}
|
|
1705
1793
|
if (!estimatedGasLimit || estimatedGasLimit.lte(0)) {
|
|
1706
|
-
return createExecuteError(
|
|
1794
|
+
return createExecuteError(ErrorMessages.GAS_ESTIMATE_FAILED);
|
|
1707
1795
|
}
|
|
1708
1796
|
if (supportsEip1559) {
|
|
1709
1797
|
if (!feeData.maxFeePerGas || !feeData.maxPriorityFeePerGas || feeData.maxFeePerGas.lte(0) || feeData.maxPriorityFeePerGas.lte(0)) {
|
|
1710
|
-
return createExecuteError(
|
|
1798
|
+
return createExecuteError(ErrorMessages.GAS_PRICE_FAILED);
|
|
1711
1799
|
}
|
|
1712
1800
|
} else {
|
|
1713
1801
|
if (!feeData.gasPrice || feeData.gasPrice.lte(0)) {
|
|
1714
|
-
return createExecuteError(
|
|
1802
|
+
return createExecuteError(ErrorMessages.GAS_PRICE_FAILED);
|
|
1715
1803
|
}
|
|
1716
1804
|
}
|
|
1717
1805
|
const txParams = {
|
|
@@ -1735,10 +1823,10 @@ var BitgetRouter = class {
|
|
|
1735
1823
|
txHashArray: result.txHash ? [result.txHash] : []
|
|
1736
1824
|
};
|
|
1737
1825
|
} else {
|
|
1738
|
-
return createExecuteError(result.message ||
|
|
1826
|
+
return createExecuteError(normalizeError(result.message) || ErrorMessages.EXECUTE_FAILED);
|
|
1739
1827
|
}
|
|
1740
1828
|
} catch (error) {
|
|
1741
|
-
return createExecuteError(error?.message ||
|
|
1829
|
+
return createExecuteError(normalizeError(error?.message) || ErrorMessages.EXECUTE_FAILED);
|
|
1742
1830
|
}
|
|
1743
1831
|
}
|
|
1744
1832
|
normalizeEvmAddress(address) {
|
|
@@ -1779,13 +1867,13 @@ async function completeQuote(params, config) {
|
|
|
1779
1867
|
const routers = dexRouters || (dexRouter ? [dexRouter] : []);
|
|
1780
1868
|
const userAddress = currentUserAddress || recipient;
|
|
1781
1869
|
if (!userAddress) {
|
|
1782
|
-
throw new Error(
|
|
1870
|
+
throw new Error(ErrorMessages.MISSING_USER_ADDRESS);
|
|
1783
1871
|
}
|
|
1784
1872
|
if (sourceToken?.address === void 0) {
|
|
1785
|
-
throw new Error(
|
|
1873
|
+
throw new Error(ErrorMessages.MISSING_TOKEN_ADDRESS);
|
|
1786
1874
|
}
|
|
1787
1875
|
if (targetToken?.address === void 0) {
|
|
1788
|
-
throw new Error(
|
|
1876
|
+
throw new Error(ErrorMessages.MISSING_TOKEN_ADDRESS);
|
|
1789
1877
|
}
|
|
1790
1878
|
const isEvmChain = evmChainId !== void 0 || sourceChain === "evm" || sourceChain === "ethereum" || sourceChain === "bsc" || sourceChain === "polygon" || sourceChain === "base" || sourceChain === "monad" || sourceToken.chain === "evm";
|
|
1791
1879
|
const isTokenIntentsSupported = customIsIntentsSupportedToken ? customIsIntentsSupportedToken(sourceToken) : isEvmChain ? isEvmIntentsSupportedToken(sourceToken, bluechipTokens) : isNearIntentsSupportedToken(sourceToken, bluechipTokens);
|
|
@@ -1794,7 +1882,7 @@ async function completeQuote(params, config) {
|
|
|
1794
1882
|
configAdapter.getEvmNativeWrappedTokenAddress?.()
|
|
1795
1883
|
) : findBestBluechipToken(bluechipTokens, wrapNearContractId);
|
|
1796
1884
|
if (!bluechipToken?.address) {
|
|
1797
|
-
throw new Error(
|
|
1885
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1798
1886
|
}
|
|
1799
1887
|
const quotePaths = [];
|
|
1800
1888
|
routers.forEach((router, index) => {
|
|
@@ -1828,7 +1916,7 @@ async function completeQuote(params, config) {
|
|
|
1828
1916
|
promise: (async () => {
|
|
1829
1917
|
const preSwapQuote = await router.quote(quoteParams);
|
|
1830
1918
|
if (!preSwapQuote.success) {
|
|
1831
|
-
throw new Error(
|
|
1919
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1832
1920
|
}
|
|
1833
1921
|
let normalizedSourceAsset;
|
|
1834
1922
|
if (isEvmChain) {
|
|
@@ -1856,11 +1944,11 @@ async function completeQuote(params, config) {
|
|
|
1856
1944
|
try {
|
|
1857
1945
|
const amountBN = new Big3__default.default(preSwapQuote.amountOut);
|
|
1858
1946
|
if (amountBN.lte(0)) {
|
|
1859
|
-
throw new Error(
|
|
1947
|
+
throw new Error(ErrorMessages.QUOTE_INVALID);
|
|
1860
1948
|
}
|
|
1861
1949
|
formattedAmountOut = amountBN.toFixed(0, Big3__default.default.roundDown);
|
|
1862
1950
|
} catch (error) {
|
|
1863
|
-
throw new Error(
|
|
1951
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1864
1952
|
}
|
|
1865
1953
|
}
|
|
1866
1954
|
try {
|
|
@@ -1876,7 +1964,7 @@ async function completeQuote(params, config) {
|
|
|
1876
1964
|
...appFees ? { appFees } : {}
|
|
1877
1965
|
});
|
|
1878
1966
|
if (intentsQuote.quoteStatus !== "success") {
|
|
1879
|
-
throw new Error(
|
|
1967
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1880
1968
|
}
|
|
1881
1969
|
return {
|
|
1882
1970
|
intentsQuote,
|
|
@@ -1939,7 +2027,7 @@ async function completeQuote(params, config) {
|
|
|
1939
2027
|
...customRecipientMsg ? { customRecipientMsg } : {}
|
|
1940
2028
|
});
|
|
1941
2029
|
if (intentsQuote.quoteStatus !== "success") {
|
|
1942
|
-
throw new Error(
|
|
2030
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1943
2031
|
}
|
|
1944
2032
|
return {
|
|
1945
2033
|
intentsQuote,
|
|
@@ -1962,7 +2050,7 @@ async function completeQuote(params, config) {
|
|
|
1962
2050
|
}
|
|
1963
2051
|
});
|
|
1964
2052
|
if (validPaths.length === 0) {
|
|
1965
|
-
throw new Error(
|
|
2053
|
+
throw new Error(ErrorMessages.QUOTE_FAILED);
|
|
1966
2054
|
}
|
|
1967
2055
|
const bestPath = validPaths.reduce((best, current) => {
|
|
1968
2056
|
const bestAmount = new Big3__default.default(best.finalAmountOut);
|
|
@@ -1971,7 +2059,7 @@ async function completeQuote(params, config) {
|
|
|
1971
2059
|
});
|
|
1972
2060
|
const depositAddress = bestPath.intentsQuote.quoteSuccessResult?.quote?.depositAddress || "";
|
|
1973
2061
|
if (!depositAddress) {
|
|
1974
|
-
throw new Error(
|
|
2062
|
+
throw new Error(ErrorMessages.QUOTE_INVALID);
|
|
1975
2063
|
}
|
|
1976
2064
|
return {
|
|
1977
2065
|
intents: {
|
|
@@ -2038,13 +2126,15 @@ async function quoteSameChainSwap(params, dexRouters) {
|
|
|
2038
2126
|
}
|
|
2039
2127
|
return null;
|
|
2040
2128
|
}).filter(Boolean);
|
|
2041
|
-
|
|
2129
|
+
const errorMessage = errors.length > 0 ? `${ErrorMessages.QUOTE_FAILED}: ${errors.join("; ")}` : ErrorMessages.QUOTE_FAILED;
|
|
2130
|
+
throw new Error(errorMessage);
|
|
2042
2131
|
}
|
|
2043
2132
|
return selectBestQuote(validQuotes);
|
|
2044
2133
|
}
|
|
2045
2134
|
|
|
2046
2135
|
exports.AggregateDexRouter = AggregateDexRouter;
|
|
2047
2136
|
exports.BitgetRouter = BitgetRouter;
|
|
2137
|
+
exports.ErrorMessages = ErrorMessages;
|
|
2048
2138
|
exports.NearSmartRouter = NearSmartRouter;
|
|
2049
2139
|
exports.completeQuote = completeQuote;
|
|
2050
2140
|
exports.convertSlippageToBasisPoints = convertSlippageToBasisPoints;
|
|
@@ -2053,10 +2143,12 @@ exports.findBestEvmBluechipToken = findBestEvmBluechipToken;
|
|
|
2053
2143
|
exports.formatGasString = formatGasString;
|
|
2054
2144
|
exports.formatGasToTgas = formatGasToTgas;
|
|
2055
2145
|
exports.getBluechipTokensConfig = getBluechipTokensConfig;
|
|
2146
|
+
exports.getErrorMessage = getErrorMessage;
|
|
2056
2147
|
exports.isEvmIntentsSupportedToken = isEvmIntentsSupportedToken;
|
|
2057
2148
|
exports.isNearIntentsSupportedToken = isNearIntentsSupportedToken;
|
|
2058
2149
|
exports.logger = logger;
|
|
2059
2150
|
exports.normalizeDestinationAsset = normalizeDestinationAsset;
|
|
2151
|
+
exports.normalizeError = normalizeError;
|
|
2060
2152
|
exports.normalizeEvmAddress = normalizeEvmAddress;
|
|
2061
2153
|
exports.normalizeTokenId = normalizeTokenId;
|
|
2062
2154
|
exports.quoteSameChainSwap = quoteSameChainSwap;
|