@rash2x/bridge-widget 0.6.53 → 0.6.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/evaa-bridge.cjs +1 -7
- package/dist/evaa-bridge.cjs.map +1 -1
- package/dist/evaa-bridge.mjs +29 -35
- package/dist/{index-BTwKvCVG.cjs → index-BLC0Ys74.cjs} +2 -2
- package/dist/{index-BTwKvCVG.cjs.map → index-BLC0Ys74.cjs.map} +1 -1
- package/dist/{index-CePOaHyN.js → index-CDUxAooI.js} +584 -1032
- package/dist/index-CDUxAooI.js.map +1 -0
- package/dist/{index-C_cDfEeV.js → index-D8sxoZ5P.js} +2 -2
- package/dist/{index-C_cDfEeV.js.map → index-D8sxoZ5P.js.map} +1 -1
- package/dist/{index-CTtu-a2U.cjs → index-DiF0Z4eu.cjs} +554 -1002
- package/dist/index-DiF0Z4eu.cjs.map +1 -0
- package/dist/index.d.ts +1 -40
- package/package.json +1 -1
- package/dist/index-CTtu-a2U.cjs.map +0 -1
- package/dist/index-CePOaHyN.js.map +0 -1
|
@@ -12,7 +12,6 @@ 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");
|
|
@@ -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": "
|
|
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": "
|
|
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
|
-
|
|
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();
|
|
@@ -2694,6 +2244,48 @@ const useWalletSelectModal = zustand.create((set2) => ({
|
|
|
2694
2244
|
onOpen: (addressType) => set2({ isOpen: true, addressType }),
|
|
2695
2245
|
onClose: () => set2({ isOpen: false, addressType: void 0 })
|
|
2696
2246
|
}));
|
|
2247
|
+
const truncateToDecimals = (num, decimals) => {
|
|
2248
|
+
if (!isFinite(num) || isNaN(num)) return "0";
|
|
2249
|
+
const multiplier = Math.pow(10, decimals);
|
|
2250
|
+
const truncated = Math.floor(num * multiplier) / multiplier;
|
|
2251
|
+
return truncated.toFixed(decimals).replace(/\.?0+$/, "");
|
|
2252
|
+
};
|
|
2253
|
+
const formatTokenAmount = (amount, symbol, options) => {
|
|
2254
|
+
const normalizedSymbol = (symbol ?? "").toUpperCase();
|
|
2255
|
+
if (["USDT", "USDC", "DAI", "BUSD"].includes(normalizedSymbol) && amount >= 1) {
|
|
2256
|
+
return `${Math.floor(amount)} ${normalizedSymbol}`;
|
|
2257
|
+
}
|
|
2258
|
+
if (options?.decimals !== void 0) {
|
|
2259
|
+
return `${amount.toFixed(options.decimals)} ${normalizedSymbol}`;
|
|
2260
|
+
}
|
|
2261
|
+
if (amount >= 1) {
|
|
2262
|
+
return `${amount.toFixed(0)} ${normalizedSymbol}`;
|
|
2263
|
+
} else if (amount >= 1e-3) {
|
|
2264
|
+
return `${amount.toFixed(3)} ${normalizedSymbol}`;
|
|
2265
|
+
} else {
|
|
2266
|
+
return `${amount.toFixed(6)} ${normalizedSymbol}`;
|
|
2267
|
+
}
|
|
2268
|
+
};
|
|
2269
|
+
const formatUsd = (value) => {
|
|
2270
|
+
if (!value || !isFinite(value)) return "$0";
|
|
2271
|
+
if (value >= 1) return `$${value.toFixed(2)}`;
|
|
2272
|
+
return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
|
|
2273
|
+
};
|
|
2274
|
+
const formatPercentage = (bps, decimals = 2) => {
|
|
2275
|
+
return `${(bps / 100).toFixed(decimals).replace(/0+$/, "").replace(/\.$/, "")}%`;
|
|
2276
|
+
};
|
|
2277
|
+
const formatBalance = (amount, decimals = 2) => {
|
|
2278
|
+
if (!isFinite(amount) || isNaN(amount) || amount <= 0) {
|
|
2279
|
+
return "0.00";
|
|
2280
|
+
}
|
|
2281
|
+
return amount.toFixed(decimals);
|
|
2282
|
+
};
|
|
2283
|
+
const formatHash = (hash, startChars = 4, endChars = 4) => {
|
|
2284
|
+
if (!hash) return "";
|
|
2285
|
+
if (hash.length <= startChars + endChars) return hash;
|
|
2286
|
+
return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
|
|
2287
|
+
};
|
|
2288
|
+
const formatAddress = formatHash;
|
|
2697
2289
|
const EditIcon = (props) => {
|
|
2698
2290
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2699
2291
|
"svg",
|
|
@@ -3119,8 +2711,8 @@ const InfoIcon = (props) => {
|
|
|
3119
2711
|
{
|
|
3120
2712
|
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
2713
|
stroke: "currentColor",
|
|
3122
|
-
|
|
3123
|
-
|
|
2714
|
+
strokeWidth: "1.68349",
|
|
2715
|
+
strokeLinecap: "round"
|
|
3124
2716
|
}
|
|
3125
2717
|
)
|
|
3126
2718
|
}
|
|
@@ -3143,6 +2735,96 @@ const TokenSymbol = ({
|
|
|
3143
2735
|
const src2 = `${BASE_URL}/${normalizedSymbol}.svg`;
|
|
3144
2736
|
return /* @__PURE__ */ jsxRuntime.jsx("img", { src: src2, alt: alt ?? symbol, className });
|
|
3145
2737
|
};
|
|
2738
|
+
function getQuoteAmounts(quote, srcToken, dstToken) {
|
|
2739
|
+
if (!quote || !srcToken || !dstToken) {
|
|
2740
|
+
return {
|
|
2741
|
+
inputHuman: 0,
|
|
2742
|
+
outputHuman: 0,
|
|
2743
|
+
outputHumanRounded: "0",
|
|
2744
|
+
minReceivedHuman: 0
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
const inputHuman = fromLD(quote.srcAmount, srcToken.decimals);
|
|
2748
|
+
const outputHuman = fromLD(quote.dstAmount, dstToken.decimals);
|
|
2749
|
+
const outputHumanRounded = truncateToDecimals(outputHuman, 2);
|
|
2750
|
+
const minReceivedHuman = fromLD(quote.dstAmountMin || "0", dstToken.decimals);
|
|
2751
|
+
return {
|
|
2752
|
+
inputHuman,
|
|
2753
|
+
outputHuman,
|
|
2754
|
+
outputHumanRounded,
|
|
2755
|
+
minReceivedHuman
|
|
2756
|
+
};
|
|
2757
|
+
}
|
|
2758
|
+
function getQuoteFees(quote, tokens, chains, srcToken, dstToken) {
|
|
2759
|
+
if (!quote || !tokens || !chains) {
|
|
2760
|
+
return {
|
|
2761
|
+
fees: { usd: /* @__PURE__ */ new Map(), original: /* @__PURE__ */ new Map(), formatted: /* @__PURE__ */ new Map() },
|
|
2762
|
+
inSrcToken: void 0,
|
|
2763
|
+
inDstToken: void 0
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
const feeData = computeFeesUsdFromArray(quote.fees, tokens, chains);
|
|
2767
|
+
let inSrcToken = void 0;
|
|
2768
|
+
let inDstToken = void 0;
|
|
2769
|
+
if (srcToken && quote.srcChainKey) {
|
|
2770
|
+
const feeInSrcLD = sumFeeByTokenLD(
|
|
2771
|
+
quote.fees,
|
|
2772
|
+
srcToken.address,
|
|
2773
|
+
quote.srcChainKey
|
|
2774
|
+
);
|
|
2775
|
+
const feeInSrcHuman = fromLD(feeInSrcLD, srcToken.decimals);
|
|
2776
|
+
if (feeInSrcHuman > 0) {
|
|
2777
|
+
inSrcToken = Number(truncateToDecimals(feeInSrcHuman, 8));
|
|
2778
|
+
} else if ((feeData.usd.get("total") || 0) > 0 && srcToken.price?.usd) {
|
|
2779
|
+
const feeInSrcApprox = (feeData.usd.get("total") || 0) / srcToken.price.usd;
|
|
2780
|
+
inSrcToken = Number(truncateToDecimals(feeInSrcApprox, 8));
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
if (dstToken && quote.dstChainKey) {
|
|
2784
|
+
const feeInDstLD = sumFeeByTokenLD(
|
|
2785
|
+
quote.fees,
|
|
2786
|
+
dstToken.address,
|
|
2787
|
+
quote.dstChainKey
|
|
2788
|
+
);
|
|
2789
|
+
const feeInDstHuman = fromLD(feeInDstLD, dstToken.decimals);
|
|
2790
|
+
if (feeInDstHuman > 0) {
|
|
2791
|
+
inDstToken = Number(truncateToDecimals(feeInDstHuman, 8));
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
return {
|
|
2795
|
+
fees: feeData,
|
|
2796
|
+
inSrcToken,
|
|
2797
|
+
inDstToken
|
|
2798
|
+
};
|
|
2799
|
+
}
|
|
2800
|
+
function calculateMinReceived(quote, slippageBps, dstToken) {
|
|
2801
|
+
if (!quote || !dstToken) return 0;
|
|
2802
|
+
const dstAmountLD = BigInt(quote.dstAmount);
|
|
2803
|
+
const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
|
|
2804
|
+
return fromLD(minAmountLD.toString(), dstToken.decimals);
|
|
2805
|
+
}
|
|
2806
|
+
function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
|
|
2807
|
+
const amounts = getQuoteAmounts(quote, srcToken, dstToken);
|
|
2808
|
+
const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
|
|
2809
|
+
const minimumReceived = calculateMinReceived(quote, slippageBps, dstToken);
|
|
2810
|
+
return {
|
|
2811
|
+
inputAmount: amounts.inputHuman,
|
|
2812
|
+
outputAmount: amounts.outputHuman,
|
|
2813
|
+
outputAmountRounded: amounts.outputHumanRounded,
|
|
2814
|
+
minimumReceived,
|
|
2815
|
+
etaSeconds: quote?.duration?.estimated,
|
|
2816
|
+
fees
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
function getRouteDisplayName(route) {
|
|
2820
|
+
if (!route) return "Stargate Bridge";
|
|
2821
|
+
const routeLower = route.toLowerCase();
|
|
2822
|
+
if (routeLower.includes("taxi")) return "Stargate V2 Fast";
|
|
2823
|
+
if (routeLower.includes("bus")) return "Stargate V2 Economy";
|
|
2824
|
+
if (routeLower.includes("oft")) return "OFT Bridge";
|
|
2825
|
+
if (routeLower.includes("v2")) return "Stargate V2";
|
|
2826
|
+
return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
2827
|
+
}
|
|
3146
2828
|
function useGasEstimate(amountNum) {
|
|
3147
2829
|
const { fromChain } = useChainsStore();
|
|
3148
2830
|
const { selectedAssetSymbol } = useTokensStore();
|
|
@@ -3152,6 +2834,9 @@ function useGasEstimate(amountNum) {
|
|
|
3152
2834
|
srcAddress
|
|
3153
2835
|
);
|
|
3154
2836
|
const { quote } = useBridgeQuoteStore();
|
|
2837
|
+
const { chainRegistry } = useChainStrategies();
|
|
2838
|
+
const [networkFeeEstimate, setNetworkFeeEstimate] = react.useState(0);
|
|
2839
|
+
const [networkFeeKnown, setNetworkFeeKnown] = react.useState(false);
|
|
3155
2840
|
const balancesKnown = !balancesLoading;
|
|
3156
2841
|
const chainKey = fromChain?.chainKey;
|
|
3157
2842
|
const nativeCurrencySymbol = fromChain?.nativeCurrency?.symbol;
|
|
@@ -3160,6 +2845,42 @@ function useGasEstimate(amountNum) {
|
|
|
3160
2845
|
const quoteFees = quote?.fees;
|
|
3161
2846
|
const quoteSrcChainKey = quote?.srcChainKey;
|
|
3162
2847
|
const nativeBalanceValue = nativeCurrencySymbol ? Number(balances[nativeCurrencySymbol.toUpperCase()]?.balance ?? 0) : 0;
|
|
2848
|
+
react.useEffect(() => {
|
|
2849
|
+
let cancelled = false;
|
|
2850
|
+
const estimate = async () => {
|
|
2851
|
+
setNetworkFeeEstimate(0);
|
|
2852
|
+
setNetworkFeeKnown(false);
|
|
2853
|
+
if (!chainKey || !quote?.steps?.length) {
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
const strategy = chainRegistry.getStrategy(chainKey);
|
|
2857
|
+
if (!strategy) {
|
|
2858
|
+
setNetworkFeeKnown(true);
|
|
2859
|
+
return;
|
|
2860
|
+
}
|
|
2861
|
+
const steps = quote.steps.filter((step) => step.chainKey === chainKey);
|
|
2862
|
+
if (!steps.length) {
|
|
2863
|
+
setNetworkFeeKnown(true);
|
|
2864
|
+
return;
|
|
2865
|
+
}
|
|
2866
|
+
try {
|
|
2867
|
+
const estimateValue = await strategy.estimateNetworkFee(steps);
|
|
2868
|
+
if (cancelled) return;
|
|
2869
|
+
setNetworkFeeEstimate(Number.isFinite(estimateValue) ? estimateValue : 0);
|
|
2870
|
+
} catch {
|
|
2871
|
+
if (cancelled) return;
|
|
2872
|
+
setNetworkFeeEstimate(0);
|
|
2873
|
+
} finally {
|
|
2874
|
+
if (!cancelled) {
|
|
2875
|
+
setNetworkFeeKnown(true);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
};
|
|
2879
|
+
void estimate();
|
|
2880
|
+
return () => {
|
|
2881
|
+
cancelled = true;
|
|
2882
|
+
};
|
|
2883
|
+
}, [chainKey, quote?.steps, chainRegistry]);
|
|
3163
2884
|
const result = react.useMemo(() => {
|
|
3164
2885
|
if (!chainKey || !nativeCurrencySymbol) {
|
|
3165
2886
|
return {
|
|
@@ -3179,7 +2900,7 @@ function useGasEstimate(amountNum) {
|
|
|
3179
2900
|
if (quoteFees && quoteSrcChainKey === chainKey) {
|
|
3180
2901
|
const fees = quoteFees;
|
|
3181
2902
|
const feesInNative = fees.filter(
|
|
3182
|
-
(f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress
|
|
2903
|
+
(f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress
|
|
3183
2904
|
).reduce(
|
|
3184
2905
|
(sum, f4) => sum + BigInt(f4.amount || "0"),
|
|
3185
2906
|
0n
|
|
@@ -3188,13 +2909,16 @@ function useGasEstimate(amountNum) {
|
|
|
3188
2909
|
requiredNative = Number(feesInNative) / Math.pow(10, decimals);
|
|
3189
2910
|
quoteFeesAvailable = true;
|
|
3190
2911
|
}
|
|
2912
|
+
if (networkFeeKnown) {
|
|
2913
|
+
requiredNative += networkFeeEstimate;
|
|
2914
|
+
}
|
|
3191
2915
|
let hasEnoughGas = true;
|
|
3192
2916
|
if (isNativeSelected) {
|
|
3193
2917
|
hasEnoughGas = nativeBalance - (amountNum ?? 0) >= requiredNative;
|
|
3194
2918
|
} else {
|
|
3195
2919
|
hasEnoughGas = nativeBalance >= requiredNative;
|
|
3196
2920
|
}
|
|
3197
|
-
const shouldCheckGas = balancesKnown && quoteFeesAvailable;
|
|
2921
|
+
const shouldCheckGas = balancesKnown && quoteFeesAvailable && networkFeeKnown;
|
|
3198
2922
|
return {
|
|
3199
2923
|
nativeSym,
|
|
3200
2924
|
nativeBalance,
|
|
@@ -3213,7 +2937,9 @@ function useGasEstimate(amountNum) {
|
|
|
3213
2937
|
quoteSrcChainKey,
|
|
3214
2938
|
amountNum,
|
|
3215
2939
|
balancesKnown,
|
|
3216
|
-
nativeBalanceValue
|
|
2940
|
+
nativeBalanceValue,
|
|
2941
|
+
networkFeeEstimate,
|
|
2942
|
+
networkFeeKnown
|
|
3217
2943
|
]);
|
|
3218
2944
|
return result;
|
|
3219
2945
|
}
|
|
@@ -3622,33 +3348,6 @@ class TransactionFailedError extends ChainStrategyError {
|
|
|
3622
3348
|
this.txHash = txHash;
|
|
3623
3349
|
}
|
|
3624
3350
|
}
|
|
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
3351
|
class ProviderNotAvailableError extends ChainStrategyError {
|
|
3653
3352
|
constructor(chainKey, reason) {
|
|
3654
3353
|
const message = reason ? `${chainKey.toUpperCase()} provider not available: ${reason}` : `${chainKey.toUpperCase()} provider not available`;
|
|
@@ -3705,6 +3404,38 @@ async function getLayerZeroMessageByTx(txHash) {
|
|
|
3705
3404
|
return null;
|
|
3706
3405
|
}
|
|
3707
3406
|
}
|
|
3407
|
+
async function waitForLayerZeroCompletion(txHash, timeoutMs = 6e5, pollIntervalMs = 1e4) {
|
|
3408
|
+
const deadline = Date.now() + timeoutMs;
|
|
3409
|
+
while (Date.now() < deadline) {
|
|
3410
|
+
try {
|
|
3411
|
+
const message = await getLayerZeroMessageByTx(txHash);
|
|
3412
|
+
if (message) {
|
|
3413
|
+
const statusName = message.status?.name;
|
|
3414
|
+
if (statusName === "DELIVERED") {
|
|
3415
|
+
return {
|
|
3416
|
+
completed: true,
|
|
3417
|
+
status: "DELIVERED",
|
|
3418
|
+
dstTxHash: message.destination?.tx?.txHash,
|
|
3419
|
+
message
|
|
3420
|
+
};
|
|
3421
|
+
}
|
|
3422
|
+
if (statusName === "FAILED") {
|
|
3423
|
+
return {
|
|
3424
|
+
completed: false,
|
|
3425
|
+
status: "FAILED",
|
|
3426
|
+
message
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
} catch {
|
|
3431
|
+
}
|
|
3432
|
+
await new Promise((r2) => setTimeout(r2, pollIntervalMs));
|
|
3433
|
+
}
|
|
3434
|
+
return {
|
|
3435
|
+
completed: false,
|
|
3436
|
+
status: "TIMEOUT"
|
|
3437
|
+
};
|
|
3438
|
+
}
|
|
3708
3439
|
function useBridgeTransaction() {
|
|
3709
3440
|
const { quote } = useBridgeQuoteStore();
|
|
3710
3441
|
const { chainRegistry } = useChainStrategies();
|
|
@@ -3780,59 +3511,76 @@ function useBridgeTransaction() {
|
|
|
3780
3511
|
txStore.setSrcHash(hash);
|
|
3781
3512
|
txStore.updateStatus("processing");
|
|
3782
3513
|
});
|
|
3783
|
-
if (txResult?.tonTransactionHash) {
|
|
3784
|
-
txStore.setTonTransactionHash(txResult.tonTransactionHash);
|
|
3785
|
-
}
|
|
3786
3514
|
if (txResult?.hash) {
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3515
|
+
const trackWithLayerZero = async () => {
|
|
3516
|
+
let hashForLayerZero = txResult.hash;
|
|
3517
|
+
const messageHash = txResult.hash;
|
|
3518
|
+
if (quote.srcChainKey === "ton" && strategy.convertMessageHashToTxHash) {
|
|
3519
|
+
const tonTxHash = await strategy.convertMessageHashToTxHash(
|
|
3520
|
+
messageHash,
|
|
3521
|
+
6e4
|
|
3522
|
+
);
|
|
3523
|
+
if (tonTxHash) {
|
|
3524
|
+
hashForLayerZero = tonTxHash;
|
|
3525
|
+
txStore.setTonTransactionHash(tonTxHash);
|
|
3526
|
+
} else {
|
|
3527
|
+
console.warn("Failed to convert TON message hash to tx hash");
|
|
3791
3528
|
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
txStore.updateActualFee(feeValue, feeSymbol);
|
|
3803
|
-
}
|
|
3529
|
+
}
|
|
3530
|
+
const lzResult = await waitForLayerZeroCompletion(
|
|
3531
|
+
hashForLayerZero,
|
|
3532
|
+
6e5,
|
|
3533
|
+
1e4
|
|
3534
|
+
);
|
|
3535
|
+
console.log("LayerZero delivery status:", lzResult.status);
|
|
3536
|
+
if (lzResult.completed) {
|
|
3537
|
+
if (lzResult.dstTxHash) {
|
|
3538
|
+
txStore.setDstHash(lzResult.dstTxHash);
|
|
3804
3539
|
}
|
|
3805
|
-
|
|
3806
|
-
console.log("Transaction completed successfully");
|
|
3807
|
-
if (txResult.hash && strategy.getSourceCost) {
|
|
3540
|
+
if (strategy.getSourceCost) {
|
|
3808
3541
|
const srcChain2 = chains?.find(
|
|
3809
3542
|
(c2) => c2.chainKey === quote.srcChainKey
|
|
3810
3543
|
);
|
|
3811
3544
|
const feeSymbol = srcChain2?.nativeCurrency?.symbol || "";
|
|
3812
3545
|
const { priceUsd } = findNativeMeta(allTokens, srcChain2);
|
|
3813
|
-
const
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
}).then((sourceTxHash) => getSourceCost(sourceTxHash)).then((sourceCost) => {
|
|
3546
|
+
const hashForSourceCost = quote.srcChainKey === "ton" ? messageHash : hashForLayerZero;
|
|
3547
|
+
try {
|
|
3548
|
+
const sourceCost = await strategy.getSourceCost(
|
|
3549
|
+
hashForSourceCost
|
|
3550
|
+
);
|
|
3819
3551
|
if (sourceCost?.totalNative !== void 0 && isFinite(sourceCost.totalNative)) {
|
|
3820
3552
|
const feeUsd = priceUsd && priceUsd > 0 ? sourceCost.totalNative * priceUsd : void 0;
|
|
3553
|
+
console.log("Source cost calculated:", {
|
|
3554
|
+
gasFee: sourceCost.breakdown?.gasFee + " " + feeSymbol,
|
|
3555
|
+
layerZeroFee: sourceCost.breakdown?.layerZeroFee + " " + feeSymbol,
|
|
3556
|
+
total: sourceCost.totalNative + " " + feeSymbol,
|
|
3557
|
+
totalUsd: feeUsd ? "$" + feeUsd.toFixed(2) : "N/A"
|
|
3558
|
+
});
|
|
3821
3559
|
txStore.updateLayerZeroTotalFee(
|
|
3822
3560
|
sourceCost.totalNative,
|
|
3823
3561
|
feeSymbol,
|
|
3824
3562
|
feeUsd
|
|
3825
3563
|
);
|
|
3826
3564
|
}
|
|
3827
|
-
}
|
|
3828
|
-
console.warn("Failed to compute
|
|
3829
|
-
}
|
|
3565
|
+
} catch (error) {
|
|
3566
|
+
console.warn("Failed to compute source cost:", error);
|
|
3567
|
+
}
|
|
3830
3568
|
}
|
|
3569
|
+
txStore.updateStatus("completed");
|
|
3570
|
+
console.log("Transaction completed successfully via LayerZero");
|
|
3831
3571
|
} else {
|
|
3832
|
-
|
|
3833
|
-
|
|
3572
|
+
if (lzResult.status === "FAILED") {
|
|
3573
|
+
txStore.setError("TRANSACTION_FAILED_TO_COMPLETE");
|
|
3574
|
+
console.error("LayerZero delivery failed");
|
|
3575
|
+
} else {
|
|
3576
|
+
txStore.updateStatus("completed");
|
|
3577
|
+
console.warn(
|
|
3578
|
+
"LayerZero tracking timed out, marking as completed"
|
|
3579
|
+
);
|
|
3580
|
+
}
|
|
3834
3581
|
}
|
|
3835
|
-
}
|
|
3582
|
+
};
|
|
3583
|
+
trackWithLayerZero().catch((err) => {
|
|
3836
3584
|
if (isUserRejection(err)) {
|
|
3837
3585
|
txStore.setError("TRANSACTION_REJECTED");
|
|
3838
3586
|
} else if (ChainStrategyError.isChainStrategyError(err)) {
|
|
@@ -4932,11 +4680,60 @@ class ChainStrategyRegistry {
|
|
|
4932
4680
|
await strategy.disconnect(options);
|
|
4933
4681
|
}
|
|
4934
4682
|
}
|
|
4683
|
+
const EVM_CONFIG = {
|
|
4684
|
+
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
4685
|
+
gasEstimates: {
|
|
4686
|
+
approve: 65000n,
|
|
4687
|
+
bridge: 300000n
|
|
4688
|
+
},
|
|
4689
|
+
gasBuffer: 1.2,
|
|
4690
|
+
// 20% buffer
|
|
4691
|
+
gasFeeMultiplier: 2,
|
|
4692
|
+
// Multiplier for wallet fee estimates
|
|
4693
|
+
timeout: 3e5,
|
|
4694
|
+
// 5 minutes (increased for slower networks)
|
|
4695
|
+
requiredConfirmations: 3
|
|
4696
|
+
// Wait for 3 confirmations for reorg protection
|
|
4697
|
+
};
|
|
4698
|
+
const TON_CONFIG = {
|
|
4699
|
+
apiUrl: "https://toncenter.com/api/v2",
|
|
4700
|
+
timeout: 36e4,
|
|
4701
|
+
// 6 minutes
|
|
4702
|
+
validUntil: 600,
|
|
4703
|
+
// 10 minutes
|
|
4704
|
+
pollingInterval: 5e3,
|
|
4705
|
+
// 5 seconds between transaction status checks
|
|
4706
|
+
estimatedNetworkFee: "1000000000"
|
|
4707
|
+
// 1 TON in nanoton (conservative estimate)
|
|
4708
|
+
};
|
|
4709
|
+
const TRON_CONFIG = {
|
|
4710
|
+
// 2 minutes (for 19 confirmations)
|
|
4711
|
+
feeLimit: 1e8,
|
|
4712
|
+
// 3 seconds between checks
|
|
4713
|
+
estimatedNetworkFee: "10000000"
|
|
4714
|
+
// 10 TRX in SUN (fallback estimate)
|
|
4715
|
+
};
|
|
4716
|
+
let tonClientInstance = null;
|
|
4717
|
+
function getTonClient(customClient, apiKey) {
|
|
4718
|
+
if (customClient) {
|
|
4719
|
+
return customClient;
|
|
4720
|
+
}
|
|
4721
|
+
if (!tonClientInstance) {
|
|
4722
|
+
tonClientInstance = new ton.TonClient({
|
|
4723
|
+
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
4724
|
+
apiKey
|
|
4725
|
+
});
|
|
4726
|
+
}
|
|
4727
|
+
return tonClientInstance;
|
|
4728
|
+
}
|
|
4935
4729
|
function isNativeAddress(addr) {
|
|
4936
4730
|
if (!addr) return false;
|
|
4937
4731
|
const a2 = addr.toLowerCase();
|
|
4938
4732
|
return a2 === "native" || a2 === "0x0000000000000000000000000000000000000000" || a2 === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" || addr === "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb";
|
|
4939
4733
|
}
|
|
4734
|
+
function sleep(ms2) {
|
|
4735
|
+
return new Promise((resolve) => setTimeout(resolve, ms2));
|
|
4736
|
+
}
|
|
4940
4737
|
function toTronBase58(addr, tronWeb) {
|
|
4941
4738
|
if (!addr) throw new Error("Empty TRON address");
|
|
4942
4739
|
if (addr.startsWith("T")) return addr;
|
|
@@ -4983,24 +4780,27 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
4983
4780
|
if (!publicClient) {
|
|
4984
4781
|
throw new Error("No public client provided");
|
|
4985
4782
|
}
|
|
4986
|
-
const nativeTokens = tokens.filter((t2) => isNativeAddress(t2.address));
|
|
4987
4783
|
const erc20Tokens = tokens.filter(
|
|
4988
4784
|
(t2) => !isNativeAddress(t2.address) && viem.isAddress(t2.address)
|
|
4989
4785
|
);
|
|
4990
|
-
|
|
4786
|
+
const chainNative = publicClient.chain?.nativeCurrency;
|
|
4787
|
+
const nativeSymbol = chainNative?.symbol ?? "ETH";
|
|
4788
|
+
const nativeDecimals = chainNative?.decimals ?? 18;
|
|
4789
|
+
const maxAttempts = 2;
|
|
4790
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
4991
4791
|
try {
|
|
4992
|
-
const
|
|
4792
|
+
const nativeBalance = await publicClient.getBalance({
|
|
4993
4793
|
address
|
|
4994
4794
|
});
|
|
4995
|
-
const balance = parseFloat(viem.formatUnits(
|
|
4795
|
+
const balance = parseFloat(viem.formatUnits(nativeBalance, nativeDecimals));
|
|
4996
4796
|
if (balance > 0) {
|
|
4997
|
-
balances[
|
|
4797
|
+
balances[nativeSymbol] = { balance, address };
|
|
4798
|
+
}
|
|
4799
|
+
break;
|
|
4800
|
+
} catch {
|
|
4801
|
+
if (attempt !== maxAttempts) {
|
|
4802
|
+
await sleep(250 * attempt);
|
|
4998
4803
|
}
|
|
4999
|
-
} catch (error) {
|
|
5000
|
-
console.debug(
|
|
5001
|
-
`Failed to get native balance for ${token.symbol}:`,
|
|
5002
|
-
error
|
|
5003
|
-
);
|
|
5004
4804
|
}
|
|
5005
4805
|
}
|
|
5006
4806
|
if (erc20Tokens.length > 0) {
|
|
@@ -5034,11 +4834,7 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
5034
4834
|
if (balance > 0) {
|
|
5035
4835
|
balances[token.symbol] = { balance, address };
|
|
5036
4836
|
}
|
|
5037
|
-
} catch
|
|
5038
|
-
console.debug(
|
|
5039
|
-
`Failed to parse balance for ${token.symbol}:`,
|
|
5040
|
-
error
|
|
5041
|
-
);
|
|
4837
|
+
} catch {
|
|
5042
4838
|
}
|
|
5043
4839
|
}
|
|
5044
4840
|
});
|
|
@@ -5069,8 +4865,7 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
5069
4865
|
if (balance > 0) {
|
|
5070
4866
|
balances[token.symbol] = { balance, address };
|
|
5071
4867
|
}
|
|
5072
|
-
} catch
|
|
5073
|
-
console.debug(`Failed to get balance for ${token.symbol}:`, error2);
|
|
4868
|
+
} catch {
|
|
5074
4869
|
}
|
|
5075
4870
|
}
|
|
5076
4871
|
}
|
|
@@ -5130,12 +4925,7 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
|
|
|
5130
4925
|
balances[symbolNorm] = entry;
|
|
5131
4926
|
}
|
|
5132
4927
|
}
|
|
5133
|
-
} catch
|
|
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
|
-
}
|
|
4928
|
+
} catch {
|
|
5139
4929
|
}
|
|
5140
4930
|
}
|
|
5141
4931
|
} catch (error) {
|
|
@@ -5157,8 +4947,7 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
5157
4947
|
if (trxBalance > 0) {
|
|
5158
4948
|
balances.TRX = { balance: trxBalance, address: ownerB58 };
|
|
5159
4949
|
}
|
|
5160
|
-
} catch
|
|
5161
|
-
console.warn("Failed to get native TRX balance:", error);
|
|
4950
|
+
} catch {
|
|
5162
4951
|
}
|
|
5163
4952
|
for (const token of tokens) {
|
|
5164
4953
|
try {
|
|
@@ -5192,21 +4981,19 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
5192
4981
|
if (balance > 0) {
|
|
5193
4982
|
balances[token.symbol] = { balance, address: ownerB58 };
|
|
5194
4983
|
}
|
|
5195
|
-
} catch
|
|
5196
|
-
console.warn(`Failed to get TRON balance for ${token.symbol}:`, error);
|
|
4984
|
+
} catch {
|
|
5197
4985
|
}
|
|
5198
4986
|
}
|
|
5199
|
-
} catch
|
|
5200
|
-
console.error("Failed to get Tron balances:", error);
|
|
4987
|
+
} catch {
|
|
5201
4988
|
}
|
|
5202
4989
|
return balances;
|
|
5203
4990
|
}
|
|
5204
|
-
const ERC20_ABI = [
|
|
4991
|
+
const ERC20_ABI = viem.parseAbi([
|
|
5205
4992
|
"function approve(address spender, uint256 amount) returns (bool)",
|
|
5206
4993
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
5207
4994
|
"function decimals() view returns (uint8)",
|
|
5208
4995
|
"function balanceOf(address owner) view returns (uint256)"
|
|
5209
|
-
];
|
|
4996
|
+
]);
|
|
5210
4997
|
class EvmChainStrategy {
|
|
5211
4998
|
constructor(config) {
|
|
5212
4999
|
__publicField(this, "config");
|
|
@@ -5254,14 +5041,9 @@ class EvmChainStrategy {
|
|
|
5254
5041
|
}
|
|
5255
5042
|
async getBalances(address, tokens) {
|
|
5256
5043
|
if (!this.publicClient) {
|
|
5257
|
-
console.warn("No publicClient available for balance query");
|
|
5258
5044
|
return {};
|
|
5259
5045
|
}
|
|
5260
|
-
return await getEvmBalances(
|
|
5261
|
-
this.publicClient,
|
|
5262
|
-
address,
|
|
5263
|
-
tokens
|
|
5264
|
-
);
|
|
5046
|
+
return await getEvmBalances(this.publicClient, address, tokens);
|
|
5265
5047
|
}
|
|
5266
5048
|
isAddressValid(address) {
|
|
5267
5049
|
if (!address) return false;
|
|
@@ -5297,7 +5079,6 @@ class EvmChainStrategy {
|
|
|
5297
5079
|
}
|
|
5298
5080
|
async getSourceCost(txHash) {
|
|
5299
5081
|
if (!this.publicClient) {
|
|
5300
|
-
console.warn("No publicClient available for source cost query");
|
|
5301
5082
|
return null;
|
|
5302
5083
|
}
|
|
5303
5084
|
try {
|
|
@@ -5312,18 +5093,61 @@ class EvmChainStrategy {
|
|
|
5312
5093
|
const gasFeeWei = gasUsed * gasPrice;
|
|
5313
5094
|
const txValueWei = tx.value ?? 0n;
|
|
5314
5095
|
const totalWei = gasFeeWei + txValueWei;
|
|
5315
|
-
|
|
5096
|
+
const sourceCost = {
|
|
5316
5097
|
totalNative: Number(viem.formatUnits(totalWei, 18)),
|
|
5317
5098
|
breakdown: {
|
|
5318
5099
|
gasFee: Number(viem.formatUnits(gasFeeWei, 18)),
|
|
5319
5100
|
layerZeroFee: Number(viem.formatUnits(txValueWei, 18))
|
|
5320
5101
|
}
|
|
5321
5102
|
};
|
|
5103
|
+
return sourceCost;
|
|
5322
5104
|
} catch (error) {
|
|
5323
5105
|
console.warn("Failed to compute EVM source cost:", error);
|
|
5324
5106
|
return null;
|
|
5325
5107
|
}
|
|
5326
5108
|
}
|
|
5109
|
+
async estimateNetworkFee(steps) {
|
|
5110
|
+
if (!this.walletClient) {
|
|
5111
|
+
return 0;
|
|
5112
|
+
}
|
|
5113
|
+
const account = this.config.evmAddress;
|
|
5114
|
+
const txSteps = steps.filter((step) => step.transaction?.to);
|
|
5115
|
+
if (!txSteps.length) {
|
|
5116
|
+
return 0;
|
|
5117
|
+
}
|
|
5118
|
+
const applyFeeMultiplier = (feePerGas) => {
|
|
5119
|
+
const multiplier = EVM_CONFIG.gasFeeMultiplier;
|
|
5120
|
+
if (!Number.isFinite(multiplier) || multiplier <= 1) {
|
|
5121
|
+
return feePerGas;
|
|
5122
|
+
}
|
|
5123
|
+
const scaled = BigInt(Math.round(multiplier * 100));
|
|
5124
|
+
return (feePerGas * scaled + 99n) / 100n;
|
|
5125
|
+
};
|
|
5126
|
+
let totalFeeWei = 0n;
|
|
5127
|
+
for (const step of txSteps) {
|
|
5128
|
+
const tx = step.transaction;
|
|
5129
|
+
if (!tx?.to) continue;
|
|
5130
|
+
try {
|
|
5131
|
+
const request = await this.walletClient.prepareTransactionRequest({
|
|
5132
|
+
account: tx.from || account,
|
|
5133
|
+
to: tx.to,
|
|
5134
|
+
data: tx.data,
|
|
5135
|
+
value: tx.value ? BigInt(tx.value) : void 0,
|
|
5136
|
+
chain: this.walletClient.chain
|
|
5137
|
+
});
|
|
5138
|
+
const gasLimit = request.gas;
|
|
5139
|
+
const maxFeePerGas = request.maxFeePerGas ?? request.gasPrice;
|
|
5140
|
+
if (gasLimit && maxFeePerGas) {
|
|
5141
|
+
totalFeeWei += gasLimit * applyFeeMultiplier(maxFeePerGas);
|
|
5142
|
+
}
|
|
5143
|
+
} catch {
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
if (totalFeeWei === 0n) {
|
|
5147
|
+
return 0;
|
|
5148
|
+
}
|
|
5149
|
+
return Number(viem.formatUnits(totalFeeWei, 18));
|
|
5150
|
+
}
|
|
5327
5151
|
async executeSteps(steps, _context, onFirstHash) {
|
|
5328
5152
|
if (!this.isConnected() || !this.walletClient) {
|
|
5329
5153
|
throw new WalletNotConnectedError("evm");
|
|
@@ -5337,14 +5161,12 @@ class EvmChainStrategy {
|
|
|
5337
5161
|
);
|
|
5338
5162
|
if (step.type === "approve") {
|
|
5339
5163
|
const hash = await this.approveTransaction(step);
|
|
5340
|
-
console.log(`Approval transaction hash: ${hash}`);
|
|
5341
5164
|
if (!firstTxHash) {
|
|
5342
5165
|
firstTxHash = hash;
|
|
5343
5166
|
onFirstHash?.(hash);
|
|
5344
5167
|
}
|
|
5345
5168
|
} else if (step.type === "bridge") {
|
|
5346
5169
|
const hash = await this.executeTransaction(step);
|
|
5347
|
-
console.log(`Bridge transaction hash: ${hash}`);
|
|
5348
5170
|
if (!firstTxHash) {
|
|
5349
5171
|
firstTxHash = hash;
|
|
5350
5172
|
onFirstHash?.(hash);
|
|
@@ -5367,106 +5189,6 @@ class EvmChainStrategy {
|
|
|
5367
5189
|
throw toChainStrategyError(error, "evm", "transaction");
|
|
5368
5190
|
}
|
|
5369
5191
|
}
|
|
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)`);
|
|
5410
|
-
}
|
|
5411
|
-
} catch (error) {
|
|
5412
|
-
console.warn("Failed to calculate actual fee:", error);
|
|
5413
|
-
}
|
|
5414
|
-
return {
|
|
5415
|
-
completed: true,
|
|
5416
|
-
actualFeeValue
|
|
5417
|
-
// Symbol will be determined by the caller based on chain info
|
|
5418
|
-
};
|
|
5419
|
-
} 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
|
-
}
|
|
5458
|
-
}
|
|
5459
|
-
const chainError = toChainStrategyError(
|
|
5460
|
-
error,
|
|
5461
|
-
"evm",
|
|
5462
|
-
"waitForCompletion"
|
|
5463
|
-
);
|
|
5464
|
-
return {
|
|
5465
|
-
completed: false,
|
|
5466
|
-
error: chainError.message
|
|
5467
|
-
};
|
|
5468
|
-
}
|
|
5469
|
-
}
|
|
5470
5192
|
async executeTransaction(step) {
|
|
5471
5193
|
const walletClient = this.walletClient;
|
|
5472
5194
|
if (!walletClient) {
|
|
@@ -5621,88 +5343,14 @@ class EvmChainStrategy {
|
|
|
5621
5343
|
blockTag: "finalized"
|
|
5622
5344
|
});
|
|
5623
5345
|
if (!finalizedBlock) {
|
|
5624
|
-
console.debug(
|
|
5625
|
-
"Finalized block not available (pre-merge or unsupported)"
|
|
5626
|
-
);
|
|
5627
5346
|
return false;
|
|
5628
5347
|
}
|
|
5629
|
-
|
|
5630
|
-
|
|
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);
|
|
5348
|
+
return blockNumber <= finalizedBlock.number;
|
|
5349
|
+
} catch {
|
|
5642
5350
|
return false;
|
|
5643
5351
|
}
|
|
5644
5352
|
}
|
|
5645
5353
|
}
|
|
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
5354
|
class TonChainStrategy {
|
|
5707
5355
|
constructor(config) {
|
|
5708
5356
|
__publicField(this, "config");
|
|
@@ -5815,40 +5463,17 @@ class TonChainStrategy {
|
|
|
5815
5463
|
validUntil: Math.floor(Date.now() / 1e3) + TON_CONFIG.validUntil,
|
|
5816
5464
|
messages: tonMessages
|
|
5817
5465
|
};
|
|
5818
|
-
const result = await this.config.tonConnectUI.sendTransaction(
|
|
5819
|
-
transaction2
|
|
5820
|
-
);
|
|
5466
|
+
const result = await this.config.tonConnectUI.sendTransaction(transaction2);
|
|
5821
5467
|
const bocBase64 = result.boc;
|
|
5822
5468
|
try {
|
|
5823
5469
|
const inMessage = core.loadMessage(core.Cell.fromBase64(bocBase64).beginParse());
|
|
5824
5470
|
const messageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
5825
5471
|
const hexHash = messageHash.toString("hex");
|
|
5826
5472
|
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
5473
|
return {
|
|
5847
5474
|
chainKey: "ton",
|
|
5848
|
-
hash: hexHash
|
|
5849
|
-
// Message hash for TONScan
|
|
5850
|
-
tonTransactionHash
|
|
5851
|
-
// Transaction hash for LayerZero (if found)
|
|
5475
|
+
hash: hexHash
|
|
5476
|
+
// Message hash for TONScan and for finding tx later
|
|
5852
5477
|
};
|
|
5853
5478
|
} catch (error) {
|
|
5854
5479
|
console.error("Error parsing BOC to hex hash:", error);
|
|
@@ -5862,39 +5487,45 @@ class TonChainStrategy {
|
|
|
5862
5487
|
throw toChainStrategyError(error, "ton", "transaction");
|
|
5863
5488
|
}
|
|
5864
5489
|
}
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5490
|
+
/**
|
|
5491
|
+
* Convert TON message hash to transaction hash.
|
|
5492
|
+
* LayerZero uses transaction hash, but TonConnect returns message hash.
|
|
5493
|
+
*/
|
|
5494
|
+
async convertMessageHashToTxHash(messageHash, timeoutMs = 6e4) {
|
|
5495
|
+
const deadline = Date.now() + timeoutMs;
|
|
5496
|
+
const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
|
|
5497
|
+
if (!this.config.tonAddress) {
|
|
5498
|
+
return null;
|
|
5499
|
+
}
|
|
5500
|
+
const targetMessageHash = Buffer.from(messageHash, "hex");
|
|
5501
|
+
const accountAddress = core.Address.parse(this.config.tonAddress);
|
|
5502
|
+
while (Date.now() < deadline) {
|
|
5503
|
+
try {
|
|
5504
|
+
const transactions = await client.getTransactions(accountAddress, {
|
|
5505
|
+
limit: 20,
|
|
5506
|
+
archival: true
|
|
5507
|
+
});
|
|
5508
|
+
for (const tx of transactions) {
|
|
5509
|
+
if (tx.inMessage?.info.type === "external-in") {
|
|
5510
|
+
try {
|
|
5511
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
5512
|
+
tx.inMessage
|
|
5513
|
+
);
|
|
5514
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
5515
|
+
const txHash = `0x${tx.hash().toString("hex")}`;
|
|
5516
|
+
return txHash;
|
|
5517
|
+
}
|
|
5518
|
+
} catch {
|
|
5519
|
+
continue;
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5523
|
+
await new Promise((r2) => setTimeout(r2, 3e3));
|
|
5524
|
+
} catch {
|
|
5525
|
+
await new Promise((r2) => setTimeout(r2, 3e3));
|
|
5881
5526
|
}
|
|
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
5527
|
}
|
|
5528
|
+
return null;
|
|
5898
5529
|
}
|
|
5899
5530
|
getNormalizedExtMessageHash(message) {
|
|
5900
5531
|
if (message.info.type !== "external-in") {
|
|
@@ -5917,6 +5548,9 @@ class TonChainStrategy {
|
|
|
5917
5548
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5918
5549
|
return BigInt(Math.trunc(value));
|
|
5919
5550
|
}
|
|
5551
|
+
if (typeof value === "object" && value !== null && "coins" in value) {
|
|
5552
|
+
return this.toBigInt(value.coins);
|
|
5553
|
+
}
|
|
5920
5554
|
if (typeof value === "string" && value.trim() !== "") {
|
|
5921
5555
|
try {
|
|
5922
5556
|
return BigInt(value);
|
|
@@ -5930,12 +5564,16 @@ class TonChainStrategy {
|
|
|
5930
5564
|
const candidate = tx.outMessages;
|
|
5931
5565
|
if (!candidate) return [];
|
|
5932
5566
|
if (Array.isArray(candidate)) return candidate;
|
|
5933
|
-
if (candidate instanceof Map) return Array.from(candidate.values());
|
|
5934
5567
|
if (typeof candidate === "object" && candidate !== null && "values" in candidate && typeof candidate.values === "function") {
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5568
|
+
const values = candidate.values();
|
|
5569
|
+
if (Array.isArray(values)) {
|
|
5570
|
+
return [...values];
|
|
5571
|
+
}
|
|
5572
|
+
if (values && typeof values === "object" && Symbol.iterator in values) {
|
|
5573
|
+
return Array.from(values);
|
|
5574
|
+
}
|
|
5938
5575
|
}
|
|
5576
|
+
if (candidate instanceof Map) return Array.from(candidate.values());
|
|
5939
5577
|
return [];
|
|
5940
5578
|
}
|
|
5941
5579
|
getMessageValue(message) {
|
|
@@ -5947,27 +5585,49 @@ class TonChainStrategy {
|
|
|
5947
5585
|
}
|
|
5948
5586
|
return this.toBigInt(value);
|
|
5949
5587
|
}
|
|
5950
|
-
|
|
5588
|
+
getTotalOutMessageValue(tx) {
|
|
5951
5589
|
const outMessages = this.getOutMessages(tx);
|
|
5952
5590
|
if (!outMessages.length) return 0n;
|
|
5953
|
-
|
|
5954
|
-
|
|
5591
|
+
let total = 0n;
|
|
5592
|
+
for (const message of outMessages) {
|
|
5593
|
+
const value = this.getMessageValue(message);
|
|
5594
|
+
if (value) {
|
|
5595
|
+
total += value;
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
return total;
|
|
5955
5599
|
}
|
|
5956
|
-
async getSourceCost(
|
|
5957
|
-
const timeoutMs =
|
|
5958
|
-
const result = await this.checkTonTransaction(
|
|
5959
|
-
if (!result.confirmed)
|
|
5600
|
+
async getSourceCost(messageHash) {
|
|
5601
|
+
const timeoutMs = 3e4;
|
|
5602
|
+
const result = await this.checkTonTransaction(messageHash, timeoutMs);
|
|
5603
|
+
if (!result.confirmed) {
|
|
5604
|
+
console.warn("Transaction not found for source cost calculation");
|
|
5605
|
+
return null;
|
|
5606
|
+
}
|
|
5960
5607
|
const totalFees = result.totalFees ?? 0n;
|
|
5961
5608
|
const outValue = result.outValue ?? 0n;
|
|
5962
5609
|
const totalNanotons = totalFees + outValue;
|
|
5963
5610
|
const toTon = (value) => Number(value) / 1e9;
|
|
5964
|
-
|
|
5611
|
+
const sourceCost = {
|
|
5965
5612
|
totalNative: toTon(totalNanotons),
|
|
5966
5613
|
breakdown: {
|
|
5967
5614
|
gasFee: toTon(totalFees),
|
|
5968
5615
|
layerZeroFee: toTon(outValue)
|
|
5969
5616
|
}
|
|
5970
5617
|
};
|
|
5618
|
+
console.log("TON source cost:", {
|
|
5619
|
+
gasFee: `${sourceCost.breakdown.gasFee} TON`,
|
|
5620
|
+
layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TON`,
|
|
5621
|
+
total: `${sourceCost.totalNative} TON`
|
|
5622
|
+
});
|
|
5623
|
+
return sourceCost;
|
|
5624
|
+
}
|
|
5625
|
+
async estimateNetworkFee() {
|
|
5626
|
+
const fee = Number(TON_CONFIG.estimatedNetworkFee);
|
|
5627
|
+
if (!Number.isFinite(fee) || fee <= 0) {
|
|
5628
|
+
return 0;
|
|
5629
|
+
}
|
|
5630
|
+
return fee / 1e9;
|
|
5971
5631
|
}
|
|
5972
5632
|
async checkTonTransaction(hashOrBoc, timeoutMs = 36e4) {
|
|
5973
5633
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -5978,10 +5638,6 @@ class TonChainStrategy {
|
|
|
5978
5638
|
try {
|
|
5979
5639
|
const inMessage = core.loadMessage(core.Cell.fromBase64(hashOrBoc).beginParse());
|
|
5980
5640
|
if (inMessage.info.type !== "external-in") {
|
|
5981
|
-
console.debug(
|
|
5982
|
-
"Expected external-in message, got:",
|
|
5983
|
-
inMessage.info.type
|
|
5984
|
-
);
|
|
5985
5641
|
return { confirmed: false };
|
|
5986
5642
|
}
|
|
5987
5643
|
accountAddress = inMessage.info.dest;
|
|
@@ -5989,63 +5645,50 @@ class TonChainStrategy {
|
|
|
5989
5645
|
} catch {
|
|
5990
5646
|
targetMessageHash = Buffer.from(hashOrBoc, "hex");
|
|
5991
5647
|
if (!this.config.tonAddress) {
|
|
5992
|
-
console.debug("No wallet address available for hex hash lookup");
|
|
5993
5648
|
return { confirmed: false };
|
|
5994
5649
|
}
|
|
5995
5650
|
accountAddress = core.Address.parse(this.config.tonAddress);
|
|
5996
5651
|
}
|
|
5997
|
-
let lt2 = void 0;
|
|
5998
|
-
let hash = void 0;
|
|
5999
5652
|
while (Date.now() < deadline) {
|
|
6000
5653
|
try {
|
|
6001
5654
|
const transactions = await client.getTransactions(accountAddress, {
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
limit: 10,
|
|
5655
|
+
limit: 20,
|
|
5656
|
+
// Check last 20 transactions
|
|
6005
5657
|
archival: true
|
|
6006
5658
|
});
|
|
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
5659
|
for (const tx of transactions) {
|
|
6014
5660
|
if (tx.inMessage?.info.type === "external-in") {
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
5661
|
+
try {
|
|
5662
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
5663
|
+
tx.inMessage
|
|
5664
|
+
);
|
|
5665
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
5666
|
+
const totalFees = this.toBigInt(tx.totalFees) ?? this.toBigInt(
|
|
5667
|
+
tx.total_fees
|
|
5668
|
+
) ?? 0n;
|
|
5669
|
+
const outValue = this.getTotalOutMessageValue(tx);
|
|
5670
|
+
const feeInTon = Number(totalFees) / 1e9;
|
|
5671
|
+
const transactionHash = tx.hash().toString("hex");
|
|
5672
|
+
return {
|
|
5673
|
+
confirmed: true,
|
|
5674
|
+
fee: feeInTon.toString(),
|
|
5675
|
+
totalFees,
|
|
5676
|
+
outValue,
|
|
5677
|
+
transactionHash
|
|
5678
|
+
};
|
|
5679
|
+
}
|
|
5680
|
+
} catch {
|
|
5681
|
+
continue;
|
|
6032
5682
|
}
|
|
6033
5683
|
}
|
|
6034
5684
|
}
|
|
6035
|
-
const lastTx = transactions[transactions.length - 1];
|
|
6036
|
-
lt2 = lastTx.lt.toString();
|
|
6037
|
-
hash = lastTx.hash().toString("base64");
|
|
6038
5685
|
await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
|
|
6039
|
-
} catch
|
|
6040
|
-
console.debug("Error fetching transactions:", error);
|
|
5686
|
+
} catch {
|
|
6041
5687
|
await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
|
|
6042
|
-
lt2 = void 0;
|
|
6043
|
-
hash = void 0;
|
|
6044
5688
|
}
|
|
6045
5689
|
}
|
|
6046
5690
|
return { confirmed: false };
|
|
6047
|
-
} catch
|
|
6048
|
-
console.debug("Error parsing BOC or checking transaction:", error);
|
|
5691
|
+
} catch {
|
|
6049
5692
|
return { confirmed: false };
|
|
6050
5693
|
}
|
|
6051
5694
|
}
|
|
@@ -6055,6 +5698,7 @@ class TronChainStrategy {
|
|
|
6055
5698
|
constructor(config) {
|
|
6056
5699
|
__publicField(this, "config");
|
|
6057
5700
|
__publicField(this, "fallbackClient");
|
|
5701
|
+
__publicField(this, "apiKeyApplied", /* @__PURE__ */ new WeakSet());
|
|
6058
5702
|
this.config = config;
|
|
6059
5703
|
}
|
|
6060
5704
|
canHandle(chainKey) {
|
|
@@ -6220,18 +5864,31 @@ class TronChainStrategy {
|
|
|
6220
5864
|
const feeTrx = feeSun / 1e6;
|
|
6221
5865
|
const lzFeeTrx = callValueSun / 1e6;
|
|
6222
5866
|
const totalTrx = (feeSun + callValueSun) / 1e6;
|
|
6223
|
-
|
|
5867
|
+
const sourceCost = {
|
|
6224
5868
|
totalNative: totalTrx,
|
|
6225
5869
|
breakdown: {
|
|
6226
5870
|
gasFee: feeTrx,
|
|
6227
5871
|
layerZeroFee: lzFeeTrx
|
|
6228
5872
|
}
|
|
6229
5873
|
};
|
|
5874
|
+
console.log("TRON source cost:", {
|
|
5875
|
+
gasFee: `${sourceCost.breakdown.gasFee} TRX`,
|
|
5876
|
+
layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TRX`,
|
|
5877
|
+
total: `${sourceCost.totalNative} TRX`
|
|
5878
|
+
});
|
|
5879
|
+
return sourceCost;
|
|
6230
5880
|
} catch (error) {
|
|
6231
5881
|
console.warn("Failed to compute TRON source cost:", error);
|
|
6232
5882
|
return null;
|
|
6233
5883
|
}
|
|
6234
5884
|
}
|
|
5885
|
+
async estimateNetworkFee() {
|
|
5886
|
+
const fee = Number(TRON_CONFIG.estimatedNetworkFee);
|
|
5887
|
+
if (!Number.isFinite(fee) || fee <= 0) {
|
|
5888
|
+
return 0;
|
|
5889
|
+
}
|
|
5890
|
+
return fee / 1e6;
|
|
5891
|
+
}
|
|
6235
5892
|
async executeSteps(steps, _context, onFirstHash) {
|
|
6236
5893
|
const tronWeb = this.getClient();
|
|
6237
5894
|
if (!tronWeb) {
|
|
@@ -6328,137 +5985,59 @@ class TronChainStrategy {
|
|
|
6328
5985
|
}
|
|
6329
5986
|
return { hash: lastTxId, chainKey: "tron" };
|
|
6330
5987
|
}
|
|
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
5988
|
getClient() {
|
|
6441
5989
|
if (typeof window !== "undefined" && window.tronWeb) {
|
|
5990
|
+
this.applyTronApiKey(window.tronWeb);
|
|
6442
5991
|
return window.tronWeb;
|
|
6443
5992
|
}
|
|
6444
5993
|
if (!this.fallbackClient) {
|
|
6445
5994
|
this.fallbackClient = this.createFallbackClient();
|
|
6446
5995
|
}
|
|
5996
|
+
if (this.fallbackClient) {
|
|
5997
|
+
this.applyTronApiKey(this.fallbackClient);
|
|
5998
|
+
}
|
|
6447
5999
|
return this.fallbackClient;
|
|
6448
6000
|
}
|
|
6449
6001
|
createFallbackClient() {
|
|
6450
6002
|
try {
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6003
|
+
if (!this.config.apiKey) {
|
|
6004
|
+
throw new Error("TRON API key is required");
|
|
6005
|
+
}
|
|
6006
|
+
const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
|
|
6007
|
+
const tronWeb = new tronweb.TronWeb({
|
|
6008
|
+
fullHost: DEFAULT_TRON_NODE,
|
|
6009
|
+
headers
|
|
6010
|
+
});
|
|
6456
6011
|
return tronWeb;
|
|
6457
6012
|
} catch (error) {
|
|
6458
6013
|
console.warn("Failed to create fallback TronWeb client", error);
|
|
6459
6014
|
return void 0;
|
|
6460
6015
|
}
|
|
6461
6016
|
}
|
|
6017
|
+
applyTronApiKey(tronWeb) {
|
|
6018
|
+
if (!this.config.apiKey) {
|
|
6019
|
+
return;
|
|
6020
|
+
}
|
|
6021
|
+
const target = tronWeb;
|
|
6022
|
+
if (this.apiKeyApplied.has(target)) {
|
|
6023
|
+
return;
|
|
6024
|
+
}
|
|
6025
|
+
try {
|
|
6026
|
+
const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
|
|
6027
|
+
if (typeof target.setHeader === "function") {
|
|
6028
|
+
target.setHeader(headers);
|
|
6029
|
+
} else {
|
|
6030
|
+
if (typeof target.setFullNodeHeader === "function") {
|
|
6031
|
+
target.setFullNodeHeader(headers);
|
|
6032
|
+
}
|
|
6033
|
+
if (typeof target.setEventHeader === "function") {
|
|
6034
|
+
target.setEventHeader(headers);
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
this.apiKeyApplied.add(target);
|
|
6038
|
+
} catch {
|
|
6039
|
+
}
|
|
6040
|
+
}
|
|
6462
6041
|
/**
|
|
6463
6042
|
* Check if TronLink wallet is actually installed
|
|
6464
6043
|
* This excludes Bybit Wallet which also injects tronLink for compatibility
|
|
@@ -6467,14 +6046,8 @@ class TronChainStrategy {
|
|
|
6467
6046
|
if (typeof window === "undefined") {
|
|
6468
6047
|
return false;
|
|
6469
6048
|
}
|
|
6470
|
-
const
|
|
6471
|
-
|
|
6472
|
-
return false;
|
|
6473
|
-
}
|
|
6474
|
-
if (!window.tronLink) {
|
|
6475
|
-
return false;
|
|
6476
|
-
}
|
|
6477
|
-
return true;
|
|
6049
|
+
const win = window;
|
|
6050
|
+
return !!(win.tronLink || win.tronWeb || win.tron);
|
|
6478
6051
|
}
|
|
6479
6052
|
ensureDefaultAddress(tronWeb, address) {
|
|
6480
6053
|
if (!address) return;
|
|
@@ -6487,18 +6060,7 @@ class TronChainStrategy {
|
|
|
6487
6060
|
hex
|
|
6488
6061
|
};
|
|
6489
6062
|
}
|
|
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
6063
|
} catch {
|
|
6501
|
-
return null;
|
|
6502
6064
|
}
|
|
6503
6065
|
}
|
|
6504
6066
|
toBase58(addr, tronWeb) {
|
|
@@ -6805,22 +6367,14 @@ class TronChainStrategy {
|
|
|
6805
6367
|
}
|
|
6806
6368
|
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
6807
6369
|
if (!info || !info.blockNumber) {
|
|
6808
|
-
console.debug(
|
|
6809
|
-
"Transaction not yet solidified (no blockNumber in info)"
|
|
6810
|
-
);
|
|
6811
6370
|
return false;
|
|
6812
6371
|
}
|
|
6813
6372
|
const result = info.receipt?.result;
|
|
6814
6373
|
if (result === "SUCCESS") {
|
|
6815
|
-
console.log(
|
|
6816
|
-
`Transaction ${txHash} is solidified in block ${info.blockNumber}`
|
|
6817
|
-
);
|
|
6818
6374
|
return true;
|
|
6819
6375
|
}
|
|
6820
|
-
console.debug(`Transaction solidified but result is: ${result}`);
|
|
6821
6376
|
return false;
|
|
6822
|
-
} catch
|
|
6823
|
-
console.debug("Error checking solidified status:", error);
|
|
6377
|
+
} catch {
|
|
6824
6378
|
return false;
|
|
6825
6379
|
}
|
|
6826
6380
|
}
|
|
@@ -6831,7 +6385,8 @@ function ChainStrategyProvider({
|
|
|
6831
6385
|
tonWallet,
|
|
6832
6386
|
tronWallet,
|
|
6833
6387
|
tonClient,
|
|
6834
|
-
tonApiKey
|
|
6388
|
+
tonApiKey,
|
|
6389
|
+
tronApiKey
|
|
6835
6390
|
}) {
|
|
6836
6391
|
const evmStrategy = react.useMemo(
|
|
6837
6392
|
() => new EvmChainStrategy({
|
|
@@ -6874,7 +6429,8 @@ function ChainStrategyProvider({
|
|
|
6874
6429
|
connect: tronWallet.walletConnect.connect,
|
|
6875
6430
|
disconnect: tronWallet.walletConnect.disconnect,
|
|
6876
6431
|
signTransaction: tronWallet.walletConnect.signTransaction
|
|
6877
|
-
} : void 0
|
|
6432
|
+
} : void 0,
|
|
6433
|
+
apiKey: tronApiKey
|
|
6878
6434
|
}),
|
|
6879
6435
|
[
|
|
6880
6436
|
tronWallet.tronLink.address,
|
|
@@ -6882,7 +6438,8 @@ function ChainStrategyProvider({
|
|
|
6882
6438
|
tronWallet.tronLink.select,
|
|
6883
6439
|
tronWallet.tronLink.connect,
|
|
6884
6440
|
tronWallet.tronLink.disconnect,
|
|
6885
|
-
tronWallet.walletConnect
|
|
6441
|
+
tronWallet.walletConnect,
|
|
6442
|
+
tronApiKey
|
|
6886
6443
|
]
|
|
6887
6444
|
);
|
|
6888
6445
|
const chainRegistry = react.useMemo(
|
|
@@ -26237,7 +25794,7 @@ class WalletConnectModal {
|
|
|
26237
25794
|
}
|
|
26238
25795
|
async initUi() {
|
|
26239
25796
|
if (typeof window !== "undefined") {
|
|
26240
|
-
await Promise.resolve().then(() => require("./index-
|
|
25797
|
+
await Promise.resolve().then(() => require("./index-BLC0Ys74.cjs"));
|
|
26241
25798
|
const modal = document.createElement("wcm-modal");
|
|
26242
25799
|
document.body.insertAdjacentElement("beforeend", modal);
|
|
26243
25800
|
OptionsCtrl.setIsUiLoaded(true);
|
|
@@ -26730,6 +26287,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
26730
26287
|
},
|
|
26731
26288
|
tonClient: props.tonClient,
|
|
26732
26289
|
tonApiKey: props.tonApiKey,
|
|
26290
|
+
tronApiKey: props.tronApiKey,
|
|
26733
26291
|
children: /* @__PURE__ */ jsxRuntime.jsx(EvaaBridgeContent, { ...props })
|
|
26734
26292
|
}
|
|
26735
26293
|
) });
|
|
@@ -26955,16 +26513,10 @@ exports.RouteType = RouteType;
|
|
|
26955
26513
|
exports.RouterCtrl = RouterCtrl;
|
|
26956
26514
|
exports.ThemeCtrl = ThemeCtrl;
|
|
26957
26515
|
exports.ToastCtrl = ToastCtrl;
|
|
26958
|
-
exports.addEvmNetworkFee = addEvmNetworkFee;
|
|
26959
|
-
exports.addTonNetworkFee = addTonNetworkFee;
|
|
26960
|
-
exports.addTronNetworkFee = addTronNetworkFee;
|
|
26961
26516
|
exports.addrForApi = addrForApi;
|
|
26962
26517
|
exports.buildAssetMatrix = buildAssetMatrix;
|
|
26963
26518
|
exports.calculateMinReceived = calculateMinReceived;
|
|
26964
26519
|
exports.computeFeesUsdFromArray = computeFeesUsdFromArray;
|
|
26965
|
-
exports.estimateEvmNetworkFee = estimateEvmNetworkFee;
|
|
26966
|
-
exports.estimateTonNetworkFee = estimateTonNetworkFee;
|
|
26967
|
-
exports.estimateTronNetworkFee = estimateTronNetworkFee;
|
|
26968
26520
|
exports.findNativeMeta = findNativeMeta;
|
|
26969
26521
|
exports.formatAddress = formatAddress;
|
|
26970
26522
|
exports.formatBalance = formatBalance;
|
|
@@ -27008,4 +26560,4 @@ exports.useSettingsStore = useSettingsStore;
|
|
|
27008
26560
|
exports.useSwapModel = useSwapModel;
|
|
27009
26561
|
exports.useTokensStore = useTokensStore;
|
|
27010
26562
|
exports.useTransactionStore = useTransactionStore;
|
|
27011
|
-
//# sourceMappingURL=index-
|
|
26563
|
+
//# sourceMappingURL=index-DiF0Z4eu.cjs.map
|