@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.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("No EVM bluechip token configured");
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: "Missing token address"
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: "Invalid token address"
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 || "No route found"
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 || "Quote failed"
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: "Invalid quote"
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: "No swap actions"
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 || "Execute swap failed"
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 || "Execute swap failed"
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: "Missing sender or recipient"
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: "Missing sender or recipient"
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: "Missing token address"
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: "Invalid token address"
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: "Failed to get quote"
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: "Failed to get quote"
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("V2 Router requires recipient parameters");
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("Failed to get quote");
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("Failed to get quote");
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: "Missing sender or receiveUser"
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: "Invalid quote"
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: "Missing receiveUser"
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: "Invalid receiveUser address"
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: "Failed to get quote"
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: "Failed to get quote"
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: "Failed to get quote"
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: "Execute swap failed"
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: "Execute swap failed"
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: "Missing sender or recipient"
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: "Missing sender or recipient"
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: "Missing token address"
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 || "Failed to get quote"
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 || "Failed to get quote"
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("Missing sender or receiveUser");
1513
+ return createExecuteError(ErrorMessages.MISSING_USER_ADDRESS);
1438
1514
  }
1439
1515
  const { quote, sender, receiveUser } = params;
1440
1516
  if (!quote.success) {
1441
- return createExecuteError("Invalid quote");
1517
+ return createExecuteError(ErrorMessages.EXECUTE_INVALID_QUOTE);
1442
1518
  }
1443
1519
  if (!receiveUser || receiveUser.trim() === "") {
1444
- return createExecuteError("Missing receiveUser");
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("Missing market from quote, please re-fetch quote");
1528
+ return createExecuteError(ErrorMessages.QUOTE_EXPIRED);
1453
1529
  }
1454
1530
  } catch (error) {
1455
- return createExecuteError("Invalid quote format: missing market");
1531
+ return createExecuteError(ErrorMessages.QUOTE_INVALID);
1456
1532
  }
1457
1533
  if (!market) {
1458
- return createExecuteError("Missing market from quote response");
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
- `Re-quote failed: ${reQuoteResponse.msg || "Please refresh quote and try again"}`
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 || "Failed to get swap calldata"
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("Invalid swap response: missing to or data");
1596
+ return createExecuteError(ErrorMessages.QUOTE_INVALID);
1523
1597
  }
1524
1598
  if (transactionData.length < 10 || !/^0x[0-9a-fA-F]+$/.test(transactionData)) {
1525
- return createExecuteError("Invalid calldata format: must be hex string starting with 0x");
1599
+ return createExecuteError(ErrorMessages.QUOTE_INVALID);
1526
1600
  }
1527
1601
  if (normalizedTokenIn && normalizedTokenIn !== "") {
1528
1602
  if (!this.evmChainAdapter.getBalance) {
1529
- return createExecuteError("getBalance method not available on evmChainAdapter");
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
- const approveResult = await this.evmChainAdapter.approve({
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
- `Token approval failed: ${error?.message || "Unknown error"}`
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("getBalance method not available on evmChainAdapter");
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 (!hasReliableEstimate) {
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("Failed to get valid gas price. Please try again.");
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("Failed to get valid gas price. Please try again.");
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(`Invalid contract address: ${to}`);
1788
+ return createExecuteError(ErrorMessages.QUOTE_INVALID);
1701
1789
  }
1702
1790
  if (!transactionData || transactionData.length < 10) {
1703
- return createExecuteError(`Invalid calldata: length ${transactionData?.length || 0}`);
1791
+ return createExecuteError(ErrorMessages.QUOTE_INVALID);
1704
1792
  }
1705
1793
  if (!estimatedGasLimit || estimatedGasLimit.lte(0)) {
1706
- return createExecuteError("Invalid gas limit estimate. Please refresh quote and try again.");
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("Invalid gas fee data. Please try again.");
1798
+ return createExecuteError(ErrorMessages.GAS_PRICE_FAILED);
1711
1799
  }
1712
1800
  } else {
1713
1801
  if (!feeData.gasPrice || feeData.gasPrice.lte(0)) {
1714
- return createExecuteError("Invalid gas price. Please try again.");
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 || "Execute swap failed");
1826
+ return createExecuteError(normalizeError(result.message) || ErrorMessages.EXECUTE_FAILED);
1739
1827
  }
1740
1828
  } catch (error) {
1741
- return createExecuteError(error?.message || "Execute swap failed");
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("currentUserAddress or recipient is required for routers that require recipient");
1870
+ throw new Error(ErrorMessages.MISSING_USER_ADDRESS);
1783
1871
  }
1784
1872
  if (sourceToken?.address === void 0) {
1785
- throw new Error("Source token address is required");
1873
+ throw new Error(ErrorMessages.MISSING_TOKEN_ADDRESS);
1786
1874
  }
1787
1875
  if (targetToken?.address === void 0) {
1788
- throw new Error("Target token address is required");
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("Failed to find bluechip token address");
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(`Pre-swap quote failed: ${preSwapQuote.error || "Unknown 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(`Invalid amountOut: ${preSwapQuote.amountOut}`);
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(`Failed to process amountOut: ${error?.message || String(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(`Intents quote failed: ${intentsQuote.message || "Unknown 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("Failed to get quote");
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("Failed to get quote");
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("Deposit address not found in intents quote");
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
- throw new Error(`All router quotes failed: ${errors.join("; ")}`);
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;