@rash2x/bridge-widget 0.6.55 → 0.6.61

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.
@@ -12,14 +12,13 @@ const wagmi = require("wagmi");
12
12
  const tronwalletAdapterReactHooks = require("@tronweb3/tronwallet-adapter-react-hooks");
13
13
  const uiReact = require("@tonconnect/ui-react");
14
14
  const core = require("@ton/core");
15
- const ton = require("@ton/ton");
16
15
  const reactQuery = require("@tanstack/react-query");
17
16
  const utils$1 = require("@/lib/utils");
18
17
  const skeleton = require("@/components/ui/skeleton");
19
18
  const input = require("@/components/ui/input");
20
19
  const dialog = require("@/components/ui/dialog");
21
- const _switch = require("@/components/ui/switch");
22
20
  const lucideReact = require("lucide-react");
21
+ const _switch = require("@/components/ui/switch");
23
22
  const framerMotion = require("framer-motion");
24
23
  const accordion = require("@/components/ui/accordion");
25
24
  const tooltip = require("@/components/ui/tooltip");
@@ -28,6 +27,7 @@ const sonner = require("sonner");
28
27
  const badge = require("@/components/ui/badge");
29
28
  const reactDialog = require("@radix-ui/react-dialog");
30
29
  const viem = require("viem");
30
+ const ton = require("@ton/ton");
31
31
  const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
32
32
  const tronweb = require("tronweb");
33
33
  const card = require("@/components/ui/card");
@@ -35,7 +35,7 @@ const reactWindow = require("react-window");
35
35
  const common$1 = { "connecting": "Connecting…", "initializing": "Initializing...", "loading": "Loading...", "paste": "paste", "close": "Close", "zeroPlaceholder": "0", "nativeToken": "Native Token" };
36
36
  const wallets$1 = { "addTonWallet": "Add TON wallet", "addEvmWallet": "Add EVM wallet", "connectTonWallet": "Connect TON wallet", "connectEvmWallet": "Connect EVM wallet", "initializingMetamask": "Initializing MetaMask SDK...", "initializingTronlink": "Initializing TronLink...", "failedToConnectTon": "Failed to connect to TON wallet", "failedToDisconnect": "Failed to disconnect", "metamaskConnectionError": "MetaMask connection error", "failedToConnectMetamask": "Failed to connect to MetaMask", "failedToDisconnectMetamask": "Failed to disconnect from MetaMask", "selectWallet": "Select Wallet", "tonWallets": "TON", "evmWallets": "EVM", "tronWallets": "TRON", "tonconnect": "TonConnect", "metaMask": "WalletConnect", "walletConnect": "WalletConnect", "tronLink": "TronLink", "addTronWallet": "Add Tron wallet", "comingSoon": "Coming Soon", "connected": "CONNECTED", "connectedStatus": "Connected", "disconnect": "Disconnect", "chooseWallet": "Connect wallet", "oneWalletPerEnv": "You can only connect one wallet per environment.", "connect": "Connect", "connectTronWallet": "Connect Tron wallet", "connectWallet": "Connect wallet" };
37
37
  const bridge$1 = { "max": "Max", "sourceNetwork": "Source network", "destinationNetwork": "Destination network", "selectToken": "Select token", "selectNetwork": "Select network", "selectSourceNetwork": "Select source network", "selectDestinationNetwork": "Select destination network", "searchToken": "Search token", "myTokens": "My tokens", "allTokens": "All tokens", "search": "Search", "select": "Select", "willChangeSourceChain": "Will change source network", "willChangeSourceNetworkAndToken": "Will change source token", "noBalancesFound": "No balances found.", "noResults": "No results", "tokenNotFound": "We couldn't find a token with that name or symbol. Please try again.", "chainNotFound": "We couldn't find a chain with that name. Please try again.", "sendToAnotherAddress": "Send to another address", "youWillReceive": "You will receive", "anotherAddressPlaceholder": "Address", "addressDoesntMatch": "Address doesn't match the {{network}} network", "checkBeforeTransfer": "Check correctness before transfer" };
38
- const transaction$1 = { "enterAmount": "Enter amount", "transfer": "Transfer", "getQuote": "Get quote", "failed": "Transaction Failed", "confirm": "Confirm transaction", "signTransaction": "Sign in transaction in wallet", "quoting": "Quoting...", "inProgress": "Transaction in progress...", "checkingBalance": "Checking balance...", "insufficientBalance": "Insufficient balance", "amountTooSmall": "Min {{min}}", "amountTooLarge": "Max {{max}}", "success": "Success", "successTitle": "Success", "done": "Done", "hashCopied": "Hash copied to clipboard", "bridged": "Bridged", "transferTitle": "Transfer", "hash": "Hash", "layerzeroScan": "LayerZero Scan", "finalFee": "Final Fee", "route": "Route", "estTime": "Est. Time", "slippage": "Slippage", "minimumReceived": "Minimum received", "totalFee": "Total Fee", "noRouteFound": "No route found", "notEnoughGas": "Not enough gas", "pasteAddressToTransfer": "Paste address to transfer", "noRouteFoundForSettings": "No route found for current settings.", "tryAdjustSettings": "Try disabling Gas on Destination, or adjust amount/networks.", "quoteError": "Quote error", "steps": { "sent": "Sent", "processing": "Processing", "processingNote": "Up to 2 minutes", "completed": "Completed" } };
38
+ const transaction$1 = { "enterAmount": "Enter amount", "transfer": "Transfer", "getQuote": "Get quote", "failed": "Transaction Failed", "confirm": "Confirm transaction", "signTransaction": "Sign in transaction in wallet", "quoting": "Quoting...", "inProgress": "Transaction in progress...", "checkingBalance": "Checking balance...", "insufficientBalance": "Insufficient balance", "amountTooSmall": "Min {{min}}", "amountTooLarge": "Max {{max}}", "success": "Success", "successTitle": "Success", "done": "Done", "hashCopied": "Hash copied to clipboard", "bridged": "Bridged", "transferTitle": "Transfer", "hash": "Hash", "layerzeroScan": "TxHash", "finalFee": "Final Fee", "route": "Route", "estTime": "Est. Time", "slippage": "Slippage", "minimumReceived": "Minimum received", "totalFee": "Total Fee", "noRouteFound": "No route found", "notEnoughGas": "Not enough gas", "pasteAddressToTransfer": "Paste address to transfer", "noRouteFoundForSettings": "No route found for current settings.", "tryAdjustSettings": "Try disabling Gas on Destination, or adjust amount/networks.", "quoteError": "Quote error", "steps": { "sent": "Sent", "processing": "Processing", "processingNote": "Up to 2 minutes", "completed": "Completed" } };
39
39
  const telegram$1 = { "openWebVersion": "Open EVAA Web to Bridge", "restrictionMessage": "You can bridge between the chosen networks on EVAA web version" };
40
40
  const app$1 = { "stargateWidgetName": "Stargate Bridge Widget", "liveWidget": "Live Widget", "getStarted": "Get Started" };
41
41
  const settings$1 = { "title": "Settings", "gasOnDestination": "Gas on destination", "gasOnDestinationDescription": "The default amount allows you to perform a couple of transactions (e.g. Approve and Swap).", "slippageTolerance": "Slippage tolerance", "slippageToleranceDescription": "Your transaction will revert if the amount you're receiving is outside of this tolerance", "routePriority": "Route Priority", "routePriorityDescription": "Choose how your transfer is routed. Recommended picks the best overall path for cost. Fastest prioritizes speed above all else.", "highSlippageWarning": "High slippage warning", "gasPresets": { "auto": "Auto", "none": "None", "medium": "Medium", "max": "Max" }, "routePresets": { "fastest": "Fastest", "cheapest": "Cheapest", "recommended": "Recommended" } };
@@ -53,7 +53,7 @@ const en$3 = {
53
53
  const common = { "connecting": "Подключение…", "initializing": "Инициализация...", "loading": "Загрузка...", "paste": "вставить", "close": "Закрыть", "zeroPlaceholder": "0", "nativeToken": "Нативный токен" };
54
54
  const wallets = { "addTonWallet": "Добавить TON кошелёк", "addEvmWallet": "Добавить EVM кошелёк", "connectTonWallet": "Подключить TON кошелёк", "connectEvmWallet": "Подключить EVM кошелёк", "initializingMetamask": "Инициализация MetaMask SDK...", "initializingTronlink": "Инициализация TronLink...", "failedToConnectTon": "Не удалось подключиться к TON кошельку", "failedToDisconnect": "Не удалось отключиться", "metamaskConnectionError": "Ошибка подключения MetaMask", "failedToConnectMetamask": "Не удалось подключиться к MetaMask", "failedToDisconnectMetamask": "Не удалось отключиться от MetaMask", "selectWallet": "Выберите кошелёк", "tonWallets": "TON", "evmWallets": "EVM", "tronWallets": "TRON", "tonconnect": "TonConnect", "metaMask": "WalletConnect", "walletConnect": "WalletConnect", "tronLink": "TronLink", "addTronWallet": "Добавить Tron кошелёк", "comingSoon": "Скоро", "connected": "ПОДКЛЮЧЕНО", "connectedStatus": "Подключён", "disconnect": "Отключить", "chooseWallet": "Подключите кошелек", "oneWalletPerEnv": "Можно подключить только один кошелёк на окружение.", "connect": "Подключить", "connectTronWallet": "Подключить Tron кошелёк", "connectWallet": "Подключить кошелёк" };
55
55
  const bridge = { "max": "Макс", "sourceNetwork": "Исходная сеть", "destinationNetwork": "Целевая сеть", "selectToken": "Выбрать токен", "selectNetwork": "Выбрать сеть", "selectSourceNetwork": "Выбрать исходную сеть", "selectDestinationNetwork": "Выбрать целевую сеть", "searchToken": "Поиск токена", "myTokens": "Мои токены", "allTokens": "Все токены", "search": "Поиск", "select": "Выбрать", "willChangeSourceChain": "Сменит исходную сеть", "willChangeSourceNetworkAndToken": "Сменит исходный токен", "noBalancesFound": "Балансы не найдены.", "noResults": "Нет результатов", "tokenNotFound": "Мы не смогли найти токен с таким названием или символом. Пожалуйста, попробуйте снова.", "chainNotFound": "Мы не смогли найти сеть с таким названием. Пожалуйста, попробуйте снова.", "sendToAnotherAddress": "Отправить на другой адрес", "youWillReceive": "Вы получите", "anotherAddressPlaceholder": "Адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
56
- const transaction = { "enterAmount": "Введите сумму", "transfer": "Перевести", "getQuote": "Получить котировку", "quoting": "Расчет котировки...", "failed": "Ошибка транзакции", "confirm": "Подтвердите транзакцию", "signTransaction": "Подпишите транзакцию в кошельке", "inProgress": "Транзакция выполняется...", "checkingBalance": "Проверка баланса...", "insufficientBalance": "Недостаточно средств", "amountTooSmall": "Минимум {{min}}", "amountTooLarge": "Максимум {{max}}", "success": "Успех", "successTitle": "Успех", "done": "Готово", "hashCopied": "Хэш скопирован в буфер обмена", "bridged": "Переведено", "transferTitle": "Перевод", "hash": "Хэш", "layerzeroScan": "LayerZero Scan", "finalFee": "Итоговая комиссия", "route": "Маршрут", "estTime": "Время", "slippage": "Проскальзывание", "minimumReceived": "Минимум к получению", "totalFee": "Общая комиссия", "noRouteFound": "Маршрут не найден", "notEnoughGas": "Недостаточно газа", "pasteAddressToTransfer": "Укажите адрес получателя", "noRouteFoundForSettings": "Маршрут не найден для текущих настроек.", "tryAdjustSettings": "Попробуйте отключить Gas on Destination или измените сумму/сети.", "quoteError": "Ошибка котировки", "steps": { "sent": "Отправлено", "processing": "Обработка", "processingNote": "До 2 минут", "completed": "Завершено" } };
56
+ const transaction = { "enterAmount": "Введите сумму", "transfer": "Перевести", "getQuote": "Получить котировку", "quoting": "Расчет котировки...", "failed": "Ошибка транзакции", "confirm": "Подтвердите транзакцию", "signTransaction": "Подпишите транзакцию в кошельке", "inProgress": "Транзакция выполняется...", "checkingBalance": "Проверка баланса...", "insufficientBalance": "Недостаточно средств", "amountTooSmall": "Минимум {{min}}", "amountTooLarge": "Максимум {{max}}", "success": "Успех", "successTitle": "Успех", "done": "Готово", "hashCopied": "Хэш скопирован в буфер обмена", "bridged": "Переведено", "transferTitle": "Перевод", "hash": "Хэш", "layerzeroScan": "TxHash", "finalFee": "Итоговая комиссия", "route": "Маршрут", "estTime": "Время", "slippage": "Проскальзывание", "minimumReceived": "Минимум к получению", "totalFee": "Общая комиссия", "noRouteFound": "Маршрут не найден", "notEnoughGas": "Недостаточно газа", "pasteAddressToTransfer": "Укажите адрес получателя", "noRouteFoundForSettings": "Маршрут не найден для текущих настроек.", "tryAdjustSettings": "Попробуйте отключить Gas on Destination или измените сумму/сети.", "quoteError": "Ошибка котировки", "steps": { "sent": "Отправлено", "processing": "Обработка", "processingNote": "До 2 минут", "completed": "Завершено" } };
57
57
  const telegram = { "openWebVersion": "Открыть EVAA веб для трансфера", "restrictionMessage": "Трансфер между выбранными сетями доступен только в веб-версии EVAA" };
58
58
  const app = { "stargateWidgetName": "Виджет Stargate Bridge", "liveWidget": "Живой виджет", "getStarted": "Начало работы" };
59
59
  const settings = { "title": "Настройки", "gasOnDestination": "Газ на назначении", "gasOnDestinationDescription": "Значение по умолчанию позволяет выполнить пару транзакций (например, Approve и Swap).", "slippageTolerance": "Толерантность к проскальзыванию", "slippageToleranceDescription": "Ваша транзакция будет отклонена, если получаемая сумма выйдет за пределы этой допустимой погрешности.", "routePriority": "Приоритет маршрута", "routePriorityDescription": "Выберите, как будет выполняться ваш трансфер. Recommended — выбирает оптимальный маршрут с учётом общей стоимости. Fastest — отдаёт приоритет максимальной скорости.", "highSlippageWarning": "Высокое проскальзывание", "gasPresets": { "auto": "Авто", "none": "Нет", "medium": "Средний", "max": "Макс" }, "routePresets": { "fastest": "Быстрейший", "cheapest": "Дешевейший", "recommended": "Рекомендуемый" } };
@@ -941,375 +941,6 @@ function useChainStrategies() {
941
941
  }
942
942
  return context;
943
943
  }
944
- const truncateToDecimals = (num, decimals) => {
945
- if (!isFinite(num) || isNaN(num)) return "0";
946
- const multiplier = Math.pow(10, decimals);
947
- const truncated = Math.floor(num * multiplier) / multiplier;
948
- return truncated.toFixed(decimals).replace(/\.?0+$/, "");
949
- };
950
- const formatTokenAmount = (amount, symbol, options) => {
951
- const normalizedSymbol = (symbol ?? "").toUpperCase();
952
- if (["USDT", "USDC", "DAI", "BUSD"].includes(normalizedSymbol) && amount >= 1) {
953
- return `${Math.floor(amount)} ${normalizedSymbol}`;
954
- }
955
- if (options?.decimals !== void 0) {
956
- return `${amount.toFixed(options.decimals)} ${normalizedSymbol}`;
957
- }
958
- if (amount >= 1) {
959
- return `${amount.toFixed(0)} ${normalizedSymbol}`;
960
- } else if (amount >= 1e-3) {
961
- return `${amount.toFixed(3)} ${normalizedSymbol}`;
962
- } else {
963
- return `${amount.toFixed(6)} ${normalizedSymbol}`;
964
- }
965
- };
966
- const formatUsd = (value) => {
967
- if (!value || !isFinite(value)) return "$0";
968
- if (value >= 1) return `$${value.toFixed(2)}`;
969
- return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
970
- };
971
- const formatPercentage = (bps, decimals = 2) => {
972
- return `${(bps / 100).toFixed(decimals).replace(/0+$/, "").replace(/\.$/, "")}%`;
973
- };
974
- const formatBalance = (amount, decimals = 2) => {
975
- if (!isFinite(amount) || isNaN(amount) || amount <= 0) {
976
- return "0.00";
977
- }
978
- return amount.toFixed(decimals);
979
- };
980
- const formatHash = (hash, startChars = 4, endChars = 4) => {
981
- if (!hash) return "";
982
- if (hash.length <= startChars + endChars) return hash;
983
- return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
984
- };
985
- const formatAddress = formatHash;
986
- const EVM_CONFIG = {
987
- usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
988
- gasEstimates: {
989
- approve: 65000n,
990
- bridge: 300000n
991
- },
992
- gasBuffer: 1.2,
993
- // 20% buffer
994
- timeout: 3e5,
995
- // 5 minutes (increased for slower networks)
996
- requiredConfirmations: 3
997
- // Wait for 3 confirmations for reorg protection
998
- };
999
- const TON_CONFIG = {
1000
- apiUrl: "https://toncenter.com/api/v2",
1001
- timeout: 36e4,
1002
- // 6 minutes
1003
- validUntil: 600,
1004
- // 10 minutes
1005
- pollingInterval: 5e3,
1006
- // 5 seconds between transaction status checks
1007
- estimatedNetworkFee: "100000000"
1008
- // 0.1 TON in nanoton (conservative estimate)
1009
- };
1010
- const TRON_CONFIG = {
1011
- timeout: 12e4,
1012
- // 2 minutes (for 19 confirmations)
1013
- feeLimit: 1e8,
1014
- // 100 TRX in sun
1015
- requiredConfirmations: 19,
1016
- // TRON standard: 19 blocks for confirmation
1017
- pollingInterval: 3e3,
1018
- // 3 seconds between checks
1019
- estimatedNetworkFee: "10000000"
1020
- // 10 TRX in SUN (fallback estimate)
1021
- };
1022
- let tonClientInstance = null;
1023
- function getTonClient(customClient, apiKey) {
1024
- if (customClient) {
1025
- return customClient;
1026
- }
1027
- if (!tonClientInstance) {
1028
- tonClientInstance = new ton.TonClient({
1029
- endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
1030
- apiKey
1031
- });
1032
- }
1033
- return tonClientInstance;
1034
- }
1035
- function getQuoteAmounts(quote, srcToken, dstToken) {
1036
- if (!quote || !srcToken || !dstToken) {
1037
- return {
1038
- inputHuman: 0,
1039
- outputHuman: 0,
1040
- outputHumanRounded: "0",
1041
- minReceivedHuman: 0
1042
- };
1043
- }
1044
- const inputHuman = fromLD(quote.srcAmount, srcToken.decimals);
1045
- const outputHuman = fromLD(quote.dstAmount, dstToken.decimals);
1046
- const outputHumanRounded = truncateToDecimals(outputHuman, 2);
1047
- const minReceivedHuman = fromLD(quote.dstAmountMin || "0", dstToken.decimals);
1048
- return {
1049
- inputHuman,
1050
- outputHuman,
1051
- outputHumanRounded,
1052
- minReceivedHuman
1053
- };
1054
- }
1055
- function getQuoteFees(quote, tokens, chains, srcToken, dstToken) {
1056
- if (!quote || !tokens || !chains) {
1057
- return {
1058
- fees: { usd: /* @__PURE__ */ new Map(), original: /* @__PURE__ */ new Map(), formatted: /* @__PURE__ */ new Map() },
1059
- inSrcToken: void 0,
1060
- inDstToken: void 0
1061
- };
1062
- }
1063
- const feeData = computeFeesUsdFromArray(quote.fees, tokens, chains);
1064
- let inSrcToken = void 0;
1065
- let inDstToken = void 0;
1066
- if (srcToken && quote.srcChainKey) {
1067
- const feeInSrcLD = sumFeeByTokenLD(
1068
- quote.fees,
1069
- srcToken.address,
1070
- quote.srcChainKey
1071
- );
1072
- const feeInSrcHuman = fromLD(feeInSrcLD, srcToken.decimals);
1073
- if (feeInSrcHuman > 0) {
1074
- inSrcToken = Number(truncateToDecimals(feeInSrcHuman, 8));
1075
- } else if ((feeData.usd.get("total") || 0) > 0 && srcToken.price?.usd) {
1076
- const feeInSrcApprox = (feeData.usd.get("total") || 0) / srcToken.price.usd;
1077
- inSrcToken = Number(truncateToDecimals(feeInSrcApprox, 8));
1078
- }
1079
- }
1080
- if (dstToken && quote.dstChainKey) {
1081
- const feeInDstLD = sumFeeByTokenLD(
1082
- quote.fees,
1083
- dstToken.address,
1084
- quote.dstChainKey
1085
- );
1086
- const feeInDstHuman = fromLD(feeInDstLD, dstToken.decimals);
1087
- if (feeInDstHuman > 0) {
1088
- inDstToken = Number(truncateToDecimals(feeInDstHuman, 8));
1089
- }
1090
- }
1091
- return {
1092
- fees: feeData,
1093
- inSrcToken,
1094
- inDstToken
1095
- };
1096
- }
1097
- function calculateMinReceived(quote, slippageBps, dstToken) {
1098
- if (!quote || !dstToken) return 0;
1099
- const dstAmountLD = BigInt(quote.dstAmount);
1100
- const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
1101
- return fromLD(minAmountLD.toString(), dstToken.decimals);
1102
- }
1103
- function estimateTonNetworkFee(quote) {
1104
- try {
1105
- const tonStep = quote.steps?.find(
1106
- (s2) => s2.chainKey.toLowerCase() === "ton" && s2.type === "bridge"
1107
- );
1108
- if (!tonStep?.transaction?.messages) {
1109
- console.warn("No TON messages found in quote, using fallback");
1110
- return TON_CONFIG.estimatedNetworkFee;
1111
- }
1112
- const messages = tonStep.transaction.messages;
1113
- const messageCount = messages.length;
1114
- const baseFeePerMessage = 10000000n;
1115
- let totalFee = 0n;
1116
- for (const message of messages) {
1117
- let messageFee = baseFeePerMessage;
1118
- if (message.payload) {
1119
- const payloadSize = message.payload.length;
1120
- const sizeFee = BigInt(Math.floor(payloadSize / 100)) * 100000n;
1121
- messageFee += sizeFee;
1122
- }
1123
- if (message.amount) {
1124
- const amount = BigInt(message.amount);
1125
- if (amount > 0n && message.payload) {
1126
- messageFee += 5000000n;
1127
- }
1128
- }
1129
- totalFee += messageFee;
1130
- }
1131
- const minBuffer = 50000000n;
1132
- totalFee = totalFee > minBuffer ? totalFee : minBuffer;
1133
- totalFee = totalFee * 120n / 100n;
1134
- const maxFee = 1000000000n;
1135
- if (totalFee > maxFee) {
1136
- totalFee = maxFee;
1137
- }
1138
- console.log(
1139
- `TON fee estimate: ${messageCount} messages = ${Number(totalFee) / 1e9} TON`
1140
- );
1141
- return totalFee.toString();
1142
- } catch (error) {
1143
- console.warn("Failed to estimate TON fee:", error);
1144
- return TON_CONFIG.estimatedNetworkFee;
1145
- }
1146
- }
1147
- function addTonNetworkFee(quote, chains, estimatedFee) {
1148
- if (!quote || quote.srcChainKey.toLowerCase() !== "ton") {
1149
- return quote;
1150
- }
1151
- const tonChain = chains?.find((c2) => c2.chainKey.toLowerCase() === "ton");
1152
- if (!tonChain?.nativeCurrency?.address) {
1153
- console.warn("Could not find TON native currency address");
1154
- return quote;
1155
- }
1156
- const networkFee = {
1157
- token: tonChain.nativeCurrency.address,
1158
- chainKey: "ton",
1159
- amount: estimatedFee || TON_CONFIG.estimatedNetworkFee,
1160
- type: "network"
1161
- };
1162
- const hasNetworkFee = quote.fees?.some(
1163
- (fee) => fee.type === "network" && fee.chainKey === "ton"
1164
- );
1165
- if (hasNetworkFee) {
1166
- return quote;
1167
- }
1168
- return {
1169
- ...quote,
1170
- fees: [...quote.fees || [], networkFee]
1171
- };
1172
- }
1173
- async function estimateTronNetworkFee(tronWeb, quote, userAddress) {
1174
- try {
1175
- const accountResources = await tronWeb.trx.getAccountResources(userAddress);
1176
- const availableEnergy = accountResources.EnergyLimit || 0;
1177
- const tronStep = quote.steps?.find(
1178
- (s2) => s2.chainKey.toLowerCase() === "tron" && s2.type === "bridge"
1179
- );
1180
- if (!tronStep?.transaction?.data || !tronStep.transaction.to) {
1181
- console.warn("No TRON transaction data in quote, using fallback");
1182
- return TRON_CONFIG.estimatedNetworkFee;
1183
- }
1184
- const contractAddress = tronWeb.address.fromHex(
1185
- tronStep.transaction.to.startsWith("41") ? tronStep.transaction.to : "41" + tronStep.transaction.to.slice(2)
1186
- );
1187
- const simulation = await tronWeb.transactionBuilder.triggerSmartContract(
1188
- contractAddress,
1189
- "function signature doesn't matter for energy estimation",
1190
- {
1191
- feeLimit: TRON_CONFIG.feeLimit,
1192
- callValue: tronStep.transaction.value ? Number(tronStep.transaction.value) : 0
1193
- },
1194
- [],
1195
- userAddress
1196
- );
1197
- const requiredEnergy = simulation.energy_used || 0;
1198
- const energyDeficit = Math.max(0, requiredEnergy - availableEnergy);
1199
- if (energyDeficit === 0) {
1200
- return "0";
1201
- }
1202
- const energyPriceInSun = 420;
1203
- const feeSun = energyDeficit * energyPriceInSun;
1204
- console.log(
1205
- `TRON fee estimation: ${requiredEnergy} energy required, ${availableEnergy} available, ${feeSun / 1e6} TRX fee`
1206
- );
1207
- return feeSun.toString();
1208
- } catch (error) {
1209
- console.warn("Failed to estimate TRON network fee:", error);
1210
- return TRON_CONFIG.estimatedNetworkFee;
1211
- }
1212
- }
1213
- function addTronNetworkFee(quote, chains, estimatedFee) {
1214
- if (!quote || quote.srcChainKey.toLowerCase() !== "tron") {
1215
- return quote;
1216
- }
1217
- const tronChain = chains?.find((c2) => c2.chainKey.toLowerCase() === "tron");
1218
- if (!tronChain?.nativeCurrency?.address) {
1219
- console.warn("Could not find TRON native currency address");
1220
- return quote;
1221
- }
1222
- const networkFee = {
1223
- token: tronChain.nativeCurrency.address,
1224
- chainKey: "tron",
1225
- amount: estimatedFee || TRON_CONFIG.estimatedNetworkFee,
1226
- type: "network"
1227
- };
1228
- const hasNetworkFee = quote.fees?.some(
1229
- (fee) => fee.type === "network" && fee.chainKey === "tron"
1230
- );
1231
- if (hasNetworkFee) {
1232
- return quote;
1233
- }
1234
- return {
1235
- ...quote,
1236
- fees: [...quote.fees || [], networkFee]
1237
- };
1238
- }
1239
- async function estimateEvmNetworkFee(publicClient, quote, chainKey) {
1240
- try {
1241
- let totalGasLimit = 0n;
1242
- for (const step of quote.steps || []) {
1243
- if (step.chainKey.toLowerCase() !== chainKey.toLowerCase()) continue;
1244
- if (step.type === "approve") {
1245
- totalGasLimit += EVM_CONFIG.gasEstimates.approve;
1246
- } else if (step.type === "bridge") {
1247
- totalGasLimit += EVM_CONFIG.gasEstimates.bridge;
1248
- }
1249
- }
1250
- if (totalGasLimit === 0n) {
1251
- return "0";
1252
- }
1253
- totalGasLimit = totalGasLimit * BigInt(Math.floor(EVM_CONFIG.gasBuffer * 100)) / 100n;
1254
- const gasPrice = await publicClient.getGasPrice();
1255
- const totalCostWei = totalGasLimit * gasPrice;
1256
- return totalCostWei.toString();
1257
- } catch (error) {
1258
- console.warn("Failed to estimate EVM gas fee:", error);
1259
- return "10000000000000000";
1260
- }
1261
- }
1262
- function addEvmNetworkFee(quote, chains, estimatedFee) {
1263
- if (!quote) return quote;
1264
- const srcChainKey = quote.srcChainKey.toLowerCase();
1265
- if (srcChainKey === "ton" || srcChainKey === "tron") {
1266
- return quote;
1267
- }
1268
- const srcChain = chains?.find(
1269
- (c2) => c2.chainKey.toLowerCase() === srcChainKey
1270
- );
1271
- if (!srcChain?.nativeCurrency?.address) {
1272
- return quote;
1273
- }
1274
- const hasNetworkFee = quote.fees?.some(
1275
- (fee) => fee.type === "network" && fee.chainKey.toLowerCase() === srcChainKey
1276
- );
1277
- if (hasNetworkFee) {
1278
- return quote;
1279
- }
1280
- const networkFee = {
1281
- token: srcChain.nativeCurrency.address,
1282
- chainKey: quote.srcChainKey,
1283
- amount: estimatedFee || "10000000000000000",
1284
- type: "network"
1285
- };
1286
- return {
1287
- ...quote,
1288
- fees: [...quote.fees || [], networkFee]
1289
- };
1290
- }
1291
- function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
1292
- const amounts = getQuoteAmounts(quote, srcToken, dstToken);
1293
- const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
1294
- const minimumReceived = calculateMinReceived(quote, slippageBps, dstToken);
1295
- return {
1296
- inputAmount: amounts.inputHuman,
1297
- outputAmount: amounts.outputHuman,
1298
- outputAmountRounded: amounts.outputHumanRounded,
1299
- minimumReceived,
1300
- etaSeconds: quote?.duration?.estimated,
1301
- fees
1302
- };
1303
- }
1304
- function getRouteDisplayName(route) {
1305
- if (!route) return "Stargate Bridge";
1306
- const routeLower = route.toLowerCase();
1307
- if (routeLower.includes("taxi")) return "Stargate V2 Fast";
1308
- if (routeLower.includes("bus")) return "Stargate V2 Economy";
1309
- if (routeLower.includes("oft")) return "OFT Bridge";
1310
- if (routeLower.includes("v2")) return "Stargate V2";
1311
- return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
1312
- }
1313
944
  const toSharedDecimals = (amount, fromDecimals, toDecimals) => {
1314
945
  const value = BigInt(amount);
1315
946
  const diff = BigInt(toDecimals) - BigInt(fromDecimals);
@@ -1432,88 +1063,7 @@ function useBridgeQuote() {
1432
1063
  return;
1433
1064
  }
1434
1065
  if (cancelled) return;
1435
- let quoteWithFees = quoteRoute;
1436
- if (quoteRoute.srcChainKey.toLowerCase() === "ton") {
1437
- try {
1438
- const estimatedFee = estimateTonNetworkFee(quoteRoute);
1439
- quoteWithFees = addTonNetworkFee(quoteRoute, chains, estimatedFee);
1440
- } catch (error) {
1441
- console.warn("Failed to estimate TON fee, using fallback:", error);
1442
- quoteWithFees = addTonNetworkFee(quoteRoute, chains);
1443
- }
1444
- }
1445
- if (quoteRoute.srcChainKey.toLowerCase() === "tron") {
1446
- const tronStrategy = chainRegistry.getStrategy("tron");
1447
- if (tronStrategy?.isConnected()) {
1448
- const tronWeb = tronStrategy.getClient();
1449
- const tronAddress = tronStrategy.getAccount();
1450
- if (tronWeb && tronAddress) {
1451
- try {
1452
- const estimatedFee = await estimateTronNetworkFee(
1453
- tronWeb,
1454
- quoteRoute,
1455
- tronAddress
1456
- );
1457
- quoteWithFees = addTronNetworkFee(
1458
- quoteWithFees || quoteRoute,
1459
- chains,
1460
- estimatedFee
1461
- );
1462
- } catch (error) {
1463
- console.warn(
1464
- "Failed to estimate TRON fee, using fallback:",
1465
- error
1466
- );
1467
- quoteWithFees = addTronNetworkFee(
1468
- quoteWithFees || quoteRoute,
1469
- chains
1470
- );
1471
- }
1472
- } else {
1473
- quoteWithFees = addTronNetworkFee(
1474
- quoteWithFees || quoteRoute,
1475
- chains
1476
- );
1477
- }
1478
- } else {
1479
- quoteWithFees = addTronNetworkFee(
1480
- quoteWithFees || quoteRoute,
1481
- chains
1482
- );
1483
- }
1484
- }
1485
- const srcChainKey = quoteRoute.srcChainKey.toLowerCase();
1486
- if (srcChainKey !== "ton" && srcChainKey !== "tron") {
1487
- if (publicClient) {
1488
- try {
1489
- const estimatedFee = await estimateEvmNetworkFee(
1490
- publicClient,
1491
- quoteRoute,
1492
- quoteRoute.srcChainKey
1493
- );
1494
- quoteWithFees = addEvmNetworkFee(
1495
- quoteWithFees || quoteRoute,
1496
- chains,
1497
- estimatedFee
1498
- );
1499
- } catch (error) {
1500
- console.warn(
1501
- "Failed to estimate EVM fee, using fallback:",
1502
- error
1503
- );
1504
- quoteWithFees = addEvmNetworkFee(
1505
- quoteWithFees || quoteRoute,
1506
- chains
1507
- );
1508
- }
1509
- } else {
1510
- quoteWithFees = addEvmNetworkFee(
1511
- quoteWithFees || quoteRoute,
1512
- chains
1513
- );
1514
- }
1515
- }
1516
- setQuote(quoteWithFees || quoteRoute);
1066
+ setQuote(quoteRoute);
1517
1067
  } catch {
1518
1068
  if (!cancelled) {
1519
1069
  resetUi();
@@ -2489,12 +2039,20 @@ const SearchInput = ({
2489
2039
  placeholder,
2490
2040
  className: utils$1.cn(
2491
2041
  "w-full outline-none px-5 py-4 relative pl-16 bg-input border transition-all border-transparent rounded-xs ring-0 leading-0 h-13 text-base focus-visible:border focus-visible:border-ring",
2042
+ value && "pr-16",
2492
2043
  className
2493
2044
  ),
2494
2045
  value,
2495
2046
  onChange: (e2) => onChange(e2.target.value)
2496
2047
  }
2497
- )
2048
+ ),
2049
+ value && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-10 right-4 top-0 bottom-0 my-auto h-5 w-5 bg-accent flex items-center justify-center rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(
2050
+ lucideReact.XIcon,
2051
+ {
2052
+ className: "w-4 h-4 text-foreground cursor-pointer hover:opacity-70 transition-opacity",
2053
+ onClick: () => onChange("")
2054
+ }
2055
+ ) })
2498
2056
  ] });
2499
2057
  };
2500
2058
  const ChainSelectModal = ({
@@ -2644,49 +2202,58 @@ const ChainSelectModal = ({
2644
2202
  chain2.chainKey
2645
2203
  );
2646
2204
  };
2647
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "md:max-h-[90dvh] md:h-[90dvh] fixed top-0 left-0 right-0 bottom-0 translate-x-0 translate-y-0 md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%] overflow-hidden flex flex-col p-10 pt-7 rounded-none md:rounded-lg", children: [
2648
- /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left pb-0", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { className: "text-xl leading-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0", children: [
2649
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: t2("bridge.select") }),
2650
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: t2(isSource ? "bridge.sourceNetwork" : "bridge.destinationNetwork") })
2651
- ] }) }) }),
2652
- /* @__PURE__ */ jsxRuntime.jsx(
2653
- SearchInput,
2654
- {
2655
- placeholder: t2("bridge.search"),
2656
- value: query,
2657
- onChange: setQuery,
2658
- className: "text-foreground placeholder:text-muted-foreground"
2659
- }
2660
- ),
2661
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30", children: [
2662
- groupedChains.available.length > 0 && groupedChains.available.map((c2) => renderChainItem(c2, false)),
2663
- groupedChains.willChangeSrc.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2664
- /* @__PURE__ */ jsxRuntime.jsx(
2665
- "p",
2666
- {
2667
- className: `px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase ${groupedChains.available.length > 0 ? "mt-10" : ""}`,
2668
- children: t2("bridge.willChangeSourceChain")
2669
- }
2670
- ),
2671
- groupedChains.willChangeSrc.map(
2672
- (c2) => renderChainItem(c2, true, false)
2673
- )
2674
- ] }),
2675
- groupedChains.willChangeTokenAndSrc.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2205
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(
2206
+ dialog.DialogContent,
2207
+ {
2208
+ className: "md:max-h-[90dvh] md:h-[90dvh] fixed top-0 left-0 right-0 bottom-0 translate-x-0 translate-y-0 md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%] overflow-hidden flex flex-col p-6 md:p-10 md:pt-8 rounded-none md:rounded-lg",
2209
+ closeButtonClassName: "right-6 md:right-10",
2210
+ children: [
2211
+ /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { className: "text-xl leading-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0", children: [
2212
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: t2("bridge.select") }),
2213
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: t2(
2214
+ isSource ? "bridge.sourceNetwork" : "bridge.destinationNetwork"
2215
+ ) })
2216
+ ] }) }) }),
2676
2217
  /* @__PURE__ */ jsxRuntime.jsx(
2677
- "p",
2218
+ SearchInput,
2678
2219
  {
2679
- className: `px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase ${groupedChains.available.length > 0 || groupedChains.willChangeSrc.length > 0 ? "mt-10" : ""}`,
2680
- children: t2("bridge.willChangeSourceNetworkAndToken")
2220
+ placeholder: t2("bridge.search"),
2221
+ value: query,
2222
+ onChange: setQuery,
2223
+ className: "text-foreground placeholder:text-muted-foreground"
2681
2224
  }
2682
2225
  ),
2683
- groupedChains.willChangeTokenAndSrc.map(
2684
- (c2) => renderChainItem(c2, false, true)
2685
- )
2686
- ] }),
2687
- groupedChains.available.length === 0 && groupedChains.willChangeSrc.length === 0 && groupedChains.willChangeTokenAndSrc.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground px-12 py-2 h-28 flex items-center justify-center text-center", children: t2("bridge.chainNotFound") })
2688
- ] })
2689
- ] }) });
2226
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30", children: [
2227
+ groupedChains.available.length > 0 && groupedChains.available.map((c2) => renderChainItem(c2, false)),
2228
+ groupedChains.willChangeSrc.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2229
+ /* @__PURE__ */ jsxRuntime.jsx(
2230
+ "p",
2231
+ {
2232
+ className: `px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase ${groupedChains.available.length > 0 ? "mt-10" : ""}`,
2233
+ children: t2("bridge.willChangeSourceChain")
2234
+ }
2235
+ ),
2236
+ groupedChains.willChangeSrc.map(
2237
+ (c2) => renderChainItem(c2, true, false)
2238
+ )
2239
+ ] }),
2240
+ groupedChains.willChangeTokenAndSrc.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2241
+ /* @__PURE__ */ jsxRuntime.jsx(
2242
+ "p",
2243
+ {
2244
+ className: `px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase ${groupedChains.available.length > 0 || groupedChains.willChangeSrc.length > 0 ? "mt-10" : ""}`,
2245
+ children: t2("bridge.willChangeSourceNetworkAndToken")
2246
+ }
2247
+ ),
2248
+ groupedChains.willChangeTokenAndSrc.map(
2249
+ (c2) => renderChainItem(c2, false, true)
2250
+ )
2251
+ ] }),
2252
+ groupedChains.available.length === 0 && groupedChains.willChangeSrc.length === 0 && groupedChains.willChangeTokenAndSrc.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-muted-foreground px-12 py-2 h-28 flex items-center justify-center text-center", children: t2("bridge.chainNotFound") })
2253
+ ] })
2254
+ ]
2255
+ }
2256
+ ) });
2690
2257
  };
2691
2258
  const useWalletSelectModal = zustand.create((set2) => ({
2692
2259
  isOpen: false,
@@ -2694,6 +2261,48 @@ const useWalletSelectModal = zustand.create((set2) => ({
2694
2261
  onOpen: (addressType) => set2({ isOpen: true, addressType }),
2695
2262
  onClose: () => set2({ isOpen: false, addressType: void 0 })
2696
2263
  }));
2264
+ const truncateToDecimals = (num, decimals) => {
2265
+ if (!isFinite(num) || isNaN(num)) return "0";
2266
+ const multiplier = Math.pow(10, decimals);
2267
+ const truncated = Math.floor(num * multiplier) / multiplier;
2268
+ return truncated.toFixed(decimals).replace(/\.?0+$/, "");
2269
+ };
2270
+ const formatTokenAmount = (amount, symbol, options) => {
2271
+ const normalizedSymbol = (symbol ?? "").toUpperCase();
2272
+ if (["USDT", "USDC", "DAI", "BUSD"].includes(normalizedSymbol) && amount >= 1) {
2273
+ return `${Math.floor(amount)} ${normalizedSymbol}`;
2274
+ }
2275
+ if (options?.decimals !== void 0) {
2276
+ return `${amount.toFixed(options.decimals)} ${normalizedSymbol}`;
2277
+ }
2278
+ if (amount >= 1) {
2279
+ return `${amount.toFixed(0)} ${normalizedSymbol}`;
2280
+ } else if (amount >= 1e-3) {
2281
+ return `${amount.toFixed(3)} ${normalizedSymbol}`;
2282
+ } else {
2283
+ return `${amount.toFixed(6)} ${normalizedSymbol}`;
2284
+ }
2285
+ };
2286
+ const formatUsd = (value) => {
2287
+ if (!value || !isFinite(value)) return "$0";
2288
+ if (value >= 1) return `$${value.toFixed(2)}`;
2289
+ return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
2290
+ };
2291
+ const formatPercentage = (bps, decimals = 2) => {
2292
+ return `${(bps / 100).toFixed(decimals).replace(/0+$/, "").replace(/\.$/, "")}%`;
2293
+ };
2294
+ const formatBalance = (amount, decimals = 2) => {
2295
+ if (!isFinite(amount) || isNaN(amount) || amount <= 0) {
2296
+ return "0.00";
2297
+ }
2298
+ return amount.toFixed(decimals);
2299
+ };
2300
+ const formatHash = (hash, startChars = 4, endChars = 4) => {
2301
+ if (!hash) return "";
2302
+ if (hash.length <= startChars + endChars) return hash;
2303
+ return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
2304
+ };
2305
+ const formatAddress = formatHash;
2697
2306
  const EditIcon = (props) => {
2698
2307
  return /* @__PURE__ */ jsxRuntime.jsxs(
2699
2308
  "svg",
@@ -3119,30 +2728,120 @@ const InfoIcon = (props) => {
3119
2728
  {
3120
2729
  d: "M6.56836 5.8519C6.56836 5.06104 7.20948 4.41992 8.00034 4.41992C8.7912 4.41992 9.43232 5.06104 9.43232 5.8519C9.43232 6.13698 9.34902 6.40259 9.20543 6.62574C8.77748 7.29081 8.00034 7.92501 8.00034 8.71587V9.07386M8.00034 11.3159V11.5798",
3121
2730
  stroke: "currentColor",
3122
- "stroke-width": "1.68349",
3123
- "stroke-linecap": "round"
2731
+ strokeWidth: "1.68349",
2732
+ strokeLinecap: "round"
3124
2733
  }
3125
2734
  )
3126
2735
  }
3127
- );
3128
- };
3129
- const Tip = (props) => {
3130
- const { children, text } = props;
3131
- return /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
3132
- /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { className: "w-4 h-4 rounded-full bg-muted text-muted-foreground", children }),
3133
- /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipContent, { className: "max-w-64", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
3134
- ] });
3135
- };
3136
- const BASE_URL = "https://icons-ckg.pages.dev/stargate-light/tokens";
3137
- const TokenSymbol = ({
3138
- symbol,
3139
- className = "w-4 h-4",
3140
- alt
3141
- }) => {
3142
- const normalizedSymbol = normalizeTickerSymbol$1(symbol).toLowerCase();
3143
- const src2 = `${BASE_URL}/${normalizedSymbol}.svg`;
3144
- return /* @__PURE__ */ jsxRuntime.jsx("img", { src: src2, alt: alt ?? symbol, className });
3145
- };
2736
+ );
2737
+ };
2738
+ const Tip = (props) => {
2739
+ const { children, text } = props;
2740
+ return /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
2741
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { className: "w-4 h-4 rounded-full bg-muted text-muted-foreground", children }),
2742
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipContent, { className: "max-w-64", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
2743
+ ] });
2744
+ };
2745
+ const BASE_URL = "https://icons-ckg.pages.dev/stargate-light/tokens";
2746
+ const TokenSymbol = ({
2747
+ symbol,
2748
+ className = "w-4 h-4",
2749
+ alt
2750
+ }) => {
2751
+ const normalizedSymbol = normalizeTickerSymbol$1(symbol).toLowerCase();
2752
+ const src2 = `${BASE_URL}/${normalizedSymbol}.svg`;
2753
+ return /* @__PURE__ */ jsxRuntime.jsx("img", { src: src2, alt: alt ?? symbol, className });
2754
+ };
2755
+ function getQuoteAmounts(quote, srcToken, dstToken) {
2756
+ if (!quote || !srcToken || !dstToken) {
2757
+ return {
2758
+ inputHuman: 0,
2759
+ outputHuman: 0,
2760
+ outputHumanRounded: "0",
2761
+ minReceivedHuman: 0
2762
+ };
2763
+ }
2764
+ const inputHuman = fromLD(quote.srcAmount, srcToken.decimals);
2765
+ const outputHuman = fromLD(quote.dstAmount, dstToken.decimals);
2766
+ const outputHumanRounded = truncateToDecimals(outputHuman, 2);
2767
+ const minReceivedHuman = fromLD(quote.dstAmountMin || "0", dstToken.decimals);
2768
+ return {
2769
+ inputHuman,
2770
+ outputHuman,
2771
+ outputHumanRounded,
2772
+ minReceivedHuman
2773
+ };
2774
+ }
2775
+ function getQuoteFees(quote, tokens, chains, srcToken, dstToken) {
2776
+ if (!quote || !tokens || !chains) {
2777
+ return {
2778
+ fees: { usd: /* @__PURE__ */ new Map(), original: /* @__PURE__ */ new Map(), formatted: /* @__PURE__ */ new Map() },
2779
+ inSrcToken: void 0,
2780
+ inDstToken: void 0
2781
+ };
2782
+ }
2783
+ const feeData = computeFeesUsdFromArray(quote.fees, tokens, chains);
2784
+ let inSrcToken = void 0;
2785
+ let inDstToken = void 0;
2786
+ if (srcToken && quote.srcChainKey) {
2787
+ const feeInSrcLD = sumFeeByTokenLD(
2788
+ quote.fees,
2789
+ srcToken.address,
2790
+ quote.srcChainKey
2791
+ );
2792
+ const feeInSrcHuman = fromLD(feeInSrcLD, srcToken.decimals);
2793
+ if (feeInSrcHuman > 0) {
2794
+ inSrcToken = Number(truncateToDecimals(feeInSrcHuman, 8));
2795
+ } else if ((feeData.usd.get("total") || 0) > 0 && srcToken.price?.usd) {
2796
+ const feeInSrcApprox = (feeData.usd.get("total") || 0) / srcToken.price.usd;
2797
+ inSrcToken = Number(truncateToDecimals(feeInSrcApprox, 8));
2798
+ }
2799
+ }
2800
+ if (dstToken && quote.dstChainKey) {
2801
+ const feeInDstLD = sumFeeByTokenLD(
2802
+ quote.fees,
2803
+ dstToken.address,
2804
+ quote.dstChainKey
2805
+ );
2806
+ const feeInDstHuman = fromLD(feeInDstLD, dstToken.decimals);
2807
+ if (feeInDstHuman > 0) {
2808
+ inDstToken = Number(truncateToDecimals(feeInDstHuman, 8));
2809
+ }
2810
+ }
2811
+ return {
2812
+ fees: feeData,
2813
+ inSrcToken,
2814
+ inDstToken
2815
+ };
2816
+ }
2817
+ function calculateMinReceived(quote, slippageBps, dstToken) {
2818
+ if (!quote || !dstToken) return 0;
2819
+ const dstAmountLD = BigInt(quote.dstAmount);
2820
+ const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
2821
+ return fromLD(minAmountLD.toString(), dstToken.decimals);
2822
+ }
2823
+ function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
2824
+ const amounts = getQuoteAmounts(quote, srcToken, dstToken);
2825
+ const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
2826
+ const minimumReceived = calculateMinReceived(quote, slippageBps, dstToken);
2827
+ return {
2828
+ inputAmount: amounts.inputHuman,
2829
+ outputAmount: amounts.outputHuman,
2830
+ outputAmountRounded: amounts.outputHumanRounded,
2831
+ minimumReceived,
2832
+ etaSeconds: quote?.duration?.estimated,
2833
+ fees
2834
+ };
2835
+ }
2836
+ function getRouteDisplayName(route) {
2837
+ if (!route) return "Stargate Bridge";
2838
+ const routeLower = route.toLowerCase();
2839
+ if (routeLower.includes("taxi")) return "Stargate V2 Fast";
2840
+ if (routeLower.includes("bus")) return "Stargate V2 Economy";
2841
+ if (routeLower.includes("oft")) return "OFT Bridge";
2842
+ if (routeLower.includes("v2")) return "Stargate V2";
2843
+ return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
2844
+ }
3146
2845
  function useGasEstimate(amountNum) {
3147
2846
  const { fromChain } = useChainsStore();
3148
2847
  const { selectedAssetSymbol } = useTokensStore();
@@ -3152,6 +2851,9 @@ function useGasEstimate(amountNum) {
3152
2851
  srcAddress
3153
2852
  );
3154
2853
  const { quote } = useBridgeQuoteStore();
2854
+ const { chainRegistry } = useChainStrategies();
2855
+ const [networkFeeEstimate, setNetworkFeeEstimate] = react.useState(0);
2856
+ const [networkFeeKnown, setNetworkFeeKnown] = react.useState(false);
3155
2857
  const balancesKnown = !balancesLoading;
3156
2858
  const chainKey = fromChain?.chainKey;
3157
2859
  const nativeCurrencySymbol = fromChain?.nativeCurrency?.symbol;
@@ -3160,6 +2862,44 @@ function useGasEstimate(amountNum) {
3160
2862
  const quoteFees = quote?.fees;
3161
2863
  const quoteSrcChainKey = quote?.srcChainKey;
3162
2864
  const nativeBalanceValue = nativeCurrencySymbol ? Number(balances[nativeCurrencySymbol.toUpperCase()]?.balance ?? 0) : 0;
2865
+ react.useEffect(() => {
2866
+ let cancelled = false;
2867
+ const estimate = async () => {
2868
+ setNetworkFeeEstimate(0);
2869
+ setNetworkFeeKnown(false);
2870
+ if (!chainKey || !quote?.steps?.length) {
2871
+ return;
2872
+ }
2873
+ const strategy = chainRegistry.getStrategy(chainKey);
2874
+ if (!strategy) {
2875
+ setNetworkFeeKnown(true);
2876
+ return;
2877
+ }
2878
+ const steps = quote.steps.filter((step) => step.chainKey === chainKey);
2879
+ if (!steps.length) {
2880
+ setNetworkFeeKnown(true);
2881
+ return;
2882
+ }
2883
+ try {
2884
+ const estimateValue = await strategy.estimateNetworkFee(steps);
2885
+ if (cancelled) return;
2886
+ setNetworkFeeEstimate(
2887
+ Number.isFinite(estimateValue) ? estimateValue : 0
2888
+ );
2889
+ } catch {
2890
+ if (cancelled) return;
2891
+ setNetworkFeeEstimate(0);
2892
+ } finally {
2893
+ if (!cancelled) {
2894
+ setNetworkFeeKnown(true);
2895
+ }
2896
+ }
2897
+ };
2898
+ void estimate();
2899
+ return () => {
2900
+ cancelled = true;
2901
+ };
2902
+ }, [chainKey, quote?.steps, chainRegistry]);
3163
2903
  const result = react.useMemo(() => {
3164
2904
  if (!chainKey || !nativeCurrencySymbol) {
3165
2905
  return {
@@ -3179,7 +2919,7 @@ function useGasEstimate(amountNum) {
3179
2919
  if (quoteFees && quoteSrcChainKey === chainKey) {
3180
2920
  const fees = quoteFees;
3181
2921
  const feesInNative = fees.filter(
3182
- (f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress && f4.type === "network"
2922
+ (f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress
3183
2923
  ).reduce(
3184
2924
  (sum, f4) => sum + BigInt(f4.amount || "0"),
3185
2925
  0n
@@ -3188,13 +2928,16 @@ function useGasEstimate(amountNum) {
3188
2928
  requiredNative = Number(feesInNative) / Math.pow(10, decimals);
3189
2929
  quoteFeesAvailable = true;
3190
2930
  }
2931
+ if (networkFeeKnown) {
2932
+ requiredNative += networkFeeEstimate;
2933
+ }
3191
2934
  let hasEnoughGas = true;
3192
2935
  if (isNativeSelected) {
3193
2936
  hasEnoughGas = nativeBalance - (amountNum ?? 0) >= requiredNative;
3194
2937
  } else {
3195
2938
  hasEnoughGas = nativeBalance >= requiredNative;
3196
2939
  }
3197
- const shouldCheckGas = balancesKnown && quoteFeesAvailable;
2940
+ const shouldCheckGas = balancesKnown && quoteFeesAvailable && networkFeeKnown;
3198
2941
  return {
3199
2942
  nativeSym,
3200
2943
  nativeBalance,
@@ -3213,7 +2956,9 @@ function useGasEstimate(amountNum) {
3213
2956
  quoteSrcChainKey,
3214
2957
  amountNum,
3215
2958
  balancesKnown,
3216
- nativeBalanceValue
2959
+ nativeBalanceValue,
2960
+ networkFeeEstimate,
2961
+ networkFeeKnown
3217
2962
  ]);
3218
2963
  return result;
3219
2964
  }
@@ -3622,33 +3367,6 @@ class TransactionFailedError extends ChainStrategyError {
3622
3367
  this.txHash = txHash;
3623
3368
  }
3624
3369
  }
3625
- class TransactionTimeoutError extends ChainStrategyError {
3626
- constructor(chainKey, txHash) {
3627
- super(
3628
- `${chainKey.toUpperCase()} transaction confirmation timeout: ${txHash}`,
3629
- "TRANSACTION_TIMEOUT",
3630
- chainKey
3631
- );
3632
- __publicField(this, "txHash");
3633
- this.name = "TransactionTimeoutError";
3634
- this.txHash = txHash;
3635
- }
3636
- }
3637
- class TransactionRevertedError extends ChainStrategyError {
3638
- constructor(chainKey, txHash, revertReason) {
3639
- const reason = revertReason ? `: ${revertReason}` : "";
3640
- super(
3641
- `${chainKey.toUpperCase()} transaction reverted on-chain${reason}`,
3642
- "TRANSACTION_REVERTED",
3643
- chainKey
3644
- );
3645
- __publicField(this, "txHash");
3646
- __publicField(this, "revertReason");
3647
- this.name = "TransactionRevertedError";
3648
- this.txHash = txHash;
3649
- this.revertReason = revertReason;
3650
- }
3651
- }
3652
3370
  class ProviderNotAvailableError extends ChainStrategyError {
3653
3371
  constructor(chainKey, reason) {
3654
3372
  const message = reason ? `${chainKey.toUpperCase()} provider not available: ${reason}` : `${chainKey.toUpperCase()} provider not available`;
@@ -3705,6 +3423,38 @@ async function getLayerZeroMessageByTx(txHash) {
3705
3423
  return null;
3706
3424
  }
3707
3425
  }
3426
+ async function waitForLayerZeroCompletion(txHash, timeoutMs = 6e5, pollIntervalMs = 1e4) {
3427
+ const deadline = Date.now() + timeoutMs;
3428
+ while (Date.now() < deadline) {
3429
+ try {
3430
+ const message = await getLayerZeroMessageByTx(txHash);
3431
+ if (message) {
3432
+ const statusName = message.status?.name;
3433
+ if (statusName === "DELIVERED") {
3434
+ return {
3435
+ completed: true,
3436
+ status: "DELIVERED",
3437
+ dstTxHash: message.destination?.tx?.txHash,
3438
+ message
3439
+ };
3440
+ }
3441
+ if (statusName === "FAILED") {
3442
+ return {
3443
+ completed: false,
3444
+ status: "FAILED",
3445
+ message
3446
+ };
3447
+ }
3448
+ }
3449
+ } catch {
3450
+ }
3451
+ await new Promise((r2) => setTimeout(r2, pollIntervalMs));
3452
+ }
3453
+ return {
3454
+ completed: false,
3455
+ status: "TIMEOUT"
3456
+ };
3457
+ }
3708
3458
  function useBridgeTransaction() {
3709
3459
  const { quote } = useBridgeQuoteStore();
3710
3460
  const { chainRegistry } = useChainStrategies();
@@ -3780,59 +3530,76 @@ function useBridgeTransaction() {
3780
3530
  txStore.setSrcHash(hash);
3781
3531
  txStore.updateStatus("processing");
3782
3532
  });
3783
- if (txResult?.tonTransactionHash) {
3784
- txStore.setTonTransactionHash(txResult.tonTransactionHash);
3785
- }
3786
3533
  if (txResult?.hash) {
3787
- strategy.waitForCompletion(txResult.hash, context).then((result) => {
3788
- if (result.completed) {
3789
- if (result.dstTxHash) {
3790
- txStore.setDstHash(result.dstTxHash);
3534
+ const trackWithLayerZero = async () => {
3535
+ let hashForLayerZero = txResult.hash;
3536
+ const messageHash = txResult.hash;
3537
+ if (quote.srcChainKey === "ton" && strategy.convertMessageHashToTxHash) {
3538
+ const tonTxHash = await strategy.convertMessageHashToTxHash(
3539
+ messageHash,
3540
+ 6e4
3541
+ );
3542
+ if (tonTxHash) {
3543
+ hashForLayerZero = tonTxHash;
3544
+ txStore.setTonTransactionHash(tonTxHash);
3545
+ } else {
3546
+ console.warn("Failed to convert TON message hash to tx hash");
3791
3547
  }
3792
- if (result.actualFeeValue) {
3793
- let feeSymbol = result.actualFeeSymbol;
3794
- if (!feeSymbol) {
3795
- const srcChain2 = chains?.find(
3796
- (c2) => c2.chainKey === quote.srcChainKey
3797
- );
3798
- feeSymbol = srcChain2?.nativeCurrency?.symbol || "";
3799
- }
3800
- const feeValue = parseFloat(result.actualFeeValue);
3801
- if (!isNaN(feeValue)) {
3802
- txStore.updateActualFee(feeValue, feeSymbol);
3803
- }
3548
+ }
3549
+ const lzResult = await waitForLayerZeroCompletion(
3550
+ hashForLayerZero,
3551
+ 6e5,
3552
+ 1e4
3553
+ );
3554
+ console.log("LayerZero delivery status:", lzResult.status);
3555
+ if (lzResult.completed) {
3556
+ if (lzResult.dstTxHash) {
3557
+ txStore.setDstHash(lzResult.dstTxHash);
3804
3558
  }
3805
- txStore.updateStatus("completed");
3806
- console.log("Transaction completed successfully");
3807
- if (txResult.hash && strategy.getSourceCost) {
3559
+ if (strategy.getSourceCost) {
3808
3560
  const srcChain2 = chains?.find(
3809
3561
  (c2) => c2.chainKey === quote.srcChainKey
3810
3562
  );
3811
3563
  const feeSymbol = srcChain2?.nativeCurrency?.symbol || "";
3812
3564
  const { priceUsd } = findNativeMeta(allTokens, srcChain2);
3813
- const srcHash = txResult.hash;
3814
- const getSourceCost = strategy.getSourceCost;
3815
- getLayerZeroMessageByTx(srcHash).then((message) => {
3816
- if (quote.srcChainKey === "ton") return srcHash;
3817
- return message?.source?.tx?.txHash ?? srcHash;
3818
- }).then((sourceTxHash) => getSourceCost(sourceTxHash)).then((sourceCost) => {
3565
+ const hashForSourceCost = quote.srcChainKey === "ton" ? messageHash : hashForLayerZero;
3566
+ try {
3567
+ const sourceCost = await strategy.getSourceCost(
3568
+ hashForSourceCost
3569
+ );
3819
3570
  if (sourceCost?.totalNative !== void 0 && isFinite(sourceCost.totalNative)) {
3820
3571
  const feeUsd = priceUsd && priceUsd > 0 ? sourceCost.totalNative * priceUsd : void 0;
3572
+ console.log("Source cost calculated:", {
3573
+ gasFee: sourceCost.breakdown?.gasFee + " " + feeSymbol,
3574
+ layerZeroFee: sourceCost.breakdown?.layerZeroFee + " " + feeSymbol,
3575
+ total: sourceCost.totalNative + " " + feeSymbol,
3576
+ totalUsd: feeUsd ? "$" + feeUsd.toFixed(2) : "N/A"
3577
+ });
3821
3578
  txStore.updateLayerZeroTotalFee(
3822
3579
  sourceCost.totalNative,
3823
3580
  feeSymbol,
3824
3581
  feeUsd
3825
3582
  );
3826
3583
  }
3827
- }).catch((error) => {
3828
- console.warn("Failed to compute LayerZero total fee:", error);
3829
- });
3584
+ } catch (error) {
3585
+ console.warn("Failed to compute source cost:", error);
3586
+ }
3830
3587
  }
3588
+ txStore.updateStatus("completed");
3589
+ console.log("Transaction completed successfully via LayerZero");
3831
3590
  } else {
3832
- txStore.setError("TRANSACTION_FAILED_TO_COMPLETE");
3833
- console.error("Transaction completion failed:", result.error);
3591
+ if (lzResult.status === "FAILED") {
3592
+ txStore.setError("TRANSACTION_FAILED_TO_COMPLETE");
3593
+ console.error("LayerZero delivery failed");
3594
+ } else {
3595
+ txStore.updateStatus("completed");
3596
+ console.warn(
3597
+ "LayerZero tracking timed out, marking as completed"
3598
+ );
3599
+ }
3834
3600
  }
3835
- }).catch((err) => {
3601
+ };
3602
+ trackWithLayerZero().catch((err) => {
3836
3603
  if (isUserRejection(err)) {
3837
3604
  txStore.setError("TRANSACTION_REJECTED");
3838
3605
  } else if (ChainStrategyError.isChainStrategyError(err)) {
@@ -4932,11 +4699,60 @@ class ChainStrategyRegistry {
4932
4699
  await strategy.disconnect(options);
4933
4700
  }
4934
4701
  }
4702
+ const EVM_CONFIG = {
4703
+ usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
4704
+ gasEstimates: {
4705
+ approve: 65000n,
4706
+ bridge: 300000n
4707
+ },
4708
+ gasBuffer: 1.2,
4709
+ // 20% buffer
4710
+ gasFeeMultiplier: 2,
4711
+ // Multiplier for wallet fee estimates
4712
+ timeout: 3e5,
4713
+ // 5 minutes (increased for slower networks)
4714
+ requiredConfirmations: 3
4715
+ // Wait for 3 confirmations for reorg protection
4716
+ };
4717
+ const TON_CONFIG = {
4718
+ apiUrl: "https://toncenter.com/api/v2",
4719
+ timeout: 36e4,
4720
+ // 6 minutes
4721
+ validUntil: 600,
4722
+ // 10 minutes
4723
+ pollingInterval: 5e3,
4724
+ // 5 seconds between transaction status checks
4725
+ estimatedNetworkFee: "1000000000"
4726
+ // 1 TON in nanoton (conservative estimate)
4727
+ };
4728
+ const TRON_CONFIG = {
4729
+ // 2 minutes (for 19 confirmations)
4730
+ feeLimit: 1e8,
4731
+ // 3 seconds between checks
4732
+ estimatedNetworkFee: "10000000"
4733
+ // 10 TRX in SUN (fallback estimate)
4734
+ };
4735
+ let tonClientInstance = null;
4736
+ function getTonClient(customClient, apiKey) {
4737
+ if (customClient) {
4738
+ return customClient;
4739
+ }
4740
+ if (!tonClientInstance) {
4741
+ tonClientInstance = new ton.TonClient({
4742
+ endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
4743
+ apiKey
4744
+ });
4745
+ }
4746
+ return tonClientInstance;
4747
+ }
4935
4748
  function isNativeAddress(addr) {
4936
4749
  if (!addr) return false;
4937
4750
  const a2 = addr.toLowerCase();
4938
4751
  return a2 === "native" || a2 === "0x0000000000000000000000000000000000000000" || a2 === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" || addr === "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb";
4939
4752
  }
4753
+ function sleep(ms2) {
4754
+ return new Promise((resolve) => setTimeout(resolve, ms2));
4755
+ }
4940
4756
  function toTronBase58(addr, tronWeb) {
4941
4757
  if (!addr) throw new Error("Empty TRON address");
4942
4758
  if (addr.startsWith("T")) return addr;
@@ -4983,24 +4799,27 @@ async function getEvmBalances(publicClient, address, tokens) {
4983
4799
  if (!publicClient) {
4984
4800
  throw new Error("No public client provided");
4985
4801
  }
4986
- const nativeTokens = tokens.filter((t2) => isNativeAddress(t2.address));
4987
4802
  const erc20Tokens = tokens.filter(
4988
4803
  (t2) => !isNativeAddress(t2.address) && viem.isAddress(t2.address)
4989
4804
  );
4990
- for (const token of nativeTokens) {
4805
+ const chainNative = publicClient.chain?.nativeCurrency;
4806
+ const nativeSymbol = chainNative?.symbol ?? "ETH";
4807
+ const nativeDecimals = chainNative?.decimals ?? 18;
4808
+ const maxAttempts = 2;
4809
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
4991
4810
  try {
4992
- const ethBalance = await publicClient.getBalance({
4811
+ const nativeBalance = await publicClient.getBalance({
4993
4812
  address
4994
4813
  });
4995
- const balance = parseFloat(viem.formatUnits(ethBalance, token.decimals));
4814
+ const balance = parseFloat(viem.formatUnits(nativeBalance, nativeDecimals));
4996
4815
  if (balance > 0) {
4997
- balances[token.symbol] = { balance, address };
4816
+ balances[nativeSymbol] = { balance, address };
4817
+ }
4818
+ break;
4819
+ } catch {
4820
+ if (attempt !== maxAttempts) {
4821
+ await sleep(250 * attempt);
4998
4822
  }
4999
- } catch (error) {
5000
- console.debug(
5001
- `Failed to get native balance for ${token.symbol}:`,
5002
- error
5003
- );
5004
4823
  }
5005
4824
  }
5006
4825
  if (erc20Tokens.length > 0) {
@@ -5034,11 +4853,7 @@ async function getEvmBalances(publicClient, address, tokens) {
5034
4853
  if (balance > 0) {
5035
4854
  balances[token.symbol] = { balance, address };
5036
4855
  }
5037
- } catch (error) {
5038
- console.debug(
5039
- `Failed to parse balance for ${token.symbol}:`,
5040
- error
5041
- );
4856
+ } catch {
5042
4857
  }
5043
4858
  }
5044
4859
  });
@@ -5069,8 +4884,7 @@ async function getEvmBalances(publicClient, address, tokens) {
5069
4884
  if (balance > 0) {
5070
4885
  balances[token.symbol] = { balance, address };
5071
4886
  }
5072
- } catch (error2) {
5073
- console.debug(`Failed to get balance for ${token.symbol}:`, error2);
4887
+ } catch {
5074
4888
  }
5075
4889
  }
5076
4890
  }
@@ -5130,12 +4944,7 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
5130
4944
  balances[symbolNorm] = entry;
5131
4945
  }
5132
4946
  }
5133
- } catch (error) {
5134
- const errorMessage = error instanceof Error ? error.message : String(error);
5135
- const isNoWalletError = errorMessage.includes("exit_code: -13") || errorMessage.includes("exit_code:-13") || errorMessage.includes("exitCode: -13");
5136
- if (!isNoWalletError) {
5137
- console.debug(`Failed to get balance for ${token.symbol}:`, error);
5138
- }
4947
+ } catch {
5139
4948
  }
5140
4949
  }
5141
4950
  } catch (error) {
@@ -5157,8 +4966,7 @@ async function getTronBalances(tronWeb, address, tokens) {
5157
4966
  if (trxBalance > 0) {
5158
4967
  balances.TRX = { balance: trxBalance, address: ownerB58 };
5159
4968
  }
5160
- } catch (error) {
5161
- console.warn("Failed to get native TRX balance:", error);
4969
+ } catch {
5162
4970
  }
5163
4971
  for (const token of tokens) {
5164
4972
  try {
@@ -5192,21 +5000,19 @@ async function getTronBalances(tronWeb, address, tokens) {
5192
5000
  if (balance > 0) {
5193
5001
  balances[token.symbol] = { balance, address: ownerB58 };
5194
5002
  }
5195
- } catch (error) {
5196
- console.warn(`Failed to get TRON balance for ${token.symbol}:`, error);
5003
+ } catch {
5197
5004
  }
5198
5005
  }
5199
- } catch (error) {
5200
- console.error("Failed to get Tron balances:", error);
5006
+ } catch {
5201
5007
  }
5202
5008
  return balances;
5203
5009
  }
5204
- const ERC20_ABI = [
5010
+ const ERC20_ABI = viem.parseAbi([
5205
5011
  "function approve(address spender, uint256 amount) returns (bool)",
5206
5012
  "function allowance(address owner, address spender) view returns (uint256)",
5207
5013
  "function decimals() view returns (uint8)",
5208
5014
  "function balanceOf(address owner) view returns (uint256)"
5209
- ];
5015
+ ]);
5210
5016
  class EvmChainStrategy {
5211
5017
  constructor(config) {
5212
5018
  __publicField(this, "config");
@@ -5254,14 +5060,9 @@ class EvmChainStrategy {
5254
5060
  }
5255
5061
  async getBalances(address, tokens) {
5256
5062
  if (!this.publicClient) {
5257
- console.warn("No publicClient available for balance query");
5258
5063
  return {};
5259
5064
  }
5260
- return await getEvmBalances(
5261
- this.publicClient,
5262
- address,
5263
- tokens
5264
- );
5065
+ return await getEvmBalances(this.publicClient, address, tokens);
5265
5066
  }
5266
5067
  isAddressValid(address) {
5267
5068
  if (!address) return false;
@@ -5297,7 +5098,6 @@ class EvmChainStrategy {
5297
5098
  }
5298
5099
  async getSourceCost(txHash) {
5299
5100
  if (!this.publicClient) {
5300
- console.warn("No publicClient available for source cost query");
5301
5101
  return null;
5302
5102
  }
5303
5103
  try {
@@ -5312,18 +5112,61 @@ class EvmChainStrategy {
5312
5112
  const gasFeeWei = gasUsed * gasPrice;
5313
5113
  const txValueWei = tx.value ?? 0n;
5314
5114
  const totalWei = gasFeeWei + txValueWei;
5315
- return {
5115
+ const sourceCost = {
5316
5116
  totalNative: Number(viem.formatUnits(totalWei, 18)),
5317
5117
  breakdown: {
5318
5118
  gasFee: Number(viem.formatUnits(gasFeeWei, 18)),
5319
5119
  layerZeroFee: Number(viem.formatUnits(txValueWei, 18))
5320
5120
  }
5321
5121
  };
5122
+ return sourceCost;
5322
5123
  } catch (error) {
5323
5124
  console.warn("Failed to compute EVM source cost:", error);
5324
5125
  return null;
5325
5126
  }
5326
5127
  }
5128
+ async estimateNetworkFee(steps) {
5129
+ if (!this.walletClient) {
5130
+ return 0;
5131
+ }
5132
+ const account = this.config.evmAddress;
5133
+ const txSteps = steps.filter((step) => step.transaction?.to);
5134
+ if (!txSteps.length) {
5135
+ return 0;
5136
+ }
5137
+ const applyFeeMultiplier = (feePerGas) => {
5138
+ const multiplier = EVM_CONFIG.gasFeeMultiplier;
5139
+ if (!Number.isFinite(multiplier) || multiplier <= 1) {
5140
+ return feePerGas;
5141
+ }
5142
+ const scaled = BigInt(Math.round(multiplier * 100));
5143
+ return (feePerGas * scaled + 99n) / 100n;
5144
+ };
5145
+ let totalFeeWei = 0n;
5146
+ for (const step of txSteps) {
5147
+ const tx = step.transaction;
5148
+ if (!tx?.to) continue;
5149
+ try {
5150
+ const request = await this.walletClient.prepareTransactionRequest({
5151
+ account: tx.from || account,
5152
+ to: tx.to,
5153
+ data: tx.data,
5154
+ value: tx.value ? BigInt(tx.value) : void 0,
5155
+ chain: this.walletClient.chain
5156
+ });
5157
+ const gasLimit = request.gas;
5158
+ const maxFeePerGas = request.maxFeePerGas ?? request.gasPrice;
5159
+ if (gasLimit && maxFeePerGas) {
5160
+ totalFeeWei += gasLimit * applyFeeMultiplier(maxFeePerGas);
5161
+ }
5162
+ } catch {
5163
+ }
5164
+ }
5165
+ if (totalFeeWei === 0n) {
5166
+ return 0;
5167
+ }
5168
+ return Number(viem.formatUnits(totalFeeWei, 18));
5169
+ }
5327
5170
  async executeSteps(steps, _context, onFirstHash) {
5328
5171
  if (!this.isConnected() || !this.walletClient) {
5329
5172
  throw new WalletNotConnectedError("evm");
@@ -5337,134 +5180,32 @@ class EvmChainStrategy {
5337
5180
  );
5338
5181
  if (step.type === "approve") {
5339
5182
  const hash = await this.approveTransaction(step);
5340
- console.log(`Approval transaction hash: ${hash}`);
5341
5183
  if (!firstTxHash) {
5342
5184
  firstTxHash = hash;
5343
5185
  onFirstHash?.(hash);
5344
5186
  }
5345
5187
  } else if (step.type === "bridge") {
5346
5188
  const hash = await this.executeTransaction(step);
5347
- console.log(`Bridge transaction hash: ${hash}`);
5348
5189
  if (!firstTxHash) {
5349
5190
  firstTxHash = hash;
5350
5191
  onFirstHash?.(hash);
5351
5192
  }
5352
5193
  } else {
5353
- throw new InvalidStepsError(
5354
- "evm",
5355
- `Unsupported step type: ${step.type}`
5356
- );
5357
- }
5358
- }
5359
- return {
5360
- hash: firstTxHash,
5361
- chainKey: steps[0]?.chainKey
5362
- };
5363
- } catch (error) {
5364
- if (error instanceof Error && error.name.includes("Error")) {
5365
- throw error;
5366
- }
5367
- throw toChainStrategyError(error, "evm", "transaction");
5368
- }
5369
- }
5370
- async waitForCompletion(txHash) {
5371
- try {
5372
- const publicClient = this.publicClient;
5373
- if (!publicClient) {
5374
- throw new ProviderNotAvailableError("evm");
5375
- }
5376
- console.log(
5377
- `Waiting for ${EVM_CONFIG.requiredConfirmations} confirmations for tx: ${txHash}`
5378
- );
5379
- const receipt = await publicClient.waitForTransactionReceipt({
5380
- hash: txHash,
5381
- confirmations: EVM_CONFIG.requiredConfirmations,
5382
- timeout: EVM_CONFIG.timeout
5383
- });
5384
- if (!receipt) {
5385
- const error = new TransactionTimeoutError("evm", txHash);
5386
- return {
5387
- completed: false,
5388
- error: error.message
5389
- };
5390
- }
5391
- if (receipt.status !== "success") {
5392
- const error = new TransactionRevertedError("evm", txHash);
5393
- return {
5394
- completed: false,
5395
- error: error.message
5396
- };
5397
- }
5398
- console.log(
5399
- `EVM transaction confirmed in block ${receipt.blockNumber} with ${EVM_CONFIG.requiredConfirmations} confirmations`
5400
- );
5401
- let actualFeeValue;
5402
- try {
5403
- const gasUsed = receipt.gasUsed;
5404
- const effectiveGasPrice = receipt.effectiveGasPrice;
5405
- if (gasUsed && effectiveGasPrice) {
5406
- const feeWei = gasUsed * effectiveGasPrice;
5407
- const feeInNative = viem.formatUnits(feeWei, 18);
5408
- actualFeeValue = feeInNative;
5409
- console.log(`EVM transaction fee: ${feeInNative} (native token)`);
5194
+ throw new InvalidStepsError(
5195
+ "evm",
5196
+ `Unsupported step type: ${step.type}`
5197
+ );
5410
5198
  }
5411
- } catch (error) {
5412
- console.warn("Failed to calculate actual fee:", error);
5413
5199
  }
5414
5200
  return {
5415
- completed: true,
5416
- actualFeeValue
5417
- // Symbol will be determined by the caller based on chain info
5201
+ hash: firstTxHash,
5202
+ chainKey: steps[0]?.chainKey
5418
5203
  };
5419
5204
  } catch (error) {
5420
- if (error && typeof error === "object" && "code" in error && error.code === "TRANSACTION_REPLACED") {
5421
- console.log(
5422
- `Transaction was replaced: ${"reason" in error ? String(error.reason) : "unknown"}`
5423
- );
5424
- if ("receipt" in error && error.receipt) {
5425
- const replacementReceipt = error.receipt;
5426
- if (replacementReceipt.status === 1) {
5427
- console.log(
5428
- `Replacement transaction succeeded in block ${replacementReceipt.blockNumber}`
5429
- );
5430
- let actualFeeValue;
5431
- try {
5432
- const receipt = error.receipt;
5433
- const gasUsed = receipt.gasUsed;
5434
- const effectiveGasPrice = receipt.effectiveGasPrice;
5435
- if (gasUsed && effectiveGasPrice) {
5436
- const feeWei = gasUsed * effectiveGasPrice;
5437
- const feeInNative = viem.formatUnits(feeWei, 18);
5438
- actualFeeValue = feeInNative;
5439
- console.log(
5440
- `Replacement transaction fee: ${feeInNative} (native token)`
5441
- );
5442
- }
5443
- } catch (feeError) {
5444
- console.warn("Failed to calculate replacement transaction fee:", feeError);
5445
- }
5446
- return {
5447
- completed: true,
5448
- actualFeeValue
5449
- };
5450
- } else {
5451
- const chainError2 = new TransactionRevertedError("evm", txHash);
5452
- return {
5453
- completed: false,
5454
- error: chainError2.message
5455
- };
5456
- }
5457
- }
5205
+ if (error instanceof Error && error.name.includes("Error")) {
5206
+ throw error;
5458
5207
  }
5459
- const chainError = toChainStrategyError(
5460
- error,
5461
- "evm",
5462
- "waitForCompletion"
5463
- );
5464
- return {
5465
- completed: false,
5466
- error: chainError.message
5467
- };
5208
+ throw toChainStrategyError(error, "evm", "transaction");
5468
5209
  }
5469
5210
  }
5470
5211
  async executeTransaction(step) {
@@ -5621,88 +5362,14 @@ class EvmChainStrategy {
5621
5362
  blockTag: "finalized"
5622
5363
  });
5623
5364
  if (!finalizedBlock) {
5624
- console.debug(
5625
- "Finalized block not available (pre-merge or unsupported)"
5626
- );
5627
5365
  return false;
5628
5366
  }
5629
- const isFinalized = blockNumber <= finalizedBlock.number;
5630
- if (isFinalized) {
5631
- console.log(
5632
- `Block ${blockNumber} has reached finality (finalized block: ${finalizedBlock.number})`
5633
- );
5634
- } else {
5635
- console.debug(
5636
- `Block ${blockNumber} not yet finalized (finalized block: ${finalizedBlock.number})`
5637
- );
5638
- }
5639
- return isFinalized;
5640
- } catch (error) {
5641
- console.debug("Error checking finality:", error);
5367
+ return blockNumber <= finalizedBlock.number;
5368
+ } catch {
5642
5369
  return false;
5643
5370
  }
5644
5371
  }
5645
5372
  }
5646
- function getNormalizedExtMessageHash(message) {
5647
- if (message.info.type !== "external-in") {
5648
- throw new Error(`Expected external-in message, got ${message.info.type}`);
5649
- }
5650
- const normalizedInfo = {
5651
- ...message.info,
5652
- src: void 0,
5653
- importFee: 0n
5654
- };
5655
- const normalizedMessage = {
5656
- ...message,
5657
- info: normalizedInfo,
5658
- init: null
5659
- };
5660
- return core.beginCell().store(core.storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
5661
- }
5662
- async function getTonTransactionHash(messageHash, userAddress, searchLimit = 20, options) {
5663
- try {
5664
- const client = options?.client ?? new ton.TonClient({
5665
- endpoint: "https://toncenter.com/api/v2/jsonRPC",
5666
- apiKey: process.env.TONCENTER_API_KEY
5667
- // Optional: for rate limit increase
5668
- });
5669
- const messageHasher = options?.messageHasher ?? getNormalizedExtMessageHash;
5670
- const address = core.Address.parse(userAddress);
5671
- const transactions = await client.getTransactions(address, {
5672
- limit: searchLimit
5673
- });
5674
- for (const tx of transactions) {
5675
- const inMsg = tx.inMessage;
5676
- if (!inMsg) continue;
5677
- try {
5678
- const inMsgHash = messageHasher(inMsg).toString("hex");
5679
- if (inMsgHash === messageHash.replace("0x", "")) {
5680
- const txHash = tx.hash().toString("hex");
5681
- return {
5682
- transactionHash: `0x${txHash}`,
5683
- messageHash,
5684
- found: true
5685
- };
5686
- }
5687
- } catch {
5688
- continue;
5689
- }
5690
- }
5691
- console.warn(`TON transaction not found for message hash: ${messageHash}`);
5692
- return {
5693
- transactionHash: null,
5694
- messageHash,
5695
- found: false
5696
- };
5697
- } catch (error) {
5698
- console.error("Failed to get TON transaction hash:", error);
5699
- return {
5700
- transactionHash: null,
5701
- messageHash,
5702
- found: false
5703
- };
5704
- }
5705
- }
5706
5373
  class TonChainStrategy {
5707
5374
  constructor(config) {
5708
5375
  __publicField(this, "config");
@@ -5815,40 +5482,17 @@ class TonChainStrategy {
5815
5482
  validUntil: Math.floor(Date.now() / 1e3) + TON_CONFIG.validUntil,
5816
5483
  messages: tonMessages
5817
5484
  };
5818
- const result = await this.config.tonConnectUI.sendTransaction(
5819
- transaction2
5820
- );
5485
+ const result = await this.config.tonConnectUI.sendTransaction(transaction2);
5821
5486
  const bocBase64 = result.boc;
5822
5487
  try {
5823
5488
  const inMessage = core.loadMessage(core.Cell.fromBase64(bocBase64).beginParse());
5824
5489
  const messageHash = this.getNormalizedExtMessageHash(inMessage);
5825
5490
  const hexHash = messageHash.toString("hex");
5826
5491
  onFirstHash?.(hexHash);
5827
- let tonTransactionHash;
5828
- if (this.config.tonAddress) {
5829
- try {
5830
- const tonTxResult = await getTonTransactionHash(
5831
- hexHash,
5832
- this.config.tonAddress,
5833
- 20
5834
- );
5835
- if (tonTxResult.found && tonTxResult.transactionHash) {
5836
- tonTransactionHash = tonTxResult.transactionHash;
5837
- } else {
5838
- console.warn(
5839
- `TON transaction hash not found for message hash: ${hexHash}`
5840
- );
5841
- }
5842
- } catch (error) {
5843
- console.error("Failed to convert TON message hash:", error);
5844
- }
5845
- }
5846
5492
  return {
5847
5493
  chainKey: "ton",
5848
- hash: hexHash,
5849
- // Message hash for TONScan
5850
- tonTransactionHash
5851
- // Transaction hash for LayerZero (if found)
5494
+ hash: hexHash
5495
+ // Message hash for TONScan and for finding tx later
5852
5496
  };
5853
5497
  } catch (error) {
5854
5498
  console.error("Error parsing BOC to hex hash:", error);
@@ -5862,39 +5506,45 @@ class TonChainStrategy {
5862
5506
  throw toChainStrategyError(error, "ton", "transaction");
5863
5507
  }
5864
5508
  }
5865
- async waitForCompletion(txHash) {
5866
- try {
5867
- const result = await this.checkTonTransaction(
5868
- txHash,
5869
- TON_CONFIG.timeout
5870
- );
5871
- if (!result.confirmed) {
5872
- const error = new TransactionFailedError(
5873
- "ton",
5874
- "Transaction not confirmed on-chain",
5875
- txHash
5876
- );
5877
- return {
5878
- completed: false,
5879
- error: error.message
5880
- };
5509
+ /**
5510
+ * Convert TON message hash to transaction hash.
5511
+ * LayerZero uses transaction hash, but TonConnect returns message hash.
5512
+ */
5513
+ async convertMessageHashToTxHash(messageHash, timeoutMs = 6e4) {
5514
+ const deadline = Date.now() + timeoutMs;
5515
+ const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
5516
+ if (!this.config.tonAddress) {
5517
+ return null;
5518
+ }
5519
+ const targetMessageHash = Buffer.from(messageHash, "hex");
5520
+ const accountAddress = core.Address.parse(this.config.tonAddress);
5521
+ while (Date.now() < deadline) {
5522
+ try {
5523
+ const transactions = await client.getTransactions(accountAddress, {
5524
+ limit: 20,
5525
+ archival: true
5526
+ });
5527
+ for (const tx of transactions) {
5528
+ if (tx.inMessage?.info.type === "external-in") {
5529
+ try {
5530
+ const txInMessageHash = this.getNormalizedExtMessageHash(
5531
+ tx.inMessage
5532
+ );
5533
+ if (txInMessageHash.equals(targetMessageHash)) {
5534
+ const txHash = `0x${tx.hash().toString("hex")}`;
5535
+ return txHash;
5536
+ }
5537
+ } catch {
5538
+ continue;
5539
+ }
5540
+ }
5541
+ }
5542
+ await new Promise((r2) => setTimeout(r2, 3e3));
5543
+ } catch {
5544
+ await new Promise((r2) => setTimeout(r2, 3e3));
5881
5545
  }
5882
- return {
5883
- completed: true,
5884
- actualFeeValue: result.fee,
5885
- actualFeeSymbol: "TON"
5886
- };
5887
- } catch (error) {
5888
- const chainError = toChainStrategyError(
5889
- error,
5890
- "ton",
5891
- "waitForCompletion"
5892
- );
5893
- return {
5894
- completed: false,
5895
- error: chainError.message
5896
- };
5897
5546
  }
5547
+ return null;
5898
5548
  }
5899
5549
  getNormalizedExtMessageHash(message) {
5900
5550
  if (message.info.type !== "external-in") {
@@ -5917,6 +5567,9 @@ class TonChainStrategy {
5917
5567
  if (typeof value === "number" && Number.isFinite(value)) {
5918
5568
  return BigInt(Math.trunc(value));
5919
5569
  }
5570
+ if (typeof value === "object" && value !== null && "coins" in value) {
5571
+ return this.toBigInt(value.coins);
5572
+ }
5920
5573
  if (typeof value === "string" && value.trim() !== "") {
5921
5574
  try {
5922
5575
  return BigInt(value);
@@ -5930,12 +5583,16 @@ class TonChainStrategy {
5930
5583
  const candidate = tx.outMessages;
5931
5584
  if (!candidate) return [];
5932
5585
  if (Array.isArray(candidate)) return candidate;
5933
- if (candidate instanceof Map) return Array.from(candidate.values());
5934
5586
  if (typeof candidate === "object" && candidate !== null && "values" in candidate && typeof candidate.values === "function") {
5935
- return Array.from(
5936
- candidate.values()
5937
- );
5587
+ const values = candidate.values();
5588
+ if (Array.isArray(values)) {
5589
+ return [...values];
5590
+ }
5591
+ if (values && typeof values === "object" && Symbol.iterator in values) {
5592
+ return Array.from(values);
5593
+ }
5938
5594
  }
5595
+ if (candidate instanceof Map) return Array.from(candidate.values());
5939
5596
  return [];
5940
5597
  }
5941
5598
  getMessageValue(message) {
@@ -5947,27 +5604,49 @@ class TonChainStrategy {
5947
5604
  }
5948
5605
  return this.toBigInt(value);
5949
5606
  }
5950
- getFirstOutMessageValue(tx) {
5607
+ getTotalOutMessageValue(tx) {
5951
5608
  const outMessages = this.getOutMessages(tx);
5952
5609
  if (!outMessages.length) return 0n;
5953
- const value = this.getMessageValue(outMessages[0]);
5954
- return value ?? 0n;
5610
+ let total = 0n;
5611
+ for (const message of outMessages) {
5612
+ const value = this.getMessageValue(message);
5613
+ if (value) {
5614
+ total += value;
5615
+ }
5616
+ }
5617
+ return total;
5955
5618
  }
5956
- async getSourceCost(txHash) {
5957
- const timeoutMs = Math.min(TON_CONFIG.timeout, 12e4);
5958
- const result = await this.checkTonTransaction(txHash, timeoutMs);
5959
- if (!result.confirmed) return null;
5619
+ async getSourceCost(messageHash) {
5620
+ const timeoutMs = 3e4;
5621
+ const result = await this.checkTonTransaction(messageHash, timeoutMs);
5622
+ if (!result.confirmed) {
5623
+ console.warn("Transaction not found for source cost calculation");
5624
+ return null;
5625
+ }
5960
5626
  const totalFees = result.totalFees ?? 0n;
5961
5627
  const outValue = result.outValue ?? 0n;
5962
5628
  const totalNanotons = totalFees + outValue;
5963
5629
  const toTon = (value) => Number(value) / 1e9;
5964
- return {
5630
+ const sourceCost = {
5965
5631
  totalNative: toTon(totalNanotons),
5966
5632
  breakdown: {
5967
5633
  gasFee: toTon(totalFees),
5968
5634
  layerZeroFee: toTon(outValue)
5969
5635
  }
5970
5636
  };
5637
+ console.log("TON source cost:", {
5638
+ gasFee: `${sourceCost.breakdown.gasFee} TON`,
5639
+ layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TON`,
5640
+ total: `${sourceCost.totalNative} TON`
5641
+ });
5642
+ return sourceCost;
5643
+ }
5644
+ async estimateNetworkFee() {
5645
+ const fee = Number(TON_CONFIG.estimatedNetworkFee);
5646
+ if (!Number.isFinite(fee) || fee <= 0) {
5647
+ return 0;
5648
+ }
5649
+ return fee / 1e9;
5971
5650
  }
5972
5651
  async checkTonTransaction(hashOrBoc, timeoutMs = 36e4) {
5973
5652
  const deadline = Date.now() + timeoutMs;
@@ -5978,10 +5657,6 @@ class TonChainStrategy {
5978
5657
  try {
5979
5658
  const inMessage = core.loadMessage(core.Cell.fromBase64(hashOrBoc).beginParse());
5980
5659
  if (inMessage.info.type !== "external-in") {
5981
- console.debug(
5982
- "Expected external-in message, got:",
5983
- inMessage.info.type
5984
- );
5985
5660
  return { confirmed: false };
5986
5661
  }
5987
5662
  accountAddress = inMessage.info.dest;
@@ -5989,63 +5664,50 @@ class TonChainStrategy {
5989
5664
  } catch {
5990
5665
  targetMessageHash = Buffer.from(hashOrBoc, "hex");
5991
5666
  if (!this.config.tonAddress) {
5992
- console.debug("No wallet address available for hex hash lookup");
5993
5667
  return { confirmed: false };
5994
5668
  }
5995
5669
  accountAddress = core.Address.parse(this.config.tonAddress);
5996
5670
  }
5997
- let lt2 = void 0;
5998
- let hash = void 0;
5999
5671
  while (Date.now() < deadline) {
6000
5672
  try {
6001
5673
  const transactions = await client.getTransactions(accountAddress, {
6002
- lt: lt2,
6003
- hash,
6004
- limit: 10,
5674
+ limit: 20,
5675
+ // Check last 20 transactions
6005
5676
  archival: true
6006
5677
  });
6007
- if (transactions.length === 0) {
6008
- await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
6009
- lt2 = void 0;
6010
- hash = void 0;
6011
- continue;
6012
- }
6013
5678
  for (const tx of transactions) {
6014
5679
  if (tx.inMessage?.info.type === "external-in") {
6015
- const txInMessageHash = this.getNormalizedExtMessageHash(
6016
- tx.inMessage
6017
- );
6018
- if (txInMessageHash.equals(targetMessageHash)) {
6019
- console.debug("Transaction found by in-message hash");
6020
- const totalFees = this.toBigInt(
6021
- tx.totalFees
6022
- ) ?? 0n;
6023
- const outValue = this.getFirstOutMessageValue(tx);
6024
- const feeInTon = Number(totalFees) / 1e9;
6025
- console.log(`TON transaction fee: ${feeInTon} TON`);
6026
- return {
6027
- confirmed: true,
6028
- fee: feeInTon.toString(),
6029
- totalFees,
6030
- outValue
6031
- };
5680
+ try {
5681
+ const txInMessageHash = this.getNormalizedExtMessageHash(
5682
+ tx.inMessage
5683
+ );
5684
+ if (txInMessageHash.equals(targetMessageHash)) {
5685
+ const totalFees = this.toBigInt(tx.totalFees) ?? this.toBigInt(
5686
+ tx.total_fees
5687
+ ) ?? 0n;
5688
+ const outValue = this.getTotalOutMessageValue(tx);
5689
+ const feeInTon = Number(totalFees) / 1e9;
5690
+ const transactionHash = tx.hash().toString("hex");
5691
+ return {
5692
+ confirmed: true,
5693
+ fee: feeInTon.toString(),
5694
+ totalFees,
5695
+ outValue,
5696
+ transactionHash
5697
+ };
5698
+ }
5699
+ } catch {
5700
+ continue;
6032
5701
  }
6033
5702
  }
6034
5703
  }
6035
- const lastTx = transactions[transactions.length - 1];
6036
- lt2 = lastTx.lt.toString();
6037
- hash = lastTx.hash().toString("base64");
6038
5704
  await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
6039
- } catch (error) {
6040
- console.debug("Error fetching transactions:", error);
5705
+ } catch {
6041
5706
  await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
6042
- lt2 = void 0;
6043
- hash = void 0;
6044
5707
  }
6045
5708
  }
6046
5709
  return { confirmed: false };
6047
- } catch (error) {
6048
- console.debug("Error parsing BOC or checking transaction:", error);
5710
+ } catch {
6049
5711
  return { confirmed: false };
6050
5712
  }
6051
5713
  }
@@ -6055,6 +5717,7 @@ class TronChainStrategy {
6055
5717
  constructor(config) {
6056
5718
  __publicField(this, "config");
6057
5719
  __publicField(this, "fallbackClient");
5720
+ __publicField(this, "apiKeyApplied", /* @__PURE__ */ new WeakSet());
6058
5721
  this.config = config;
6059
5722
  }
6060
5723
  canHandle(chainKey) {
@@ -6220,18 +5883,31 @@ class TronChainStrategy {
6220
5883
  const feeTrx = feeSun / 1e6;
6221
5884
  const lzFeeTrx = callValueSun / 1e6;
6222
5885
  const totalTrx = (feeSun + callValueSun) / 1e6;
6223
- return {
5886
+ const sourceCost = {
6224
5887
  totalNative: totalTrx,
6225
5888
  breakdown: {
6226
5889
  gasFee: feeTrx,
6227
5890
  layerZeroFee: lzFeeTrx
6228
5891
  }
6229
5892
  };
5893
+ console.log("TRON source cost:", {
5894
+ gasFee: `${sourceCost.breakdown.gasFee} TRX`,
5895
+ layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TRX`,
5896
+ total: `${sourceCost.totalNative} TRX`
5897
+ });
5898
+ return sourceCost;
6230
5899
  } catch (error) {
6231
5900
  console.warn("Failed to compute TRON source cost:", error);
6232
5901
  return null;
6233
5902
  }
6234
5903
  }
5904
+ async estimateNetworkFee() {
5905
+ const fee = Number(TRON_CONFIG.estimatedNetworkFee);
5906
+ if (!Number.isFinite(fee) || fee <= 0) {
5907
+ return 0;
5908
+ }
5909
+ return fee / 1e6;
5910
+ }
6235
5911
  async executeSteps(steps, _context, onFirstHash) {
6236
5912
  const tronWeb = this.getClient();
6237
5913
  if (!tronWeb) {
@@ -6328,137 +6004,59 @@ class TronChainStrategy {
6328
6004
  }
6329
6005
  return { hash: lastTxId, chainKey: "tron" };
6330
6006
  }
6331
- async waitForCompletion(txHash) {
6332
- try {
6333
- const tronWeb = this.getClient();
6334
- if (!tronWeb) {
6335
- throw new ProviderNotAvailableError("tron");
6336
- }
6337
- console.log(
6338
- `Waiting for ${TRON_CONFIG.requiredConfirmations} confirmations for TRON tx: ${txHash}`
6339
- );
6340
- const deadline = Date.now() + TRON_CONFIG.timeout;
6341
- let txBlockNumber = null;
6342
- let actualFeeTrx = null;
6343
- while (Date.now() < deadline && !txBlockNumber) {
6344
- try {
6345
- const info = await tronWeb.trx.getTransactionInfo(txHash);
6346
- if (info && info.blockNumber) {
6347
- const result = info.receipt?.result;
6348
- if (result !== "SUCCESS") {
6349
- const msg = this.hexToAscii(info.resMessage) || null;
6350
- let reason = msg;
6351
- const cr2 = info.contractResult?.[0];
6352
- if (cr2 && /^0x?08c379a0/i.test(cr2)) {
6353
- try {
6354
- const clean2 = cr2.replace(/^0x/, "");
6355
- const len = parseInt(clean2.slice(8 + 64, 8 + 64 + 64), 16);
6356
- const strHex = clean2.slice(
6357
- 8 + 64 + 64,
6358
- 8 + 64 + 64 + len * 2
6359
- );
6360
- const str = this.hexToAscii("0x" + strHex);
6361
- if (str) reason = str;
6362
- } catch (e2) {
6363
- console.debug("TRON revert string decode error", e2);
6364
- }
6365
- }
6366
- const error2 = new TransactionRevertedError(
6367
- "tron",
6368
- txHash,
6369
- reason || "Unknown error"
6370
- );
6371
- return {
6372
- completed: false,
6373
- error: error2.message
6374
- };
6375
- }
6376
- txBlockNumber = info.blockNumber;
6377
- const feeSun = info.fee || 0;
6378
- actualFeeTrx = feeSun / 1e6;
6379
- console.log(
6380
- `TRON transaction found in block ${txBlockNumber}, fee: ${actualFeeTrx} TRX`
6381
- );
6382
- }
6383
- } catch (e2) {
6384
- console.debug("TRON getTransactionInfo error:", e2);
6385
- }
6386
- if (!txBlockNumber) {
6387
- await new Promise((r2) => setTimeout(r2, TRON_CONFIG.pollingInterval));
6388
- }
6389
- }
6390
- if (!txBlockNumber) {
6391
- const error2 = new TransactionTimeoutError("tron", txHash);
6392
- return {
6393
- completed: false,
6394
- error: error2.message
6395
- };
6396
- }
6397
- let confirmations = 0;
6398
- while (Date.now() < deadline) {
6399
- try {
6400
- const currentBlock = await tronWeb.trx.getCurrentBlock();
6401
- const currentBlockNumber = currentBlock?.block_header?.raw_data?.number;
6402
- if (currentBlockNumber) {
6403
- confirmations = currentBlockNumber - txBlockNumber;
6404
- if (confirmations >= TRON_CONFIG.requiredConfirmations) {
6405
- console.log(
6406
- `TRON transaction confirmed in block ${txBlockNumber} with ${confirmations} confirmations`
6407
- );
6408
- return {
6409
- completed: true,
6410
- actualFeeValue: actualFeeTrx?.toString(),
6411
- actualFeeSymbol: "TRX"
6412
- };
6413
- }
6414
- console.log(
6415
- `TRON transaction confirmations: ${confirmations}/${TRON_CONFIG.requiredConfirmations}`
6416
- );
6417
- }
6418
- } catch (e2) {
6419
- console.debug("TRON getCurrentBlock error:", e2);
6420
- }
6421
- await new Promise((r2) => setTimeout(r2, TRON_CONFIG.pollingInterval));
6422
- }
6423
- const error = new TransactionTimeoutError("tron", txHash);
6424
- return {
6425
- completed: false,
6426
- error: error.message
6427
- };
6428
- } catch (error) {
6429
- const chainError = toChainStrategyError(
6430
- error,
6431
- "tron",
6432
- "waitForCompletion"
6433
- );
6434
- return {
6435
- completed: false,
6436
- error: chainError.message
6437
- };
6438
- }
6439
- }
6440
6007
  getClient() {
6441
6008
  if (typeof window !== "undefined" && window.tronWeb) {
6009
+ this.applyTronApiKey(window.tronWeb);
6442
6010
  return window.tronWeb;
6443
6011
  }
6444
6012
  if (!this.fallbackClient) {
6445
6013
  this.fallbackClient = this.createFallbackClient();
6446
6014
  }
6015
+ if (this.fallbackClient) {
6016
+ this.applyTronApiKey(this.fallbackClient);
6017
+ }
6447
6018
  return this.fallbackClient;
6448
6019
  }
6449
6020
  createFallbackClient() {
6450
6021
  try {
6451
- const tronWeb = new tronweb.TronWeb(
6452
- DEFAULT_TRON_NODE,
6453
- DEFAULT_TRON_NODE,
6454
- DEFAULT_TRON_NODE
6455
- );
6022
+ if (!this.config.apiKey) {
6023
+ throw new Error("TRON API key is required");
6024
+ }
6025
+ const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
6026
+ const tronWeb = new tronweb.TronWeb({
6027
+ fullHost: DEFAULT_TRON_NODE,
6028
+ headers
6029
+ });
6456
6030
  return tronWeb;
6457
6031
  } catch (error) {
6458
6032
  console.warn("Failed to create fallback TronWeb client", error);
6459
6033
  return void 0;
6460
6034
  }
6461
6035
  }
6036
+ applyTronApiKey(tronWeb) {
6037
+ if (!this.config.apiKey) {
6038
+ return;
6039
+ }
6040
+ const target = tronWeb;
6041
+ if (this.apiKeyApplied.has(target)) {
6042
+ return;
6043
+ }
6044
+ try {
6045
+ const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
6046
+ if (typeof target.setHeader === "function") {
6047
+ target.setHeader(headers);
6048
+ } else {
6049
+ if (typeof target.setFullNodeHeader === "function") {
6050
+ target.setFullNodeHeader(headers);
6051
+ }
6052
+ if (typeof target.setEventHeader === "function") {
6053
+ target.setEventHeader(headers);
6054
+ }
6055
+ }
6056
+ this.apiKeyApplied.add(target);
6057
+ } catch {
6058
+ }
6059
+ }
6462
6060
  /**
6463
6061
  * Check if TronLink wallet is actually installed
6464
6062
  * This excludes Bybit Wallet which also injects tronLink for compatibility
@@ -6467,14 +6065,8 @@ class TronChainStrategy {
6467
6065
  if (typeof window === "undefined") {
6468
6066
  return false;
6469
6067
  }
6470
- const hasBybitWallet = typeof window.bybitWallet !== "undefined" && typeof window.bybitWallet.tronLink !== "undefined";
6471
- if (hasBybitWallet && !window.tronLink) {
6472
- return false;
6473
- }
6474
- if (!window.tronLink) {
6475
- return false;
6476
- }
6477
- return true;
6068
+ const win = window;
6069
+ return !!(win.tronLink || win.tronWeb || win.tron);
6478
6070
  }
6479
6071
  ensureDefaultAddress(tronWeb, address) {
6480
6072
  if (!address) return;
@@ -6487,18 +6079,7 @@ class TronChainStrategy {
6487
6079
  hex
6488
6080
  };
6489
6081
  }
6490
- } catch (error) {
6491
- console.debug("Failed to set TronWeb default address:", error);
6492
- }
6493
- }
6494
- hexToAscii(h4) {
6495
- if (!h4) return null;
6496
- const clean2 = h4.replace(/^0x/, "");
6497
- const bytes = clean2.match(/.{1,2}/g) || [];
6498
- try {
6499
- return bytes.map((b2) => String.fromCharCode(parseInt(b2, 16))).join("");
6500
6082
  } catch {
6501
- return null;
6502
6083
  }
6503
6084
  }
6504
6085
  toBase58(addr, tronWeb) {
@@ -6805,22 +6386,14 @@ class TronChainStrategy {
6805
6386
  }
6806
6387
  const info = await tronWeb.trx.getTransactionInfo(txHash);
6807
6388
  if (!info || !info.blockNumber) {
6808
- console.debug(
6809
- "Transaction not yet solidified (no blockNumber in info)"
6810
- );
6811
6389
  return false;
6812
6390
  }
6813
6391
  const result = info.receipt?.result;
6814
6392
  if (result === "SUCCESS") {
6815
- console.log(
6816
- `Transaction ${txHash} is solidified in block ${info.blockNumber}`
6817
- );
6818
6393
  return true;
6819
6394
  }
6820
- console.debug(`Transaction solidified but result is: ${result}`);
6821
6395
  return false;
6822
- } catch (error) {
6823
- console.debug("Error checking solidified status:", error);
6396
+ } catch {
6824
6397
  return false;
6825
6398
  }
6826
6399
  }
@@ -6831,7 +6404,8 @@ function ChainStrategyProvider({
6831
6404
  tonWallet,
6832
6405
  tronWallet,
6833
6406
  tonClient,
6834
- tonApiKey
6407
+ tonApiKey,
6408
+ tronApiKey
6835
6409
  }) {
6836
6410
  const evmStrategy = react.useMemo(
6837
6411
  () => new EvmChainStrategy({
@@ -6874,7 +6448,8 @@ function ChainStrategyProvider({
6874
6448
  connect: tronWallet.walletConnect.connect,
6875
6449
  disconnect: tronWallet.walletConnect.disconnect,
6876
6450
  signTransaction: tronWallet.walletConnect.signTransaction
6877
- } : void 0
6451
+ } : void 0,
6452
+ apiKey: tronApiKey
6878
6453
  }),
6879
6454
  [
6880
6455
  tronWallet.tronLink.address,
@@ -6882,7 +6457,8 @@ function ChainStrategyProvider({
6882
6457
  tronWallet.tronLink.select,
6883
6458
  tronWallet.tronLink.connect,
6884
6459
  tronWallet.tronLink.disconnect,
6885
- tronWallet.walletConnect
6460
+ tronWallet.walletConnect,
6461
+ tronApiKey
6886
6462
  ]
6887
6463
  );
6888
6464
  const chainRegistry = react.useMemo(
@@ -7067,6 +6643,7 @@ const SettingsModal = ({ isOpen, onClose }) => {
7067
6643
  const TOKEN_ROW_HEIGHT = 52;
7068
6644
  const TokenRow = ({
7069
6645
  symbol,
6646
+ willChangeSrc,
7070
6647
  name,
7071
6648
  isSelected,
7072
6649
  hasAnyWallet,
@@ -7079,7 +6656,7 @@ const TokenRow = ({
7079
6656
  button.Button,
7080
6657
  {
7081
6658
  onClick: onPick,
7082
- className: `w-full px-5 rounded-xs bg-transparent flex items-center justify-between gap-3 hover:bg-accent hover:scale-100 ${isSelected ? "border border-primary" : ""}`,
6659
+ className: `w-full px-5 rounded-xs bg-transparent flex items-center justify-between gap-3 hover:bg-accent hover:scale-100 ${isSelected ? "border border-primary" : ""} ${willChangeSrc ? "opacity-50 hover:opacity-100" : ""}`,
7083
6660
  children: [
7084
6661
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
7085
6662
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -7315,7 +6892,7 @@ const TokenSelectModal = ({
7315
6892
  "div",
7316
6893
  {
7317
6894
  style: { ...style, height: TOKEN_ROW_HEIGHT },
7318
- className: "px-5 flex leading-4 text-base py-2 text-muted-foreground uppercase mt-8",
6895
+ className: "px-5 flex leading-4 text-base py-2 text-muted-foreground uppercase mt-3",
7319
6896
  children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: item.text })
7320
6897
  }
7321
6898
  );
@@ -7334,6 +6911,7 @@ const TokenSelectModal = ({
7334
6911
  balance: bal,
7335
6912
  usdValue: usd,
7336
6913
  isBalanceLoading: balancesQuery.isLoading || balancesQuery.isFetching,
6914
+ willChangeSrc,
7337
6915
  onPick: () => onPick(token.symbol, willChangeSrc)
7338
6916
  }
7339
6917
  ) });
@@ -7358,67 +6936,74 @@ const TokenSelectModal = ({
7358
6936
  },
7359
6937
  [effectiveTab, virtualItems]
7360
6938
  );
7361
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "md:max-h-[90dvh] md:h-[90dvh] overflow-hidden flex flex-col fixed top-0 left-0 right-0 bottom-0 translate-x-0 translate-y-0 md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%] p-10 pt-7 rounded-none md:rounded-lg", children: [
7362
- /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { className: "text-2xl leading-8", children: t2("bridge.selectToken") }) }),
7363
- /* @__PURE__ */ jsxRuntime.jsx(
7364
- SearchInput,
7365
- {
7366
- placeholder: t2("bridge.searchToken"),
7367
- value: query,
7368
- onChange: setQuery
7369
- }
7370
- ),
7371
- hasSourceWallet() && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
7372
- /* @__PURE__ */ jsxRuntime.jsx(
7373
- button.Button,
7374
- {
7375
- variant: effectiveTab === "my" ? "default" : "ghost",
7376
- onClick: () => {
7377
- setTab("my");
7378
- setManualTabSwitch(true);
7379
- },
7380
- size: "sm",
7381
- className: utils$1.cn(
7382
- "px-4 cursor-pointer",
7383
- effectiveTab !== "my" && "bg-muted hover:bg-accent"
7384
- ),
7385
- children: t2("bridge.myTokens")
7386
- }
7387
- ),
7388
- /* @__PURE__ */ jsxRuntime.jsx(
7389
- button.Button,
7390
- {
7391
- variant: effectiveTab === "all" ? "default" : "ghost",
7392
- onClick: () => {
7393
- setTab("all");
7394
- setManualTabSwitch(true);
7395
- },
7396
- size: "sm",
7397
- className: utils$1.cn(
7398
- "px-4 cursor-pointer",
7399
- effectiveTab !== "all" && "bg-muted hover:bg-accent"
6939
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(
6940
+ dialog.DialogContent,
6941
+ {
6942
+ className: "md:max-h-[90dvh] md:h-[90dvh] overflow-hidden flex flex-col fixed top-0 left-0 right-0 bottom-0 translate-x-0 translate-y-0 md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%] p-6 md:p-10 md:pt-8 rounded-none md:rounded-lg",
6943
+ closeButtonClassName: "right-6 md:right-10",
6944
+ children: [
6945
+ /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { className: "text-2xl leading-8", children: t2("bridge.selectToken") }) }),
6946
+ /* @__PURE__ */ jsxRuntime.jsx(
6947
+ SearchInput,
6948
+ {
6949
+ placeholder: t2("bridge.searchToken"),
6950
+ value: query,
6951
+ onChange: setQuery
6952
+ }
6953
+ ),
6954
+ hasSourceWallet() && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
6955
+ /* @__PURE__ */ jsxRuntime.jsx(
6956
+ button.Button,
6957
+ {
6958
+ variant: effectiveTab === "my" ? "default" : "ghost",
6959
+ onClick: () => {
6960
+ setTab("my");
6961
+ setManualTabSwitch(true);
6962
+ },
6963
+ size: "sm",
6964
+ className: utils$1.cn(
6965
+ "px-4 h-9 cursor-pointer",
6966
+ effectiveTab !== "my" && "bg-muted hover:bg-accent"
6967
+ ),
6968
+ children: t2("bridge.myTokens")
6969
+ }
7400
6970
  ),
7401
- children: t2("bridge.allTokens")
7402
- }
7403
- )
7404
- ] }),
7405
- /* @__PURE__ */ jsxRuntime.jsx("div", { id: "token-select-list", className: "flex-1 -mx-5 min-h-0", children: hasNoResults ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground px-12 py-2 h-28 flex items-center justify-center text-center", children: t2("bridge.tokenNotFound") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7406
- effectiveTab === "my" && myTokens.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-4 px-5 text-base text-muted-foreground uppercase py-2", children: t2("bridge.noBalancesFound") }),
7407
- /* @__PURE__ */ jsxRuntime.jsx(
7408
- reactWindow.FixedSizeList,
7409
- {
7410
- height: listHeight,
7411
- itemCount: virtualItems.length,
7412
- itemSize: TOKEN_ROW_HEIGHT,
7413
- width: "100%",
7414
- itemKey,
7415
- className: "[&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30",
7416
- overscanCount: 5,
7417
- children: VirtualRow
7418
- }
7419
- )
7420
- ] }) })
7421
- ] }) });
6971
+ /* @__PURE__ */ jsxRuntime.jsx(
6972
+ button.Button,
6973
+ {
6974
+ variant: effectiveTab === "all" ? "default" : "ghost",
6975
+ onClick: () => {
6976
+ setTab("all");
6977
+ setManualTabSwitch(true);
6978
+ },
6979
+ size: "sm",
6980
+ className: utils$1.cn(
6981
+ "px-4 h-9 cursor-pointer",
6982
+ effectiveTab !== "all" && "bg-muted hover:bg-accent"
6983
+ ),
6984
+ children: t2("bridge.allTokens")
6985
+ }
6986
+ )
6987
+ ] }),
6988
+ /* @__PURE__ */ jsxRuntime.jsx("div", { id: "token-select-list", className: "flex-1 -mx-5 min-h-0", children: hasNoResults ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground px-12 py-2 h-28 flex items-center justify-center text-center", children: t2("bridge.tokenNotFound") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6989
+ effectiveTab === "my" && myTokens.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-4 px-5 text-base text-muted-foreground uppercase py-2", children: t2("bridge.noBalancesFound") }),
6990
+ /* @__PURE__ */ jsxRuntime.jsx(
6991
+ reactWindow.FixedSizeList,
6992
+ {
6993
+ height: listHeight,
6994
+ itemCount: virtualItems.length,
6995
+ itemSize: TOKEN_ROW_HEIGHT,
6996
+ width: "100%",
6997
+ itemKey,
6998
+ className: "[&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:bg-muted-foreground/20 [&::-webkit-scrollbar-thumb]:rounded-full hover:[&::-webkit-scrollbar-thumb]:bg-muted-foreground/30",
6999
+ overscanCount: 5,
7000
+ children: VirtualRow
7001
+ }
7002
+ )
7003
+ ] }) })
7004
+ ]
7005
+ }
7006
+ ) });
7422
7007
  };
7423
7008
  function useBridgeRefresh() {
7424
7009
  const qc = reactQuery.useQueryClient();
@@ -26237,7 +25822,7 @@ class WalletConnectModal {
26237
25822
  }
26238
25823
  async initUi() {
26239
25824
  if (typeof window !== "undefined") {
26240
- await Promise.resolve().then(() => require("./index-BTwKvCVG.cjs"));
25825
+ await Promise.resolve().then(() => require("./index-Bl9Q1m-4.cjs"));
26241
25826
  const modal = document.createElement("wcm-modal");
26242
25827
  document.body.insertAdjacentElement("beforeend", modal);
26243
25828
  OptionsCtrl.setIsUiLoaded(true);
@@ -26730,6 +26315,7 @@ const EvaaBridgeWithProviders = (props) => {
26730
26315
  },
26731
26316
  tonClient: props.tonClient,
26732
26317
  tonApiKey: props.tonApiKey,
26318
+ tronApiKey: props.tronApiKey,
26733
26319
  children: /* @__PURE__ */ jsxRuntime.jsx(EvaaBridgeContent, { ...props })
26734
26320
  }
26735
26321
  ) });
@@ -26955,16 +26541,10 @@ exports.RouteType = RouteType;
26955
26541
  exports.RouterCtrl = RouterCtrl;
26956
26542
  exports.ThemeCtrl = ThemeCtrl;
26957
26543
  exports.ToastCtrl = ToastCtrl;
26958
- exports.addEvmNetworkFee = addEvmNetworkFee;
26959
- exports.addTonNetworkFee = addTonNetworkFee;
26960
- exports.addTronNetworkFee = addTronNetworkFee;
26961
26544
  exports.addrForApi = addrForApi;
26962
26545
  exports.buildAssetMatrix = buildAssetMatrix;
26963
26546
  exports.calculateMinReceived = calculateMinReceived;
26964
26547
  exports.computeFeesUsdFromArray = computeFeesUsdFromArray;
26965
- exports.estimateEvmNetworkFee = estimateEvmNetworkFee;
26966
- exports.estimateTonNetworkFee = estimateTonNetworkFee;
26967
- exports.estimateTronNetworkFee = estimateTronNetworkFee;
26968
26548
  exports.findNativeMeta = findNativeMeta;
26969
26549
  exports.formatAddress = formatAddress;
26970
26550
  exports.formatBalance = formatBalance;
@@ -27008,4 +26588,4 @@ exports.useSettingsStore = useSettingsStore;
27008
26588
  exports.useSwapModel = useSwapModel;
27009
26589
  exports.useTokensStore = useTokensStore;
27010
26590
  exports.useTransactionStore = useTransactionStore;
27011
- //# sourceMappingURL=index-CTtu-a2U.cjs.map
26591
+ //# sourceMappingURL=index-rAch8BQe.cjs.map