@rash2x/bridge-widget 0.6.55 → 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
|
@@ -10,8 +10,7 @@ import { create } from "zustand";
|
|
|
10
10
|
import { useAccount, usePublicClient, useConnect, useDisconnect, useWalletClient } from "wagmi";
|
|
11
11
|
import { useWallet } from "@tronweb3/tronwallet-adapter-react-hooks";
|
|
12
12
|
import { useTonAddress, useTonConnectUI } from "@tonconnect/ui-react";
|
|
13
|
-
import { Address, beginCell as beginCell$1, storeMessage
|
|
14
|
-
import { TonClient, Address as Address$1, beginCell } from "@ton/ton";
|
|
13
|
+
import { Address, loadMessage, Cell, beginCell as beginCell$1, storeMessage } from "@ton/core";
|
|
15
14
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
16
15
|
import { cn as cn$2 } from "@/lib/utils";
|
|
17
16
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
@@ -26,7 +25,8 @@ import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
|
26
25
|
import { toast, Toaster } from "sonner";
|
|
27
26
|
import { Badge } from "@/components/ui/badge";
|
|
28
27
|
import { DialogDescription as DialogDescription$1 } from "@radix-ui/react-dialog";
|
|
29
|
-
import { isAddress, formatUnits, parseUnits } from "viem";
|
|
28
|
+
import { isAddress, formatUnits, parseAbi, parseUnits } from "viem";
|
|
29
|
+
import { TonClient, Address as Address$1, beginCell } from "@ton/ton";
|
|
30
30
|
import { TronLinkAdapterName } from "@tronweb3/tronwallet-adapters";
|
|
31
31
|
import { TronWeb } from "tronweb";
|
|
32
32
|
import { CardHeader, CardTitle, CardAction, Card, CardContent, CardFooter } from "@/components/ui/card";
|
|
@@ -34,7 +34,7 @@ import { FixedSizeList } from "react-window";
|
|
|
34
34
|
const common$1 = { "connecting": "Connecting…", "initializing": "Initializing...", "loading": "Loading...", "paste": "paste", "close": "Close", "zeroPlaceholder": "0", "nativeToken": "Native Token" };
|
|
35
35
|
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" };
|
|
36
36
|
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" };
|
|
37
|
-
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": "
|
|
37
|
+
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" } };
|
|
38
38
|
const telegram$1 = { "openWebVersion": "Open EVAA Web to Bridge", "restrictionMessage": "You can bridge between the chosen networks on EVAA web version" };
|
|
39
39
|
const app$1 = { "stargateWidgetName": "Stargate Bridge Widget", "liveWidget": "Live Widget", "getStarted": "Get Started" };
|
|
40
40
|
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" } };
|
|
@@ -52,7 +52,7 @@ const en$3 = {
|
|
|
52
52
|
const common = { "connecting": "Подключение…", "initializing": "Инициализация...", "loading": "Загрузка...", "paste": "вставить", "close": "Закрыть", "zeroPlaceholder": "0", "nativeToken": "Нативный токен" };
|
|
53
53
|
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": "Подключить кошелёк" };
|
|
54
54
|
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": "Проверьте корректность перед переводом" };
|
|
55
|
-
const transaction = { "enterAmount": "Введите сумму", "transfer": "Перевести", "getQuote": "Получить котировку", "quoting": "Расчет котировки...", "failed": "Ошибка транзакции", "confirm": "Подтвердите транзакцию", "signTransaction": "Подпишите транзакцию в кошельке", "inProgress": "Транзакция выполняется...", "checkingBalance": "Проверка баланса...", "insufficientBalance": "Недостаточно средств", "amountTooSmall": "Минимум {{min}}", "amountTooLarge": "Максимум {{max}}", "success": "Успех", "successTitle": "Успех", "done": "Готово", "hashCopied": "Хэш скопирован в буфер обмена", "bridged": "Переведено", "transferTitle": "Перевод", "hash": "Хэш", "layerzeroScan": "
|
|
55
|
+
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": "Завершено" } };
|
|
56
56
|
const telegram = { "openWebVersion": "Открыть EVAA веб для трансфера", "restrictionMessage": "Трансфер между выбранными сетями доступен только в веб-версии EVAA" };
|
|
57
57
|
const app = { "stargateWidgetName": "Виджет Stargate Bridge", "liveWidget": "Живой виджет", "getStarted": "Начало работы" };
|
|
58
58
|
const settings = { "title": "Настройки", "gasOnDestination": "Газ на назначении", "gasOnDestinationDescription": "Значение по умолчанию позволяет выполнить пару транзакций (например, Approve и Swap).", "slippageTolerance": "Толерантность к проскальзыванию", "slippageToleranceDescription": "Ваша транзакция будет отклонена, если получаемая сумма выйдет за пределы этой допустимой погрешности.", "routePriority": "Приоритет маршрута", "routePriorityDescription": "Выберите, как будет выполняться ваш трансфер. Recommended — выбирает оптимальный маршрут с учётом общей стоимости. Fastest — отдаёт приоритет максимальной скорости.", "highSlippageWarning": "Высокое проскальзывание", "gasPresets": { "auto": "Авто", "none": "Нет", "medium": "Средний", "max": "Макс" }, "routePresets": { "fastest": "Быстрейший", "cheapest": "Дешевейший", "recommended": "Рекомендуемый" } };
|
|
@@ -940,375 +940,6 @@ function useChainStrategies() {
|
|
|
940
940
|
}
|
|
941
941
|
return context;
|
|
942
942
|
}
|
|
943
|
-
const truncateToDecimals = (num, decimals) => {
|
|
944
|
-
if (!isFinite(num) || isNaN(num)) return "0";
|
|
945
|
-
const multiplier = Math.pow(10, decimals);
|
|
946
|
-
const truncated = Math.floor(num * multiplier) / multiplier;
|
|
947
|
-
return truncated.toFixed(decimals).replace(/\.?0+$/, "");
|
|
948
|
-
};
|
|
949
|
-
const formatTokenAmount = (amount, symbol, options) => {
|
|
950
|
-
const normalizedSymbol = (symbol ?? "").toUpperCase();
|
|
951
|
-
if (["USDT", "USDC", "DAI", "BUSD"].includes(normalizedSymbol) && amount >= 1) {
|
|
952
|
-
return `${Math.floor(amount)} ${normalizedSymbol}`;
|
|
953
|
-
}
|
|
954
|
-
if (options?.decimals !== void 0) {
|
|
955
|
-
return `${amount.toFixed(options.decimals)} ${normalizedSymbol}`;
|
|
956
|
-
}
|
|
957
|
-
if (amount >= 1) {
|
|
958
|
-
return `${amount.toFixed(0)} ${normalizedSymbol}`;
|
|
959
|
-
} else if (amount >= 1e-3) {
|
|
960
|
-
return `${amount.toFixed(3)} ${normalizedSymbol}`;
|
|
961
|
-
} else {
|
|
962
|
-
return `${amount.toFixed(6)} ${normalizedSymbol}`;
|
|
963
|
-
}
|
|
964
|
-
};
|
|
965
|
-
const formatUsd = (value) => {
|
|
966
|
-
if (!value || !isFinite(value)) return "$0";
|
|
967
|
-
if (value >= 1) return `$${value.toFixed(2)}`;
|
|
968
|
-
return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
|
|
969
|
-
};
|
|
970
|
-
const formatPercentage = (bps, decimals = 2) => {
|
|
971
|
-
return `${(bps / 100).toFixed(decimals).replace(/0+$/, "").replace(/\.$/, "")}%`;
|
|
972
|
-
};
|
|
973
|
-
const formatBalance = (amount, decimals = 2) => {
|
|
974
|
-
if (!isFinite(amount) || isNaN(amount) || amount <= 0) {
|
|
975
|
-
return "0.00";
|
|
976
|
-
}
|
|
977
|
-
return amount.toFixed(decimals);
|
|
978
|
-
};
|
|
979
|
-
const formatHash = (hash, startChars = 4, endChars = 4) => {
|
|
980
|
-
if (!hash) return "";
|
|
981
|
-
if (hash.length <= startChars + endChars) return hash;
|
|
982
|
-
return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
|
|
983
|
-
};
|
|
984
|
-
const formatAddress = formatHash;
|
|
985
|
-
const EVM_CONFIG = {
|
|
986
|
-
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
987
|
-
gasEstimates: {
|
|
988
|
-
approve: 65000n,
|
|
989
|
-
bridge: 300000n
|
|
990
|
-
},
|
|
991
|
-
gasBuffer: 1.2,
|
|
992
|
-
// 20% buffer
|
|
993
|
-
timeout: 3e5,
|
|
994
|
-
// 5 minutes (increased for slower networks)
|
|
995
|
-
requiredConfirmations: 3
|
|
996
|
-
// Wait for 3 confirmations for reorg protection
|
|
997
|
-
};
|
|
998
|
-
const TON_CONFIG = {
|
|
999
|
-
apiUrl: "https://toncenter.com/api/v2",
|
|
1000
|
-
timeout: 36e4,
|
|
1001
|
-
// 6 minutes
|
|
1002
|
-
validUntil: 600,
|
|
1003
|
-
// 10 minutes
|
|
1004
|
-
pollingInterval: 5e3,
|
|
1005
|
-
// 5 seconds between transaction status checks
|
|
1006
|
-
estimatedNetworkFee: "100000000"
|
|
1007
|
-
// 0.1 TON in nanoton (conservative estimate)
|
|
1008
|
-
};
|
|
1009
|
-
const TRON_CONFIG = {
|
|
1010
|
-
timeout: 12e4,
|
|
1011
|
-
// 2 minutes (for 19 confirmations)
|
|
1012
|
-
feeLimit: 1e8,
|
|
1013
|
-
// 100 TRX in sun
|
|
1014
|
-
requiredConfirmations: 19,
|
|
1015
|
-
// TRON standard: 19 blocks for confirmation
|
|
1016
|
-
pollingInterval: 3e3,
|
|
1017
|
-
// 3 seconds between checks
|
|
1018
|
-
estimatedNetworkFee: "10000000"
|
|
1019
|
-
// 10 TRX in SUN (fallback estimate)
|
|
1020
|
-
};
|
|
1021
|
-
let tonClientInstance = null;
|
|
1022
|
-
function getTonClient(customClient, apiKey) {
|
|
1023
|
-
if (customClient) {
|
|
1024
|
-
return customClient;
|
|
1025
|
-
}
|
|
1026
|
-
if (!tonClientInstance) {
|
|
1027
|
-
tonClientInstance = new TonClient({
|
|
1028
|
-
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
1029
|
-
apiKey
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
return tonClientInstance;
|
|
1033
|
-
}
|
|
1034
|
-
function getQuoteAmounts(quote, srcToken, dstToken) {
|
|
1035
|
-
if (!quote || !srcToken || !dstToken) {
|
|
1036
|
-
return {
|
|
1037
|
-
inputHuman: 0,
|
|
1038
|
-
outputHuman: 0,
|
|
1039
|
-
outputHumanRounded: "0",
|
|
1040
|
-
minReceivedHuman: 0
|
|
1041
|
-
};
|
|
1042
|
-
}
|
|
1043
|
-
const inputHuman = fromLD(quote.srcAmount, srcToken.decimals);
|
|
1044
|
-
const outputHuman = fromLD(quote.dstAmount, dstToken.decimals);
|
|
1045
|
-
const outputHumanRounded = truncateToDecimals(outputHuman, 2);
|
|
1046
|
-
const minReceivedHuman = fromLD(quote.dstAmountMin || "0", dstToken.decimals);
|
|
1047
|
-
return {
|
|
1048
|
-
inputHuman,
|
|
1049
|
-
outputHuman,
|
|
1050
|
-
outputHumanRounded,
|
|
1051
|
-
minReceivedHuman
|
|
1052
|
-
};
|
|
1053
|
-
}
|
|
1054
|
-
function getQuoteFees(quote, tokens, chains, srcToken, dstToken) {
|
|
1055
|
-
if (!quote || !tokens || !chains) {
|
|
1056
|
-
return {
|
|
1057
|
-
fees: { usd: /* @__PURE__ */ new Map(), original: /* @__PURE__ */ new Map(), formatted: /* @__PURE__ */ new Map() },
|
|
1058
|
-
inSrcToken: void 0,
|
|
1059
|
-
inDstToken: void 0
|
|
1060
|
-
};
|
|
1061
|
-
}
|
|
1062
|
-
const feeData = computeFeesUsdFromArray(quote.fees, tokens, chains);
|
|
1063
|
-
let inSrcToken = void 0;
|
|
1064
|
-
let inDstToken = void 0;
|
|
1065
|
-
if (srcToken && quote.srcChainKey) {
|
|
1066
|
-
const feeInSrcLD = sumFeeByTokenLD(
|
|
1067
|
-
quote.fees,
|
|
1068
|
-
srcToken.address,
|
|
1069
|
-
quote.srcChainKey
|
|
1070
|
-
);
|
|
1071
|
-
const feeInSrcHuman = fromLD(feeInSrcLD, srcToken.decimals);
|
|
1072
|
-
if (feeInSrcHuman > 0) {
|
|
1073
|
-
inSrcToken = Number(truncateToDecimals(feeInSrcHuman, 8));
|
|
1074
|
-
} else if ((feeData.usd.get("total") || 0) > 0 && srcToken.price?.usd) {
|
|
1075
|
-
const feeInSrcApprox = (feeData.usd.get("total") || 0) / srcToken.price.usd;
|
|
1076
|
-
inSrcToken = Number(truncateToDecimals(feeInSrcApprox, 8));
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
if (dstToken && quote.dstChainKey) {
|
|
1080
|
-
const feeInDstLD = sumFeeByTokenLD(
|
|
1081
|
-
quote.fees,
|
|
1082
|
-
dstToken.address,
|
|
1083
|
-
quote.dstChainKey
|
|
1084
|
-
);
|
|
1085
|
-
const feeInDstHuman = fromLD(feeInDstLD, dstToken.decimals);
|
|
1086
|
-
if (feeInDstHuman > 0) {
|
|
1087
|
-
inDstToken = Number(truncateToDecimals(feeInDstHuman, 8));
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
return {
|
|
1091
|
-
fees: feeData,
|
|
1092
|
-
inSrcToken,
|
|
1093
|
-
inDstToken
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
function calculateMinReceived(quote, slippageBps, dstToken) {
|
|
1097
|
-
if (!quote || !dstToken) return 0;
|
|
1098
|
-
const dstAmountLD = BigInt(quote.dstAmount);
|
|
1099
|
-
const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
|
|
1100
|
-
return fromLD(minAmountLD.toString(), dstToken.decimals);
|
|
1101
|
-
}
|
|
1102
|
-
function estimateTonNetworkFee(quote) {
|
|
1103
|
-
try {
|
|
1104
|
-
const tonStep = quote.steps?.find(
|
|
1105
|
-
(s2) => s2.chainKey.toLowerCase() === "ton" && s2.type === "bridge"
|
|
1106
|
-
);
|
|
1107
|
-
if (!tonStep?.transaction?.messages) {
|
|
1108
|
-
console.warn("No TON messages found in quote, using fallback");
|
|
1109
|
-
return TON_CONFIG.estimatedNetworkFee;
|
|
1110
|
-
}
|
|
1111
|
-
const messages = tonStep.transaction.messages;
|
|
1112
|
-
const messageCount = messages.length;
|
|
1113
|
-
const baseFeePerMessage = 10000000n;
|
|
1114
|
-
let totalFee = 0n;
|
|
1115
|
-
for (const message of messages) {
|
|
1116
|
-
let messageFee = baseFeePerMessage;
|
|
1117
|
-
if (message.payload) {
|
|
1118
|
-
const payloadSize = message.payload.length;
|
|
1119
|
-
const sizeFee = BigInt(Math.floor(payloadSize / 100)) * 100000n;
|
|
1120
|
-
messageFee += sizeFee;
|
|
1121
|
-
}
|
|
1122
|
-
if (message.amount) {
|
|
1123
|
-
const amount = BigInt(message.amount);
|
|
1124
|
-
if (amount > 0n && message.payload) {
|
|
1125
|
-
messageFee += 5000000n;
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
totalFee += messageFee;
|
|
1129
|
-
}
|
|
1130
|
-
const minBuffer = 50000000n;
|
|
1131
|
-
totalFee = totalFee > minBuffer ? totalFee : minBuffer;
|
|
1132
|
-
totalFee = totalFee * 120n / 100n;
|
|
1133
|
-
const maxFee = 1000000000n;
|
|
1134
|
-
if (totalFee > maxFee) {
|
|
1135
|
-
totalFee = maxFee;
|
|
1136
|
-
}
|
|
1137
|
-
console.log(
|
|
1138
|
-
`TON fee estimate: ${messageCount} messages = ${Number(totalFee) / 1e9} TON`
|
|
1139
|
-
);
|
|
1140
|
-
return totalFee.toString();
|
|
1141
|
-
} catch (error) {
|
|
1142
|
-
console.warn("Failed to estimate TON fee:", error);
|
|
1143
|
-
return TON_CONFIG.estimatedNetworkFee;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
function addTonNetworkFee(quote, chains, estimatedFee) {
|
|
1147
|
-
if (!quote || quote.srcChainKey.toLowerCase() !== "ton") {
|
|
1148
|
-
return quote;
|
|
1149
|
-
}
|
|
1150
|
-
const tonChain = chains?.find((c2) => c2.chainKey.toLowerCase() === "ton");
|
|
1151
|
-
if (!tonChain?.nativeCurrency?.address) {
|
|
1152
|
-
console.warn("Could not find TON native currency address");
|
|
1153
|
-
return quote;
|
|
1154
|
-
}
|
|
1155
|
-
const networkFee = {
|
|
1156
|
-
token: tonChain.nativeCurrency.address,
|
|
1157
|
-
chainKey: "ton",
|
|
1158
|
-
amount: estimatedFee || TON_CONFIG.estimatedNetworkFee,
|
|
1159
|
-
type: "network"
|
|
1160
|
-
};
|
|
1161
|
-
const hasNetworkFee = quote.fees?.some(
|
|
1162
|
-
(fee) => fee.type === "network" && fee.chainKey === "ton"
|
|
1163
|
-
);
|
|
1164
|
-
if (hasNetworkFee) {
|
|
1165
|
-
return quote;
|
|
1166
|
-
}
|
|
1167
|
-
return {
|
|
1168
|
-
...quote,
|
|
1169
|
-
fees: [...quote.fees || [], networkFee]
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
async function estimateTronNetworkFee(tronWeb, quote, userAddress) {
|
|
1173
|
-
try {
|
|
1174
|
-
const accountResources = await tronWeb.trx.getAccountResources(userAddress);
|
|
1175
|
-
const availableEnergy = accountResources.EnergyLimit || 0;
|
|
1176
|
-
const tronStep = quote.steps?.find(
|
|
1177
|
-
(s2) => s2.chainKey.toLowerCase() === "tron" && s2.type === "bridge"
|
|
1178
|
-
);
|
|
1179
|
-
if (!tronStep?.transaction?.data || !tronStep.transaction.to) {
|
|
1180
|
-
console.warn("No TRON transaction data in quote, using fallback");
|
|
1181
|
-
return TRON_CONFIG.estimatedNetworkFee;
|
|
1182
|
-
}
|
|
1183
|
-
const contractAddress = tronWeb.address.fromHex(
|
|
1184
|
-
tronStep.transaction.to.startsWith("41") ? tronStep.transaction.to : "41" + tronStep.transaction.to.slice(2)
|
|
1185
|
-
);
|
|
1186
|
-
const simulation = await tronWeb.transactionBuilder.triggerSmartContract(
|
|
1187
|
-
contractAddress,
|
|
1188
|
-
"function signature doesn't matter for energy estimation",
|
|
1189
|
-
{
|
|
1190
|
-
feeLimit: TRON_CONFIG.feeLimit,
|
|
1191
|
-
callValue: tronStep.transaction.value ? Number(tronStep.transaction.value) : 0
|
|
1192
|
-
},
|
|
1193
|
-
[],
|
|
1194
|
-
userAddress
|
|
1195
|
-
);
|
|
1196
|
-
const requiredEnergy = simulation.energy_used || 0;
|
|
1197
|
-
const energyDeficit = Math.max(0, requiredEnergy - availableEnergy);
|
|
1198
|
-
if (energyDeficit === 0) {
|
|
1199
|
-
return "0";
|
|
1200
|
-
}
|
|
1201
|
-
const energyPriceInSun = 420;
|
|
1202
|
-
const feeSun = energyDeficit * energyPriceInSun;
|
|
1203
|
-
console.log(
|
|
1204
|
-
`TRON fee estimation: ${requiredEnergy} energy required, ${availableEnergy} available, ${feeSun / 1e6} TRX fee`
|
|
1205
|
-
);
|
|
1206
|
-
return feeSun.toString();
|
|
1207
|
-
} catch (error) {
|
|
1208
|
-
console.warn("Failed to estimate TRON network fee:", error);
|
|
1209
|
-
return TRON_CONFIG.estimatedNetworkFee;
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
function addTronNetworkFee(quote, chains, estimatedFee) {
|
|
1213
|
-
if (!quote || quote.srcChainKey.toLowerCase() !== "tron") {
|
|
1214
|
-
return quote;
|
|
1215
|
-
}
|
|
1216
|
-
const tronChain = chains?.find((c2) => c2.chainKey.toLowerCase() === "tron");
|
|
1217
|
-
if (!tronChain?.nativeCurrency?.address) {
|
|
1218
|
-
console.warn("Could not find TRON native currency address");
|
|
1219
|
-
return quote;
|
|
1220
|
-
}
|
|
1221
|
-
const networkFee = {
|
|
1222
|
-
token: tronChain.nativeCurrency.address,
|
|
1223
|
-
chainKey: "tron",
|
|
1224
|
-
amount: estimatedFee || TRON_CONFIG.estimatedNetworkFee,
|
|
1225
|
-
type: "network"
|
|
1226
|
-
};
|
|
1227
|
-
const hasNetworkFee = quote.fees?.some(
|
|
1228
|
-
(fee) => fee.type === "network" && fee.chainKey === "tron"
|
|
1229
|
-
);
|
|
1230
|
-
if (hasNetworkFee) {
|
|
1231
|
-
return quote;
|
|
1232
|
-
}
|
|
1233
|
-
return {
|
|
1234
|
-
...quote,
|
|
1235
|
-
fees: [...quote.fees || [], networkFee]
|
|
1236
|
-
};
|
|
1237
|
-
}
|
|
1238
|
-
async function estimateEvmNetworkFee(publicClient, quote, chainKey) {
|
|
1239
|
-
try {
|
|
1240
|
-
let totalGasLimit = 0n;
|
|
1241
|
-
for (const step of quote.steps || []) {
|
|
1242
|
-
if (step.chainKey.toLowerCase() !== chainKey.toLowerCase()) continue;
|
|
1243
|
-
if (step.type === "approve") {
|
|
1244
|
-
totalGasLimit += EVM_CONFIG.gasEstimates.approve;
|
|
1245
|
-
} else if (step.type === "bridge") {
|
|
1246
|
-
totalGasLimit += EVM_CONFIG.gasEstimates.bridge;
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
if (totalGasLimit === 0n) {
|
|
1250
|
-
return "0";
|
|
1251
|
-
}
|
|
1252
|
-
totalGasLimit = totalGasLimit * BigInt(Math.floor(EVM_CONFIG.gasBuffer * 100)) / 100n;
|
|
1253
|
-
const gasPrice = await publicClient.getGasPrice();
|
|
1254
|
-
const totalCostWei = totalGasLimit * gasPrice;
|
|
1255
|
-
return totalCostWei.toString();
|
|
1256
|
-
} catch (error) {
|
|
1257
|
-
console.warn("Failed to estimate EVM gas fee:", error);
|
|
1258
|
-
return "10000000000000000";
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
function addEvmNetworkFee(quote, chains, estimatedFee) {
|
|
1262
|
-
if (!quote) return quote;
|
|
1263
|
-
const srcChainKey = quote.srcChainKey.toLowerCase();
|
|
1264
|
-
if (srcChainKey === "ton" || srcChainKey === "tron") {
|
|
1265
|
-
return quote;
|
|
1266
|
-
}
|
|
1267
|
-
const srcChain = chains?.find(
|
|
1268
|
-
(c2) => c2.chainKey.toLowerCase() === srcChainKey
|
|
1269
|
-
);
|
|
1270
|
-
if (!srcChain?.nativeCurrency?.address) {
|
|
1271
|
-
return quote;
|
|
1272
|
-
}
|
|
1273
|
-
const hasNetworkFee = quote.fees?.some(
|
|
1274
|
-
(fee) => fee.type === "network" && fee.chainKey.toLowerCase() === srcChainKey
|
|
1275
|
-
);
|
|
1276
|
-
if (hasNetworkFee) {
|
|
1277
|
-
return quote;
|
|
1278
|
-
}
|
|
1279
|
-
const networkFee = {
|
|
1280
|
-
token: srcChain.nativeCurrency.address,
|
|
1281
|
-
chainKey: quote.srcChainKey,
|
|
1282
|
-
amount: estimatedFee || "10000000000000000",
|
|
1283
|
-
type: "network"
|
|
1284
|
-
};
|
|
1285
|
-
return {
|
|
1286
|
-
...quote,
|
|
1287
|
-
fees: [...quote.fees || [], networkFee]
|
|
1288
|
-
};
|
|
1289
|
-
}
|
|
1290
|
-
function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
|
|
1291
|
-
const amounts = getQuoteAmounts(quote, srcToken, dstToken);
|
|
1292
|
-
const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
|
|
1293
|
-
const minimumReceived = calculateMinReceived(quote, slippageBps, dstToken);
|
|
1294
|
-
return {
|
|
1295
|
-
inputAmount: amounts.inputHuman,
|
|
1296
|
-
outputAmount: amounts.outputHuman,
|
|
1297
|
-
outputAmountRounded: amounts.outputHumanRounded,
|
|
1298
|
-
minimumReceived,
|
|
1299
|
-
etaSeconds: quote?.duration?.estimated,
|
|
1300
|
-
fees
|
|
1301
|
-
};
|
|
1302
|
-
}
|
|
1303
|
-
function getRouteDisplayName(route) {
|
|
1304
|
-
if (!route) return "Stargate Bridge";
|
|
1305
|
-
const routeLower = route.toLowerCase();
|
|
1306
|
-
if (routeLower.includes("taxi")) return "Stargate V2 Fast";
|
|
1307
|
-
if (routeLower.includes("bus")) return "Stargate V2 Economy";
|
|
1308
|
-
if (routeLower.includes("oft")) return "OFT Bridge";
|
|
1309
|
-
if (routeLower.includes("v2")) return "Stargate V2";
|
|
1310
|
-
return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
1311
|
-
}
|
|
1312
943
|
const toSharedDecimals = (amount, fromDecimals, toDecimals) => {
|
|
1313
944
|
const value = BigInt(amount);
|
|
1314
945
|
const diff = BigInt(toDecimals) - BigInt(fromDecimals);
|
|
@@ -1431,88 +1062,7 @@ function useBridgeQuote() {
|
|
|
1431
1062
|
return;
|
|
1432
1063
|
}
|
|
1433
1064
|
if (cancelled) return;
|
|
1434
|
-
|
|
1435
|
-
if (quoteRoute.srcChainKey.toLowerCase() === "ton") {
|
|
1436
|
-
try {
|
|
1437
|
-
const estimatedFee = estimateTonNetworkFee(quoteRoute);
|
|
1438
|
-
quoteWithFees = addTonNetworkFee(quoteRoute, chains, estimatedFee);
|
|
1439
|
-
} catch (error) {
|
|
1440
|
-
console.warn("Failed to estimate TON fee, using fallback:", error);
|
|
1441
|
-
quoteWithFees = addTonNetworkFee(quoteRoute, chains);
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
if (quoteRoute.srcChainKey.toLowerCase() === "tron") {
|
|
1445
|
-
const tronStrategy = chainRegistry.getStrategy("tron");
|
|
1446
|
-
if (tronStrategy?.isConnected()) {
|
|
1447
|
-
const tronWeb = tronStrategy.getClient();
|
|
1448
|
-
const tronAddress = tronStrategy.getAccount();
|
|
1449
|
-
if (tronWeb && tronAddress) {
|
|
1450
|
-
try {
|
|
1451
|
-
const estimatedFee = await estimateTronNetworkFee(
|
|
1452
|
-
tronWeb,
|
|
1453
|
-
quoteRoute,
|
|
1454
|
-
tronAddress
|
|
1455
|
-
);
|
|
1456
|
-
quoteWithFees = addTronNetworkFee(
|
|
1457
|
-
quoteWithFees || quoteRoute,
|
|
1458
|
-
chains,
|
|
1459
|
-
estimatedFee
|
|
1460
|
-
);
|
|
1461
|
-
} catch (error) {
|
|
1462
|
-
console.warn(
|
|
1463
|
-
"Failed to estimate TRON fee, using fallback:",
|
|
1464
|
-
error
|
|
1465
|
-
);
|
|
1466
|
-
quoteWithFees = addTronNetworkFee(
|
|
1467
|
-
quoteWithFees || quoteRoute,
|
|
1468
|
-
chains
|
|
1469
|
-
);
|
|
1470
|
-
}
|
|
1471
|
-
} else {
|
|
1472
|
-
quoteWithFees = addTronNetworkFee(
|
|
1473
|
-
quoteWithFees || quoteRoute,
|
|
1474
|
-
chains
|
|
1475
|
-
);
|
|
1476
|
-
}
|
|
1477
|
-
} else {
|
|
1478
|
-
quoteWithFees = addTronNetworkFee(
|
|
1479
|
-
quoteWithFees || quoteRoute,
|
|
1480
|
-
chains
|
|
1481
|
-
);
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
const srcChainKey = quoteRoute.srcChainKey.toLowerCase();
|
|
1485
|
-
if (srcChainKey !== "ton" && srcChainKey !== "tron") {
|
|
1486
|
-
if (publicClient) {
|
|
1487
|
-
try {
|
|
1488
|
-
const estimatedFee = await estimateEvmNetworkFee(
|
|
1489
|
-
publicClient,
|
|
1490
|
-
quoteRoute,
|
|
1491
|
-
quoteRoute.srcChainKey
|
|
1492
|
-
);
|
|
1493
|
-
quoteWithFees = addEvmNetworkFee(
|
|
1494
|
-
quoteWithFees || quoteRoute,
|
|
1495
|
-
chains,
|
|
1496
|
-
estimatedFee
|
|
1497
|
-
);
|
|
1498
|
-
} catch (error) {
|
|
1499
|
-
console.warn(
|
|
1500
|
-
"Failed to estimate EVM fee, using fallback:",
|
|
1501
|
-
error
|
|
1502
|
-
);
|
|
1503
|
-
quoteWithFees = addEvmNetworkFee(
|
|
1504
|
-
quoteWithFees || quoteRoute,
|
|
1505
|
-
chains
|
|
1506
|
-
);
|
|
1507
|
-
}
|
|
1508
|
-
} else {
|
|
1509
|
-
quoteWithFees = addEvmNetworkFee(
|
|
1510
|
-
quoteWithFees || quoteRoute,
|
|
1511
|
-
chains
|
|
1512
|
-
);
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
setQuote(quoteWithFees || quoteRoute);
|
|
1065
|
+
setQuote(quoteRoute);
|
|
1516
1066
|
} catch {
|
|
1517
1067
|
if (!cancelled) {
|
|
1518
1068
|
resetUi();
|
|
@@ -2693,6 +2243,48 @@ const useWalletSelectModal = create((set2) => ({
|
|
|
2693
2243
|
onOpen: (addressType) => set2({ isOpen: true, addressType }),
|
|
2694
2244
|
onClose: () => set2({ isOpen: false, addressType: void 0 })
|
|
2695
2245
|
}));
|
|
2246
|
+
const truncateToDecimals = (num, decimals) => {
|
|
2247
|
+
if (!isFinite(num) || isNaN(num)) return "0";
|
|
2248
|
+
const multiplier = Math.pow(10, decimals);
|
|
2249
|
+
const truncated = Math.floor(num * multiplier) / multiplier;
|
|
2250
|
+
return truncated.toFixed(decimals).replace(/\.?0+$/, "");
|
|
2251
|
+
};
|
|
2252
|
+
const formatTokenAmount = (amount, symbol, options) => {
|
|
2253
|
+
const normalizedSymbol = (symbol ?? "").toUpperCase();
|
|
2254
|
+
if (["USDT", "USDC", "DAI", "BUSD"].includes(normalizedSymbol) && amount >= 1) {
|
|
2255
|
+
return `${Math.floor(amount)} ${normalizedSymbol}`;
|
|
2256
|
+
}
|
|
2257
|
+
if (options?.decimals !== void 0) {
|
|
2258
|
+
return `${amount.toFixed(options.decimals)} ${normalizedSymbol}`;
|
|
2259
|
+
}
|
|
2260
|
+
if (amount >= 1) {
|
|
2261
|
+
return `${amount.toFixed(0)} ${normalizedSymbol}`;
|
|
2262
|
+
} else if (amount >= 1e-3) {
|
|
2263
|
+
return `${amount.toFixed(3)} ${normalizedSymbol}`;
|
|
2264
|
+
} else {
|
|
2265
|
+
return `${amount.toFixed(6)} ${normalizedSymbol}`;
|
|
2266
|
+
}
|
|
2267
|
+
};
|
|
2268
|
+
const formatUsd = (value) => {
|
|
2269
|
+
if (!value || !isFinite(value)) return "$0";
|
|
2270
|
+
if (value >= 1) return `$${value.toFixed(2)}`;
|
|
2271
|
+
return `$${value.toFixed(6).replace(/0+$/, "").replace(/\.$/, "")}`;
|
|
2272
|
+
};
|
|
2273
|
+
const formatPercentage = (bps, decimals = 2) => {
|
|
2274
|
+
return `${(bps / 100).toFixed(decimals).replace(/0+$/, "").replace(/\.$/, "")}%`;
|
|
2275
|
+
};
|
|
2276
|
+
const formatBalance = (amount, decimals = 2) => {
|
|
2277
|
+
if (!isFinite(amount) || isNaN(amount) || amount <= 0) {
|
|
2278
|
+
return "0.00";
|
|
2279
|
+
}
|
|
2280
|
+
return amount.toFixed(decimals);
|
|
2281
|
+
};
|
|
2282
|
+
const formatHash = (hash, startChars = 4, endChars = 4) => {
|
|
2283
|
+
if (!hash) return "";
|
|
2284
|
+
if (hash.length <= startChars + endChars) return hash;
|
|
2285
|
+
return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
|
|
2286
|
+
};
|
|
2287
|
+
const formatAddress = formatHash;
|
|
2696
2288
|
const EditIcon = (props) => {
|
|
2697
2289
|
return /* @__PURE__ */ jsxs(
|
|
2698
2290
|
"svg",
|
|
@@ -3118,8 +2710,8 @@ const InfoIcon = (props) => {
|
|
|
3118
2710
|
{
|
|
3119
2711
|
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",
|
|
3120
2712
|
stroke: "currentColor",
|
|
3121
|
-
|
|
3122
|
-
|
|
2713
|
+
strokeWidth: "1.68349",
|
|
2714
|
+
strokeLinecap: "round"
|
|
3123
2715
|
}
|
|
3124
2716
|
)
|
|
3125
2717
|
}
|
|
@@ -3142,6 +2734,96 @@ const TokenSymbol = ({
|
|
|
3142
2734
|
const src2 = `${BASE_URL}/${normalizedSymbol}.svg`;
|
|
3143
2735
|
return /* @__PURE__ */ jsx("img", { src: src2, alt: alt ?? symbol, className });
|
|
3144
2736
|
};
|
|
2737
|
+
function getQuoteAmounts(quote, srcToken, dstToken) {
|
|
2738
|
+
if (!quote || !srcToken || !dstToken) {
|
|
2739
|
+
return {
|
|
2740
|
+
inputHuman: 0,
|
|
2741
|
+
outputHuman: 0,
|
|
2742
|
+
outputHumanRounded: "0",
|
|
2743
|
+
minReceivedHuman: 0
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
const inputHuman = fromLD(quote.srcAmount, srcToken.decimals);
|
|
2747
|
+
const outputHuman = fromLD(quote.dstAmount, dstToken.decimals);
|
|
2748
|
+
const outputHumanRounded = truncateToDecimals(outputHuman, 2);
|
|
2749
|
+
const minReceivedHuman = fromLD(quote.dstAmountMin || "0", dstToken.decimals);
|
|
2750
|
+
return {
|
|
2751
|
+
inputHuman,
|
|
2752
|
+
outputHuman,
|
|
2753
|
+
outputHumanRounded,
|
|
2754
|
+
minReceivedHuman
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
function getQuoteFees(quote, tokens, chains, srcToken, dstToken) {
|
|
2758
|
+
if (!quote || !tokens || !chains) {
|
|
2759
|
+
return {
|
|
2760
|
+
fees: { usd: /* @__PURE__ */ new Map(), original: /* @__PURE__ */ new Map(), formatted: /* @__PURE__ */ new Map() },
|
|
2761
|
+
inSrcToken: void 0,
|
|
2762
|
+
inDstToken: void 0
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
const feeData = computeFeesUsdFromArray(quote.fees, tokens, chains);
|
|
2766
|
+
let inSrcToken = void 0;
|
|
2767
|
+
let inDstToken = void 0;
|
|
2768
|
+
if (srcToken && quote.srcChainKey) {
|
|
2769
|
+
const feeInSrcLD = sumFeeByTokenLD(
|
|
2770
|
+
quote.fees,
|
|
2771
|
+
srcToken.address,
|
|
2772
|
+
quote.srcChainKey
|
|
2773
|
+
);
|
|
2774
|
+
const feeInSrcHuman = fromLD(feeInSrcLD, srcToken.decimals);
|
|
2775
|
+
if (feeInSrcHuman > 0) {
|
|
2776
|
+
inSrcToken = Number(truncateToDecimals(feeInSrcHuman, 8));
|
|
2777
|
+
} else if ((feeData.usd.get("total") || 0) > 0 && srcToken.price?.usd) {
|
|
2778
|
+
const feeInSrcApprox = (feeData.usd.get("total") || 0) / srcToken.price.usd;
|
|
2779
|
+
inSrcToken = Number(truncateToDecimals(feeInSrcApprox, 8));
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
if (dstToken && quote.dstChainKey) {
|
|
2783
|
+
const feeInDstLD = sumFeeByTokenLD(
|
|
2784
|
+
quote.fees,
|
|
2785
|
+
dstToken.address,
|
|
2786
|
+
quote.dstChainKey
|
|
2787
|
+
);
|
|
2788
|
+
const feeInDstHuman = fromLD(feeInDstLD, dstToken.decimals);
|
|
2789
|
+
if (feeInDstHuman > 0) {
|
|
2790
|
+
inDstToken = Number(truncateToDecimals(feeInDstHuman, 8));
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
return {
|
|
2794
|
+
fees: feeData,
|
|
2795
|
+
inSrcToken,
|
|
2796
|
+
inDstToken
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
function calculateMinReceived(quote, slippageBps, dstToken) {
|
|
2800
|
+
if (!quote || !dstToken) return 0;
|
|
2801
|
+
const dstAmountLD = BigInt(quote.dstAmount);
|
|
2802
|
+
const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
|
|
2803
|
+
return fromLD(minAmountLD.toString(), dstToken.decimals);
|
|
2804
|
+
}
|
|
2805
|
+
function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
|
|
2806
|
+
const amounts = getQuoteAmounts(quote, srcToken, dstToken);
|
|
2807
|
+
const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
|
|
2808
|
+
const minimumReceived = calculateMinReceived(quote, slippageBps, dstToken);
|
|
2809
|
+
return {
|
|
2810
|
+
inputAmount: amounts.inputHuman,
|
|
2811
|
+
outputAmount: amounts.outputHuman,
|
|
2812
|
+
outputAmountRounded: amounts.outputHumanRounded,
|
|
2813
|
+
minimumReceived,
|
|
2814
|
+
etaSeconds: quote?.duration?.estimated,
|
|
2815
|
+
fees
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
function getRouteDisplayName(route) {
|
|
2819
|
+
if (!route) return "Stargate Bridge";
|
|
2820
|
+
const routeLower = route.toLowerCase();
|
|
2821
|
+
if (routeLower.includes("taxi")) return "Stargate V2 Fast";
|
|
2822
|
+
if (routeLower.includes("bus")) return "Stargate V2 Economy";
|
|
2823
|
+
if (routeLower.includes("oft")) return "OFT Bridge";
|
|
2824
|
+
if (routeLower.includes("v2")) return "Stargate V2";
|
|
2825
|
+
return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
2826
|
+
}
|
|
3145
2827
|
function useGasEstimate(amountNum) {
|
|
3146
2828
|
const { fromChain } = useChainsStore();
|
|
3147
2829
|
const { selectedAssetSymbol } = useTokensStore();
|
|
@@ -3151,6 +2833,9 @@ function useGasEstimate(amountNum) {
|
|
|
3151
2833
|
srcAddress
|
|
3152
2834
|
);
|
|
3153
2835
|
const { quote } = useBridgeQuoteStore();
|
|
2836
|
+
const { chainRegistry } = useChainStrategies();
|
|
2837
|
+
const [networkFeeEstimate, setNetworkFeeEstimate] = useState(0);
|
|
2838
|
+
const [networkFeeKnown, setNetworkFeeKnown] = useState(false);
|
|
3154
2839
|
const balancesKnown = !balancesLoading;
|
|
3155
2840
|
const chainKey = fromChain?.chainKey;
|
|
3156
2841
|
const nativeCurrencySymbol = fromChain?.nativeCurrency?.symbol;
|
|
@@ -3159,6 +2844,42 @@ function useGasEstimate(amountNum) {
|
|
|
3159
2844
|
const quoteFees = quote?.fees;
|
|
3160
2845
|
const quoteSrcChainKey = quote?.srcChainKey;
|
|
3161
2846
|
const nativeBalanceValue = nativeCurrencySymbol ? Number(balances[nativeCurrencySymbol.toUpperCase()]?.balance ?? 0) : 0;
|
|
2847
|
+
useEffect(() => {
|
|
2848
|
+
let cancelled = false;
|
|
2849
|
+
const estimate = async () => {
|
|
2850
|
+
setNetworkFeeEstimate(0);
|
|
2851
|
+
setNetworkFeeKnown(false);
|
|
2852
|
+
if (!chainKey || !quote?.steps?.length) {
|
|
2853
|
+
return;
|
|
2854
|
+
}
|
|
2855
|
+
const strategy = chainRegistry.getStrategy(chainKey);
|
|
2856
|
+
if (!strategy) {
|
|
2857
|
+
setNetworkFeeKnown(true);
|
|
2858
|
+
return;
|
|
2859
|
+
}
|
|
2860
|
+
const steps = quote.steps.filter((step) => step.chainKey === chainKey);
|
|
2861
|
+
if (!steps.length) {
|
|
2862
|
+
setNetworkFeeKnown(true);
|
|
2863
|
+
return;
|
|
2864
|
+
}
|
|
2865
|
+
try {
|
|
2866
|
+
const estimateValue = await strategy.estimateNetworkFee(steps);
|
|
2867
|
+
if (cancelled) return;
|
|
2868
|
+
setNetworkFeeEstimate(Number.isFinite(estimateValue) ? estimateValue : 0);
|
|
2869
|
+
} catch {
|
|
2870
|
+
if (cancelled) return;
|
|
2871
|
+
setNetworkFeeEstimate(0);
|
|
2872
|
+
} finally {
|
|
2873
|
+
if (!cancelled) {
|
|
2874
|
+
setNetworkFeeKnown(true);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
};
|
|
2878
|
+
void estimate();
|
|
2879
|
+
return () => {
|
|
2880
|
+
cancelled = true;
|
|
2881
|
+
};
|
|
2882
|
+
}, [chainKey, quote?.steps, chainRegistry]);
|
|
3162
2883
|
const result = useMemo(() => {
|
|
3163
2884
|
if (!chainKey || !nativeCurrencySymbol) {
|
|
3164
2885
|
return {
|
|
@@ -3178,7 +2899,7 @@ function useGasEstimate(amountNum) {
|
|
|
3178
2899
|
if (quoteFees && quoteSrcChainKey === chainKey) {
|
|
3179
2900
|
const fees = quoteFees;
|
|
3180
2901
|
const feesInNative = fees.filter(
|
|
3181
|
-
(f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress
|
|
2902
|
+
(f4) => f4.chainKey === chainKey && f4.token === nativeCurrencyAddress
|
|
3182
2903
|
).reduce(
|
|
3183
2904
|
(sum, f4) => sum + BigInt(f4.amount || "0"),
|
|
3184
2905
|
0n
|
|
@@ -3187,13 +2908,16 @@ function useGasEstimate(amountNum) {
|
|
|
3187
2908
|
requiredNative = Number(feesInNative) / Math.pow(10, decimals);
|
|
3188
2909
|
quoteFeesAvailable = true;
|
|
3189
2910
|
}
|
|
2911
|
+
if (networkFeeKnown) {
|
|
2912
|
+
requiredNative += networkFeeEstimate;
|
|
2913
|
+
}
|
|
3190
2914
|
let hasEnoughGas = true;
|
|
3191
2915
|
if (isNativeSelected) {
|
|
3192
2916
|
hasEnoughGas = nativeBalance - (amountNum ?? 0) >= requiredNative;
|
|
3193
2917
|
} else {
|
|
3194
2918
|
hasEnoughGas = nativeBalance >= requiredNative;
|
|
3195
2919
|
}
|
|
3196
|
-
const shouldCheckGas = balancesKnown && quoteFeesAvailable;
|
|
2920
|
+
const shouldCheckGas = balancesKnown && quoteFeesAvailable && networkFeeKnown;
|
|
3197
2921
|
return {
|
|
3198
2922
|
nativeSym,
|
|
3199
2923
|
nativeBalance,
|
|
@@ -3212,7 +2936,9 @@ function useGasEstimate(amountNum) {
|
|
|
3212
2936
|
quoteSrcChainKey,
|
|
3213
2937
|
amountNum,
|
|
3214
2938
|
balancesKnown,
|
|
3215
|
-
nativeBalanceValue
|
|
2939
|
+
nativeBalanceValue,
|
|
2940
|
+
networkFeeEstimate,
|
|
2941
|
+
networkFeeKnown
|
|
3216
2942
|
]);
|
|
3217
2943
|
return result;
|
|
3218
2944
|
}
|
|
@@ -3621,33 +3347,6 @@ class TransactionFailedError extends ChainStrategyError {
|
|
|
3621
3347
|
this.txHash = txHash;
|
|
3622
3348
|
}
|
|
3623
3349
|
}
|
|
3624
|
-
class TransactionTimeoutError extends ChainStrategyError {
|
|
3625
|
-
constructor(chainKey, txHash) {
|
|
3626
|
-
super(
|
|
3627
|
-
`${chainKey.toUpperCase()} transaction confirmation timeout: ${txHash}`,
|
|
3628
|
-
"TRANSACTION_TIMEOUT",
|
|
3629
|
-
chainKey
|
|
3630
|
-
);
|
|
3631
|
-
__publicField(this, "txHash");
|
|
3632
|
-
this.name = "TransactionTimeoutError";
|
|
3633
|
-
this.txHash = txHash;
|
|
3634
|
-
}
|
|
3635
|
-
}
|
|
3636
|
-
class TransactionRevertedError extends ChainStrategyError {
|
|
3637
|
-
constructor(chainKey, txHash, revertReason) {
|
|
3638
|
-
const reason = revertReason ? `: ${revertReason}` : "";
|
|
3639
|
-
super(
|
|
3640
|
-
`${chainKey.toUpperCase()} transaction reverted on-chain${reason}`,
|
|
3641
|
-
"TRANSACTION_REVERTED",
|
|
3642
|
-
chainKey
|
|
3643
|
-
);
|
|
3644
|
-
__publicField(this, "txHash");
|
|
3645
|
-
__publicField(this, "revertReason");
|
|
3646
|
-
this.name = "TransactionRevertedError";
|
|
3647
|
-
this.txHash = txHash;
|
|
3648
|
-
this.revertReason = revertReason;
|
|
3649
|
-
}
|
|
3650
|
-
}
|
|
3651
3350
|
class ProviderNotAvailableError extends ChainStrategyError {
|
|
3652
3351
|
constructor(chainKey, reason) {
|
|
3653
3352
|
const message = reason ? `${chainKey.toUpperCase()} provider not available: ${reason}` : `${chainKey.toUpperCase()} provider not available`;
|
|
@@ -3704,6 +3403,38 @@ async function getLayerZeroMessageByTx(txHash) {
|
|
|
3704
3403
|
return null;
|
|
3705
3404
|
}
|
|
3706
3405
|
}
|
|
3406
|
+
async function waitForLayerZeroCompletion(txHash, timeoutMs = 6e5, pollIntervalMs = 1e4) {
|
|
3407
|
+
const deadline = Date.now() + timeoutMs;
|
|
3408
|
+
while (Date.now() < deadline) {
|
|
3409
|
+
try {
|
|
3410
|
+
const message = await getLayerZeroMessageByTx(txHash);
|
|
3411
|
+
if (message) {
|
|
3412
|
+
const statusName = message.status?.name;
|
|
3413
|
+
if (statusName === "DELIVERED") {
|
|
3414
|
+
return {
|
|
3415
|
+
completed: true,
|
|
3416
|
+
status: "DELIVERED",
|
|
3417
|
+
dstTxHash: message.destination?.tx?.txHash,
|
|
3418
|
+
message
|
|
3419
|
+
};
|
|
3420
|
+
}
|
|
3421
|
+
if (statusName === "FAILED") {
|
|
3422
|
+
return {
|
|
3423
|
+
completed: false,
|
|
3424
|
+
status: "FAILED",
|
|
3425
|
+
message
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
} catch {
|
|
3430
|
+
}
|
|
3431
|
+
await new Promise((r2) => setTimeout(r2, pollIntervalMs));
|
|
3432
|
+
}
|
|
3433
|
+
return {
|
|
3434
|
+
completed: false,
|
|
3435
|
+
status: "TIMEOUT"
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3707
3438
|
function useBridgeTransaction() {
|
|
3708
3439
|
const { quote } = useBridgeQuoteStore();
|
|
3709
3440
|
const { chainRegistry } = useChainStrategies();
|
|
@@ -3779,59 +3510,76 @@ function useBridgeTransaction() {
|
|
|
3779
3510
|
txStore.setSrcHash(hash);
|
|
3780
3511
|
txStore.updateStatus("processing");
|
|
3781
3512
|
});
|
|
3782
|
-
if (txResult?.tonTransactionHash) {
|
|
3783
|
-
txStore.setTonTransactionHash(txResult.tonTransactionHash);
|
|
3784
|
-
}
|
|
3785
3513
|
if (txResult?.hash) {
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3514
|
+
const trackWithLayerZero = async () => {
|
|
3515
|
+
let hashForLayerZero = txResult.hash;
|
|
3516
|
+
const messageHash = txResult.hash;
|
|
3517
|
+
if (quote.srcChainKey === "ton" && strategy.convertMessageHashToTxHash) {
|
|
3518
|
+
const tonTxHash = await strategy.convertMessageHashToTxHash(
|
|
3519
|
+
messageHash,
|
|
3520
|
+
6e4
|
|
3521
|
+
);
|
|
3522
|
+
if (tonTxHash) {
|
|
3523
|
+
hashForLayerZero = tonTxHash;
|
|
3524
|
+
txStore.setTonTransactionHash(tonTxHash);
|
|
3525
|
+
} else {
|
|
3526
|
+
console.warn("Failed to convert TON message hash to tx hash");
|
|
3790
3527
|
}
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
txStore.updateActualFee(feeValue, feeSymbol);
|
|
3802
|
-
}
|
|
3528
|
+
}
|
|
3529
|
+
const lzResult = await waitForLayerZeroCompletion(
|
|
3530
|
+
hashForLayerZero,
|
|
3531
|
+
6e5,
|
|
3532
|
+
1e4
|
|
3533
|
+
);
|
|
3534
|
+
console.log("LayerZero delivery status:", lzResult.status);
|
|
3535
|
+
if (lzResult.completed) {
|
|
3536
|
+
if (lzResult.dstTxHash) {
|
|
3537
|
+
txStore.setDstHash(lzResult.dstTxHash);
|
|
3803
3538
|
}
|
|
3804
|
-
|
|
3805
|
-
console.log("Transaction completed successfully");
|
|
3806
|
-
if (txResult.hash && strategy.getSourceCost) {
|
|
3539
|
+
if (strategy.getSourceCost) {
|
|
3807
3540
|
const srcChain2 = chains?.find(
|
|
3808
3541
|
(c2) => c2.chainKey === quote.srcChainKey
|
|
3809
3542
|
);
|
|
3810
3543
|
const feeSymbol = srcChain2?.nativeCurrency?.symbol || "";
|
|
3811
3544
|
const { priceUsd } = findNativeMeta(allTokens, srcChain2);
|
|
3812
|
-
const
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
}).then((sourceTxHash) => getSourceCost(sourceTxHash)).then((sourceCost) => {
|
|
3545
|
+
const hashForSourceCost = quote.srcChainKey === "ton" ? messageHash : hashForLayerZero;
|
|
3546
|
+
try {
|
|
3547
|
+
const sourceCost = await strategy.getSourceCost(
|
|
3548
|
+
hashForSourceCost
|
|
3549
|
+
);
|
|
3818
3550
|
if (sourceCost?.totalNative !== void 0 && isFinite(sourceCost.totalNative)) {
|
|
3819
3551
|
const feeUsd = priceUsd && priceUsd > 0 ? sourceCost.totalNative * priceUsd : void 0;
|
|
3552
|
+
console.log("Source cost calculated:", {
|
|
3553
|
+
gasFee: sourceCost.breakdown?.gasFee + " " + feeSymbol,
|
|
3554
|
+
layerZeroFee: sourceCost.breakdown?.layerZeroFee + " " + feeSymbol,
|
|
3555
|
+
total: sourceCost.totalNative + " " + feeSymbol,
|
|
3556
|
+
totalUsd: feeUsd ? "$" + feeUsd.toFixed(2) : "N/A"
|
|
3557
|
+
});
|
|
3820
3558
|
txStore.updateLayerZeroTotalFee(
|
|
3821
3559
|
sourceCost.totalNative,
|
|
3822
3560
|
feeSymbol,
|
|
3823
3561
|
feeUsd
|
|
3824
3562
|
);
|
|
3825
3563
|
}
|
|
3826
|
-
}
|
|
3827
|
-
console.warn("Failed to compute
|
|
3828
|
-
}
|
|
3564
|
+
} catch (error) {
|
|
3565
|
+
console.warn("Failed to compute source cost:", error);
|
|
3566
|
+
}
|
|
3829
3567
|
}
|
|
3568
|
+
txStore.updateStatus("completed");
|
|
3569
|
+
console.log("Transaction completed successfully via LayerZero");
|
|
3830
3570
|
} else {
|
|
3831
|
-
|
|
3832
|
-
|
|
3571
|
+
if (lzResult.status === "FAILED") {
|
|
3572
|
+
txStore.setError("TRANSACTION_FAILED_TO_COMPLETE");
|
|
3573
|
+
console.error("LayerZero delivery failed");
|
|
3574
|
+
} else {
|
|
3575
|
+
txStore.updateStatus("completed");
|
|
3576
|
+
console.warn(
|
|
3577
|
+
"LayerZero tracking timed out, marking as completed"
|
|
3578
|
+
);
|
|
3579
|
+
}
|
|
3833
3580
|
}
|
|
3834
|
-
}
|
|
3581
|
+
};
|
|
3582
|
+
trackWithLayerZero().catch((err) => {
|
|
3835
3583
|
if (isUserRejection(err)) {
|
|
3836
3584
|
txStore.setError("TRANSACTION_REJECTED");
|
|
3837
3585
|
} else if (ChainStrategyError.isChainStrategyError(err)) {
|
|
@@ -4931,11 +4679,60 @@ class ChainStrategyRegistry {
|
|
|
4931
4679
|
await strategy.disconnect(options);
|
|
4932
4680
|
}
|
|
4933
4681
|
}
|
|
4682
|
+
const EVM_CONFIG = {
|
|
4683
|
+
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
4684
|
+
gasEstimates: {
|
|
4685
|
+
approve: 65000n,
|
|
4686
|
+
bridge: 300000n
|
|
4687
|
+
},
|
|
4688
|
+
gasBuffer: 1.2,
|
|
4689
|
+
// 20% buffer
|
|
4690
|
+
gasFeeMultiplier: 2,
|
|
4691
|
+
// Multiplier for wallet fee estimates
|
|
4692
|
+
timeout: 3e5,
|
|
4693
|
+
// 5 minutes (increased for slower networks)
|
|
4694
|
+
requiredConfirmations: 3
|
|
4695
|
+
// Wait for 3 confirmations for reorg protection
|
|
4696
|
+
};
|
|
4697
|
+
const TON_CONFIG = {
|
|
4698
|
+
apiUrl: "https://toncenter.com/api/v2",
|
|
4699
|
+
timeout: 36e4,
|
|
4700
|
+
// 6 minutes
|
|
4701
|
+
validUntil: 600,
|
|
4702
|
+
// 10 minutes
|
|
4703
|
+
pollingInterval: 5e3,
|
|
4704
|
+
// 5 seconds between transaction status checks
|
|
4705
|
+
estimatedNetworkFee: "1000000000"
|
|
4706
|
+
// 1 TON in nanoton (conservative estimate)
|
|
4707
|
+
};
|
|
4708
|
+
const TRON_CONFIG = {
|
|
4709
|
+
// 2 minutes (for 19 confirmations)
|
|
4710
|
+
feeLimit: 1e8,
|
|
4711
|
+
// 3 seconds between checks
|
|
4712
|
+
estimatedNetworkFee: "10000000"
|
|
4713
|
+
// 10 TRX in SUN (fallback estimate)
|
|
4714
|
+
};
|
|
4715
|
+
let tonClientInstance = null;
|
|
4716
|
+
function getTonClient(customClient, apiKey) {
|
|
4717
|
+
if (customClient) {
|
|
4718
|
+
return customClient;
|
|
4719
|
+
}
|
|
4720
|
+
if (!tonClientInstance) {
|
|
4721
|
+
tonClientInstance = new TonClient({
|
|
4722
|
+
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
4723
|
+
apiKey
|
|
4724
|
+
});
|
|
4725
|
+
}
|
|
4726
|
+
return tonClientInstance;
|
|
4727
|
+
}
|
|
4934
4728
|
function isNativeAddress(addr) {
|
|
4935
4729
|
if (!addr) return false;
|
|
4936
4730
|
const a2 = addr.toLowerCase();
|
|
4937
4731
|
return a2 === "native" || a2 === "0x0000000000000000000000000000000000000000" || a2 === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" || addr === "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb";
|
|
4938
4732
|
}
|
|
4733
|
+
function sleep(ms2) {
|
|
4734
|
+
return new Promise((resolve) => setTimeout(resolve, ms2));
|
|
4735
|
+
}
|
|
4939
4736
|
function toTronBase58(addr, tronWeb) {
|
|
4940
4737
|
if (!addr) throw new Error("Empty TRON address");
|
|
4941
4738
|
if (addr.startsWith("T")) return addr;
|
|
@@ -4982,24 +4779,27 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
4982
4779
|
if (!publicClient) {
|
|
4983
4780
|
throw new Error("No public client provided");
|
|
4984
4781
|
}
|
|
4985
|
-
const nativeTokens = tokens.filter((t2) => isNativeAddress(t2.address));
|
|
4986
4782
|
const erc20Tokens = tokens.filter(
|
|
4987
4783
|
(t2) => !isNativeAddress(t2.address) && isAddress(t2.address)
|
|
4988
4784
|
);
|
|
4989
|
-
|
|
4785
|
+
const chainNative = publicClient.chain?.nativeCurrency;
|
|
4786
|
+
const nativeSymbol = chainNative?.symbol ?? "ETH";
|
|
4787
|
+
const nativeDecimals = chainNative?.decimals ?? 18;
|
|
4788
|
+
const maxAttempts = 2;
|
|
4789
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
4990
4790
|
try {
|
|
4991
|
-
const
|
|
4791
|
+
const nativeBalance = await publicClient.getBalance({
|
|
4992
4792
|
address
|
|
4993
4793
|
});
|
|
4994
|
-
const balance = parseFloat(formatUnits(
|
|
4794
|
+
const balance = parseFloat(formatUnits(nativeBalance, nativeDecimals));
|
|
4995
4795
|
if (balance > 0) {
|
|
4996
|
-
balances[
|
|
4796
|
+
balances[nativeSymbol] = { balance, address };
|
|
4797
|
+
}
|
|
4798
|
+
break;
|
|
4799
|
+
} catch {
|
|
4800
|
+
if (attempt !== maxAttempts) {
|
|
4801
|
+
await sleep(250 * attempt);
|
|
4997
4802
|
}
|
|
4998
|
-
} catch (error) {
|
|
4999
|
-
console.debug(
|
|
5000
|
-
`Failed to get native balance for ${token.symbol}:`,
|
|
5001
|
-
error
|
|
5002
|
-
);
|
|
5003
4803
|
}
|
|
5004
4804
|
}
|
|
5005
4805
|
if (erc20Tokens.length > 0) {
|
|
@@ -5033,11 +4833,7 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
5033
4833
|
if (balance > 0) {
|
|
5034
4834
|
balances[token.symbol] = { balance, address };
|
|
5035
4835
|
}
|
|
5036
|
-
} catch
|
|
5037
|
-
console.debug(
|
|
5038
|
-
`Failed to parse balance for ${token.symbol}:`,
|
|
5039
|
-
error
|
|
5040
|
-
);
|
|
4836
|
+
} catch {
|
|
5041
4837
|
}
|
|
5042
4838
|
}
|
|
5043
4839
|
});
|
|
@@ -5068,8 +4864,7 @@ async function getEvmBalances(publicClient, address, tokens) {
|
|
|
5068
4864
|
if (balance > 0) {
|
|
5069
4865
|
balances[token.symbol] = { balance, address };
|
|
5070
4866
|
}
|
|
5071
|
-
} catch
|
|
5072
|
-
console.debug(`Failed to get balance for ${token.symbol}:`, error2);
|
|
4867
|
+
} catch {
|
|
5073
4868
|
}
|
|
5074
4869
|
}
|
|
5075
4870
|
}
|
|
@@ -5129,12 +4924,7 @@ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
|
|
|
5129
4924
|
balances[symbolNorm] = entry;
|
|
5130
4925
|
}
|
|
5131
4926
|
}
|
|
5132
|
-
} catch
|
|
5133
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5134
|
-
const isNoWalletError = errorMessage.includes("exit_code: -13") || errorMessage.includes("exit_code:-13") || errorMessage.includes("exitCode: -13");
|
|
5135
|
-
if (!isNoWalletError) {
|
|
5136
|
-
console.debug(`Failed to get balance for ${token.symbol}:`, error);
|
|
5137
|
-
}
|
|
4927
|
+
} catch {
|
|
5138
4928
|
}
|
|
5139
4929
|
}
|
|
5140
4930
|
} catch (error) {
|
|
@@ -5156,8 +4946,7 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
5156
4946
|
if (trxBalance > 0) {
|
|
5157
4947
|
balances.TRX = { balance: trxBalance, address: ownerB58 };
|
|
5158
4948
|
}
|
|
5159
|
-
} catch
|
|
5160
|
-
console.warn("Failed to get native TRX balance:", error);
|
|
4949
|
+
} catch {
|
|
5161
4950
|
}
|
|
5162
4951
|
for (const token of tokens) {
|
|
5163
4952
|
try {
|
|
@@ -5191,21 +4980,19 @@ async function getTronBalances(tronWeb, address, tokens) {
|
|
|
5191
4980
|
if (balance > 0) {
|
|
5192
4981
|
balances[token.symbol] = { balance, address: ownerB58 };
|
|
5193
4982
|
}
|
|
5194
|
-
} catch
|
|
5195
|
-
console.warn(`Failed to get TRON balance for ${token.symbol}:`, error);
|
|
4983
|
+
} catch {
|
|
5196
4984
|
}
|
|
5197
4985
|
}
|
|
5198
|
-
} catch
|
|
5199
|
-
console.error("Failed to get Tron balances:", error);
|
|
4986
|
+
} catch {
|
|
5200
4987
|
}
|
|
5201
4988
|
return balances;
|
|
5202
4989
|
}
|
|
5203
|
-
const ERC20_ABI = [
|
|
4990
|
+
const ERC20_ABI = parseAbi([
|
|
5204
4991
|
"function approve(address spender, uint256 amount) returns (bool)",
|
|
5205
4992
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
5206
4993
|
"function decimals() view returns (uint8)",
|
|
5207
4994
|
"function balanceOf(address owner) view returns (uint256)"
|
|
5208
|
-
];
|
|
4995
|
+
]);
|
|
5209
4996
|
class EvmChainStrategy {
|
|
5210
4997
|
constructor(config) {
|
|
5211
4998
|
__publicField(this, "config");
|
|
@@ -5253,14 +5040,9 @@ class EvmChainStrategy {
|
|
|
5253
5040
|
}
|
|
5254
5041
|
async getBalances(address, tokens) {
|
|
5255
5042
|
if (!this.publicClient) {
|
|
5256
|
-
console.warn("No publicClient available for balance query");
|
|
5257
5043
|
return {};
|
|
5258
5044
|
}
|
|
5259
|
-
return await getEvmBalances(
|
|
5260
|
-
this.publicClient,
|
|
5261
|
-
address,
|
|
5262
|
-
tokens
|
|
5263
|
-
);
|
|
5045
|
+
return await getEvmBalances(this.publicClient, address, tokens);
|
|
5264
5046
|
}
|
|
5265
5047
|
isAddressValid(address) {
|
|
5266
5048
|
if (!address) return false;
|
|
@@ -5296,7 +5078,6 @@ class EvmChainStrategy {
|
|
|
5296
5078
|
}
|
|
5297
5079
|
async getSourceCost(txHash) {
|
|
5298
5080
|
if (!this.publicClient) {
|
|
5299
|
-
console.warn("No publicClient available for source cost query");
|
|
5300
5081
|
return null;
|
|
5301
5082
|
}
|
|
5302
5083
|
try {
|
|
@@ -5311,18 +5092,61 @@ class EvmChainStrategy {
|
|
|
5311
5092
|
const gasFeeWei = gasUsed * gasPrice;
|
|
5312
5093
|
const txValueWei = tx.value ?? 0n;
|
|
5313
5094
|
const totalWei = gasFeeWei + txValueWei;
|
|
5314
|
-
|
|
5095
|
+
const sourceCost = {
|
|
5315
5096
|
totalNative: Number(formatUnits(totalWei, 18)),
|
|
5316
5097
|
breakdown: {
|
|
5317
5098
|
gasFee: Number(formatUnits(gasFeeWei, 18)),
|
|
5318
5099
|
layerZeroFee: Number(formatUnits(txValueWei, 18))
|
|
5319
5100
|
}
|
|
5320
5101
|
};
|
|
5102
|
+
return sourceCost;
|
|
5321
5103
|
} catch (error) {
|
|
5322
5104
|
console.warn("Failed to compute EVM source cost:", error);
|
|
5323
5105
|
return null;
|
|
5324
5106
|
}
|
|
5325
5107
|
}
|
|
5108
|
+
async estimateNetworkFee(steps) {
|
|
5109
|
+
if (!this.walletClient) {
|
|
5110
|
+
return 0;
|
|
5111
|
+
}
|
|
5112
|
+
const account = this.config.evmAddress;
|
|
5113
|
+
const txSteps = steps.filter((step) => step.transaction?.to);
|
|
5114
|
+
if (!txSteps.length) {
|
|
5115
|
+
return 0;
|
|
5116
|
+
}
|
|
5117
|
+
const applyFeeMultiplier = (feePerGas) => {
|
|
5118
|
+
const multiplier = EVM_CONFIG.gasFeeMultiplier;
|
|
5119
|
+
if (!Number.isFinite(multiplier) || multiplier <= 1) {
|
|
5120
|
+
return feePerGas;
|
|
5121
|
+
}
|
|
5122
|
+
const scaled = BigInt(Math.round(multiplier * 100));
|
|
5123
|
+
return (feePerGas * scaled + 99n) / 100n;
|
|
5124
|
+
};
|
|
5125
|
+
let totalFeeWei = 0n;
|
|
5126
|
+
for (const step of txSteps) {
|
|
5127
|
+
const tx = step.transaction;
|
|
5128
|
+
if (!tx?.to) continue;
|
|
5129
|
+
try {
|
|
5130
|
+
const request = await this.walletClient.prepareTransactionRequest({
|
|
5131
|
+
account: tx.from || account,
|
|
5132
|
+
to: tx.to,
|
|
5133
|
+
data: tx.data,
|
|
5134
|
+
value: tx.value ? BigInt(tx.value) : void 0,
|
|
5135
|
+
chain: this.walletClient.chain
|
|
5136
|
+
});
|
|
5137
|
+
const gasLimit = request.gas;
|
|
5138
|
+
const maxFeePerGas = request.maxFeePerGas ?? request.gasPrice;
|
|
5139
|
+
if (gasLimit && maxFeePerGas) {
|
|
5140
|
+
totalFeeWei += gasLimit * applyFeeMultiplier(maxFeePerGas);
|
|
5141
|
+
}
|
|
5142
|
+
} catch {
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
if (totalFeeWei === 0n) {
|
|
5146
|
+
return 0;
|
|
5147
|
+
}
|
|
5148
|
+
return Number(formatUnits(totalFeeWei, 18));
|
|
5149
|
+
}
|
|
5326
5150
|
async executeSteps(steps, _context, onFirstHash) {
|
|
5327
5151
|
if (!this.isConnected() || !this.walletClient) {
|
|
5328
5152
|
throw new WalletNotConnectedError("evm");
|
|
@@ -5336,14 +5160,12 @@ class EvmChainStrategy {
|
|
|
5336
5160
|
);
|
|
5337
5161
|
if (step.type === "approve") {
|
|
5338
5162
|
const hash = await this.approveTransaction(step);
|
|
5339
|
-
console.log(`Approval transaction hash: ${hash}`);
|
|
5340
5163
|
if (!firstTxHash) {
|
|
5341
5164
|
firstTxHash = hash;
|
|
5342
5165
|
onFirstHash?.(hash);
|
|
5343
5166
|
}
|
|
5344
5167
|
} else if (step.type === "bridge") {
|
|
5345
5168
|
const hash = await this.executeTransaction(step);
|
|
5346
|
-
console.log(`Bridge transaction hash: ${hash}`);
|
|
5347
5169
|
if (!firstTxHash) {
|
|
5348
5170
|
firstTxHash = hash;
|
|
5349
5171
|
onFirstHash?.(hash);
|
|
@@ -5366,106 +5188,6 @@ class EvmChainStrategy {
|
|
|
5366
5188
|
throw toChainStrategyError(error, "evm", "transaction");
|
|
5367
5189
|
}
|
|
5368
5190
|
}
|
|
5369
|
-
async waitForCompletion(txHash) {
|
|
5370
|
-
try {
|
|
5371
|
-
const publicClient = this.publicClient;
|
|
5372
|
-
if (!publicClient) {
|
|
5373
|
-
throw new ProviderNotAvailableError("evm");
|
|
5374
|
-
}
|
|
5375
|
-
console.log(
|
|
5376
|
-
`Waiting for ${EVM_CONFIG.requiredConfirmations} confirmations for tx: ${txHash}`
|
|
5377
|
-
);
|
|
5378
|
-
const receipt = await publicClient.waitForTransactionReceipt({
|
|
5379
|
-
hash: txHash,
|
|
5380
|
-
confirmations: EVM_CONFIG.requiredConfirmations,
|
|
5381
|
-
timeout: EVM_CONFIG.timeout
|
|
5382
|
-
});
|
|
5383
|
-
if (!receipt) {
|
|
5384
|
-
const error = new TransactionTimeoutError("evm", txHash);
|
|
5385
|
-
return {
|
|
5386
|
-
completed: false,
|
|
5387
|
-
error: error.message
|
|
5388
|
-
};
|
|
5389
|
-
}
|
|
5390
|
-
if (receipt.status !== "success") {
|
|
5391
|
-
const error = new TransactionRevertedError("evm", txHash);
|
|
5392
|
-
return {
|
|
5393
|
-
completed: false,
|
|
5394
|
-
error: error.message
|
|
5395
|
-
};
|
|
5396
|
-
}
|
|
5397
|
-
console.log(
|
|
5398
|
-
`EVM transaction confirmed in block ${receipt.blockNumber} with ${EVM_CONFIG.requiredConfirmations} confirmations`
|
|
5399
|
-
);
|
|
5400
|
-
let actualFeeValue;
|
|
5401
|
-
try {
|
|
5402
|
-
const gasUsed = receipt.gasUsed;
|
|
5403
|
-
const effectiveGasPrice = receipt.effectiveGasPrice;
|
|
5404
|
-
if (gasUsed && effectiveGasPrice) {
|
|
5405
|
-
const feeWei = gasUsed * effectiveGasPrice;
|
|
5406
|
-
const feeInNative = formatUnits(feeWei, 18);
|
|
5407
|
-
actualFeeValue = feeInNative;
|
|
5408
|
-
console.log(`EVM transaction fee: ${feeInNative} (native token)`);
|
|
5409
|
-
}
|
|
5410
|
-
} catch (error) {
|
|
5411
|
-
console.warn("Failed to calculate actual fee:", error);
|
|
5412
|
-
}
|
|
5413
|
-
return {
|
|
5414
|
-
completed: true,
|
|
5415
|
-
actualFeeValue
|
|
5416
|
-
// Symbol will be determined by the caller based on chain info
|
|
5417
|
-
};
|
|
5418
|
-
} catch (error) {
|
|
5419
|
-
if (error && typeof error === "object" && "code" in error && error.code === "TRANSACTION_REPLACED") {
|
|
5420
|
-
console.log(
|
|
5421
|
-
`Transaction was replaced: ${"reason" in error ? String(error.reason) : "unknown"}`
|
|
5422
|
-
);
|
|
5423
|
-
if ("receipt" in error && error.receipt) {
|
|
5424
|
-
const replacementReceipt = error.receipt;
|
|
5425
|
-
if (replacementReceipt.status === 1) {
|
|
5426
|
-
console.log(
|
|
5427
|
-
`Replacement transaction succeeded in block ${replacementReceipt.blockNumber}`
|
|
5428
|
-
);
|
|
5429
|
-
let actualFeeValue;
|
|
5430
|
-
try {
|
|
5431
|
-
const receipt = error.receipt;
|
|
5432
|
-
const gasUsed = receipt.gasUsed;
|
|
5433
|
-
const effectiveGasPrice = receipt.effectiveGasPrice;
|
|
5434
|
-
if (gasUsed && effectiveGasPrice) {
|
|
5435
|
-
const feeWei = gasUsed * effectiveGasPrice;
|
|
5436
|
-
const feeInNative = formatUnits(feeWei, 18);
|
|
5437
|
-
actualFeeValue = feeInNative;
|
|
5438
|
-
console.log(
|
|
5439
|
-
`Replacement transaction fee: ${feeInNative} (native token)`
|
|
5440
|
-
);
|
|
5441
|
-
}
|
|
5442
|
-
} catch (feeError) {
|
|
5443
|
-
console.warn("Failed to calculate replacement transaction fee:", feeError);
|
|
5444
|
-
}
|
|
5445
|
-
return {
|
|
5446
|
-
completed: true,
|
|
5447
|
-
actualFeeValue
|
|
5448
|
-
};
|
|
5449
|
-
} else {
|
|
5450
|
-
const chainError2 = new TransactionRevertedError("evm", txHash);
|
|
5451
|
-
return {
|
|
5452
|
-
completed: false,
|
|
5453
|
-
error: chainError2.message
|
|
5454
|
-
};
|
|
5455
|
-
}
|
|
5456
|
-
}
|
|
5457
|
-
}
|
|
5458
|
-
const chainError = toChainStrategyError(
|
|
5459
|
-
error,
|
|
5460
|
-
"evm",
|
|
5461
|
-
"waitForCompletion"
|
|
5462
|
-
);
|
|
5463
|
-
return {
|
|
5464
|
-
completed: false,
|
|
5465
|
-
error: chainError.message
|
|
5466
|
-
};
|
|
5467
|
-
}
|
|
5468
|
-
}
|
|
5469
5191
|
async executeTransaction(step) {
|
|
5470
5192
|
const walletClient = this.walletClient;
|
|
5471
5193
|
if (!walletClient) {
|
|
@@ -5620,88 +5342,14 @@ class EvmChainStrategy {
|
|
|
5620
5342
|
blockTag: "finalized"
|
|
5621
5343
|
});
|
|
5622
5344
|
if (!finalizedBlock) {
|
|
5623
|
-
console.debug(
|
|
5624
|
-
"Finalized block not available (pre-merge or unsupported)"
|
|
5625
|
-
);
|
|
5626
5345
|
return false;
|
|
5627
5346
|
}
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
console.log(
|
|
5631
|
-
`Block ${blockNumber} has reached finality (finalized block: ${finalizedBlock.number})`
|
|
5632
|
-
);
|
|
5633
|
-
} else {
|
|
5634
|
-
console.debug(
|
|
5635
|
-
`Block ${blockNumber} not yet finalized (finalized block: ${finalizedBlock.number})`
|
|
5636
|
-
);
|
|
5637
|
-
}
|
|
5638
|
-
return isFinalized;
|
|
5639
|
-
} catch (error) {
|
|
5640
|
-
console.debug("Error checking finality:", error);
|
|
5347
|
+
return blockNumber <= finalizedBlock.number;
|
|
5348
|
+
} catch {
|
|
5641
5349
|
return false;
|
|
5642
5350
|
}
|
|
5643
5351
|
}
|
|
5644
5352
|
}
|
|
5645
|
-
function getNormalizedExtMessageHash(message) {
|
|
5646
|
-
if (message.info.type !== "external-in") {
|
|
5647
|
-
throw new Error(`Expected external-in message, got ${message.info.type}`);
|
|
5648
|
-
}
|
|
5649
|
-
const normalizedInfo = {
|
|
5650
|
-
...message.info,
|
|
5651
|
-
src: void 0,
|
|
5652
|
-
importFee: 0n
|
|
5653
|
-
};
|
|
5654
|
-
const normalizedMessage = {
|
|
5655
|
-
...message,
|
|
5656
|
-
info: normalizedInfo,
|
|
5657
|
-
init: null
|
|
5658
|
-
};
|
|
5659
|
-
return beginCell$1().store(storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
|
|
5660
|
-
}
|
|
5661
|
-
async function getTonTransactionHash(messageHash, userAddress, searchLimit = 20, options) {
|
|
5662
|
-
try {
|
|
5663
|
-
const client = options?.client ?? new TonClient({
|
|
5664
|
-
endpoint: "https://toncenter.com/api/v2/jsonRPC",
|
|
5665
|
-
apiKey: process.env.TONCENTER_API_KEY
|
|
5666
|
-
// Optional: for rate limit increase
|
|
5667
|
-
});
|
|
5668
|
-
const messageHasher = options?.messageHasher ?? getNormalizedExtMessageHash;
|
|
5669
|
-
const address = Address.parse(userAddress);
|
|
5670
|
-
const transactions = await client.getTransactions(address, {
|
|
5671
|
-
limit: searchLimit
|
|
5672
|
-
});
|
|
5673
|
-
for (const tx of transactions) {
|
|
5674
|
-
const inMsg = tx.inMessage;
|
|
5675
|
-
if (!inMsg) continue;
|
|
5676
|
-
try {
|
|
5677
|
-
const inMsgHash = messageHasher(inMsg).toString("hex");
|
|
5678
|
-
if (inMsgHash === messageHash.replace("0x", "")) {
|
|
5679
|
-
const txHash = tx.hash().toString("hex");
|
|
5680
|
-
return {
|
|
5681
|
-
transactionHash: `0x${txHash}`,
|
|
5682
|
-
messageHash,
|
|
5683
|
-
found: true
|
|
5684
|
-
};
|
|
5685
|
-
}
|
|
5686
|
-
} catch {
|
|
5687
|
-
continue;
|
|
5688
|
-
}
|
|
5689
|
-
}
|
|
5690
|
-
console.warn(`TON transaction not found for message hash: ${messageHash}`);
|
|
5691
|
-
return {
|
|
5692
|
-
transactionHash: null,
|
|
5693
|
-
messageHash,
|
|
5694
|
-
found: false
|
|
5695
|
-
};
|
|
5696
|
-
} catch (error) {
|
|
5697
|
-
console.error("Failed to get TON transaction hash:", error);
|
|
5698
|
-
return {
|
|
5699
|
-
transactionHash: null,
|
|
5700
|
-
messageHash,
|
|
5701
|
-
found: false
|
|
5702
|
-
};
|
|
5703
|
-
}
|
|
5704
|
-
}
|
|
5705
5353
|
class TonChainStrategy {
|
|
5706
5354
|
constructor(config) {
|
|
5707
5355
|
__publicField(this, "config");
|
|
@@ -5814,40 +5462,17 @@ class TonChainStrategy {
|
|
|
5814
5462
|
validUntil: Math.floor(Date.now() / 1e3) + TON_CONFIG.validUntil,
|
|
5815
5463
|
messages: tonMessages
|
|
5816
5464
|
};
|
|
5817
|
-
const result = await this.config.tonConnectUI.sendTransaction(
|
|
5818
|
-
transaction2
|
|
5819
|
-
);
|
|
5465
|
+
const result = await this.config.tonConnectUI.sendTransaction(transaction2);
|
|
5820
5466
|
const bocBase64 = result.boc;
|
|
5821
5467
|
try {
|
|
5822
5468
|
const inMessage = loadMessage(Cell.fromBase64(bocBase64).beginParse());
|
|
5823
5469
|
const messageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
5824
5470
|
const hexHash = messageHash.toString("hex");
|
|
5825
5471
|
onFirstHash?.(hexHash);
|
|
5826
|
-
let tonTransactionHash;
|
|
5827
|
-
if (this.config.tonAddress) {
|
|
5828
|
-
try {
|
|
5829
|
-
const tonTxResult = await getTonTransactionHash(
|
|
5830
|
-
hexHash,
|
|
5831
|
-
this.config.tonAddress,
|
|
5832
|
-
20
|
|
5833
|
-
);
|
|
5834
|
-
if (tonTxResult.found && tonTxResult.transactionHash) {
|
|
5835
|
-
tonTransactionHash = tonTxResult.transactionHash;
|
|
5836
|
-
} else {
|
|
5837
|
-
console.warn(
|
|
5838
|
-
`TON transaction hash not found for message hash: ${hexHash}`
|
|
5839
|
-
);
|
|
5840
|
-
}
|
|
5841
|
-
} catch (error) {
|
|
5842
|
-
console.error("Failed to convert TON message hash:", error);
|
|
5843
|
-
}
|
|
5844
|
-
}
|
|
5845
5472
|
return {
|
|
5846
5473
|
chainKey: "ton",
|
|
5847
|
-
hash: hexHash
|
|
5848
|
-
// Message hash for TONScan
|
|
5849
|
-
tonTransactionHash
|
|
5850
|
-
// Transaction hash for LayerZero (if found)
|
|
5474
|
+
hash: hexHash
|
|
5475
|
+
// Message hash for TONScan and for finding tx later
|
|
5851
5476
|
};
|
|
5852
5477
|
} catch (error) {
|
|
5853
5478
|
console.error("Error parsing BOC to hex hash:", error);
|
|
@@ -5861,39 +5486,45 @@ class TonChainStrategy {
|
|
|
5861
5486
|
throw toChainStrategyError(error, "ton", "transaction");
|
|
5862
5487
|
}
|
|
5863
5488
|
}
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5489
|
+
/**
|
|
5490
|
+
* Convert TON message hash to transaction hash.
|
|
5491
|
+
* LayerZero uses transaction hash, but TonConnect returns message hash.
|
|
5492
|
+
*/
|
|
5493
|
+
async convertMessageHashToTxHash(messageHash, timeoutMs = 6e4) {
|
|
5494
|
+
const deadline = Date.now() + timeoutMs;
|
|
5495
|
+
const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
|
|
5496
|
+
if (!this.config.tonAddress) {
|
|
5497
|
+
return null;
|
|
5498
|
+
}
|
|
5499
|
+
const targetMessageHash = Buffer.from(messageHash, "hex");
|
|
5500
|
+
const accountAddress = Address.parse(this.config.tonAddress);
|
|
5501
|
+
while (Date.now() < deadline) {
|
|
5502
|
+
try {
|
|
5503
|
+
const transactions = await client.getTransactions(accountAddress, {
|
|
5504
|
+
limit: 20,
|
|
5505
|
+
archival: true
|
|
5506
|
+
});
|
|
5507
|
+
for (const tx of transactions) {
|
|
5508
|
+
if (tx.inMessage?.info.type === "external-in") {
|
|
5509
|
+
try {
|
|
5510
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
5511
|
+
tx.inMessage
|
|
5512
|
+
);
|
|
5513
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
5514
|
+
const txHash = `0x${tx.hash().toString("hex")}`;
|
|
5515
|
+
return txHash;
|
|
5516
|
+
}
|
|
5517
|
+
} catch {
|
|
5518
|
+
continue;
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
await new Promise((r2) => setTimeout(r2, 3e3));
|
|
5523
|
+
} catch {
|
|
5524
|
+
await new Promise((r2) => setTimeout(r2, 3e3));
|
|
5880
5525
|
}
|
|
5881
|
-
return {
|
|
5882
|
-
completed: true,
|
|
5883
|
-
actualFeeValue: result.fee,
|
|
5884
|
-
actualFeeSymbol: "TON"
|
|
5885
|
-
};
|
|
5886
|
-
} catch (error) {
|
|
5887
|
-
const chainError = toChainStrategyError(
|
|
5888
|
-
error,
|
|
5889
|
-
"ton",
|
|
5890
|
-
"waitForCompletion"
|
|
5891
|
-
);
|
|
5892
|
-
return {
|
|
5893
|
-
completed: false,
|
|
5894
|
-
error: chainError.message
|
|
5895
|
-
};
|
|
5896
5526
|
}
|
|
5527
|
+
return null;
|
|
5897
5528
|
}
|
|
5898
5529
|
getNormalizedExtMessageHash(message) {
|
|
5899
5530
|
if (message.info.type !== "external-in") {
|
|
@@ -5916,6 +5547,9 @@ class TonChainStrategy {
|
|
|
5916
5547
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
5917
5548
|
return BigInt(Math.trunc(value));
|
|
5918
5549
|
}
|
|
5550
|
+
if (typeof value === "object" && value !== null && "coins" in value) {
|
|
5551
|
+
return this.toBigInt(value.coins);
|
|
5552
|
+
}
|
|
5919
5553
|
if (typeof value === "string" && value.trim() !== "") {
|
|
5920
5554
|
try {
|
|
5921
5555
|
return BigInt(value);
|
|
@@ -5929,12 +5563,16 @@ class TonChainStrategy {
|
|
|
5929
5563
|
const candidate = tx.outMessages;
|
|
5930
5564
|
if (!candidate) return [];
|
|
5931
5565
|
if (Array.isArray(candidate)) return candidate;
|
|
5932
|
-
if (candidate instanceof Map) return Array.from(candidate.values());
|
|
5933
5566
|
if (typeof candidate === "object" && candidate !== null && "values" in candidate && typeof candidate.values === "function") {
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5567
|
+
const values = candidate.values();
|
|
5568
|
+
if (Array.isArray(values)) {
|
|
5569
|
+
return [...values];
|
|
5570
|
+
}
|
|
5571
|
+
if (values && typeof values === "object" && Symbol.iterator in values) {
|
|
5572
|
+
return Array.from(values);
|
|
5573
|
+
}
|
|
5937
5574
|
}
|
|
5575
|
+
if (candidate instanceof Map) return Array.from(candidate.values());
|
|
5938
5576
|
return [];
|
|
5939
5577
|
}
|
|
5940
5578
|
getMessageValue(message) {
|
|
@@ -5946,27 +5584,49 @@ class TonChainStrategy {
|
|
|
5946
5584
|
}
|
|
5947
5585
|
return this.toBigInt(value);
|
|
5948
5586
|
}
|
|
5949
|
-
|
|
5587
|
+
getTotalOutMessageValue(tx) {
|
|
5950
5588
|
const outMessages = this.getOutMessages(tx);
|
|
5951
5589
|
if (!outMessages.length) return 0n;
|
|
5952
|
-
|
|
5953
|
-
|
|
5590
|
+
let total = 0n;
|
|
5591
|
+
for (const message of outMessages) {
|
|
5592
|
+
const value = this.getMessageValue(message);
|
|
5593
|
+
if (value) {
|
|
5594
|
+
total += value;
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5597
|
+
return total;
|
|
5954
5598
|
}
|
|
5955
|
-
async getSourceCost(
|
|
5956
|
-
const timeoutMs =
|
|
5957
|
-
const result = await this.checkTonTransaction(
|
|
5958
|
-
if (!result.confirmed)
|
|
5599
|
+
async getSourceCost(messageHash) {
|
|
5600
|
+
const timeoutMs = 3e4;
|
|
5601
|
+
const result = await this.checkTonTransaction(messageHash, timeoutMs);
|
|
5602
|
+
if (!result.confirmed) {
|
|
5603
|
+
console.warn("Transaction not found for source cost calculation");
|
|
5604
|
+
return null;
|
|
5605
|
+
}
|
|
5959
5606
|
const totalFees = result.totalFees ?? 0n;
|
|
5960
5607
|
const outValue = result.outValue ?? 0n;
|
|
5961
5608
|
const totalNanotons = totalFees + outValue;
|
|
5962
5609
|
const toTon = (value) => Number(value) / 1e9;
|
|
5963
|
-
|
|
5610
|
+
const sourceCost = {
|
|
5964
5611
|
totalNative: toTon(totalNanotons),
|
|
5965
5612
|
breakdown: {
|
|
5966
5613
|
gasFee: toTon(totalFees),
|
|
5967
5614
|
layerZeroFee: toTon(outValue)
|
|
5968
5615
|
}
|
|
5969
5616
|
};
|
|
5617
|
+
console.log("TON source cost:", {
|
|
5618
|
+
gasFee: `${sourceCost.breakdown.gasFee} TON`,
|
|
5619
|
+
layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TON`,
|
|
5620
|
+
total: `${sourceCost.totalNative} TON`
|
|
5621
|
+
});
|
|
5622
|
+
return sourceCost;
|
|
5623
|
+
}
|
|
5624
|
+
async estimateNetworkFee() {
|
|
5625
|
+
const fee = Number(TON_CONFIG.estimatedNetworkFee);
|
|
5626
|
+
if (!Number.isFinite(fee) || fee <= 0) {
|
|
5627
|
+
return 0;
|
|
5628
|
+
}
|
|
5629
|
+
return fee / 1e9;
|
|
5970
5630
|
}
|
|
5971
5631
|
async checkTonTransaction(hashOrBoc, timeoutMs = 36e4) {
|
|
5972
5632
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -5977,10 +5637,6 @@ class TonChainStrategy {
|
|
|
5977
5637
|
try {
|
|
5978
5638
|
const inMessage = loadMessage(Cell.fromBase64(hashOrBoc).beginParse());
|
|
5979
5639
|
if (inMessage.info.type !== "external-in") {
|
|
5980
|
-
console.debug(
|
|
5981
|
-
"Expected external-in message, got:",
|
|
5982
|
-
inMessage.info.type
|
|
5983
|
-
);
|
|
5984
5640
|
return { confirmed: false };
|
|
5985
5641
|
}
|
|
5986
5642
|
accountAddress = inMessage.info.dest;
|
|
@@ -5988,63 +5644,50 @@ class TonChainStrategy {
|
|
|
5988
5644
|
} catch {
|
|
5989
5645
|
targetMessageHash = Buffer.from(hashOrBoc, "hex");
|
|
5990
5646
|
if (!this.config.tonAddress) {
|
|
5991
|
-
console.debug("No wallet address available for hex hash lookup");
|
|
5992
5647
|
return { confirmed: false };
|
|
5993
5648
|
}
|
|
5994
5649
|
accountAddress = Address.parse(this.config.tonAddress);
|
|
5995
5650
|
}
|
|
5996
|
-
let lt2 = void 0;
|
|
5997
|
-
let hash = void 0;
|
|
5998
5651
|
while (Date.now() < deadline) {
|
|
5999
5652
|
try {
|
|
6000
5653
|
const transactions = await client.getTransactions(accountAddress, {
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
limit: 10,
|
|
5654
|
+
limit: 20,
|
|
5655
|
+
// Check last 20 transactions
|
|
6004
5656
|
archival: true
|
|
6005
5657
|
});
|
|
6006
|
-
if (transactions.length === 0) {
|
|
6007
|
-
await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
|
|
6008
|
-
lt2 = void 0;
|
|
6009
|
-
hash = void 0;
|
|
6010
|
-
continue;
|
|
6011
|
-
}
|
|
6012
5658
|
for (const tx of transactions) {
|
|
6013
5659
|
if (tx.inMessage?.info.type === "external-in") {
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
5660
|
+
try {
|
|
5661
|
+
const txInMessageHash = this.getNormalizedExtMessageHash(
|
|
5662
|
+
tx.inMessage
|
|
5663
|
+
);
|
|
5664
|
+
if (txInMessageHash.equals(targetMessageHash)) {
|
|
5665
|
+
const totalFees = this.toBigInt(tx.totalFees) ?? this.toBigInt(
|
|
5666
|
+
tx.total_fees
|
|
5667
|
+
) ?? 0n;
|
|
5668
|
+
const outValue = this.getTotalOutMessageValue(tx);
|
|
5669
|
+
const feeInTon = Number(totalFees) / 1e9;
|
|
5670
|
+
const transactionHash = tx.hash().toString("hex");
|
|
5671
|
+
return {
|
|
5672
|
+
confirmed: true,
|
|
5673
|
+
fee: feeInTon.toString(),
|
|
5674
|
+
totalFees,
|
|
5675
|
+
outValue,
|
|
5676
|
+
transactionHash
|
|
5677
|
+
};
|
|
5678
|
+
}
|
|
5679
|
+
} catch {
|
|
5680
|
+
continue;
|
|
6031
5681
|
}
|
|
6032
5682
|
}
|
|
6033
5683
|
}
|
|
6034
|
-
const lastTx = transactions[transactions.length - 1];
|
|
6035
|
-
lt2 = lastTx.lt.toString();
|
|
6036
|
-
hash = lastTx.hash().toString("base64");
|
|
6037
5684
|
await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
|
|
6038
|
-
} catch
|
|
6039
|
-
console.debug("Error fetching transactions:", error);
|
|
5685
|
+
} catch {
|
|
6040
5686
|
await new Promise((r2) => setTimeout(r2, TON_CONFIG.pollingInterval));
|
|
6041
|
-
lt2 = void 0;
|
|
6042
|
-
hash = void 0;
|
|
6043
5687
|
}
|
|
6044
5688
|
}
|
|
6045
5689
|
return { confirmed: false };
|
|
6046
|
-
} catch
|
|
6047
|
-
console.debug("Error parsing BOC or checking transaction:", error);
|
|
5690
|
+
} catch {
|
|
6048
5691
|
return { confirmed: false };
|
|
6049
5692
|
}
|
|
6050
5693
|
}
|
|
@@ -6054,6 +5697,7 @@ class TronChainStrategy {
|
|
|
6054
5697
|
constructor(config) {
|
|
6055
5698
|
__publicField(this, "config");
|
|
6056
5699
|
__publicField(this, "fallbackClient");
|
|
5700
|
+
__publicField(this, "apiKeyApplied", /* @__PURE__ */ new WeakSet());
|
|
6057
5701
|
this.config = config;
|
|
6058
5702
|
}
|
|
6059
5703
|
canHandle(chainKey) {
|
|
@@ -6219,18 +5863,31 @@ class TronChainStrategy {
|
|
|
6219
5863
|
const feeTrx = feeSun / 1e6;
|
|
6220
5864
|
const lzFeeTrx = callValueSun / 1e6;
|
|
6221
5865
|
const totalTrx = (feeSun + callValueSun) / 1e6;
|
|
6222
|
-
|
|
5866
|
+
const sourceCost = {
|
|
6223
5867
|
totalNative: totalTrx,
|
|
6224
5868
|
breakdown: {
|
|
6225
5869
|
gasFee: feeTrx,
|
|
6226
5870
|
layerZeroFee: lzFeeTrx
|
|
6227
5871
|
}
|
|
6228
5872
|
};
|
|
5873
|
+
console.log("TRON source cost:", {
|
|
5874
|
+
gasFee: `${sourceCost.breakdown.gasFee} TRX`,
|
|
5875
|
+
layerZeroFee: `${sourceCost.breakdown.layerZeroFee} TRX`,
|
|
5876
|
+
total: `${sourceCost.totalNative} TRX`
|
|
5877
|
+
});
|
|
5878
|
+
return sourceCost;
|
|
6229
5879
|
} catch (error) {
|
|
6230
5880
|
console.warn("Failed to compute TRON source cost:", error);
|
|
6231
5881
|
return null;
|
|
6232
5882
|
}
|
|
6233
5883
|
}
|
|
5884
|
+
async estimateNetworkFee() {
|
|
5885
|
+
const fee = Number(TRON_CONFIG.estimatedNetworkFee);
|
|
5886
|
+
if (!Number.isFinite(fee) || fee <= 0) {
|
|
5887
|
+
return 0;
|
|
5888
|
+
}
|
|
5889
|
+
return fee / 1e6;
|
|
5890
|
+
}
|
|
6234
5891
|
async executeSteps(steps, _context, onFirstHash) {
|
|
6235
5892
|
const tronWeb = this.getClient();
|
|
6236
5893
|
if (!tronWeb) {
|
|
@@ -6327,137 +5984,59 @@ class TronChainStrategy {
|
|
|
6327
5984
|
}
|
|
6328
5985
|
return { hash: lastTxId, chainKey: "tron" };
|
|
6329
5986
|
}
|
|
6330
|
-
async waitForCompletion(txHash) {
|
|
6331
|
-
try {
|
|
6332
|
-
const tronWeb = this.getClient();
|
|
6333
|
-
if (!tronWeb) {
|
|
6334
|
-
throw new ProviderNotAvailableError("tron");
|
|
6335
|
-
}
|
|
6336
|
-
console.log(
|
|
6337
|
-
`Waiting for ${TRON_CONFIG.requiredConfirmations} confirmations for TRON tx: ${txHash}`
|
|
6338
|
-
);
|
|
6339
|
-
const deadline = Date.now() + TRON_CONFIG.timeout;
|
|
6340
|
-
let txBlockNumber = null;
|
|
6341
|
-
let actualFeeTrx = null;
|
|
6342
|
-
while (Date.now() < deadline && !txBlockNumber) {
|
|
6343
|
-
try {
|
|
6344
|
-
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
6345
|
-
if (info && info.blockNumber) {
|
|
6346
|
-
const result = info.receipt?.result;
|
|
6347
|
-
if (result !== "SUCCESS") {
|
|
6348
|
-
const msg = this.hexToAscii(info.resMessage) || null;
|
|
6349
|
-
let reason = msg;
|
|
6350
|
-
const cr2 = info.contractResult?.[0];
|
|
6351
|
-
if (cr2 && /^0x?08c379a0/i.test(cr2)) {
|
|
6352
|
-
try {
|
|
6353
|
-
const clean2 = cr2.replace(/^0x/, "");
|
|
6354
|
-
const len = parseInt(clean2.slice(8 + 64, 8 + 64 + 64), 16);
|
|
6355
|
-
const strHex = clean2.slice(
|
|
6356
|
-
8 + 64 + 64,
|
|
6357
|
-
8 + 64 + 64 + len * 2
|
|
6358
|
-
);
|
|
6359
|
-
const str = this.hexToAscii("0x" + strHex);
|
|
6360
|
-
if (str) reason = str;
|
|
6361
|
-
} catch (e2) {
|
|
6362
|
-
console.debug("TRON revert string decode error", e2);
|
|
6363
|
-
}
|
|
6364
|
-
}
|
|
6365
|
-
const error2 = new TransactionRevertedError(
|
|
6366
|
-
"tron",
|
|
6367
|
-
txHash,
|
|
6368
|
-
reason || "Unknown error"
|
|
6369
|
-
);
|
|
6370
|
-
return {
|
|
6371
|
-
completed: false,
|
|
6372
|
-
error: error2.message
|
|
6373
|
-
};
|
|
6374
|
-
}
|
|
6375
|
-
txBlockNumber = info.blockNumber;
|
|
6376
|
-
const feeSun = info.fee || 0;
|
|
6377
|
-
actualFeeTrx = feeSun / 1e6;
|
|
6378
|
-
console.log(
|
|
6379
|
-
`TRON transaction found in block ${txBlockNumber}, fee: ${actualFeeTrx} TRX`
|
|
6380
|
-
);
|
|
6381
|
-
}
|
|
6382
|
-
} catch (e2) {
|
|
6383
|
-
console.debug("TRON getTransactionInfo error:", e2);
|
|
6384
|
-
}
|
|
6385
|
-
if (!txBlockNumber) {
|
|
6386
|
-
await new Promise((r2) => setTimeout(r2, TRON_CONFIG.pollingInterval));
|
|
6387
|
-
}
|
|
6388
|
-
}
|
|
6389
|
-
if (!txBlockNumber) {
|
|
6390
|
-
const error2 = new TransactionTimeoutError("tron", txHash);
|
|
6391
|
-
return {
|
|
6392
|
-
completed: false,
|
|
6393
|
-
error: error2.message
|
|
6394
|
-
};
|
|
6395
|
-
}
|
|
6396
|
-
let confirmations = 0;
|
|
6397
|
-
while (Date.now() < deadline) {
|
|
6398
|
-
try {
|
|
6399
|
-
const currentBlock = await tronWeb.trx.getCurrentBlock();
|
|
6400
|
-
const currentBlockNumber = currentBlock?.block_header?.raw_data?.number;
|
|
6401
|
-
if (currentBlockNumber) {
|
|
6402
|
-
confirmations = currentBlockNumber - txBlockNumber;
|
|
6403
|
-
if (confirmations >= TRON_CONFIG.requiredConfirmations) {
|
|
6404
|
-
console.log(
|
|
6405
|
-
`TRON transaction confirmed in block ${txBlockNumber} with ${confirmations} confirmations`
|
|
6406
|
-
);
|
|
6407
|
-
return {
|
|
6408
|
-
completed: true,
|
|
6409
|
-
actualFeeValue: actualFeeTrx?.toString(),
|
|
6410
|
-
actualFeeSymbol: "TRX"
|
|
6411
|
-
};
|
|
6412
|
-
}
|
|
6413
|
-
console.log(
|
|
6414
|
-
`TRON transaction confirmations: ${confirmations}/${TRON_CONFIG.requiredConfirmations}`
|
|
6415
|
-
);
|
|
6416
|
-
}
|
|
6417
|
-
} catch (e2) {
|
|
6418
|
-
console.debug("TRON getCurrentBlock error:", e2);
|
|
6419
|
-
}
|
|
6420
|
-
await new Promise((r2) => setTimeout(r2, TRON_CONFIG.pollingInterval));
|
|
6421
|
-
}
|
|
6422
|
-
const error = new TransactionTimeoutError("tron", txHash);
|
|
6423
|
-
return {
|
|
6424
|
-
completed: false,
|
|
6425
|
-
error: error.message
|
|
6426
|
-
};
|
|
6427
|
-
} catch (error) {
|
|
6428
|
-
const chainError = toChainStrategyError(
|
|
6429
|
-
error,
|
|
6430
|
-
"tron",
|
|
6431
|
-
"waitForCompletion"
|
|
6432
|
-
);
|
|
6433
|
-
return {
|
|
6434
|
-
completed: false,
|
|
6435
|
-
error: chainError.message
|
|
6436
|
-
};
|
|
6437
|
-
}
|
|
6438
|
-
}
|
|
6439
5987
|
getClient() {
|
|
6440
5988
|
if (typeof window !== "undefined" && window.tronWeb) {
|
|
5989
|
+
this.applyTronApiKey(window.tronWeb);
|
|
6441
5990
|
return window.tronWeb;
|
|
6442
5991
|
}
|
|
6443
5992
|
if (!this.fallbackClient) {
|
|
6444
5993
|
this.fallbackClient = this.createFallbackClient();
|
|
6445
5994
|
}
|
|
5995
|
+
if (this.fallbackClient) {
|
|
5996
|
+
this.applyTronApiKey(this.fallbackClient);
|
|
5997
|
+
}
|
|
6446
5998
|
return this.fallbackClient;
|
|
6447
5999
|
}
|
|
6448
6000
|
createFallbackClient() {
|
|
6449
6001
|
try {
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6002
|
+
if (!this.config.apiKey) {
|
|
6003
|
+
throw new Error("TRON API key is required");
|
|
6004
|
+
}
|
|
6005
|
+
const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
|
|
6006
|
+
const tronWeb = new TronWeb({
|
|
6007
|
+
fullHost: DEFAULT_TRON_NODE,
|
|
6008
|
+
headers
|
|
6009
|
+
});
|
|
6455
6010
|
return tronWeb;
|
|
6456
6011
|
} catch (error) {
|
|
6457
6012
|
console.warn("Failed to create fallback TronWeb client", error);
|
|
6458
6013
|
return void 0;
|
|
6459
6014
|
}
|
|
6460
6015
|
}
|
|
6016
|
+
applyTronApiKey(tronWeb) {
|
|
6017
|
+
if (!this.config.apiKey) {
|
|
6018
|
+
return;
|
|
6019
|
+
}
|
|
6020
|
+
const target = tronWeb;
|
|
6021
|
+
if (this.apiKeyApplied.has(target)) {
|
|
6022
|
+
return;
|
|
6023
|
+
}
|
|
6024
|
+
try {
|
|
6025
|
+
const headers = { "TRON-PRO-API-KEY": this.config.apiKey };
|
|
6026
|
+
if (typeof target.setHeader === "function") {
|
|
6027
|
+
target.setHeader(headers);
|
|
6028
|
+
} else {
|
|
6029
|
+
if (typeof target.setFullNodeHeader === "function") {
|
|
6030
|
+
target.setFullNodeHeader(headers);
|
|
6031
|
+
}
|
|
6032
|
+
if (typeof target.setEventHeader === "function") {
|
|
6033
|
+
target.setEventHeader(headers);
|
|
6034
|
+
}
|
|
6035
|
+
}
|
|
6036
|
+
this.apiKeyApplied.add(target);
|
|
6037
|
+
} catch {
|
|
6038
|
+
}
|
|
6039
|
+
}
|
|
6461
6040
|
/**
|
|
6462
6041
|
* Check if TronLink wallet is actually installed
|
|
6463
6042
|
* This excludes Bybit Wallet which also injects tronLink for compatibility
|
|
@@ -6466,14 +6045,8 @@ class TronChainStrategy {
|
|
|
6466
6045
|
if (typeof window === "undefined") {
|
|
6467
6046
|
return false;
|
|
6468
6047
|
}
|
|
6469
|
-
const
|
|
6470
|
-
|
|
6471
|
-
return false;
|
|
6472
|
-
}
|
|
6473
|
-
if (!window.tronLink) {
|
|
6474
|
-
return false;
|
|
6475
|
-
}
|
|
6476
|
-
return true;
|
|
6048
|
+
const win = window;
|
|
6049
|
+
return !!(win.tronLink || win.tronWeb || win.tron);
|
|
6477
6050
|
}
|
|
6478
6051
|
ensureDefaultAddress(tronWeb, address) {
|
|
6479
6052
|
if (!address) return;
|
|
@@ -6486,18 +6059,7 @@ class TronChainStrategy {
|
|
|
6486
6059
|
hex
|
|
6487
6060
|
};
|
|
6488
6061
|
}
|
|
6489
|
-
} catch (error) {
|
|
6490
|
-
console.debug("Failed to set TronWeb default address:", error);
|
|
6491
|
-
}
|
|
6492
|
-
}
|
|
6493
|
-
hexToAscii(h4) {
|
|
6494
|
-
if (!h4) return null;
|
|
6495
|
-
const clean2 = h4.replace(/^0x/, "");
|
|
6496
|
-
const bytes = clean2.match(/.{1,2}/g) || [];
|
|
6497
|
-
try {
|
|
6498
|
-
return bytes.map((b2) => String.fromCharCode(parseInt(b2, 16))).join("");
|
|
6499
6062
|
} catch {
|
|
6500
|
-
return null;
|
|
6501
6063
|
}
|
|
6502
6064
|
}
|
|
6503
6065
|
toBase58(addr, tronWeb) {
|
|
@@ -6804,22 +6366,14 @@ class TronChainStrategy {
|
|
|
6804
6366
|
}
|
|
6805
6367
|
const info = await tronWeb.trx.getTransactionInfo(txHash);
|
|
6806
6368
|
if (!info || !info.blockNumber) {
|
|
6807
|
-
console.debug(
|
|
6808
|
-
"Transaction not yet solidified (no blockNumber in info)"
|
|
6809
|
-
);
|
|
6810
6369
|
return false;
|
|
6811
6370
|
}
|
|
6812
6371
|
const result = info.receipt?.result;
|
|
6813
6372
|
if (result === "SUCCESS") {
|
|
6814
|
-
console.log(
|
|
6815
|
-
`Transaction ${txHash} is solidified in block ${info.blockNumber}`
|
|
6816
|
-
);
|
|
6817
6373
|
return true;
|
|
6818
6374
|
}
|
|
6819
|
-
console.debug(`Transaction solidified but result is: ${result}`);
|
|
6820
6375
|
return false;
|
|
6821
|
-
} catch
|
|
6822
|
-
console.debug("Error checking solidified status:", error);
|
|
6376
|
+
} catch {
|
|
6823
6377
|
return false;
|
|
6824
6378
|
}
|
|
6825
6379
|
}
|
|
@@ -6830,7 +6384,8 @@ function ChainStrategyProvider({
|
|
|
6830
6384
|
tonWallet,
|
|
6831
6385
|
tronWallet,
|
|
6832
6386
|
tonClient,
|
|
6833
|
-
tonApiKey
|
|
6387
|
+
tonApiKey,
|
|
6388
|
+
tronApiKey
|
|
6834
6389
|
}) {
|
|
6835
6390
|
const evmStrategy = useMemo(
|
|
6836
6391
|
() => new EvmChainStrategy({
|
|
@@ -6873,7 +6428,8 @@ function ChainStrategyProvider({
|
|
|
6873
6428
|
connect: tronWallet.walletConnect.connect,
|
|
6874
6429
|
disconnect: tronWallet.walletConnect.disconnect,
|
|
6875
6430
|
signTransaction: tronWallet.walletConnect.signTransaction
|
|
6876
|
-
} : void 0
|
|
6431
|
+
} : void 0,
|
|
6432
|
+
apiKey: tronApiKey
|
|
6877
6433
|
}),
|
|
6878
6434
|
[
|
|
6879
6435
|
tronWallet.tronLink.address,
|
|
@@ -6881,7 +6437,8 @@ function ChainStrategyProvider({
|
|
|
6881
6437
|
tronWallet.tronLink.select,
|
|
6882
6438
|
tronWallet.tronLink.connect,
|
|
6883
6439
|
tronWallet.tronLink.disconnect,
|
|
6884
|
-
tronWallet.walletConnect
|
|
6440
|
+
tronWallet.walletConnect,
|
|
6441
|
+
tronApiKey
|
|
6885
6442
|
]
|
|
6886
6443
|
);
|
|
6887
6444
|
const chainRegistry = useMemo(
|
|
@@ -26236,7 +25793,7 @@ class WalletConnectModal {
|
|
|
26236
25793
|
}
|
|
26237
25794
|
async initUi() {
|
|
26238
25795
|
if (typeof window !== "undefined") {
|
|
26239
|
-
await import("./index-
|
|
25796
|
+
await import("./index-D8sxoZ5P.js");
|
|
26240
25797
|
const modal = document.createElement("wcm-modal");
|
|
26241
25798
|
document.body.insertAdjacentElement("beforeend", modal);
|
|
26242
25799
|
OptionsCtrl.setIsUiLoaded(true);
|
|
@@ -26729,6 +26286,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
26729
26286
|
},
|
|
26730
26287
|
tonClient: props.tonClient,
|
|
26731
26288
|
tonApiKey: props.tonApiKey,
|
|
26289
|
+
tronApiKey: props.tronApiKey,
|
|
26732
26290
|
children: /* @__PURE__ */ jsx(EvaaBridgeContent, { ...props })
|
|
26733
26291
|
}
|
|
26734
26292
|
) });
|
|
@@ -26942,47 +26500,41 @@ async function pollUntilDelivered(args) {
|
|
|
26942
26500
|
}
|
|
26943
26501
|
}
|
|
26944
26502
|
export {
|
|
26945
|
-
|
|
26946
|
-
|
|
26947
|
-
|
|
26503
|
+
getQuotesByPriority as $,
|
|
26504
|
+
getQuoteDetails as A,
|
|
26505
|
+
getRouteDisplayName as B,
|
|
26948
26506
|
ConfigCtrl as C,
|
|
26949
|
-
|
|
26507
|
+
toLD as D,
|
|
26950
26508
|
EventsCtrl as E,
|
|
26951
|
-
|
|
26952
|
-
|
|
26953
|
-
|
|
26954
|
-
|
|
26955
|
-
|
|
26956
|
-
|
|
26957
|
-
|
|
26509
|
+
fromLD as F,
|
|
26510
|
+
buildAssetMatrix as G,
|
|
26511
|
+
listAssetsForSelect as H,
|
|
26512
|
+
resolveTokenOnChain as I,
|
|
26513
|
+
resolveTokenOnChainFromMatrix$2 as J,
|
|
26514
|
+
DEFAULT_SLIPPAGE_BPS as K,
|
|
26515
|
+
tonNorm as L,
|
|
26958
26516
|
ModalCtrl as M,
|
|
26959
|
-
|
|
26517
|
+
isZeroAddr as N,
|
|
26960
26518
|
OptionsCtrl as O,
|
|
26961
|
-
|
|
26962
|
-
|
|
26519
|
+
addrForApi as P,
|
|
26520
|
+
isNativeAddrEqual as Q,
|
|
26963
26521
|
RouterCtrl as R,
|
|
26964
|
-
|
|
26522
|
+
findNativeMeta as S,
|
|
26965
26523
|
ToastCtrl as T,
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
26971
|
-
|
|
26972
|
-
|
|
26524
|
+
lookupTokenMeta as U,
|
|
26525
|
+
computeFeesUsdFromArray as V,
|
|
26526
|
+
sumFeeByTokenLD as W,
|
|
26527
|
+
normalizeTickerSymbol$1 as X,
|
|
26528
|
+
getChains as Y,
|
|
26529
|
+
getTokens as Z,
|
|
26530
|
+
getDestTokens as _,
|
|
26973
26531
|
ThemeCtrl as a,
|
|
26974
|
-
|
|
26975
|
-
|
|
26976
|
-
|
|
26977
|
-
|
|
26978
|
-
|
|
26979
|
-
|
|
26980
|
-
isNativeAddress as a6,
|
|
26981
|
-
getEvmBalances as a7,
|
|
26982
|
-
getTonBalances as a8,
|
|
26983
|
-
getTronBalances as a9,
|
|
26984
|
-
getDeliveryStatus as aa,
|
|
26985
|
-
pollUntilDelivered as ab,
|
|
26532
|
+
isNativeAddress as a0,
|
|
26533
|
+
getEvmBalances as a1,
|
|
26534
|
+
getTonBalances as a2,
|
|
26535
|
+
getTronBalances as a3,
|
|
26536
|
+
getDeliveryStatus as a4,
|
|
26537
|
+
pollUntilDelivered as a5,
|
|
26986
26538
|
ExplorerCtrl as b,
|
|
26987
26539
|
CoreUtil as c,
|
|
26988
26540
|
EvaaBridge as d,
|
|
@@ -27009,4 +26561,4 @@ export {
|
|
|
27009
26561
|
getQuoteFees as y,
|
|
27010
26562
|
calculateMinReceived as z
|
|
27011
26563
|
};
|
|
27012
|
-
//# sourceMappingURL=index-
|
|
26564
|
+
//# sourceMappingURL=index-CDUxAooI.js.map
|