@rash2x/bridge-widget 0.2.10 → 0.2.11
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/README.md +57 -53
- package/dist/evaa-bridge.cjs +307 -103
- package/dist/evaa-bridge.cjs.map +1 -1
- package/dist/evaa-bridge.mjs +309 -105
- package/dist/evaa-bridge.mjs.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/evaa-bridge.cjs
CHANGED
|
@@ -44,16 +44,17 @@ const lucideReact = require("lucide-react");
|
|
|
44
44
|
const framerMotion = require("framer-motion");
|
|
45
45
|
const accordion = require("@/components/ui/accordion");
|
|
46
46
|
const tooltip = require("@/components/ui/tooltip");
|
|
47
|
+
const ton = require("@ton/ton");
|
|
47
48
|
const sonner = require("sonner");
|
|
49
|
+
const reactDialog = require("@radix-ui/react-dialog");
|
|
48
50
|
const ethers = require("ethers");
|
|
49
51
|
const viem = require("viem");
|
|
50
|
-
const ton = require("@ton/ton");
|
|
51
52
|
const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
|
|
52
53
|
const card = require("@/components/ui/card");
|
|
53
54
|
const badge = require("@/components/ui/badge");
|
|
54
55
|
const common$1 = { "connecting": "Connecting…", "initializing": "Initializing...", "loading": "Loading...", "paste": "paste", "close": "Close", "zeroPlaceholder": "0", "nativeToken": "Native Token" };
|
|
55
56
|
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", "tonKeeper": "TonKeeper", "metaMask": "WalletConnect", "tronLink": "TronLink", "addTronWallet": "Add Tron wallet", "comingSoon": "Coming Soon", "connected": "CONNECTED", "disconnect": "Disconnect", "chooseWallet": "Choose wallet", "oneWalletPerEnv": "You can only connect one wallet per environment.", "connect": "Connect", "connectTronWallet": "Connect Tron wallet", "connectWallet": "Connect wallet" };
|
|
56
|
-
const bridge$1 = { "sourceNetwork": "Source network", "destinationNetwork": "Destination network", "selectToken": "Select token", "selectNetwork": "Select network", "searchToken": "Search token", "searchDestinationChain": "Search destination chain", "myTokens": "My tokens", "allTokens": "All tokens", "willChangeSourceChain": "Will Change Source Chain", "noBalancesFound": "No balances found.", "noResults": "No results", "sendToAnotherAddress": "Send to another address", "youWillReceive": "You will receive", "anotherAddressPlaceholder": "Address", "addressDoesntMatch": "Address doesn't match the {{network}} network", "checkBeforeTransfer": "Check correctness before transfer" };
|
|
57
|
+
const bridge$1 = { "max": "Max", "sourceNetwork": "Source network", "destinationNetwork": "Destination network", "selectToken": "Select token", "selectNetwork": "Select network", "searchToken": "Search token", "searchDestinationChain": "Search destination chain", "myTokens": "My tokens", "allTokens": "All tokens", "willChangeSourceChain": "Will Change Source Chain", "noBalancesFound": "No balances found.", "noResults": "No results", "sendToAnotherAddress": "Send to another address", "youWillReceive": "You will receive", "anotherAddressPlaceholder": "Address", "addressDoesntMatch": "Address doesn't match the {{network}} network", "checkBeforeTransfer": "Check correctness before transfer" };
|
|
57
58
|
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": "Processing...", "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", "finalFee": "Final Fee", "route": "Route", "estTime": "Est. Time", "slippage": "Slippage", "minimumReceived": "Minimum received", "totalFee": "Total Fee", "noRouteFound": "No route found", "notEnoughGas": "Not enough gas", "noRouteFoundForSettings": "No route found for current settings.", "tryAdjustSettings": "Try disabling Gas on Destination, or adjust amount/networks.", "quoteError": "Quote error" };
|
|
58
59
|
const app$1 = { "stargateWidgetName": "Stargate Bridge Widget", "liveWidget": "Live Widget", "getStarted": "Get Started" };
|
|
59
60
|
const settings$1 = { "title": "Settings", "gasOnDestination": "Gas on destination", "slippageTolerance": "Slippage tolerance", "routePriority": "Route Priority", "highSlippageWarning": "High slippage warning", "gasPresets": { "auto": "Auto", "none": "None", "medium": "Medium", "max": "Max" }, "routePresets": { "fastest": "Fastest", "cheapest": "Cheapest", "recommended": "Recommended" } };
|
|
@@ -69,7 +70,7 @@ const en = {
|
|
|
69
70
|
};
|
|
70
71
|
const common = { "connecting": "Подключение…", "initializing": "Инициализация...", "loading": "Загрузка...", "paste": "вставить", "close": "Закрыть", "zeroPlaceholder": "0", "nativeToken": "Нативный токен" };
|
|
71
72
|
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", "tonKeeper": "TonKeeper", "metaMask": "WalletConnect", "tronLink": "TronLink", "addTronWallet": "Добавить Tron кошелёк", "comingSoon": "Скоро", "connected": "ПОДКЛЮЧЕНО", "disconnect": "Отключить", "chooseWallet": "Выберите кошелёк", "oneWalletPerEnv": "Можно подключить только один кошелёк на окружение.", "connect": "Подключить", "connectTronWallet": "Подключить Tron кошелёк", "connectWallet": "Подключить кошелёк" };
|
|
72
|
-
const bridge = { "sourceNetwork": "Исходная сеть", "destinationNetwork": "Целевая сеть", "selectToken": "Выбрать токен", "selectNetwork": "Выбрать сеть", "searchToken": "Поиск токена", "searchDestinationChain": "Поиск целевой сети", "myTokens": "Мои токены", "allTokens": "Все токены", "willChangeSourceChain": "Сменит исходную сеть", "noBalancesFound": "Балансы не найдены.", "noResults": "Нет результатов", "sendToAnotherAddress": "Отправить на другой адрес", "youWillReceive": "Вы получите", "anotherAddressPlaceholder": "Адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
|
|
73
|
+
const bridge = { "max": "Макс", "sourceNetwork": "Исходная сеть", "destinationNetwork": "Целевая сеть", "selectToken": "Выбрать токен", "selectNetwork": "Выбрать сеть", "searchToken": "Поиск токена", "searchDestinationChain": "Поиск целевой сети", "myTokens": "Мои токены", "allTokens": "Все токены", "willChangeSourceChain": "Сменит исходную сеть", "noBalancesFound": "Балансы не найдены.", "noResults": "Нет результатов", "sendToAnotherAddress": "Отправить на другой адрес", "youWillReceive": "Вы получите", "anotherAddressPlaceholder": "Адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
|
|
73
74
|
const transaction = { "enterAmount": "Введите сумму", "transfer": "Перевести", "getQuote": "Получить котировку", "quoting": "Расчет котировки...", "failed": "Ошибка транзакции", "confirm": "Подтвердите транзакцию", "signTransaction": "Подпишите транзакцию в кошельке", "inProgress": "Выполнение...", "checkingBalance": "Проверка баланса...", "insufficientBalance": "Недостаточно средств", "amountTooSmall": "Минимум {{min}}", "amountTooLarge": "Максимум {{max}}", "success": "Успех", "successTitle": "Успех", "done": "Готово", "hashCopied": "Хэш скопирован в буфер обмена", "bridged": "Переведено", "transferTitle": "Перевод", "hash": "Хэш", "finalFee": "Итоговая комиссия", "route": "Маршрут", "estTime": "Время", "slippage": "Проскальзывание", "minimumReceived": "Минимум к получению", "totalFee": "Общая комиссия", "noRouteFound": "Маршрут не найден", "notEnoughGas": "Недостаточно газа", "noRouteFoundForSettings": "Маршрут не найден для текущих настроек.", "tryAdjustSettings": "Попробуйте отключить Gas on Destination или измените сумму/сети.", "quoteError": "Ошибка котировки" };
|
|
74
75
|
const app = { "stargateWidgetName": "Виджет Stargate Bridge", "liveWidget": "Живой виджет", "getStarted": "Начало работы" };
|
|
75
76
|
const settings = { "title": "Настройки", "gasOnDestination": "Газ на назначении", "slippageTolerance": "Толерантность к проскальзыванию", "routePriority": "Приоритет маршрута", "highSlippageWarning": "Высокое проскальзывание", "gasPresets": { "auto": "Авто", "none": "Нет", "medium": "Средний", "max": "Макс" }, "routePresets": { "fastest": "Быстрейший", "cheapest": "Дешевейший", "recommended": "Рекомендуемый" } };
|
|
@@ -1607,18 +1608,30 @@ const SwapButton = () => {
|
|
|
1607
1608
|
) });
|
|
1608
1609
|
};
|
|
1609
1610
|
const WalletBalance = (props) => {
|
|
1610
|
-
const { value, isLoading = false } = props;
|
|
1611
|
+
const { value, isLoading = false, showMax = false, onMaxClick } = props;
|
|
1612
|
+
const { t } = useBridgeTranslation();
|
|
1611
1613
|
const hasNoData = !value || value === "0" || value === "0.00" || value === "0.0";
|
|
1612
1614
|
const shouldShowSkeleton = isLoading && hasNoData;
|
|
1615
|
+
const shouldShowMaxButton = showMax && !hasNoData && !isLoading;
|
|
1613
1616
|
if (shouldShowSkeleton) {
|
|
1614
1617
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
|
|
1615
1618
|
/* @__PURE__ */ jsxRuntime.jsx(WalletIcon, { className: "text-muted-foreground" }),
|
|
1616
|
-
/* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-4 w-
|
|
1619
|
+
/* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-4 w-12 rounded-md" })
|
|
1617
1620
|
] });
|
|
1618
1621
|
}
|
|
1619
1622
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
|
|
1620
1623
|
/* @__PURE__ */ jsxRuntime.jsx(WalletIcon, { className: "text-muted-foreground" }),
|
|
1621
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-5 font-medium text-muted-foreground", children: value })
|
|
1624
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-5 font-medium text-muted-foreground", children: value }),
|
|
1625
|
+
shouldShowMaxButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1626
|
+
button.Button,
|
|
1627
|
+
{
|
|
1628
|
+
variant: "ghost",
|
|
1629
|
+
size: "sm",
|
|
1630
|
+
onClick: onMaxClick,
|
|
1631
|
+
className: "h-auto p-0 px-0 text-xs font-medium border-b border-foreground rounded-none",
|
|
1632
|
+
children: t("bridge.max")
|
|
1633
|
+
}
|
|
1634
|
+
)
|
|
1622
1635
|
] });
|
|
1623
1636
|
};
|
|
1624
1637
|
const BASE_URL$1 = "https://icons-ckg.pages.dev/stargate-light/networks";
|
|
@@ -1859,7 +1872,7 @@ const ChainSelectModal = ({
|
|
|
1859
1872
|
);
|
|
1860
1873
|
};
|
|
1861
1874
|
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "max-h-[90dvh] h-[90dvh] overflow-hidden flex flex-col", children: [
|
|
1862
|
-
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectNetwork") }) }),
|
|
1875
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectNetwork") }) }),
|
|
1863
1876
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1864
1877
|
SearchInput,
|
|
1865
1878
|
{
|
|
@@ -1984,7 +1997,7 @@ const WalletInlineButton = ({
|
|
|
1984
1997
|
disabled: isButtonDisabled,
|
|
1985
1998
|
variant: "ghost",
|
|
1986
1999
|
size: "sm",
|
|
1987
|
-
className: "flex gap-1 cursor-pointer px-0 pr-1 h-5",
|
|
2000
|
+
className: "flex gap-1 cursor-pointer !px-0 pr-1 h-5",
|
|
1988
2001
|
children: [
|
|
1989
2002
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isConnected ? prefixIcons[wallet] : null }),
|
|
1990
2003
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "leading-3 text-sm border-b border-dotted border-link text-link", children: buttonText })
|
|
@@ -2049,6 +2062,11 @@ const SwapSection = ({
|
|
|
2049
2062
|
},
|
|
2050
2063
|
[onSelect, onClose]
|
|
2051
2064
|
);
|
|
2065
|
+
const handleMaxClick = react.useCallback(() => {
|
|
2066
|
+
if (balance.balance && onAmountChange) {
|
|
2067
|
+
onAmountChange(balance.balance.toString());
|
|
2068
|
+
}
|
|
2069
|
+
}, [balance.balance, onAmountChange]);
|
|
2052
2070
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2053
2071
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2054
2072
|
"div",
|
|
@@ -2065,7 +2083,9 @@ const SwapSection = ({
|
|
|
2065
2083
|
WalletBalance,
|
|
2066
2084
|
{
|
|
2067
2085
|
value: truncateToDecimals(balance.balance, 2),
|
|
2068
|
-
isLoading: balance.isLoading
|
|
2086
|
+
isLoading: balance.isLoading,
|
|
2087
|
+
showMax: isSource,
|
|
2088
|
+
onMaxClick: handleMaxClick
|
|
2069
2089
|
}
|
|
2070
2090
|
)
|
|
2071
2091
|
] }),
|
|
@@ -2315,6 +2335,53 @@ const TokenSymbol = ({
|
|
|
2315
2335
|
const src = `${BASE_URL}/${normalizedSymbol}.svg`;
|
|
2316
2336
|
return /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: alt ?? symbol, className });
|
|
2317
2337
|
};
|
|
2338
|
+
const EVM_CONFIG = {
|
|
2339
|
+
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
2340
|
+
gasEstimates: {
|
|
2341
|
+
approve: 65000n,
|
|
2342
|
+
bridge: 300000n
|
|
2343
|
+
},
|
|
2344
|
+
gasBuffer: 1.2,
|
|
2345
|
+
// 20% buffer
|
|
2346
|
+
timeout: 3e5,
|
|
2347
|
+
// 5 minutes (increased for slower networks)
|
|
2348
|
+
requiredConfirmations: 3
|
|
2349
|
+
// Wait for 3 confirmations for reorg protection
|
|
2350
|
+
};
|
|
2351
|
+
const TON_CONFIG = {
|
|
2352
|
+
apiUrl: "https://toncenter.com/api/v2",
|
|
2353
|
+
timeout: 36e4,
|
|
2354
|
+
// 6 minutes
|
|
2355
|
+
validUntil: 600,
|
|
2356
|
+
// 10 minutes
|
|
2357
|
+
pollingInterval: 5e3,
|
|
2358
|
+
// 5 seconds between transaction status checks
|
|
2359
|
+
estimatedNetworkFee: "100000000"
|
|
2360
|
+
// 0.1 TON in nanoton (conservative estimate)
|
|
2361
|
+
};
|
|
2362
|
+
const TRON_CONFIG = {
|
|
2363
|
+
timeout: 12e4,
|
|
2364
|
+
// 2 minutes (for 19 confirmations)
|
|
2365
|
+
feeLimit: 1e8,
|
|
2366
|
+
// 100 TRX in sun
|
|
2367
|
+
requiredConfirmations: 19,
|
|
2368
|
+
// TRON standard: 19 blocks for confirmation
|
|
2369
|
+
pollingInterval: 3e3
|
|
2370
|
+
// 3 seconds between checks
|
|
2371
|
+
};
|
|
2372
|
+
let tonClientInstance = null;
|
|
2373
|
+
function getTonClient(customClient, apiKey) {
|
|
2374
|
+
if (customClient) {
|
|
2375
|
+
return customClient;
|
|
2376
|
+
}
|
|
2377
|
+
if (!tonClientInstance) {
|
|
2378
|
+
tonClientInstance = new ton.TonClient({
|
|
2379
|
+
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
2380
|
+
apiKey
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
return tonClientInstance;
|
|
2384
|
+
}
|
|
2318
2385
|
function getQuoteAmounts(quote, srcToken, dstToken) {
|
|
2319
2386
|
if (!quote || !srcToken || !dstToken) {
|
|
2320
2387
|
return {
|
|
@@ -2394,6 +2461,34 @@ function calculateMinReceived(quote, slippageBps, dstToken) {
|
|
|
2394
2461
|
const minAmountLD = dstAmountLD * BigInt(1e4 - slippageBps) / BigInt(1e4);
|
|
2395
2462
|
return fromLD(minAmountLD.toString(), dstToken.decimals);
|
|
2396
2463
|
}
|
|
2464
|
+
function addTonNetworkFee(quote, chains) {
|
|
2465
|
+
if (!quote || quote.srcChainKey.toLowerCase() !== "ton") {
|
|
2466
|
+
return quote;
|
|
2467
|
+
}
|
|
2468
|
+
const tonChain = chains?.find(
|
|
2469
|
+
(c) => c.chainKey.toLowerCase() === "ton"
|
|
2470
|
+
);
|
|
2471
|
+
if (!tonChain?.nativeCurrency?.address) {
|
|
2472
|
+
console.warn("Could not find TON native currency address");
|
|
2473
|
+
return quote;
|
|
2474
|
+
}
|
|
2475
|
+
const networkFee = {
|
|
2476
|
+
token: tonChain.nativeCurrency.address,
|
|
2477
|
+
chainKey: "ton",
|
|
2478
|
+
amount: TON_CONFIG.estimatedNetworkFee,
|
|
2479
|
+
type: "network"
|
|
2480
|
+
};
|
|
2481
|
+
const hasNetworkFee = quote.fees?.some(
|
|
2482
|
+
(fee) => fee.type === "network" && fee.chainKey === "ton"
|
|
2483
|
+
);
|
|
2484
|
+
if (hasNetworkFee) {
|
|
2485
|
+
return quote;
|
|
2486
|
+
}
|
|
2487
|
+
return {
|
|
2488
|
+
...quote,
|
|
2489
|
+
fees: [...quote.fees || [], networkFee]
|
|
2490
|
+
};
|
|
2491
|
+
}
|
|
2397
2492
|
function getQuoteDetails(quote, srcToken, dstToken, tokens, chains, slippageBps) {
|
|
2398
2493
|
const amounts = getQuoteAmounts(quote, srcToken, dstToken);
|
|
2399
2494
|
const fees = getQuoteFees(quote, tokens, chains, srcToken, dstToken);
|
|
@@ -2432,8 +2527,9 @@ const Details = () => {
|
|
|
2432
2527
|
selectedAssetSymbol,
|
|
2433
2528
|
fromChain?.chainKey
|
|
2434
2529
|
);
|
|
2530
|
+
const quoteWithFees = addTonNetworkFee(quote, chains);
|
|
2435
2531
|
const quoteDetails = getQuoteDetails(
|
|
2436
|
-
quote,
|
|
2532
|
+
quoteWithFees || quote,
|
|
2437
2533
|
srcToken,
|
|
2438
2534
|
dstToken,
|
|
2439
2535
|
tokens,
|
|
@@ -2461,7 +2557,7 @@ const Details = () => {
|
|
|
2461
2557
|
})();
|
|
2462
2558
|
const currentSlippageText = formatPercentage(slippageBps);
|
|
2463
2559
|
const routeText = quote?.route ? getRouteDisplayName(quote.route) : t(`settings.routePresets.${routePriority}`);
|
|
2464
|
-
return /* @__PURE__ */ jsxRuntime.jsx(accordion.Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(accordion.AccordionItem, { value: "item-1", className: "bg-muted rounded-sm", children: [
|
|
2560
|
+
return /* @__PURE__ */ jsxRuntime.jsx(accordion.Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(accordion.AccordionItem, { value: "item-1", className: "bg-muted/50 rounded-sm", children: [
|
|
2465
2561
|
/* @__PURE__ */ jsxRuntime.jsx(accordion.AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-sm data-[state=open]:pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-center justify-between", children: [
|
|
2466
2562
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-normal text-priority leading-4", children: t("bridge.youWillReceive", { defaultValue: "You will receive" }) }),
|
|
2467
2563
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-transparent hover:bg-transparent shadow-none h-4 p-0 px-0 py-0 flex items-center gap-2", children: [
|
|
@@ -2778,8 +2874,9 @@ function useBridgeTransaction() {
|
|
|
2778
2874
|
}
|
|
2779
2875
|
const srcChain = chains?.find((c) => c.chainKey === quote.srcChainKey);
|
|
2780
2876
|
const dstChain = chains?.find((c) => c.chainKey === quote.dstChainKey);
|
|
2781
|
-
const
|
|
2782
|
-
const
|
|
2877
|
+
const quoteWithFees = addTonNetworkFee(quote, chains) || quote;
|
|
2878
|
+
const amounts = getQuoteAmounts(quoteWithFees, srcToken, dstToken);
|
|
2879
|
+
const fees = getQuoteFees(quoteWithFees, tokens, chains, srcToken, dstToken);
|
|
2783
2880
|
const metadata = {
|
|
2784
2881
|
srcChainName: srcChain?.name || quote.srcChainKey,
|
|
2785
2882
|
dstChainName: dstChain?.name || quote.dstChainKey,
|
|
@@ -3178,6 +3275,7 @@ const WalletModalButton = (props) => {
|
|
|
3178
3275
|
const { icon: IconComponent, name, onClose } = props;
|
|
3179
3276
|
const { chainRegistry } = useChainStrategies();
|
|
3180
3277
|
const { connect, isPending } = wagmi.useConnect();
|
|
3278
|
+
const [isConnecting, setIsConnecting] = react.useState(false);
|
|
3181
3279
|
if (props.variant === "connected") {
|
|
3182
3280
|
const { address, onDisconnect } = props;
|
|
3183
3281
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: buttonBaseClasses, children: [
|
|
@@ -3201,6 +3299,7 @@ const WalletModalButton = (props) => {
|
|
|
3201
3299
|
}
|
|
3202
3300
|
const { walletId, connector } = props;
|
|
3203
3301
|
const handleConnect = async () => {
|
|
3302
|
+
setIsConnecting(true);
|
|
3204
3303
|
try {
|
|
3205
3304
|
if (connector) {
|
|
3206
3305
|
connect({ connector });
|
|
@@ -3213,9 +3312,13 @@ const WalletModalButton = (props) => {
|
|
|
3213
3312
|
onClose?.();
|
|
3214
3313
|
} catch (error) {
|
|
3215
3314
|
console.error("Failed to connect wallet:", error);
|
|
3315
|
+
const errorMessage = error instanceof Error ? error.message : "Failed to connect wallet. Please try again.";
|
|
3316
|
+
sonner.toast.error(errorMessage);
|
|
3317
|
+
} finally {
|
|
3318
|
+
setIsConnecting(false);
|
|
3216
3319
|
}
|
|
3217
3320
|
};
|
|
3218
|
-
const isDisabled = connector ? isPending :
|
|
3321
|
+
const isDisabled = connector ? isPending : isConnecting;
|
|
3219
3322
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3220
3323
|
button.Button,
|
|
3221
3324
|
{
|
|
@@ -3326,7 +3429,7 @@ const WalletSelectModal = () => {
|
|
|
3326
3429
|
}
|
|
3327
3430
|
].filter((category) => category.wallets.length > 0);
|
|
3328
3431
|
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { children: [
|
|
3329
|
-
/* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogHeader, { children: [
|
|
3432
|
+
/* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogHeader, { className: "text-left", children: [
|
|
3330
3433
|
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("wallets.chooseWallet") }),
|
|
3331
3434
|
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogDescription, { children: t("wallets.oneWalletPerEnv") })
|
|
3332
3435
|
] }),
|
|
@@ -3369,7 +3472,7 @@ const WalletSelectModal = () => {
|
|
|
3369
3472
|
] }) });
|
|
3370
3473
|
};
|
|
3371
3474
|
const ProgressStep = ({
|
|
3372
|
-
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-
|
|
3475
|
+
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-16 h-16 animate-spin" })
|
|
3373
3476
|
}) => {
|
|
3374
3477
|
const { t } = useBridgeTranslation();
|
|
3375
3478
|
return /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogContent, { showCloseButton: false, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex relative flex-col gap-4 py-10 px-8 flex-1 items-center justify-start text-center noise bg-background", children: [
|
|
@@ -3379,33 +3482,123 @@ const ProgressStep = ({
|
|
|
3379
3482
|
] }) });
|
|
3380
3483
|
};
|
|
3381
3484
|
const FailedStep = ({
|
|
3382
|
-
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "w-
|
|
3485
|
+
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "w-16 h-16" })
|
|
3383
3486
|
}) => {
|
|
3384
3487
|
const { current, reset } = useTransactionStore();
|
|
3385
3488
|
const { t } = useBridgeTranslation();
|
|
3386
3489
|
return /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { showCloseButton: false, children: [
|
|
3387
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col relative gap-4
|
|
3490
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col relative gap-4 py-10 px-8 flex-1 items-center justify-start text-center noise", children: [
|
|
3388
3491
|
icon,
|
|
3389
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3492
|
+
/* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogHeader, { children: [
|
|
3493
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("transaction.failed") }),
|
|
3494
|
+
current?.errorCode && /* @__PURE__ */ jsxRuntime.jsx(reactDialog.DialogDescription, { children: t(
|
|
3495
|
+
`errors.${current.errorCode}`,
|
|
3496
|
+
current.errorParams || {}
|
|
3497
|
+
) })
|
|
3498
|
+
] })
|
|
3394
3499
|
] }),
|
|
3395
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3500
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", className: "w-full min-w-40", onClick: reset, children: t("common.close") }) })
|
|
3396
3501
|
] });
|
|
3397
3502
|
};
|
|
3503
|
+
const EXPLORER_CONFIGS = {
|
|
3504
|
+
// TON
|
|
3505
|
+
ton: {
|
|
3506
|
+
baseUrl: "https://tonscan.org",
|
|
3507
|
+
txPath: "/tx/"
|
|
3508
|
+
},
|
|
3509
|
+
// TRON
|
|
3510
|
+
tron: {
|
|
3511
|
+
baseUrl: "https://tronscan.org",
|
|
3512
|
+
txPath: "/#/transaction/"
|
|
3513
|
+
},
|
|
3514
|
+
// Ethereum & EVM chains
|
|
3515
|
+
ethereum: {
|
|
3516
|
+
baseUrl: "https://etherscan.io",
|
|
3517
|
+
txPath: "/tx/"
|
|
3518
|
+
},
|
|
3519
|
+
eth: {
|
|
3520
|
+
baseUrl: "https://etherscan.io",
|
|
3521
|
+
txPath: "/tx/"
|
|
3522
|
+
},
|
|
3523
|
+
// BSC (Binance Smart Chain)
|
|
3524
|
+
bsc: {
|
|
3525
|
+
baseUrl: "https://bscscan.com",
|
|
3526
|
+
txPath: "/tx/"
|
|
3527
|
+
},
|
|
3528
|
+
"binance-smart-chain": {
|
|
3529
|
+
baseUrl: "https://bscscan.com",
|
|
3530
|
+
txPath: "/tx/"
|
|
3531
|
+
},
|
|
3532
|
+
// Polygon
|
|
3533
|
+
polygon: {
|
|
3534
|
+
baseUrl: "https://polygonscan.com",
|
|
3535
|
+
txPath: "/tx/"
|
|
3536
|
+
},
|
|
3537
|
+
matic: {
|
|
3538
|
+
baseUrl: "https://polygonscan.com",
|
|
3539
|
+
txPath: "/tx/"
|
|
3540
|
+
},
|
|
3541
|
+
// Avalanche
|
|
3542
|
+
avalanche: {
|
|
3543
|
+
baseUrl: "https://snowtrace.io",
|
|
3544
|
+
txPath: "/tx/"
|
|
3545
|
+
},
|
|
3546
|
+
avax: {
|
|
3547
|
+
baseUrl: "https://snowtrace.io",
|
|
3548
|
+
txPath: "/tx/"
|
|
3549
|
+
},
|
|
3550
|
+
// Arbitrum
|
|
3551
|
+
arbitrum: {
|
|
3552
|
+
baseUrl: "https://arbiscan.io",
|
|
3553
|
+
txPath: "/tx/"
|
|
3554
|
+
},
|
|
3555
|
+
// Optimism
|
|
3556
|
+
optimism: {
|
|
3557
|
+
baseUrl: "https://optimistic.etherscan.io",
|
|
3558
|
+
txPath: "/tx/"
|
|
3559
|
+
},
|
|
3560
|
+
// Base
|
|
3561
|
+
base: {
|
|
3562
|
+
baseUrl: "https://basescan.org",
|
|
3563
|
+
txPath: "/tx/"
|
|
3564
|
+
},
|
|
3565
|
+
// Fantom
|
|
3566
|
+
fantom: {
|
|
3567
|
+
baseUrl: "https://ftmscan.com",
|
|
3568
|
+
txPath: "/tx/"
|
|
3569
|
+
}
|
|
3570
|
+
};
|
|
3571
|
+
function getExplorerTxUrl(chainKey, txHash) {
|
|
3572
|
+
if (!chainKey || !txHash) {
|
|
3573
|
+
return null;
|
|
3574
|
+
}
|
|
3575
|
+
const normalizedChainKey = chainKey.toLowerCase();
|
|
3576
|
+
const config = EXPLORER_CONFIGS[normalizedChainKey];
|
|
3577
|
+
if (!config) {
|
|
3578
|
+
console.warn(
|
|
3579
|
+
`No explorer config found for chain: ${chainKey}. Please add it to EXPLORER_CONFIGS.`
|
|
3580
|
+
);
|
|
3581
|
+
return null;
|
|
3582
|
+
}
|
|
3583
|
+
return `${config.baseUrl}${config.txPath}${txHash}`;
|
|
3584
|
+
}
|
|
3585
|
+
function openTransactionInExplorer(chainKey, txHash) {
|
|
3586
|
+
const url = getExplorerTxUrl(chainKey, txHash);
|
|
3587
|
+
if (url && typeof window !== "undefined") {
|
|
3588
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3398
3591
|
const SuccessStep = ({
|
|
3399
|
-
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "w-
|
|
3592
|
+
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "w-16 h-16" })
|
|
3400
3593
|
}) => {
|
|
3401
3594
|
const { current, reset } = useTransactionStore();
|
|
3402
3595
|
const { t } = useBridgeTranslation();
|
|
3403
3596
|
const metadata = current?.metadata;
|
|
3404
3597
|
const srcTxHash = current?.srcTxHash;
|
|
3405
|
-
const
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3598
|
+
const srcChainKey = current?.quote?.srcChainKey;
|
|
3599
|
+
const handleOpenExplorer = () => {
|
|
3600
|
+
if (srcTxHash && srcChainKey) {
|
|
3601
|
+
openTransactionInExplorer(srcChainKey, srcTxHash);
|
|
3409
3602
|
}
|
|
3410
3603
|
};
|
|
3411
3604
|
return /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { showCloseButton: false, children: [
|
|
@@ -3445,8 +3638,8 @@ const SuccessStep = ({
|
|
|
3445
3638
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3446
3639
|
"button",
|
|
3447
3640
|
{
|
|
3448
|
-
onClick:
|
|
3449
|
-
className: "font-medium hover:underline cursor-pointer",
|
|
3641
|
+
onClick: handleOpenExplorer,
|
|
3642
|
+
className: "font-medium hover:underline cursor-pointer inline-flex items-center gap-1",
|
|
3450
3643
|
children: formatHash(srcTxHash)
|
|
3451
3644
|
}
|
|
3452
3645
|
)
|
|
@@ -3482,7 +3675,7 @@ const useCountdown = (initialSeconds) => {
|
|
|
3482
3675
|
};
|
|
3483
3676
|
};
|
|
3484
3677
|
const ConfirmStep = ({
|
|
3485
|
-
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-
|
|
3678
|
+
icon = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-16 h-16" })
|
|
3486
3679
|
}) => {
|
|
3487
3680
|
const { t } = useBridgeTranslation();
|
|
3488
3681
|
const { formatTime } = useCountdown(90);
|
|
@@ -3636,49 +3829,6 @@ class ChainStrategyRegistry {
|
|
|
3636
3829
|
await strategy.disconnect();
|
|
3637
3830
|
}
|
|
3638
3831
|
}
|
|
3639
|
-
const EVM_CONFIG = {
|
|
3640
|
-
usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
3641
|
-
gasEstimates: {
|
|
3642
|
-
approve: 65000n,
|
|
3643
|
-
bridge: 300000n
|
|
3644
|
-
},
|
|
3645
|
-
gasBuffer: 1.2,
|
|
3646
|
-
// 20% buffer
|
|
3647
|
-
timeout: 3e5,
|
|
3648
|
-
// 5 minutes (increased for slower networks)
|
|
3649
|
-
requiredConfirmations: 3
|
|
3650
|
-
// Wait for 3 confirmations for reorg protection
|
|
3651
|
-
};
|
|
3652
|
-
const TON_CONFIG = {
|
|
3653
|
-
apiUrl: "https://toncenter.com/api/v2",
|
|
3654
|
-
timeout: 36e4,
|
|
3655
|
-
// 6 minutes
|
|
3656
|
-
validUntil: 600
|
|
3657
|
-
// 10 minutes
|
|
3658
|
-
};
|
|
3659
|
-
const TRON_CONFIG = {
|
|
3660
|
-
timeout: 12e4,
|
|
3661
|
-
// 2 minutes (for 19 confirmations)
|
|
3662
|
-
feeLimit: 1e8,
|
|
3663
|
-
// 100 TRX in sun
|
|
3664
|
-
requiredConfirmations: 19,
|
|
3665
|
-
// TRON standard: 19 blocks for confirmation
|
|
3666
|
-
pollingInterval: 3e3
|
|
3667
|
-
// 3 seconds between checks
|
|
3668
|
-
};
|
|
3669
|
-
let tonClientInstance = null;
|
|
3670
|
-
function getTonClient(customClient, apiKey) {
|
|
3671
|
-
if (customClient) {
|
|
3672
|
-
return customClient;
|
|
3673
|
-
}
|
|
3674
|
-
if (!tonClientInstance) {
|
|
3675
|
-
tonClientInstance = new ton.TonClient({
|
|
3676
|
-
endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
|
|
3677
|
-
apiKey
|
|
3678
|
-
});
|
|
3679
|
-
}
|
|
3680
|
-
return tonClientInstance;
|
|
3681
|
-
}
|
|
3682
3832
|
function isNativeAddress(addr) {
|
|
3683
3833
|
if (!addr) return false;
|
|
3684
3834
|
const a = addr.toLowerCase();
|
|
@@ -4422,13 +4572,17 @@ class TonChainStrategy {
|
|
|
4422
4572
|
nativeTokenSymbol,
|
|
4423
4573
|
amount,
|
|
4424
4574
|
balances,
|
|
4575
|
+
nativeDecimals = 9,
|
|
4425
4576
|
reserveFallback
|
|
4426
4577
|
} = params;
|
|
4427
4578
|
const nativeSym = nativeTokenSymbol.toUpperCase();
|
|
4428
4579
|
const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
|
|
4429
4580
|
const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
|
|
4430
|
-
const
|
|
4431
|
-
const
|
|
4581
|
+
const { formatUnits } = await import("ethers");
|
|
4582
|
+
const estimatedGas = Number(
|
|
4583
|
+
formatUnits(TON_CONFIG.estimatedNetworkFee, nativeDecimals)
|
|
4584
|
+
);
|
|
4585
|
+
const requiredNative = estimatedGas > 0 ? estimatedGas : reserveFallback;
|
|
4432
4586
|
const amountNum = amount ?? 0;
|
|
4433
4587
|
let hasEnoughGas = true;
|
|
4434
4588
|
if (isNativeSelected) {
|
|
@@ -4497,12 +4651,24 @@ class TonChainStrategy {
|
|
|
4497
4651
|
const result = await this.config.tonConnectUI.sendTransaction(
|
|
4498
4652
|
transaction2
|
|
4499
4653
|
);
|
|
4500
|
-
const
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4654
|
+
const bocBase64 = result.boc;
|
|
4655
|
+
try {
|
|
4656
|
+
const inMessage = core.loadMessage(core.Cell.fromBase64(bocBase64).beginParse());
|
|
4657
|
+
const messageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
4658
|
+
const hexHash = messageHash.toString("hex");
|
|
4659
|
+
onFirstHash?.(hexHash);
|
|
4660
|
+
return {
|
|
4661
|
+
chainKey: "ton",
|
|
4662
|
+
hash: hexHash
|
|
4663
|
+
};
|
|
4664
|
+
} catch (error) {
|
|
4665
|
+
console.error("Error parsing BOC to hex hash:", error);
|
|
4666
|
+
onFirstHash?.(bocBase64);
|
|
4667
|
+
return {
|
|
4668
|
+
chainKey: "ton",
|
|
4669
|
+
hash: bocBase64
|
|
4670
|
+
};
|
|
4671
|
+
}
|
|
4506
4672
|
} catch (error) {
|
|
4507
4673
|
throw toChainStrategyError(error, "ton", "transaction");
|
|
4508
4674
|
}
|
|
@@ -4555,20 +4721,31 @@ class TonChainStrategy {
|
|
|
4555
4721
|
};
|
|
4556
4722
|
return core.beginCell().store(core.storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
|
|
4557
4723
|
}
|
|
4558
|
-
async checkTonTransaction(
|
|
4724
|
+
async checkTonTransaction(hashOrBoc, timeoutMs = 36e4) {
|
|
4559
4725
|
const deadline = Date.now() + timeoutMs;
|
|
4560
4726
|
const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
|
|
4561
4727
|
try {
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4728
|
+
let targetMessageHash;
|
|
4729
|
+
let accountAddress;
|
|
4730
|
+
try {
|
|
4731
|
+
const inMessage = core.loadMessage(core.Cell.fromBase64(hashOrBoc).beginParse());
|
|
4732
|
+
if (inMessage.info.type !== "external-in") {
|
|
4733
|
+
console.debug(
|
|
4734
|
+
"Expected external-in message, got:",
|
|
4735
|
+
inMessage.info.type
|
|
4736
|
+
);
|
|
4737
|
+
return false;
|
|
4738
|
+
}
|
|
4739
|
+
accountAddress = inMessage.info.dest;
|
|
4740
|
+
targetMessageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
4741
|
+
} catch {
|
|
4742
|
+
targetMessageHash = Buffer.from(hashOrBoc, "hex");
|
|
4743
|
+
if (!this.config.tonAddress) {
|
|
4744
|
+
console.debug("No wallet address available for hex hash lookup");
|
|
4745
|
+
return false;
|
|
4746
|
+
}
|
|
4747
|
+
accountAddress = core.Address.parse(this.config.tonAddress);
|
|
4569
4748
|
}
|
|
4570
|
-
const accountAddress = inMessage.info.dest;
|
|
4571
|
-
const targetMessageHash = this.getNormalizedExtMessageHash(inMessage);
|
|
4572
4749
|
let lt = void 0;
|
|
4573
4750
|
let hash = void 0;
|
|
4574
4751
|
while (Date.now() < deadline) {
|
|
@@ -4580,7 +4757,7 @@ class TonChainStrategy {
|
|
|
4580
4757
|
archival: true
|
|
4581
4758
|
});
|
|
4582
4759
|
if (transactions.length === 0) {
|
|
4583
|
-
await new Promise((r) => setTimeout(r,
|
|
4760
|
+
await new Promise((r) => setTimeout(r, TON_CONFIG.pollingInterval));
|
|
4584
4761
|
lt = void 0;
|
|
4585
4762
|
hash = void 0;
|
|
4586
4763
|
continue;
|
|
@@ -4599,9 +4776,10 @@ class TonChainStrategy {
|
|
|
4599
4776
|
const lastTx = transactions[transactions.length - 1];
|
|
4600
4777
|
lt = lastTx.lt.toString();
|
|
4601
4778
|
hash = lastTx.hash().toString("base64");
|
|
4779
|
+
await new Promise((r) => setTimeout(r, TON_CONFIG.pollingInterval));
|
|
4602
4780
|
} catch (error) {
|
|
4603
4781
|
console.debug("Error fetching transactions:", error);
|
|
4604
|
-
await new Promise((r) => setTimeout(r,
|
|
4782
|
+
await new Promise((r) => setTimeout(r, TON_CONFIG.pollingInterval));
|
|
4605
4783
|
lt = void 0;
|
|
4606
4784
|
hash = void 0;
|
|
4607
4785
|
}
|
|
@@ -4628,9 +4806,14 @@ class TronChainStrategy {
|
|
|
4628
4806
|
return "TRON Chain Strategy";
|
|
4629
4807
|
}
|
|
4630
4808
|
async connect() {
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4809
|
+
if (!this.isTronLinkInstalled()) {
|
|
4810
|
+
if (typeof window !== "undefined") {
|
|
4811
|
+
window.open("https://www.tronlink.org/", "_blank");
|
|
4812
|
+
}
|
|
4813
|
+
throw new WalletNotFoundError(
|
|
4814
|
+
"tron",
|
|
4815
|
+
"TronLink wallet is not installed. Please install TronLink extension and try again."
|
|
4816
|
+
);
|
|
4634
4817
|
}
|
|
4635
4818
|
this.config.tronSelect(tronwalletAdapters.TronLinkAdapterName);
|
|
4636
4819
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -4909,6 +5092,23 @@ class TronChainStrategy {
|
|
|
4909
5092
|
getTronWeb() {
|
|
4910
5093
|
return typeof window !== "undefined" ? window.tronWeb : void 0;
|
|
4911
5094
|
}
|
|
5095
|
+
/**
|
|
5096
|
+
* Check if TronLink wallet is actually installed
|
|
5097
|
+
* This excludes Bybit Wallet which also injects tronLink for compatibility
|
|
5098
|
+
*/
|
|
5099
|
+
isTronLinkInstalled() {
|
|
5100
|
+
if (typeof window === "undefined") {
|
|
5101
|
+
return false;
|
|
5102
|
+
}
|
|
5103
|
+
const hasBybitWallet = typeof window.bybitWallet !== "undefined" && typeof window.bybitWallet.tronLink !== "undefined";
|
|
5104
|
+
if (hasBybitWallet && !window.tronLink) {
|
|
5105
|
+
return false;
|
|
5106
|
+
}
|
|
5107
|
+
if (!window.tronLink) {
|
|
5108
|
+
return false;
|
|
5109
|
+
}
|
|
5110
|
+
return true;
|
|
5111
|
+
}
|
|
4912
5112
|
hexToAscii(h) {
|
|
4913
5113
|
if (!h) return null;
|
|
4914
5114
|
const clean = h.replace(/^0x/, "");
|
|
@@ -5312,7 +5512,7 @@ const routePresets = [
|
|
|
5312
5512
|
RoutePriority.CHEAPEST,
|
|
5313
5513
|
RoutePriority.RECOMMENDED
|
|
5314
5514
|
];
|
|
5315
|
-
const
|
|
5515
|
+
const SettingsModal = ({ isOpen, onClose }) => {
|
|
5316
5516
|
const { t } = useBridgeTranslation();
|
|
5317
5517
|
const { toChain } = useChainsStore();
|
|
5318
5518
|
const { tokens } = useTokensStore();
|
|
@@ -5345,8 +5545,8 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
5345
5545
|
);
|
|
5346
5546
|
const activeBtn = "bg-primary hover:bg-primary/80 text-primary-foreground transition-colors";
|
|
5347
5547
|
const notActiveBtn = "bg-accent hover:bg-accent/80 text-accent-foreground transition-colors";
|
|
5348
|
-
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { children: [
|
|
5349
|
-
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title") }) }),
|
|
5548
|
+
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { onOpenAutoFocus: (e) => e.preventDefault(), children: [
|
|
5549
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title") }) }),
|
|
5350
5550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
5351
5551
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
|
|
5352
5552
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
@@ -5374,6 +5574,7 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
5374
5574
|
badge.Badge,
|
|
5375
5575
|
{
|
|
5376
5576
|
onClick: () => setGasPreset(g),
|
|
5577
|
+
size: "lg",
|
|
5377
5578
|
className: utils.cn(
|
|
5378
5579
|
"cursor-pointer",
|
|
5379
5580
|
gasPreset === g ? activeBtn : notActiveBtn
|
|
@@ -5400,6 +5601,7 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
5400
5601
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: slippagePresets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5401
5602
|
badge.Badge,
|
|
5402
5603
|
{
|
|
5604
|
+
size: "lg",
|
|
5403
5605
|
onClick: () => {
|
|
5404
5606
|
const bps = parseFloat(p.replace("%", "")) * 100;
|
|
5405
5607
|
setSlippageBps(bps);
|
|
@@ -5423,6 +5625,7 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
5423
5625
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-2", children: routePresets.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5424
5626
|
badge.Badge,
|
|
5425
5627
|
{
|
|
5628
|
+
size: "lg",
|
|
5426
5629
|
onClick: () => setRoutePriority(r),
|
|
5427
5630
|
className: utils.cn(
|
|
5428
5631
|
"cursor-pointer",
|
|
@@ -5615,7 +5818,7 @@ const TokenSelectModal = ({
|
|
|
5615
5818
|
);
|
|
5616
5819
|
const hasNoResults = tokensToRender.length === 0 && willChangeSrcTokens.length === 0;
|
|
5617
5820
|
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "max-h-[90dvh] h-[90dvh] overflow-hidden flex flex-col", children: [
|
|
5618
|
-
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectToken") }) }),
|
|
5821
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { className: "text-left", children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectToken") }) }),
|
|
5619
5822
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5620
5823
|
SearchInput,
|
|
5621
5824
|
{
|
|
@@ -5839,7 +6042,7 @@ const Toolbar = () => {
|
|
|
5839
6042
|
}
|
|
5840
6043
|
}
|
|
5841
6044
|
),
|
|
5842
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6045
|
+
/* @__PURE__ */ jsxRuntime.jsx(SettingsModal, { isOpen: isOpenSettings, onClose: onCloseSettings })
|
|
5843
6046
|
] });
|
|
5844
6047
|
};
|
|
5845
6048
|
const EvaaBridgeWithProviders = (props) => {
|
|
@@ -6101,6 +6304,7 @@ exports.DEFAULT_SLIPPAGE_BPS = DEFAULT_SLIPPAGE_BPS;
|
|
|
6101
6304
|
exports.EvaaBridge = EvaaBridge;
|
|
6102
6305
|
exports.RoutePriority = RoutePriority;
|
|
6103
6306
|
exports.RouteType = RouteType;
|
|
6307
|
+
exports.addTonNetworkFee = addTonNetworkFee;
|
|
6104
6308
|
exports.addrForApi = addrForApi;
|
|
6105
6309
|
exports.buildAssetMatrix = buildAssetMatrix;
|
|
6106
6310
|
exports.calculateMinReceived = calculateMinReceived;
|