@rash2x/bridge-widget 0.1.13 → 0.1.16

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.
@@ -31,16 +31,16 @@ const i18n = require("i18next");
31
31
  const zustand = require("zustand");
32
32
  const button = require("@/components/ui/button");
33
33
  const dialog = require("@/components/ui/dialog");
34
+ const badge = require("@/components/ui/badge");
34
35
  const tooltip = require("@/components/ui/tooltip");
35
36
  const utils = require("@/lib/utils");
36
- const input = require("@/components/ui/input");
37
+ const skeleton = require("@/components/ui/skeleton");
37
38
  const wagmi = require("wagmi");
38
39
  const tronwalletAdapterReactHooks = require("@tronweb3/tronwallet-adapter-react-hooks");
39
40
  const uiReact = require("@tonconnect/ui-react");
40
41
  const reactQuery = require("@tanstack/react-query");
41
42
  const core = require("@ton/core");
42
- const reactWindow = require("react-window");
43
- const skeleton = require("@/components/ui/skeleton");
43
+ const input = require("@/components/ui/input");
44
44
  const card = require("@/components/ui/card");
45
45
  const _switch = require("@/components/ui/switch");
46
46
  const lucideReact = require("lucide-react");
@@ -53,7 +53,7 @@ const ton = require("@ton/ton");
53
53
  const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
54
54
  const common$1 = { "connecting": "Connecting…", "initializing": "Initializing...", "loading": "Loading...", "paste": "paste", "close": "Close", "zeroPlaceholder": "0", "nativeToken": "Native Token" };
55
55
  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", "tonAddressPlaceholder": "TON address", "evmAddressPlaceholder": "0x… EVM address", "addressDoesntMatch": "Address doesn't match the {{network}} network", "checkBeforeTransfer": "Check correctness before transfer" };
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
57
  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}}", "successTitle": "Success", "bridged": "Bridged", "transferTitle": "Transfer", "hash": "Hash", "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
58
  const app$1 = { "stargateWidgetName": "Stargate Bridge Widget", "liveWidget": "Live Widget", "getStarted": "Get Started" };
59
59
  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" } };
@@ -67,7 +67,7 @@ const en = {
67
67
  };
68
68
  const common = { "connecting": "Подключение…", "initializing": "Инициализация...", "loading": "Загрузка...", "paste": "вставить", "close": "Закрыть", "zeroPlaceholder": "0", "nativeToken": "Нативный токен" };
69
69
  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": "Подключить кошелёк" };
70
- const bridge = { "sourceNetwork": "Исходная сеть", "destinationNetwork": "Целевая сеть", "selectToken": "Выбрать токен", "selectNetwork": "Выбрать сеть", "searchToken": "Поиск токена", "searchDestinationChain": "Поиск целевой сети", "myTokens": "Мои токены", "allTokens": "Все токены", "willChangeSourceChain": "Сменит исходную сеть", "noBalancesFound": "Балансы не найдены.", "noResults": "Нет результатов", "sendToAnotherAddress": "Отправить на другой адрес", "youWillReceive": "Вы получите", "tonAddressPlaceholder": "TON адрес", "evmAddressPlaceholder": "0x… EVM адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
70
+ const bridge = { "sourceNetwork": "Исходная сеть", "destinationNetwork": "Целевая сеть", "selectToken": "Выбрать токен", "selectNetwork": "Выбрать сеть", "searchToken": "Поиск токена", "searchDestinationChain": "Поиск целевой сети", "myTokens": "Мои токены", "allTokens": "Все токены", "willChangeSourceChain": "Сменит исходную сеть", "noBalancesFound": "Балансы не найдены.", "noResults": "Нет результатов", "sendToAnotherAddress": "Отправить на другой адрес", "youWillReceive": "Вы получите", "anotherAddressPlaceholder": "Адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
71
71
  const transaction = { "enterAmount": "Введите сумму", "transfer": "Перевести", "getQuote": "Получить котировку", "quoting": "Расчет котировки...", "failed": "Ошибка транзакции", "confirm": "Подтвердите транзакцию", "signTransaction": "Подпишите транзакцию в кошельке", "inProgress": "Выполнение...", "checkingBalance": "Проверка баланса...", "insufficientBalance": "Недостаточно средств", "amountTooSmall": "Минимум {{min}}", "amountTooLarge": "Максимум {{max}}", "successTitle": "Успех", "bridged": "Переведено", "transferTitle": "Перевод", "hash": "Хэш", "route": "Маршрут", "estTime": "Время", "slippage": "Проскальзывание", "minimumReceived": "Минимум к получению", "totalFee": "Общая комиссия", "noRouteFound": "Маршрут не найден", "notEnoughGas": "Недостаточно газа", "noRouteFoundForSettings": "Маршрут не найден для текущих настроек.", "tryAdjustSettings": "Попробуйте отключить Gas on Destination или измените сумму/сети.", "quoteError": "Ошибка котировки" };
72
72
  const app = { "stargateWidgetName": "Виджет Stargate Bridge", "liveWidget": "Живой виджет", "getStarted": "Начало работы" };
73
73
  const settings = { "title": "Настройки", "gasOnDestination": "Газ на назначении", "slippageTolerance": "Толерантность к проскальзыванию", "routePriority": "Приоритет маршрута", "highSlippageWarning": "Высокое проскальзывание", "gasPresets": { "auto": "Авто", "none": "Нет", "medium": "Средний", "max": "Макс" }, "routePresets": { "fastest": "Быстрейший", "cheapest": "Дешевейший", "recommended": "Рекомендуемый" } };
@@ -926,21 +926,21 @@ const SettingModal = ({ isOpen, onClose }) => {
926
926
  toChain?.chainKey,
927
927
  dstNativeToken?.decimals || 18
928
928
  );
929
- const activeBtn = "bg-settings-active hover:bg-settings-active/80 text-settings-active-foreground";
930
- const notActiveBtn = "bg-settings-button hover:bg-settings-button/80 text-settings-button-foreground";
929
+ const activeBtn = "bg-primary hover:bg-primary/80 text-primary-foreground transition-colors";
930
+ const notActiveBtn = "bg-accent hover:bg-accent/80 text-accent-foreground transition-colors";
931
931
  return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { children: [
932
- /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title", { defaultValue: "Settings" }) }) }),
932
+ /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title") }) }),
933
933
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
934
934
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
935
935
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
936
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
937
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-3.5", children: t("settings.gasOnDestination") }),
936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
937
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-4", children: t("settings.gasOnDestination") }),
938
938
  /* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.gasOnDestination"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
939
939
  ] }),
940
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground text-sm font-medium leading-3.5", children: formatUsd(gasUsdValue) })
940
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground text-sm font-medium leading-4", children: formatUsd(gasUsdValue) })
941
941
  ] }),
942
942
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
943
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center w-1/3 gap-1.5 shrink-0", children: [
943
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center w-1/3 gap-2 shrink-0", children: [
944
944
  /* @__PURE__ */ jsxRuntime.jsx(
945
945
  TokenSymbol,
946
946
  {
@@ -953,13 +953,12 @@ const SettingModal = ({ isOpen, onClose }) => {
953
953
  gasDisplayAmount < 1e-3 ? 6 : 3
954
954
  ) }) })
955
955
  ] }),
956
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", children: gasPresets.map((g) => /* @__PURE__ */ jsxRuntime.jsx(
957
- button.Button,
956
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: gasPresets.map((g) => /* @__PURE__ */ jsxRuntime.jsx(
957
+ badge.Badge,
958
958
  {
959
- type: "button",
960
959
  onClick: () => setGasPreset(g),
961
960
  className: utils.cn(
962
- `cursor-pointer rounded-6 px-2 py-2.5 h-7 text-xs font-semibold leading-2 transition`,
961
+ "cursor-pointer",
963
962
  gasPreset === g ? activeBtn : notActiveBtn
964
963
  ),
965
964
  children: t(`settings.gasPresets.${g}`)
@@ -971,26 +970,25 @@ const SettingModal = ({ isOpen, onClose }) => {
971
970
  /* @__PURE__ */ jsxRuntime.jsx("hr", {}),
972
971
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
973
972
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
974
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
973
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
975
974
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-3.5", children: t("settings.slippageTolerance") }),
976
975
  /* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.slippageTolerance"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
977
976
  ] }),
978
- slippageBps >= 500 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-orange-500 text-xs font-medium", children: t("settings.highSlippageWarning", {
977
+ slippageBps >= 500 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-xs font-medium", children: t("settings.highSlippageWarning", {
979
978
  defaultValue: "High slippage warning"
980
979
  }) })
981
980
  ] }),
982
981
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-6", children: [
983
982
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-foreground leading-4.5 font-semibold h-4.5", children: slippagePercent }) }),
984
983
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: slippagePresets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
985
- button.Button,
984
+ badge.Badge,
986
985
  {
987
- type: "button",
988
986
  onClick: () => {
989
987
  const bps = parseFloat(p.replace("%", "")) * 100;
990
988
  setSlippageBps(bps);
991
989
  },
992
990
  className: utils.cn(
993
- `cursor-pointer rounded-6 px-2 py-2.5 h-7 text-xs font-semibold leading-2 transition`,
991
+ "cursor-pointer",
994
992
  activeSlippagePreset === p ? activeBtn : notActiveBtn
995
993
  ),
996
994
  children: p
@@ -1001,17 +999,16 @@ const SettingModal = ({ isOpen, onClose }) => {
1001
999
  ] }),
1002
1000
  /* @__PURE__ */ jsxRuntime.jsx("hr", {}),
1003
1001
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
1004
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1002
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1005
1003
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-3.5", children: t("settings.routePriority") }),
1006
1004
  /* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.routePriority"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
1007
1005
  ] }) }),
1008
1006
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-2", children: routePresets.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
1009
- button.Button,
1007
+ badge.Badge,
1010
1008
  {
1011
- type: "button",
1012
1009
  onClick: () => setRoutePriority(r),
1013
1010
  className: utils.cn(
1014
- `cursor-pointer rounded-6 px-2 py-2.5 h-7 text-xs font-semibold leading-2 transition`,
1011
+ "cursor-pointer",
1015
1012
  routePriority === r ? activeBtn : notActiveBtn
1016
1013
  ),
1017
1014
  children: t(`settings.routePresets.${r}`)
@@ -1079,168 +1076,31 @@ function useChainStrategies() {
1079
1076
  }
1080
1077
  return context;
1081
1078
  }
1082
- function toLD(human, decimals) {
1083
- const [i = "0", f = ""] = human.replace(",", ".").split(".");
1084
- const frac = (f + "0".repeat(decimals)).slice(0, decimals);
1085
- return BigInt(i + frac).toString();
1086
- }
1087
- function fromLD(ld, decimals) {
1088
- const bi = BigInt(ld || "0");
1089
- if (decimals === 0) return Number(bi);
1090
- const base = BigInt(10) ** BigInt(decimals);
1091
- const int = bi / base;
1092
- const frac = Number(bi % base) / Number(base);
1093
- return Number(int) + frac;
1094
- }
1095
- function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
1096
- if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
1097
- const byChain = assetMatrix[assetSymbol.toUpperCase()];
1098
- return byChain?.[chainKey];
1099
- }
1100
- const DEFAULT_SLIPPAGE_BPS = 50;
1101
- const lower = (s) => (s ?? "").toLowerCase();
1102
- const normSym = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
1103
- function tonNorm(addr) {
1104
- if (!addr) return null;
1079
+ const isEvmAddress = (addr) => {
1080
+ return /^0x[0-9a-fA-F]{40}$/.test(addr ?? "");
1081
+ };
1082
+ const isTronAddress = (addr) => {
1083
+ return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(addr ?? "");
1084
+ };
1085
+ const isTonAddress = (addr) => {
1086
+ if (!addr) return false;
1105
1087
  try {
1106
1088
  if (addr.includes(":")) {
1107
- return core.Address.parseRaw(addr).toString({
1108
- bounceable: false,
1109
- urlSafe: true
1110
- });
1089
+ core.Address.parseRaw(addr);
1090
+ return true;
1111
1091
  }
1112
- return core.Address.parse(addr).toString({ bounceable: false, urlSafe: true });
1092
+ core.Address.parse(addr);
1093
+ return true;
1113
1094
  } catch {
1114
- return null;
1095
+ return false;
1115
1096
  }
1116
- }
1117
- const isEvmAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a ?? "");
1118
- const isTronAddress = (a) => /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(a ?? "");
1119
- const isZeroAddr = (a) => (
1120
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1121
- !!a && /^0x0{40}$/i.test(a) || /^0x[eE]{4}e{36}$/i.test(a)
1122
- );
1097
+ };
1123
1098
  function isAddressValidForChain(chainKey, addr) {
1124
1099
  if (!chainKey || !addr) return false;
1125
- if (chainKey === "ton") return tonNorm(addr) !== null;
1100
+ if (chainKey === "ton") return isTonAddress(addr);
1126
1101
  if (chainKey === "tron") return isTronAddress(addr);
1127
1102
  return isEvmAddress(addr);
1128
1103
  }
1129
- function addrForApi(chainKey, addr) {
1130
- if (chainKey === "ton") return tonNorm(addr);
1131
- return addr;
1132
- }
1133
- function isNativeAddrEqual(chain, tokenAddr) {
1134
- if (!chain) return false;
1135
- if (!tokenAddr) return false;
1136
- if (isZeroAddr(tokenAddr)) return true;
1137
- const nativeAddr = chain.nativeCurrency?.address;
1138
- if (!nativeAddr) return false;
1139
- if (chain.chainKey === "ton") {
1140
- const a = tonNorm(tokenAddr);
1141
- const b = tonNorm(nativeAddr);
1142
- return !!a && !!b && a === b;
1143
- }
1144
- return lower(nativeAddr) === lower(tokenAddr);
1145
- }
1146
- function findNativeMeta(tokens, chain) {
1147
- if (!chain) return { decimals: 18, priceUsd: void 0 };
1148
- const sym = normSym(chain.nativeCurrency?.symbol);
1149
- if (!sym) {
1150
- return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1151
- }
1152
- const sameChain = tokens?.find(
1153
- (t) => t.chainKey === chain.chainKey && normSym(t.symbol) === sym
1154
- ) ?? void 0;
1155
- if (sameChain)
1156
- return { decimals: sameChain.decimals, priceUsd: sameChain.price?.usd };
1157
- const anyChain = tokens?.find((t) => normSym(t.symbol) === sym);
1158
- if (anyChain)
1159
- return { decimals: anyChain.decimals, priceUsd: anyChain.price?.usd };
1160
- return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1161
- }
1162
- function lookupTokenMeta(tokens, chains, chainKey, tokenAddr) {
1163
- if (!chainKey) return { decimals: 18, priceUsd: void 0 };
1164
- const chain = chains?.find((c) => c.chainKey === chainKey);
1165
- const hit = tokens?.find((t) => {
1166
- if (t.chainKey !== chainKey) return false;
1167
- if (chainKey === "ton") {
1168
- const a = tonNorm(t.address);
1169
- const b = tonNorm(tokenAddr);
1170
- return !!a && !!b && a === b;
1171
- }
1172
- return lower(t.address) === lower(tokenAddr);
1173
- }) ?? void 0;
1174
- if (hit) return { decimals: hit.decimals, priceUsd: hit.price?.usd };
1175
- if (isNativeAddrEqual(chain, tokenAddr)) {
1176
- return findNativeMeta(tokens, chain);
1177
- }
1178
- return { decimals: chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1179
- }
1180
- function computeFeesUsdFromArray(fees, tokens, chains) {
1181
- if (!fees?.length) return { totalUsd: 0 };
1182
- let total = 0;
1183
- let protocolFeeUsd = 0;
1184
- let messageFeeUsd = 0;
1185
- const byType = /* @__PURE__ */ new Map();
1186
- for (const f of fees) {
1187
- let usd = Number(f.usd ?? 0);
1188
- if (!usd) {
1189
- const { decimals, priceUsd } = lookupTokenMeta(
1190
- tokens,
1191
- chains,
1192
- f.chainKey,
1193
- f.token
1194
- );
1195
- const human = fromLD(String(f.amount ?? "0"), decimals);
1196
- usd = (priceUsd ?? 0) * human;
1197
- }
1198
- total += usd;
1199
- const type = (f.type ?? "other").toLowerCase();
1200
- byType.set(type, (byType.get(type) ?? 0) + usd);
1201
- if (type === "protocol" || type === "service") {
1202
- protocolFeeUsd += usd;
1203
- } else if (type === "message" || type === "gas" || type === "network") {
1204
- messageFeeUsd += usd;
1205
- }
1206
- }
1207
- const serviceUsd = byType.get("protocol") ?? byType.get("service") ?? void 0;
1208
- const blockchainUsd = byType.get("gas") ?? byType.get("network") ?? byType.get("message") ?? void 0;
1209
- return {
1210
- totalUsd: total,
1211
- protocolFeeUsd: protocolFeeUsd > 0 ? protocolFeeUsd : void 0,
1212
- messageFeeUsd: messageFeeUsd > 0 ? messageFeeUsd : void 0,
1213
- serviceUsd,
1214
- blockchainUsd
1215
- };
1216
- }
1217
- function dollarsFromNativeFees(feeNative, feeLzToken, chain, tokens) {
1218
- let total = 0;
1219
- if (feeNative && chain) {
1220
- const { decimals, priceUsd } = findNativeMeta(tokens, chain);
1221
- const human = fromLD(String(feeNative), decimals);
1222
- total += (priceUsd ?? 0) * human;
1223
- }
1224
- if (feeLzToken) {
1225
- const lz = tokens?.find((t) => normSym(t.symbol) === "LZ");
1226
- if (lz?.price?.usd && lz.decimals != null) {
1227
- const human = fromLD(String(feeLzToken), lz.decimals);
1228
- total += lz.price.usd * human;
1229
- }
1230
- }
1231
- return total;
1232
- }
1233
- function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
1234
- if (!fees?.length || !dstTokenAddr || !dstChainKey) return "0";
1235
- let acc = 0n;
1236
- for (const f of fees) {
1237
- if (f.chainKey !== dstChainKey) continue;
1238
- const same = dstChainKey === "ton" ? tonNorm(f.token) === tonNorm(dstTokenAddr) : lower(f.token) === lower(dstTokenAddr);
1239
- if (!same) continue;
1240
- acc += BigInt(f.amount ?? "0");
1241
- }
1242
- return acc.toString();
1243
- }
1244
1104
  function useBalances(chainKey, address, priorityTokenSymbol) {
1245
1105
  const { chainRegistry } = useChainStrategies();
1246
1106
  const { assetMatrix } = useTokensStore();
@@ -1302,10 +1162,92 @@ function useBalances(chainKey, address, priorityTokenSymbol) {
1302
1162
  query
1303
1163
  };
1304
1164
  }
1305
- function useTokenSelectData(items) {
1165
+ const SearchInput = ({
1166
+ placeholder,
1167
+ value,
1168
+ onChange,
1169
+ className,
1170
+ containerClassName
1171
+ }) => {
1172
+ const [isFocused, setIsFocused] = require$$0.useState(false);
1173
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1174
+ "div",
1175
+ {
1176
+ className: utils.cn(
1177
+ "flex items-center gap-3 px-5 py-4 bg-input rounded-md h-13 transition-all duration-200",
1178
+ isFocused ? "border border-ring" : "border border-transparent",
1179
+ containerClassName
1180
+ ),
1181
+ children: [
1182
+ /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "size-6 text-input-icon" }),
1183
+ /* @__PURE__ */ jsxRuntime.jsx(
1184
+ input.Input,
1185
+ {
1186
+ placeholder,
1187
+ className: utils.cn(
1188
+ "w-full outline-none bg-transparent border-none ring-0 leading-0 p-0 h-6 text-base text-input-text placeholder:text-input-placeholder bg-none dark:bg-transparent",
1189
+ className
1190
+ ),
1191
+ value,
1192
+ onChange: (e) => onChange(e.target.value),
1193
+ onFocus: () => setIsFocused(true),
1194
+ onBlur: () => setIsFocused(false)
1195
+ }
1196
+ )
1197
+ ]
1198
+ }
1199
+ );
1200
+ };
1201
+ const TokenRow = ({
1202
+ symbol,
1203
+ name,
1204
+ isSelected,
1205
+ hasAnyWallet,
1206
+ balance,
1207
+ usdValue,
1208
+ isBalanceLoading,
1209
+ onPick
1210
+ }) => {
1211
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1212
+ button.Button,
1213
+ {
1214
+ onClick: onPick,
1215
+ className: `w-full bg-transparent flex items-center justify-between gap-3 px-5 hover:bg-accent hover:scale-100 ${isSelected ? "border border-ring" : ""}`,
1216
+ children: [
1217
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1218
+ /* @__PURE__ */ jsxRuntime.jsx(
1219
+ TokenSymbol,
1220
+ {
1221
+ symbol,
1222
+ className: "size-8 rounded-full",
1223
+ alt: symbol
1224
+ }
1225
+ ),
1226
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-1", children: [
1227
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-lg leading-4 truncate flex items-center gap-1", children: symbol }),
1228
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground truncate", children: name })
1229
+ ] })
1230
+ ] }),
1231
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right space-y-1", children: isBalanceLoading && hasAnyWallet ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end gap-1", children: [
1232
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-5 w-16 rounded-md" }),
1233
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-3 w-12 rounded-md" })
1234
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1235
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-extrabold text-foreground text-lg leading-4 truncate", children: hasAnyWallet ? formatBalance(balance) : "—" }),
1236
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 text-muted-foreground", children: hasAnyWallet && balance > 0 && usdValue > 0 ? formatUsd(usdValue) : "—" })
1237
+ ] }) })
1238
+ ]
1239
+ }
1240
+ );
1241
+ };
1242
+ const TokenSelectModal = ({
1243
+ isOpen,
1244
+ onClose,
1245
+ items,
1246
+ onChangeAsset
1247
+ }) => {
1248
+ const { t } = useBridgeTranslation();
1306
1249
  const [query, setQuery] = require$$0.useState("");
1307
1250
  const [tab, setTab] = require$$0.useState("my");
1308
- const [isFocused, setIsFocused] = require$$0.useState(false);
1309
1251
  const { srcAddress } = useAddresses();
1310
1252
  const { fromChain, setFromChain, chains } = useChainsStore();
1311
1253
  const { assetMatrix, selectedAssetSymbol } = useTokensStore();
@@ -1390,159 +1332,7 @@ function useTokenSelectData(items) {
1390
1332
  const resetState = require$$0.useCallback(() => {
1391
1333
  setQuery("");
1392
1334
  setTab("my");
1393
- setIsFocused(false);
1394
1335
  }, []);
1395
- return {
1396
- query,
1397
- setQuery,
1398
- tab,
1399
- setTab,
1400
- isFocused,
1401
- setIsFocused,
1402
- effectiveTab,
1403
- resetState,
1404
- fromChain,
1405
- setFromChain,
1406
- selectedAssetSymbol,
1407
- balancesQuery,
1408
- groupedTokens,
1409
- myTokens,
1410
- getBalance,
1411
- getTokenUsdValue,
1412
- findFirstAvailableChain,
1413
- hasAnyWallet
1414
- };
1415
- }
1416
- const TokenRow = ({
1417
- symbol,
1418
- name,
1419
- isSelected,
1420
- hasAnyWallet,
1421
- balance,
1422
- usdValue,
1423
- isBalanceLoading,
1424
- onPick
1425
- }) => {
1426
- return /* @__PURE__ */ jsxRuntime.jsxs(
1427
- button.Button,
1428
- {
1429
- onClick: onPick,
1430
- className: `w-full h-12.5 rounded-md cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-modal-item-hover transition-[300] ${isSelected ? "border border-ring" : ""}`,
1431
- children: [
1432
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1433
- /* @__PURE__ */ jsxRuntime.jsx(
1434
- TokenSymbol,
1435
- {
1436
- symbol,
1437
- className: "size-7.5 max-w-7.5 rounded-full",
1438
- alt: symbol
1439
- }
1440
- ),
1441
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-1", children: [
1442
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-lg leading-4 truncate flex items-center gap-1", children: symbol }),
1443
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground truncate", children: name })
1444
- ] })
1445
- ] }),
1446
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right space-y-1", children: isBalanceLoading && hasAnyWallet ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end gap-1", children: [
1447
- /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-5 w-16 rounded-md" }),
1448
- /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-3 w-12 rounded-md" })
1449
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1450
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-extrabold text-foreground text-lg leading-4 truncate", children: hasAnyWallet ? formatBalance(balance) : "—" }),
1451
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 text-muted-foreground", children: hasAnyWallet && balance > 0 && usdValue > 0 ? formatUsd(usdValue) : "—" })
1452
- ] }) })
1453
- ]
1454
- }
1455
- );
1456
- };
1457
- const HEADER_H = 30;
1458
- const ROW_H = 50;
1459
- const HEADER_TOP_GAP = 30;
1460
- const VirtualizedTokenList = ({
1461
- nodes,
1462
- balancesLoading,
1463
- hasAnyWallet,
1464
- selectedAssetSymbol,
1465
- getBalance,
1466
- getTokenUsdValue,
1467
- onPick
1468
- }) => {
1469
- const Row = ({ index, style }) => {
1470
- const node = nodes[index];
1471
- if (node.kind === "header") {
1472
- const gap = index === 0 ? 0 : HEADER_TOP_GAP;
1473
- return /* @__PURE__ */ jsxRuntime.jsx(
1474
- "div",
1475
- {
1476
- style: { ...style, paddingTop: gap },
1477
- className: "px-5 flex leading-4 text-base py-1.5 font-semibold text-muted-foreground uppercase",
1478
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: node.title })
1479
- }
1480
- );
1481
- }
1482
- const bal = getBalance(node.token.symbol);
1483
- const usd = getTokenUsdValue(node.token.symbol, node.token.price?.usd);
1484
- const isSelected = selectedAssetSymbol?.toUpperCase() === node.token.symbol.toUpperCase();
1485
- return /* @__PURE__ */ jsxRuntime.jsx(
1486
- TokenRow,
1487
- {
1488
- symbol: node.token.symbol,
1489
- name: node.token.name,
1490
- isSelected: !!isSelected,
1491
- hasAnyWallet,
1492
- balance: bal,
1493
- usdValue: usd,
1494
- isBalanceLoading: balancesLoading,
1495
- onPick: () => onPick(node.token.symbol, node.willChangeSrc)
1496
- }
1497
- );
1498
- };
1499
- const getItemSize = (index) => {
1500
- const node = nodes[index];
1501
- if (node.kind === "header") {
1502
- const gap = index === 0 ? 0 : HEADER_TOP_GAP;
1503
- return HEADER_H + gap;
1504
- }
1505
- return ROW_H;
1506
- };
1507
- return /* @__PURE__ */ jsxRuntime.jsx(
1508
- reactWindow.VariableSizeList,
1509
- {
1510
- height: 480,
1511
- width: "100%",
1512
- itemCount: nodes.length,
1513
- itemSize: getItemSize,
1514
- overscanCount: 8,
1515
- style: { willChange: "transform", paddingBottom: "40px" },
1516
- children: Row
1517
- }
1518
- );
1519
- };
1520
- const TokenSelectModal = ({
1521
- isOpen,
1522
- onClose,
1523
- items,
1524
- onChangeAsset
1525
- }) => {
1526
- const { t } = useBridgeTranslation();
1527
- const {
1528
- query,
1529
- setQuery,
1530
- tab,
1531
- setTab,
1532
- isFocused,
1533
- setIsFocused,
1534
- effectiveTab,
1535
- resetState,
1536
- setFromChain,
1537
- selectedAssetSymbol,
1538
- balancesQuery,
1539
- groupedTokens,
1540
- myTokens,
1541
- getBalance,
1542
- getTokenUsdValue,
1543
- findFirstAvailableChain,
1544
- hasAnyWallet
1545
- } = useTokenSelectData(items);
1546
1336
  const handleClose = require$$0.useCallback(() => {
1547
1337
  resetState();
1548
1338
  onClose();
@@ -1559,68 +1349,41 @@ const TokenSelectModal = ({
1559
1349
  onChangeAsset(sym);
1560
1350
  handleClose();
1561
1351
  };
1562
- const virtualNodes = require$$0.useMemo(() => {
1563
- const out = [];
1352
+ const tokensToRender = require$$0.useMemo(() => {
1564
1353
  if (effectiveTab === "my") {
1565
- for (const token of myTokens) {
1566
- out.push({
1567
- kind: "token",
1568
- key: `my:${token.symbol}`,
1569
- token,
1570
- willChangeSrc: false
1571
- });
1572
- }
1573
- return out;
1574
- }
1575
- const mainTokens = [
1576
- ...groupedTokens.withBalance,
1577
- ...groupedTokens.onSrcChain
1578
- ];
1579
- for (const token of mainTokens) {
1580
- out.push({
1581
- kind: "token",
1582
- key: `main:${token.symbol}`,
1354
+ return myTokens.map((token) => ({
1583
1355
  token,
1584
1356
  willChangeSrc: false
1585
- });
1586
- }
1587
- if (groupedTokens.willChangeSrcChain.length > 0) {
1588
- out.push({
1589
- kind: "header",
1590
- key: "hdr:willChange",
1591
- title: t("bridge.willChangeSourceChain")
1592
- });
1593
- for (const token of groupedTokens.willChangeSrcChain) {
1594
- out.push({
1595
- kind: "token",
1596
- key: `will:${token.symbol}`,
1597
- token,
1598
- willChangeSrc: true
1599
- });
1600
- }
1357
+ }));
1601
1358
  }
1602
- return out;
1603
- }, [effectiveTab, myTokens, groupedTokens, t]);
1604
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "!max-h-[80dvh] overflow-auto", children: [
1359
+ const mainTokens = [
1360
+ ...groupedTokens.withBalance.map((token) => ({
1361
+ token,
1362
+ willChangeSrc: false
1363
+ })),
1364
+ ...groupedTokens.onSrcChain.map((token) => ({
1365
+ token,
1366
+ willChangeSrc: false
1367
+ }))
1368
+ ];
1369
+ return mainTokens;
1370
+ }, [effectiveTab, myTokens, groupedTokens]);
1371
+ const willChangeSrcTokens = require$$0.useMemo(
1372
+ () => groupedTokens.willChangeSrcChain.map((token) => ({
1373
+ token,
1374
+ willChangeSrc: true
1375
+ })),
1376
+ [groupedTokens.willChangeSrcChain]
1377
+ );
1378
+ const hasNoResults = tokensToRender.length === 0 && willChangeSrcTokens.length === 0;
1379
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "!h-[90dvh] overflow-hidden flex flex-col", children: [
1605
1380
  /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectToken") }) }),
1606
- /* @__PURE__ */ jsxRuntime.jsxs(
1607
- "div",
1381
+ /* @__PURE__ */ jsxRuntime.jsx(
1382
+ SearchInput,
1608
1383
  {
1609
- className: `flex items-center gap-2.5 px-5 py-3.5 bg-input rounded-12 h-12.5 transition-all duration-200 ${isFocused ? "border border-ring" : "border border-transparent"}`,
1610
- children: [
1611
- /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "size-6 text-input-icon" }),
1612
- /* @__PURE__ */ jsxRuntime.jsx(
1613
- input.Input,
1614
- {
1615
- placeholder: t("bridge.searchToken"),
1616
- className: "w-full outline-none leading-0 p-0 h-6 text-base text-input-text placeholder:text-input-placeholder bg-none dark:bg-transparent",
1617
- value: query,
1618
- onChange: (e) => setQuery(e.target.value),
1619
- onFocus: () => setIsFocused(true),
1620
- onBlur: () => setIsFocused(false)
1621
- }
1622
- )
1623
- ]
1384
+ placeholder: t("bridge.searchToken"),
1385
+ value: query,
1386
+ onChange: setQuery
1624
1387
  }
1625
1388
  ),
1626
1389
  hasAnyWallet() && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
@@ -1643,20 +1406,52 @@ const TokenSelectModal = ({
1643
1406
  }
1644
1407
  )
1645
1408
  ] }),
1646
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden -mx-5", children: virtualNodes.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground px-5 py-3.5", children: t("bridge.noResults") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1409
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-auto -mx-5", children: hasNoResults ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground px-5 py-4", children: t("bridge.noResults") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1647
1410
  effectiveTab === "my" && myTokens.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-4 text-base font-semibold text-muted-foreground uppercase px-5 py-2", children: t("bridge.noBalancesFound") }),
1648
- /* @__PURE__ */ jsxRuntime.jsx(
1649
- VirtualizedTokenList,
1650
- {
1651
- nodes: virtualNodes,
1652
- balancesLoading: balancesQuery.isLoading || balancesQuery.isFetching,
1653
- hasAnyWallet: hasAnyWallet(),
1654
- selectedAssetSymbol,
1655
- getBalance,
1656
- getTokenUsdValue,
1657
- onPick
1658
- }
1659
- )
1411
+ tokensToRender.map(({ token, willChangeSrc }) => {
1412
+ const bal = getBalance(token.symbol);
1413
+ const usd = getTokenUsdValue(token.symbol, token.price?.usd);
1414
+ const isSelected = selectedAssetSymbol?.toUpperCase() === token.symbol.toUpperCase();
1415
+ return /* @__PURE__ */ jsxRuntime.jsx(
1416
+ TokenRow,
1417
+ {
1418
+ symbol: token.symbol,
1419
+ name: token.name,
1420
+ isSelected: !!isSelected,
1421
+ hasAnyWallet: hasAnyWallet(),
1422
+ balance: bal,
1423
+ usdValue: usd,
1424
+ isBalanceLoading: balancesQuery.isLoading || balancesQuery.isFetching,
1425
+ onPick: () => onPick(token.symbol, willChangeSrc)
1426
+ },
1427
+ `${effectiveTab}:${token.symbol}`
1428
+ );
1429
+ }),
1430
+ effectiveTab === "all" && willChangeSrcTokens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1431
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 flex leading-4 text-base py-2 font-semibold text-muted-foreground uppercase mt-8", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: t("bridge.willChangeSourceChain") }) }),
1432
+ willChangeSrcTokens.map(({ token, willChangeSrc }) => {
1433
+ const bal = getBalance(token.symbol);
1434
+ const usd = getTokenUsdValue(
1435
+ token.symbol,
1436
+ token.price?.usd
1437
+ );
1438
+ const isSelected = selectedAssetSymbol?.toUpperCase() === token.symbol.toUpperCase();
1439
+ return /* @__PURE__ */ jsxRuntime.jsx(
1440
+ TokenRow,
1441
+ {
1442
+ symbol: token.symbol,
1443
+ name: token.name,
1444
+ isSelected: !!isSelected,
1445
+ hasAnyWallet: hasAnyWallet(),
1446
+ balance: bal,
1447
+ usdValue: usd,
1448
+ isBalanceLoading: balancesQuery.isLoading || balancesQuery.isFetching,
1449
+ onPick: () => onPick(token.symbol, willChangeSrc)
1450
+ },
1451
+ `will:${token.symbol}`
1452
+ );
1453
+ })
1454
+ ] })
1660
1455
  ] }) })
1661
1456
  ] }) });
1662
1457
  };
@@ -1770,7 +1565,7 @@ const SelectTokenButton = ({
1770
1565
  type: "button",
1771
1566
  "aria-label": label,
1772
1567
  children: [
1773
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 items-center", children: [
1568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
1774
1569
  /* @__PURE__ */ jsxRuntime.jsx(
1775
1570
  TokenSymbol,
1776
1571
  {
@@ -1779,7 +1574,7 @@ const SelectTokenButton = ({
1779
1574
  alt: label
1780
1575
  }
1781
1576
  ),
1782
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-secondary-foreground text-sm leading-4.5 font-semibold ", children: label })
1577
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-secondary-foreground text-sm font-semibold", children: label })
1783
1578
  ] }),
1784
1579
  /* @__PURE__ */ jsxRuntime.jsx(ArrowDownIcon, { className: "size-4 text-secondary-foreground" })
1785
1580
  ]
@@ -1802,12 +1597,12 @@ const FormHeaderComponent = () => {
1802
1597
  const sum = selectedAssetSymbol.toUpperCase();
1803
1598
  return assets.find((a) => a.symbol.toUpperCase() === sum) ?? assets[0];
1804
1599
  }, [assets, selectedAssetSymbol]);
1805
- return /* @__PURE__ */ jsxRuntime.jsxs(card.CardHeader, { className: "gap-y-0 flex justify-between items-center", children: [
1806
- /* @__PURE__ */ jsxRuntime.jsxs(card.CardTitle, { className: "flex items-center gap-2.5", children: [
1807
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t("bridge.selectToken") }),
1600
+ return /* @__PURE__ */ jsxRuntime.jsxs(card.CardHeader, { className: "gap-y-0 flex flex-row justify-between items-center", children: [
1601
+ /* @__PURE__ */ jsxRuntime.jsxs(card.CardTitle, { className: "flex items-center gap-3", children: [
1602
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-4 text-muted-foreground", children: t("bridge.selectToken") }),
1808
1603
  /* @__PURE__ */ jsxRuntime.jsx(SelectTokenButton, { token: current, onClick: onOpen })
1809
1604
  ] }),
1810
- /* @__PURE__ */ jsxRuntime.jsxs(card.CardAction, { className: "flex items-center gap-2.5", children: [
1605
+ /* @__PURE__ */ jsxRuntime.jsxs(card.CardAction, { className: "flex items-center gap-3", children: [
1811
1606
  /* @__PURE__ */ jsxRuntime.jsx(RefreshButton, {}),
1812
1607
  /* @__PURE__ */ jsxRuntime.jsx(button.Button, { onClick: onOpenSettings, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(BoltIcon, { stroke: "currentColor" }) })
1813
1608
  ] }),
@@ -1823,16 +1618,23 @@ const FormHeaderComponent = () => {
1823
1618
  }
1824
1619
  }
1825
1620
  ),
1826
- /* @__PURE__ */ jsxRuntime.jsx(
1827
- SettingModal,
1828
- {
1829
- isOpen: isOpenSettings,
1830
- onClose: onCloseSettings
1831
- }
1832
- )
1621
+ /* @__PURE__ */ jsxRuntime.jsx(SettingModal, { isOpen: isOpenSettings, onClose: onCloseSettings })
1833
1622
  ] });
1834
1623
  };
1835
1624
  const FormHeader = require$$0.memo(FormHeaderComponent);
1625
+ function toLD(human, decimals) {
1626
+ const [i = "0", f = ""] = human.replace(",", ".").split(".");
1627
+ const frac = (f + "0".repeat(decimals)).slice(0, decimals);
1628
+ return BigInt(i + frac).toString();
1629
+ }
1630
+ function fromLD(ld, decimals) {
1631
+ const bi = BigInt(ld || "0");
1632
+ if (decimals === 0) return Number(bi);
1633
+ const base = BigInt(10) ** BigInt(decimals);
1634
+ const int = bi / base;
1635
+ const frac = Number(bi % base) / Number(base);
1636
+ return Number(int) + frac;
1637
+ }
1836
1638
  async function fetchQuotes(req) {
1837
1639
  const params = {
1838
1640
  srcChainKey: req.srcChainKey,
@@ -1891,6 +1693,131 @@ async function getQuotesByPriority(req) {
1891
1693
  const priority = req.routePriority || RoutePriority.RECOMMENDED;
1892
1694
  return selectQuoteByPriority(routes, priority);
1893
1695
  }
1696
+ function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
1697
+ if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
1698
+ const byChain = assetMatrix[assetSymbol.toUpperCase()];
1699
+ return byChain?.[chainKey];
1700
+ }
1701
+ const DEFAULT_SLIPPAGE_BPS = 50;
1702
+ const lower = (s) => (s ?? "").toLowerCase();
1703
+ const normSym = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
1704
+ function tonNorm(addr) {
1705
+ if (!addr) return null;
1706
+ try {
1707
+ if (addr.includes(":")) {
1708
+ return core.Address.parseRaw(addr).toString({
1709
+ bounceable: false,
1710
+ urlSafe: true
1711
+ });
1712
+ }
1713
+ return core.Address.parse(addr).toString({ bounceable: false, urlSafe: true });
1714
+ } catch {
1715
+ return null;
1716
+ }
1717
+ }
1718
+ const isZeroAddr = (a) => (
1719
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1720
+ !!a && /^0x0{40}$/i.test(a) || /^0x[eE]{4}e{36}$/i.test(a)
1721
+ );
1722
+ function addrForApi(chainKey, addr) {
1723
+ if (chainKey === "ton") return tonNorm(addr);
1724
+ return addr;
1725
+ }
1726
+ function isNativeAddrEqual(chain, tokenAddr) {
1727
+ if (!chain) return false;
1728
+ if (!tokenAddr) return false;
1729
+ if (isZeroAddr(tokenAddr)) return true;
1730
+ const nativeAddr = chain.nativeCurrency?.address;
1731
+ if (!nativeAddr) return false;
1732
+ if (chain.chainKey === "ton") {
1733
+ const a = tonNorm(tokenAddr);
1734
+ const b = tonNorm(nativeAddr);
1735
+ return !!a && !!b && a === b;
1736
+ }
1737
+ return lower(nativeAddr) === lower(tokenAddr);
1738
+ }
1739
+ function findNativeMeta(tokens, chain) {
1740
+ if (!chain) return { decimals: 18, priceUsd: void 0 };
1741
+ const sym = normSym(chain.nativeCurrency?.symbol);
1742
+ if (!sym) {
1743
+ return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1744
+ }
1745
+ const sameChain = tokens?.find(
1746
+ (t) => t.chainKey === chain.chainKey && normSym(t.symbol) === sym
1747
+ ) ?? void 0;
1748
+ if (sameChain)
1749
+ return { decimals: sameChain.decimals, priceUsd: sameChain.price?.usd };
1750
+ const anyChain = tokens?.find((t) => normSym(t.symbol) === sym);
1751
+ if (anyChain)
1752
+ return { decimals: anyChain.decimals, priceUsd: anyChain.price?.usd };
1753
+ return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1754
+ }
1755
+ function lookupTokenMeta(tokens, chains, chainKey, tokenAddr) {
1756
+ if (!chainKey) return { decimals: 18, priceUsd: void 0 };
1757
+ const chain = chains?.find((c) => c.chainKey === chainKey);
1758
+ const hit = tokens?.find((t) => {
1759
+ if (t.chainKey !== chainKey) return false;
1760
+ if (chainKey === "ton") {
1761
+ const a = tonNorm(t.address);
1762
+ const b = tonNorm(tokenAddr);
1763
+ return !!a && !!b && a === b;
1764
+ }
1765
+ return lower(t.address) === lower(tokenAddr);
1766
+ }) ?? void 0;
1767
+ if (hit) return { decimals: hit.decimals, priceUsd: hit.price?.usd };
1768
+ if (isNativeAddrEqual(chain, tokenAddr)) {
1769
+ return findNativeMeta(tokens, chain);
1770
+ }
1771
+ return { decimals: chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
1772
+ }
1773
+ function computeFeesUsdFromArray(fees, tokens, chains) {
1774
+ if (!fees?.length) return { totalUsd: 0 };
1775
+ let total = 0;
1776
+ let protocolFeeUsd = 0;
1777
+ let messageFeeUsd = 0;
1778
+ const byType = /* @__PURE__ */ new Map();
1779
+ for (const f of fees) {
1780
+ let usd = Number(f.usd ?? 0);
1781
+ if (!usd) {
1782
+ const { decimals, priceUsd } = lookupTokenMeta(
1783
+ tokens,
1784
+ chains,
1785
+ f.chainKey,
1786
+ f.token
1787
+ );
1788
+ const human = fromLD(String(f.amount ?? "0"), decimals);
1789
+ usd = (priceUsd ?? 0) * human;
1790
+ }
1791
+ total += usd;
1792
+ const type = (f.type ?? "other").toLowerCase();
1793
+ byType.set(type, (byType.get(type) ?? 0) + usd);
1794
+ if (type === "protocol" || type === "service") {
1795
+ protocolFeeUsd += usd;
1796
+ } else if (type === "message" || type === "gas" || type === "network") {
1797
+ messageFeeUsd += usd;
1798
+ }
1799
+ }
1800
+ const serviceUsd = byType.get("protocol") ?? byType.get("service") ?? void 0;
1801
+ const blockchainUsd = byType.get("gas") ?? byType.get("network") ?? byType.get("message") ?? void 0;
1802
+ return {
1803
+ totalUsd: total,
1804
+ protocolFeeUsd: protocolFeeUsd > 0 ? protocolFeeUsd : void 0,
1805
+ messageFeeUsd: messageFeeUsd > 0 ? messageFeeUsd : void 0,
1806
+ serviceUsd,
1807
+ blockchainUsd
1808
+ };
1809
+ }
1810
+ function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
1811
+ if (!fees?.length || !dstTokenAddr || !dstChainKey) return "0";
1812
+ let acc = 0n;
1813
+ for (const f of fees) {
1814
+ if (f.chainKey !== dstChainKey) continue;
1815
+ const same = dstChainKey === "ton" ? tonNorm(f.token) === tonNorm(dstTokenAddr) : lower(f.token) === lower(dstTokenAddr);
1816
+ if (!same) continue;
1817
+ acc += BigInt(f.amount ?? "0");
1818
+ }
1819
+ return acc.toString();
1820
+ }
1894
1821
  function useBridgeQuote() {
1895
1822
  const { assetMatrix, selectedAssetSymbol } = useTokensStore();
1896
1823
  const { fromChain, toChain } = useChainsStore();
@@ -2268,14 +2195,14 @@ const SwapButton = () => {
2268
2195
  const WalletBalance = (props) => {
2269
2196
  const { value, isLoading = false } = props;
2270
2197
  if (isLoading) {
2271
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 items-center", children: [
2198
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
2272
2199
  /* @__PURE__ */ jsxRuntime.jsx(WalletIcon, { className: "text-muted-foreground" }),
2273
2200
  /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-4 w-16 rounded-md" })
2274
2201
  ] });
2275
2202
  }
2276
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 items-center", children: [
2203
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
2277
2204
  /* @__PURE__ */ jsxRuntime.jsx(WalletIcon, { className: "text-muted-foreground" }),
2278
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: value })
2205
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-5 font-medium text-muted-foreground", children: value })
2279
2206
  ] });
2280
2207
  };
2281
2208
  const BASE_URL = "https://icons-ckg.pages.dev/stargate-light/networks";
@@ -2305,7 +2232,7 @@ const SelectNetworkButton = ({
2305
2232
  type: "button",
2306
2233
  "aria-label": label,
2307
2234
  children: [
2308
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5 items-center", children: [
2235
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
2309
2236
  /* @__PURE__ */ jsxRuntime.jsx(
2310
2237
  NetworkSymbol,
2311
2238
  {
@@ -2314,7 +2241,7 @@ const SelectNetworkButton = ({
2314
2241
  alt: label
2315
2242
  }
2316
2243
  ),
2317
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-secondary-foreground text-sm leading-4.5 font-semibold ", children: label })
2244
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-secondary-foreground text-sm leading-5 font-semibold ", children: label })
2318
2245
  ] }),
2319
2246
  /* @__PURE__ */ jsxRuntime.jsx(ArrowDownIcon, { className: "size-4 text-secondary-foreground" })
2320
2247
  ]
@@ -2372,7 +2299,7 @@ const CurrencyInput = require$$0.forwardRef(
2372
2299
  pattern: "[0-9]*[.,]?[0-9]*",
2373
2300
  readOnly,
2374
2301
  className: utils.cn(
2375
- "text-[32px] h-8.5 font-medium leading-8.5 rounded-none text-end bg-transparent dark:bg-transparent text-foreground shadow-none border-none outline-none ring-0 focus:outline-none",
2302
+ "text-[32px] h-12 font-medium leading-9 rounded-none text-end bg-transparent dark:bg-transparent text-foreground shadow-none border-none outline-none ring-0 focus:outline-none",
2376
2303
  className
2377
2304
  ),
2378
2305
  max,
@@ -2391,12 +2318,10 @@ const ChainSelectModal = ({
2391
2318
  }) => {
2392
2319
  const { t } = useBridgeTranslation();
2393
2320
  const [query, setQuery] = require$$0.useState("");
2394
- const [isFocused, setIsFocused] = require$$0.useState(false);
2395
2321
  const { setFromChain, chains, fromChain, toChain } = useChainsStore();
2396
2322
  const { assetMatrix, selectedAssetSymbol } = useTokensStore();
2397
2323
  const handleClose = require$$0.useCallback(() => {
2398
2324
  setQuery("");
2399
- setIsFocused(false);
2400
2325
  onClose();
2401
2326
  }, [onClose]);
2402
2327
  const findCompatibleSrcChain = require$$0.useCallback(
@@ -2456,8 +2381,8 @@ const ChainSelectModal = ({
2456
2381
  button.Button,
2457
2382
  {
2458
2383
  onClick: () => onChainPick(chain, willChangeSrc),
2459
- className: `w-full cursor-pointer flex shadow-none items-center justify-between gap-2.5 px-5 py-3.5 h-12.5 font-extrabold capitalize hover:bg-muted bg-transparent rounded-12 transition-[300] ${isSelected ? "border border-ring" : ""}`,
2460
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
2384
+ className: `w-full cursor-pointer flex shadow-none items-center justify-between gap-3 px-5 py-3.5 h-12.5 font-extrabold capitalize hover:bg-muted bg-transparent rounded-md transition-[300] ${isSelected ? "border border-ring" : ""}`,
2385
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
2461
2386
  /* @__PURE__ */ jsxRuntime.jsx(
2462
2387
  NetworkSymbol,
2463
2388
  {
@@ -2472,26 +2397,16 @@ const ChainSelectModal = ({
2472
2397
  chain.chainKey
2473
2398
  );
2474
2399
  };
2475
- return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "!max-h-[80dvh] overflow-hidden", children: [
2400
+ return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "!h-[90dvh] flex flex-col", children: [
2476
2401
  /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectNetwork") }) }),
2477
- /* @__PURE__ */ jsxRuntime.jsxs(
2478
- "div",
2402
+ /* @__PURE__ */ jsxRuntime.jsx(
2403
+ SearchInput,
2479
2404
  {
2480
- className: `flex items-center gap-2.5 px-5 py-3.5 bg-input rounded-md h-12.5 transition-all duration-200 ${isFocused ? "border border-ring" : "border border-transparent"}`,
2481
- children: [
2482
- /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { className: "size-6 text-muted-foreground" }),
2483
- /* @__PURE__ */ jsxRuntime.jsx(
2484
- input.Input,
2485
- {
2486
- placeholder: t("bridge.searchDestinationChain"),
2487
- className: "w-full outline-none leading-0 p-0 h-6 text-base text-foreground placeholder:text-muted-foreground bg-none dark:bg-transparent",
2488
- value: query,
2489
- onChange: (e) => setQuery(e.target.value),
2490
- onFocus: () => setIsFocused(true),
2491
- onBlur: () => setIsFocused(false)
2492
- }
2493
- )
2494
- ]
2405
+ placeholder: t("bridge.searchDestinationChain"),
2406
+ value: query,
2407
+ onChange: setQuery,
2408
+ containerClassName: "rounded-md",
2409
+ className: "text-foreground placeholder:text-muted-foreground"
2495
2410
  }
2496
2411
  ),
2497
2412
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
@@ -2516,9 +2431,9 @@ function short$1(addr) {
2516
2431
  return addr.slice(0, 4) + "…" + addr.slice(-4);
2517
2432
  }
2518
2433
  const prefixIcons = {
2519
- tronlink: /* @__PURE__ */ jsxRuntime.jsx(TronLinkIcon, { className: "size-4.5" }),
2520
- metamask: /* @__PURE__ */ jsxRuntime.jsx(MetaMaskIcon, { className: "size-4.5" }),
2521
- ton: /* @__PURE__ */ jsxRuntime.jsx(TonKeeperIcon, { className: "size-4.5" })
2434
+ tronlink: /* @__PURE__ */ jsxRuntime.jsx(TronLinkIcon, { className: "size-5" }),
2435
+ metamask: /* @__PURE__ */ jsxRuntime.jsx(MetaMaskIcon, { className: "size-5" }),
2436
+ ton: /* @__PURE__ */ jsxRuntime.jsx(TonKeeperIcon, { className: "size-5" })
2522
2437
  };
2523
2438
  const mapWalletToType = (wallet) => {
2524
2439
  switch (wallet) {
@@ -2567,7 +2482,7 @@ const WalletButton = ({
2567
2482
  e.preventDefault();
2568
2483
  },
2569
2484
  disabled: isButtonDisabled,
2570
- className: "p-0 !px-0 py-0 flex gap-1 cursor-pointer shadow-none hover:bg-transparent bg-transparent rounded-none h-4.5",
2485
+ className: "p-0 !px-0 py-0 flex gap-1 cursor-pointer shadow-none hover:bg-transparent bg-transparent rounded-none h-5",
2571
2486
  children: [
2572
2487
  isConnected ? prefixIcons[wallet] : null,
2573
2488
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-4 text-sm font-medium text-link border-b-2 border-dotted border-link", children: buttonText })
@@ -2643,7 +2558,7 @@ const SwapSection = ({
2643
2558
  ),
2644
2559
  children: [
2645
2560
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
2646
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: label }),
2561
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-5 font-medium text-muted-foreground", children: label }),
2647
2562
  /* @__PURE__ */ jsxRuntime.jsx(
2648
2563
  WalletBalance,
2649
2564
  {
@@ -2706,63 +2621,30 @@ const useCustomAddressStore = zustand.create((set) => ({
2706
2621
  setCustomDstAddress: (address) => set({ customDstAddress: address }),
2707
2622
  clearCustomDstAddress: () => set({ customDstAddress: void 0 })
2708
2623
  }));
2709
- const tonNormalize = (addr) => {
2710
- if (!addr) return null;
2711
- try {
2712
- if (addr.includes(":")) {
2713
- return core.Address.parseRaw(addr).toString({
2714
- bounceable: false,
2715
- urlSafe: true
2716
- });
2717
- }
2718
- return core.Address.parse(addr).toString({ bounceable: false, urlSafe: true });
2719
- } catch {
2720
- return null;
2721
- }
2624
+ const useIsAddressValid = (address, chainKey) => {
2625
+ const isValid = require$$0.useMemo(() => {
2626
+ return isAddressValidForChain(chainKey, address);
2627
+ }, [address, chainKey]);
2628
+ return { isValid };
2722
2629
  };
2723
- const ToggleRow = ({ enabled, onToggle }) => {
2630
+ const AnotherAddress = () => {
2631
+ const [enabled, setEnabled] = require$$0.useState(false);
2632
+ const [isFocused, setIsFocused] = require$$0.useState(false);
2724
2633
  const { t } = useBridgeTranslation();
2725
2634
  const { toChain } = useChainsStore();
2726
- const { dstAddress } = useAddresses();
2727
- const { setCustomDstAddress, clearCustomDstAddress } = useCustomAddressStore();
2635
+ const { setCustomDstAddress } = useCustomAddressStore();
2728
2636
  const [value, setValue] = require$$0.useState("");
2729
- const [invalid, setInvalid] = require$$0.useState(false);
2730
- const prevDstRef = require$$0.useRef(void 0);
2731
- const prevEnabledRef = require$$0.useRef(enabled);
2732
- require$$0.useEffect(() => {
2733
- const wasEnabled = prevEnabledRef.current;
2734
- if (enabled && !wasEnabled) {
2735
- prevDstRef.current = dstAddress;
2736
- setValue(dstAddress ?? "");
2737
- setInvalid(false);
2738
- }
2739
- if (!enabled && wasEnabled) {
2740
- clearCustomDstAddress();
2741
- setInvalid(false);
2742
- }
2743
- prevEnabledRef.current = enabled;
2744
- }, [enabled]);
2637
+ const { isValid } = useIsAddressValid(value.trim(), toChain?.chainKey);
2638
+ const invalid = value.trim() && !isValid;
2745
2639
  const pushToStoreIfValid = (raw) => {
2746
2640
  if (!enabled) return;
2747
2641
  const v = raw.trim();
2748
2642
  if (!v) {
2749
2643
  setCustomDstAddress(void 0);
2750
- setInvalid(false);
2751
- return;
2752
- }
2753
- const ck = toChain?.chainKey;
2754
- if (!ck) {
2755
- setInvalid(true);
2756
2644
  return;
2757
2645
  }
2758
- const valueForStore = ck === "ton" ? tonNormalize(v) ?? void 0 : v;
2759
- const valid = isAddressValidForChain(ck, valueForStore ?? "");
2760
- if (valid && valueForStore) {
2761
- setInvalid(false);
2762
- setCustomDstAddress(valueForStore);
2763
- if (ck === "ton") setValue(valueForStore);
2764
- } else {
2765
- setInvalid(true);
2646
+ if (isValid) {
2647
+ setCustomDstAddress(v);
2766
2648
  }
2767
2649
  };
2768
2650
  const onChange = (text) => {
@@ -2777,16 +2659,16 @@ const ToggleRow = ({ enabled, onToggle }) => {
2777
2659
  } catch {
2778
2660
  }
2779
2661
  };
2780
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-lg gap-2 bg-muted", children: [
2662
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-lg bg-muted", children: [
2781
2663
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2782
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: t("bridge.sendToAnotherAddress") }),
2664
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-5 font-medium text-muted-foreground", children: t("bridge.sendToAnotherAddress") }),
2783
2665
  /* @__PURE__ */ jsxRuntime.jsx(
2784
2666
  _switch.Switch,
2785
2667
  {
2786
2668
  className: "data-[state=unchecked]:bg-switch-inactive data-[state=checked]:bg-switch-active",
2787
2669
  "aria-pressed": enabled,
2788
2670
  checked: enabled,
2789
- onClick: onToggle
2671
+ onClick: () => setEnabled((v) => !v)
2790
2672
  }
2791
2673
  )
2792
2674
  ] }),
@@ -2801,16 +2683,27 @@ const ToggleRow = ({ enabled, onToggle }) => {
2801
2683
  children: /* @__PURE__ */ jsxRuntime.jsxs(
2802
2684
  "div",
2803
2685
  {
2804
- className: `bg-input py-2 px-4 w-full flex items-center gap-4 rounded-12 justify-between border ${invalid ? "border-destructive" : "border-transparent"}`,
2686
+ className: utils.cn(
2687
+ "bg-input py-2 px-4 mt-2 w-full flex items-center gap-4 rounded-md justify-between border border-transparent transition-all",
2688
+ {
2689
+ "py-4": value,
2690
+ "border border-ring": isFocused,
2691
+ "border-destructive": invalid
2692
+ }
2693
+ ),
2805
2694
  children: [
2806
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
2695
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 w-full", children: [
2807
2696
  /* @__PURE__ */ jsxRuntime.jsx(
2808
2697
  input.Input,
2809
2698
  {
2810
- className: "p-0 h-auto text-base leading-5 font-semibold w-full bg-transparent dark:bg-transparent placeholder:text-input-placeholder text-input-text border-none",
2811
- placeholder: toChain?.chainKey === "ton" ? t("bridge.tonAddressPlaceholder") : t("bridge.evmAddressPlaceholder"),
2699
+ className: utils.cn(
2700
+ "p-0 h-auto text-base leading-5 font-semibold w-full bg-transparent dark:bg-transparent placeholder:text-muted-foreground/50 border-none"
2701
+ ),
2702
+ placeholder: t("bridge.anotherAddressPlaceholder"),
2812
2703
  type: "text",
2813
2704
  value,
2705
+ onFocus: () => setIsFocused(true),
2706
+ onBlur: () => setIsFocused(false),
2814
2707
  onChange: (e) => onChange(e.target.value)
2815
2708
  }
2816
2709
  ),
@@ -2820,21 +2713,14 @@ const ToggleRow = ({ enabled, onToggle }) => {
2820
2713
  defaultValue: "Check correctness before transfer"
2821
2714
  }) }) })
2822
2715
  ] }),
2823
- !value ? /* @__PURE__ */ jsxRuntime.jsx(
2824
- button.Button,
2825
- {
2826
- variant: "default",
2827
- className: "self-center py-2 h-8.5 px-3 hover:bg-input-button bg-input-button text-input-button-foreground text-sm leading-4.5 font-semibold uppercase !rounded-40",
2828
- onClick: onPaste,
2829
- children: t("common.paste")
2830
- }
2831
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2716
+ !value ? /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "secondary", size: "sm", onClick: onPaste, children: t("common.paste") }) : /* @__PURE__ */ jsxRuntime.jsx(
2832
2717
  button.Button,
2833
2718
  {
2834
2719
  variant: "ghost",
2835
- className: "h-5 w-5 self-start\n bg-input-x-bg hover:bg-input-x-bg \n p-0.5 m-0 rounded-full\n border-0 shadow-none\n focus:outline-none focus:ring-0 has-[>svg]:px-0",
2720
+ size: "sm",
2721
+ className: "rounded-full p-0 size-5 self-start",
2836
2722
  onClick: () => setValue(""),
2837
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3 text-input-x" })
2723
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4" })
2838
2724
  }
2839
2725
  )
2840
2726
  ]
@@ -2993,10 +2879,10 @@ const Details = () => {
2993
2879
  const routeText = quote?.route ? getRouteDisplayName(quote.route) : t(`settings.routePresets.${routePriority}`);
2994
2880
  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-lg", children: [
2995
2881
  /* @__PURE__ */ jsxRuntime.jsx(accordion.AccordionTrigger, { className: "w-full gap-1 items-center py-6 px-5 rounded-b-lg data-[state=open]:pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-center justify-between", children: [
2996
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-normal text-priority leading-3.5", children: t("bridge.youWillReceive", { defaultValue: "You will receive" }) }),
2997
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-transparent hover:bg-transparent shadow-none h-4 p-0 px-0 py-0 flex items-center gap-1.5", children: [
2882
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-normal text-priority leading-4", children: t("bridge.youWillReceive", { defaultValue: "You will receive" }) }),
2883
+ /* @__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: [
2998
2884
  /* @__PURE__ */ jsxRuntime.jsx(TokenSymbol, { symbol, className: "w-4 h-4", alt: "token" }),
2999
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-4 w-24 rounded-md" }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold leading-3.5 text-foreground", children: [
2885
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-4 w-24 rounded-md" }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold leading-4 text-foreground", children: [
3000
2886
  receiveText,
3001
2887
  " ",
3002
2888
  symbol
@@ -3008,7 +2894,7 @@ const Details = () => {
3008
2894
  DetailsRow,
3009
2895
  {
3010
2896
  label: t("transaction.route"),
3011
- value: /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "flex items-center gap-1.5", children: [
2897
+ value: /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "flex items-center gap-2", children: [
3012
2898
  /* @__PURE__ */ jsxRuntime.jsx(StargateIcon, { className: "size-4" }),
3013
2899
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "", children: routeText })
3014
2900
  ] })
@@ -3048,7 +2934,7 @@ const DetailsRow = ({
3048
2934
  value,
3049
2935
  isLoading = false
3050
2936
  }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
3051
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
2937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3052
2938
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-priority font-normal", children: label }),
3053
2939
  /* @__PURE__ */ jsxRuntime.jsx(Tip, { text: label, children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-receive-icon" }) })
3054
2940
  ] }),
@@ -3812,9 +3698,9 @@ const WalletSelectModal = () => {
3812
3698
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 font-semibold text-muted-foreground uppercase", children: t("wallets.connected") }),
3813
3699
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: connectedWallets.map((wallet) => {
3814
3700
  const IconComponent = wallet.icon;
3815
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-5", children: /* @__PURE__ */ jsxRuntime.jsxs(button.Button, { className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-muted h-auto rounded-12 transition-[300]", children: [
3816
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
3817
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-7.5" }) }),
3701
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-5", children: /* @__PURE__ */ jsxRuntime.jsxs(button.Button, { className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-3 px-5 py-3 hover:bg-muted h-auto rounded-md transition-[300]", children: [
3702
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3703
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-8 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-8" }) }),
3818
3704
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
3819
3705
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: short(wallet.address) }),
3820
3706
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: wallet.name })
@@ -3853,9 +3739,9 @@ const WalletSelectModal = () => {
3853
3739
  }
3854
3740
  },
3855
3741
  disabled: isEvmConnector ? isPending : !wallet.enabled,
3856
- className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-2.5 px-5 py-2.5 hover:bg-muted h-auto rounded-12 transition-[300] disabled:opacity-50 disabled:cursor-not-allowed",
3742
+ className: "w-full cursor-pointer bg-transparent flex shadow-none items-center justify-between gap-3 px-5 py-3 hover:bg-muted h-auto rounded-md transition-[300] disabled:opacity-50 disabled:cursor-not-allowed",
3857
3743
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
3858
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-7.5 h-7.5 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-7.5" }) }),
3744
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: "size-8" }) }),
3859
3745
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
3860
3746
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: wallet.name }),
3861
3747
  wallet.comingSoon ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t("wallets.comingSoon") }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: t("wallets.connect") })
@@ -5904,7 +5790,7 @@ class ChainStrategyRegistry {
5904
5790
  async getBalances(chainKey, address, tokens, priorityToken) {
5905
5791
  const strategy = this.getStrategy(chainKey);
5906
5792
  if (!strategy) return {};
5907
- return await strategy.getBalances(address, tokens, priorityToken);
5793
+ return await strategy.getBalances(address, tokens, chainKey, priorityToken);
5908
5794
  }
5909
5795
  isAddressValid(chainKey, address) {
5910
5796
  const strategy = this.getStrategy(chainKey);
@@ -6015,14 +5901,9 @@ function parseTonAddress(address) {
6015
5901
  }
6016
5902
  return ton.Address.parse(address);
6017
5903
  }
6018
- async function getEvmBalances(publicClient, address, tokens, priorityToken) {
5904
+ async function getEvmBalances(publicClient, address, tokens, chainKey, priorityToken) {
6019
5905
  const balances = {};
6020
5906
  try {
6021
- console.log("start getEvmBalances");
6022
- console.log("publicClient:", publicClient);
6023
- console.log("isAddress:", viem.isAddress(address));
6024
- console.log("tokens:", tokens);
6025
- console.log("priorityToken:", priorityToken);
6026
5907
  if (!address || !viem.isAddress(address)) {
6027
5908
  console.warn(`Invalid EVM address provided: ${address}`);
6028
5909
  return balances;
@@ -6031,40 +5912,55 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6031
5912
  throw new Error("No public client provided");
6032
5913
  }
6033
5914
  const nativeTokens = tokens.filter((t) => isNativeAddress(t.address));
6034
- const erc20Tokens = tokens.filter((t) => !isNativeAddress(t.address) && viem.isAddress(t.address));
5915
+ const erc20Tokens = tokens.filter(
5916
+ (t) => !isNativeAddress(t.address) && viem.isAddress(t.address)
5917
+ );
6035
5918
  if (priorityToken) {
6036
- try {
6037
- const isPriorityNative = isNativeAddress(priorityToken.address);
6038
- if (isPriorityNative) {
6039
- const ethBalance = await publicClient.getBalance({
6040
- address
6041
- });
6042
- const balance = parseFloat(viem.formatUnits(ethBalance, priorityToken.decimals));
6043
- if (balance > 0) {
6044
- balances[priorityToken.symbol] = { balance, address };
6045
- }
6046
- } else if (viem.isAddress(priorityToken.address)) {
6047
- const tokenBalance = await publicClient.readContract({
6048
- address: priorityToken.address,
6049
- abi: [
6050
- {
6051
- name: "balanceOf",
6052
- type: "function",
6053
- stateMutability: "view",
6054
- inputs: [{ name: "owner", type: "address" }],
6055
- outputs: [{ name: "balance", type: "uint256" }]
6056
- }
6057
- ],
6058
- functionName: "balanceOf",
6059
- args: [address]
6060
- });
6061
- const balance = parseFloat(viem.formatUnits(tokenBalance, priorityToken.decimals));
6062
- if (balance > 0) {
6063
- balances[priorityToken.symbol] = { balance, address };
5919
+ if (priorityToken.chainKey !== chainKey) {
5920
+ console.debug(
5921
+ `Skipping priority token ${priorityToken.symbol}: chain mismatch (expected ${chainKey}, got ${priorityToken.chainKey})`
5922
+ );
5923
+ } else {
5924
+ try {
5925
+ const isPriorityNative = isNativeAddress(priorityToken.address);
5926
+ if (isPriorityNative) {
5927
+ const ethBalance = await publicClient.getBalance({
5928
+ address
5929
+ });
5930
+ const balance = parseFloat(
5931
+ viem.formatUnits(ethBalance, priorityToken.decimals)
5932
+ );
5933
+ if (balance > 0) {
5934
+ balances[priorityToken.symbol] = { balance, address };
5935
+ }
5936
+ } else if (viem.isAddress(priorityToken.address)) {
5937
+ const tokenBalance = await publicClient.readContract({
5938
+ address: priorityToken.address,
5939
+ abi: [
5940
+ {
5941
+ name: "balanceOf",
5942
+ type: "function",
5943
+ stateMutability: "view",
5944
+ inputs: [{ name: "owner", type: "address" }],
5945
+ outputs: [{ name: "balance", type: "uint256" }]
5946
+ }
5947
+ ],
5948
+ functionName: "balanceOf",
5949
+ args: [address]
5950
+ });
5951
+ const balance = parseFloat(
5952
+ viem.formatUnits(tokenBalance, priorityToken.decimals)
5953
+ );
5954
+ if (balance > 0) {
5955
+ balances[priorityToken.symbol] = { balance, address };
5956
+ }
6064
5957
  }
5958
+ } catch (error) {
5959
+ console.debug(
5960
+ `Failed to get priority token balance for ${priorityToken.symbol}:`,
5961
+ error
5962
+ );
6065
5963
  }
6066
- } catch (error) {
6067
- console.debug(`Failed to get priority token balance for ${priorityToken.symbol}:`, error);
6068
5964
  }
6069
5965
  }
6070
5966
  for (const token of nativeTokens) {
@@ -6077,7 +5973,10 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6077
5973
  balances[token.symbol] = { balance, address };
6078
5974
  }
6079
5975
  } catch (error) {
6080
- console.debug(`Failed to get native balance for ${token.symbol}:`, error);
5976
+ console.debug(
5977
+ `Failed to get native balance for ${token.symbol}:`,
5978
+ error
5979
+ );
6081
5980
  }
6082
5981
  }
6083
5982
  if (erc20Tokens.length > 0) {
@@ -6105,17 +6004,25 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6105
6004
  if (!token) return;
6106
6005
  if (result.status === "success" && result.result !== void 0) {
6107
6006
  try {
6108
- const balance = parseFloat(viem.formatUnits(result.result, token.decimals));
6007
+ const balance = parseFloat(
6008
+ viem.formatUnits(result.result, token.decimals)
6009
+ );
6109
6010
  if (balance > 0) {
6110
6011
  balances[token.symbol] = { balance, address };
6111
6012
  }
6112
6013
  } catch (error) {
6113
- console.debug(`Failed to parse balance for ${token.symbol}:`, error);
6014
+ console.debug(
6015
+ `Failed to parse balance for ${token.symbol}:`,
6016
+ error
6017
+ );
6114
6018
  }
6115
6019
  }
6116
6020
  });
6117
6021
  } catch (error) {
6118
- console.warn("Multicall failed, falling back to individual calls:", error);
6022
+ console.warn(
6023
+ "Multicall failed, falling back to individual calls:",
6024
+ error
6025
+ );
6119
6026
  for (const token of erc20Tokens) {
6120
6027
  try {
6121
6028
  const tokenBalance = await publicClient.readContract({
@@ -6149,7 +6056,7 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
6149
6056
  }
6150
6057
  return balances;
6151
6058
  }
6152
- async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
6059
+ async function getTonBalances(address, tokens, chainKey, customTonClient, tonApiKey) {
6153
6060
  const balances = {};
6154
6061
  try {
6155
6062
  if (!isTonFriendlyAddress(address)) {
@@ -6308,13 +6215,18 @@ class EvmChainStrategy {
6308
6215
  getConnectLabel(t) {
6309
6216
  return t("wallets.connectEvmWallet");
6310
6217
  }
6311
- async getBalances(address, tokens, priorityToken) {
6218
+ async getBalances(address, tokens, chainKey, priorityToken) {
6312
6219
  if (!this.publicClient) {
6313
6220
  console.warn("No publicClient available for balance query");
6314
6221
  return {};
6315
6222
  }
6316
- console.log("publicClient", this.publicClient);
6317
- return await getEvmBalances(this.publicClient, address, tokens, priorityToken);
6223
+ return await getEvmBalances(
6224
+ this.publicClient,
6225
+ address,
6226
+ tokens,
6227
+ chainKey,
6228
+ priorityToken
6229
+ );
6318
6230
  }
6319
6231
  isAddressValid(address) {
6320
6232
  if (!address) return false;
@@ -6670,10 +6582,11 @@ class TonChainStrategy {
6670
6582
  getConnectLabel(t) {
6671
6583
  return t("wallets.connectTonWallet");
6672
6584
  }
6673
- async getBalances(address, tokens) {
6585
+ async getBalances(address, tokens, chainKey) {
6674
6586
  return await getTonBalances(
6675
6587
  address,
6676
6588
  tokens,
6589
+ chainKey,
6677
6590
  this.config.tonClient,
6678
6591
  this.config.tonApiKey
6679
6592
  );
@@ -6882,7 +6795,6 @@ class TronChainStrategy {
6882
6795
  __publicField(this, "config");
6883
6796
  this.config = config;
6884
6797
  }
6885
- // ========== Identity ==========
6886
6798
  canHandle(chainKey) {
6887
6799
  return chainKey.toLowerCase() === "tron";
6888
6800
  }
@@ -6892,7 +6804,6 @@ class TronChainStrategy {
6892
6804
  getName() {
6893
6805
  return "TRON Chain Strategy";
6894
6806
  }
6895
- // ========== Wallet Management ==========
6896
6807
  async connect() {
6897
6808
  const tronWeb = this.getTronWeb();
6898
6809
  if (!tronWeb && (typeof window === "undefined" || !window.tronLink)) {
@@ -6923,7 +6834,6 @@ class TronChainStrategy {
6923
6834
  getConnectLabel(t) {
6924
6835
  return t("wallets.connectTronWallet");
6925
6836
  }
6926
- // ========== Balance & Validation ==========
6927
6837
  async getBalances(address, tokens) {
6928
6838
  const tronWeb = this.getTronWeb();
6929
6839
  if (!tronWeb) return {};
@@ -6933,7 +6843,6 @@ class TronChainStrategy {
6933
6843
  if (!address) return false;
6934
6844
  return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(address);
6935
6845
  }
6936
- // ========== Gas Estimation ==========
6937
6846
  async estimateGasRequirement(params) {
6938
6847
  const {
6939
6848
  selectedToken,
@@ -7616,7 +7525,6 @@ const EvaaBridgeContent = ({
7616
7525
  const { t } = useBridgeTranslation();
7617
7526
  useTokensRequest();
7618
7527
  useChainsRequest();
7619
- const [sendToAnother, setSendToAnother] = require$$0.useState(false);
7620
7528
  const swap = useSwapModel();
7621
7529
  const { fromChain, toChain } = swap;
7622
7530
  const { selectedAssetSymbol, assetMatrix } = useTokensStore();
@@ -7744,13 +7652,7 @@ const EvaaBridgeContent = ({
7744
7652
  onSelect: handleToChainChange
7745
7653
  }
7746
7654
  ),
7747
- /* @__PURE__ */ jsxRuntime.jsx(
7748
- ToggleRow,
7749
- {
7750
- enabled: sendToAnother,
7751
- onToggle: () => setSendToAnother((v) => !v)
7752
- }
7753
- ),
7655
+ /* @__PURE__ */ jsxRuntime.jsx(AnotherAddress, {}),
7754
7656
  /* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {})
7755
7657
  ] }),
7756
7658
  /* @__PURE__ */ jsxRuntime.jsx(card.CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Details, {}) })
@@ -7825,7 +7727,6 @@ exports.addrForApi = addrForApi;
7825
7727
  exports.buildAssetMatrix = buildAssetMatrix;
7826
7728
  exports.calculateMinReceived = calculateMinReceived;
7827
7729
  exports.computeFeesUsdFromArray = computeFeesUsdFromArray;
7828
- exports.dollarsFromNativeFees = dollarsFromNativeFees;
7829
7730
  exports.findNativeMeta = findNativeMeta;
7830
7731
  exports.formatBalance = formatBalance;
7831
7732
  exports.formatHash = formatHash;
@@ -7844,10 +7745,7 @@ exports.getQuotesByPriority = getQuotesByPriority;
7844
7745
  exports.getTokens = getTokens;
7845
7746
  exports.getTonBalances = getTonBalances;
7846
7747
  exports.getTronBalances = getTronBalances;
7847
- exports.isAddressValidForChain = isAddressValidForChain;
7848
- exports.isEvmAddress = isEvmAddress;
7849
7748
  exports.isNativeAddrEqual = isNativeAddrEqual;
7850
- exports.isTronAddress = isTronAddress;
7851
7749
  exports.isZeroAddr = isZeroAddr;
7852
7750
  exports.listAssetsForSelect = listAssetsForSelect;
7853
7751
  exports.lookupTokenMeta = lookupTokenMeta;