@rash2x/bridge-widget 0.1.12 → 0.1.15
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 +5 -2
- package/dist/evaa-bridge.cjs +541 -563
- package/dist/evaa-bridge.cjs.map +1 -1
- package/dist/evaa-bridge.mjs +539 -561
- package/dist/evaa-bridge.mjs.map +1 -1
- package/dist/index.d.ts +3 -10
- package/package.json +1 -1
package/dist/evaa-bridge.cjs
CHANGED
|
@@ -25,32 +25,97 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
26
26
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
27
27
|
const jsxRuntime = require("react/jsx-runtime");
|
|
28
|
-
const reactI18next = require("react-i18next");
|
|
29
28
|
const require$$0 = require("react");
|
|
29
|
+
const reactI18next = require("react-i18next");
|
|
30
|
+
const i18n = require("i18next");
|
|
30
31
|
const zustand = require("zustand");
|
|
31
32
|
const button = require("@/components/ui/button");
|
|
32
33
|
const dialog = require("@/components/ui/dialog");
|
|
34
|
+
const badge = require("@/components/ui/badge");
|
|
33
35
|
const tooltip = require("@/components/ui/tooltip");
|
|
34
36
|
const utils = require("@/lib/utils");
|
|
35
|
-
const
|
|
37
|
+
const skeleton = require("@/components/ui/skeleton");
|
|
36
38
|
const wagmi = require("wagmi");
|
|
37
39
|
const tronwalletAdapterReactHooks = require("@tronweb3/tronwallet-adapter-react-hooks");
|
|
38
40
|
const uiReact = require("@tonconnect/ui-react");
|
|
39
41
|
const reactQuery = require("@tanstack/react-query");
|
|
40
42
|
const core = require("@ton/core");
|
|
41
|
-
const
|
|
42
|
-
const skeleton = require("@/components/ui/skeleton");
|
|
43
|
+
const input = require("@/components/ui/input");
|
|
43
44
|
const card = require("@/components/ui/card");
|
|
44
45
|
const _switch = require("@/components/ui/switch");
|
|
45
46
|
const lucideReact = require("lucide-react");
|
|
46
47
|
const framerMotion = require("framer-motion");
|
|
47
48
|
const accordion = require("@/components/ui/accordion");
|
|
48
|
-
const i18next = require("i18next");
|
|
49
49
|
const sonner = require("sonner");
|
|
50
50
|
const ethers = require("ethers");
|
|
51
51
|
const viem = require("viem");
|
|
52
52
|
const ton = require("@ton/ton");
|
|
53
53
|
const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
|
|
54
|
+
const common$1 = { "connecting": "Connecting…", "initializing": "Initializing...", "loading": "Loading...", "paste": "paste", "close": "Close", "zeroPlaceholder": "0", "nativeToken": "Native Token" };
|
|
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", "anotherAddressPlaceholder": "Address", "addressDoesntMatch": "Address doesn't match the {{network}} network", "checkBeforeTransfer": "Check correctness before transfer" };
|
|
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
|
+
const app$1 = { "stargateWidgetName": "Stargate Bridge Widget", "liveWidget": "Live Widget", "getStarted": "Get Started" };
|
|
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" } };
|
|
60
|
+
const en = {
|
|
61
|
+
common: common$1,
|
|
62
|
+
wallets: wallets$1,
|
|
63
|
+
bridge: bridge$1,
|
|
64
|
+
transaction: transaction$1,
|
|
65
|
+
app: app$1,
|
|
66
|
+
settings: settings$1
|
|
67
|
+
};
|
|
68
|
+
const common = { "connecting": "Подключение…", "initializing": "Инициализация...", "loading": "Загрузка...", "paste": "вставить", "close": "Закрыть", "zeroPlaceholder": "0", "nativeToken": "Нативный токен" };
|
|
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": "Вы получите", "anotherAddressPlaceholder": "Адрес", "addressDoesntMatch": "Адрес не соответствует сети {{network}}", "checkBeforeTransfer": "Проверьте корректность перед переводом" };
|
|
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
|
+
const app = { "stargateWidgetName": "Виджет Stargate Bridge", "liveWidget": "Живой виджет", "getStarted": "Начало работы" };
|
|
73
|
+
const settings = { "title": "Настройки", "gasOnDestination": "Газ на назначении", "slippageTolerance": "Толерантность к проскальзыванию", "routePriority": "Приоритет маршрута", "highSlippageWarning": "Высокое проскальзывание", "gasPresets": { "auto": "Авто", "none": "Нет", "medium": "Средний", "max": "Макс" }, "routePresets": { "fastest": "Быстрейший", "cheapest": "Дешевейший", "recommended": "Рекомендуемый" } };
|
|
74
|
+
const ru = {
|
|
75
|
+
common,
|
|
76
|
+
wallets,
|
|
77
|
+
bridge,
|
|
78
|
+
transaction,
|
|
79
|
+
app,
|
|
80
|
+
settings
|
|
81
|
+
};
|
|
82
|
+
const bridgeI18n = i18n.createInstance();
|
|
83
|
+
const resources = {
|
|
84
|
+
en: {
|
|
85
|
+
"evaa-bridge": en
|
|
86
|
+
},
|
|
87
|
+
ru: {
|
|
88
|
+
"evaa-bridge": ru
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
bridgeI18n.use(reactI18next.initReactI18next).init({
|
|
92
|
+
resources,
|
|
93
|
+
lng: "en",
|
|
94
|
+
// Will be overridden by defaultLanguage prop
|
|
95
|
+
fallbackLng: "en",
|
|
96
|
+
debug: false,
|
|
97
|
+
// Use a dedicated namespace to avoid conflicts
|
|
98
|
+
defaultNS: "evaa-bridge",
|
|
99
|
+
ns: ["evaa-bridge"],
|
|
100
|
+
interpolation: {
|
|
101
|
+
escapeValue: false
|
|
102
|
+
// react already does escaping
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
function BridgeI18nProvider({
|
|
106
|
+
children,
|
|
107
|
+
defaultLanguage = "en"
|
|
108
|
+
}) {
|
|
109
|
+
require$$0.useEffect(() => {
|
|
110
|
+
if (bridgeI18n.language !== defaultLanguage) {
|
|
111
|
+
bridgeI18n.changeLanguage(defaultLanguage);
|
|
112
|
+
}
|
|
113
|
+
}, [defaultLanguage]);
|
|
114
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactI18next.I18nextProvider, { i18n: bridgeI18n, children });
|
|
115
|
+
}
|
|
116
|
+
function useBridgeTranslation() {
|
|
117
|
+
return reactI18next.useTranslation("evaa-bridge", { i18n: bridgeI18n });
|
|
118
|
+
}
|
|
54
119
|
const norm = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
55
120
|
const POPULAR_ORDER = [
|
|
56
121
|
"USDT",
|
|
@@ -831,7 +896,7 @@ const routePresets = [
|
|
|
831
896
|
RoutePriority.RECOMMENDED
|
|
832
897
|
];
|
|
833
898
|
const SettingModal = ({ isOpen, onClose }) => {
|
|
834
|
-
const { t } =
|
|
899
|
+
const { t } = useBridgeTranslation();
|
|
835
900
|
const { toChain } = useChainsStore();
|
|
836
901
|
const { tokens } = useTokensStore();
|
|
837
902
|
const {
|
|
@@ -861,16 +926,16 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
861
926
|
toChain?.chainKey,
|
|
862
927
|
dstNativeToken?.decimals || 18
|
|
863
928
|
);
|
|
864
|
-
const activeBtn = "bg-
|
|
865
|
-
const notActiveBtn = "bg-
|
|
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";
|
|
866
931
|
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { children: [
|
|
867
|
-
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title"
|
|
932
|
+
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("settings.title") }) }),
|
|
868
933
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
869
934
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5", children: [
|
|
870
935
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
871
936
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
872
937
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-3.5", children: t("settings.gasOnDestination") }),
|
|
873
|
-
/* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.
|
|
938
|
+
/* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.gasOnDestinationTip"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
|
|
874
939
|
] }),
|
|
875
940
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground text-sm font-medium leading-3.5", children: formatUsd(gasUsdValue) })
|
|
876
941
|
] }),
|
|
@@ -889,12 +954,11 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
889
954
|
) }) })
|
|
890
955
|
] }),
|
|
891
956
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", children: gasPresets.map((g) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
892
|
-
|
|
957
|
+
badge.Badge,
|
|
893
958
|
{
|
|
894
|
-
type: "button",
|
|
895
959
|
onClick: () => setGasPreset(g),
|
|
896
960
|
className: utils.cn(
|
|
897
|
-
|
|
961
|
+
"cursor-pointer",
|
|
898
962
|
gasPreset === g ? activeBtn : notActiveBtn
|
|
899
963
|
),
|
|
900
964
|
children: t(`settings.gasPresets.${g}`)
|
|
@@ -910,22 +974,21 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
910
974
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm font-medium leading-3.5", children: t("settings.slippageTolerance") }),
|
|
911
975
|
/* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.slippageTolerance"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
|
|
912
976
|
] }),
|
|
913
|
-
slippageBps >= 500 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-
|
|
977
|
+
slippageBps >= 500 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-xs font-medium", children: t("settings.highSlippageWarning", {
|
|
914
978
|
defaultValue: "High slippage warning"
|
|
915
979
|
}) })
|
|
916
980
|
] }),
|
|
917
981
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-6", children: [
|
|
918
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 }) }),
|
|
919
983
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: slippagePresets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
920
|
-
|
|
984
|
+
badge.Badge,
|
|
921
985
|
{
|
|
922
|
-
type: "button",
|
|
923
986
|
onClick: () => {
|
|
924
987
|
const bps = parseFloat(p.replace("%", "")) * 100;
|
|
925
988
|
setSlippageBps(bps);
|
|
926
989
|
},
|
|
927
990
|
className: utils.cn(
|
|
928
|
-
|
|
991
|
+
"cursor-pointer",
|
|
929
992
|
activeSlippagePreset === p ? activeBtn : notActiveBtn
|
|
930
993
|
),
|
|
931
994
|
children: p
|
|
@@ -941,12 +1004,11 @@ const SettingModal = ({ isOpen, onClose }) => {
|
|
|
941
1004
|
/* @__PURE__ */ jsxRuntime.jsx(Tip, { text: t("settings.routePriority"), children: /* @__PURE__ */ jsxRuntime.jsx(TipIcon, { className: "size-4 text-muted-foreground" }) })
|
|
942
1005
|
] }) }),
|
|
943
1006
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-end gap-2", children: routePresets.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
944
|
-
|
|
1007
|
+
badge.Badge,
|
|
945
1008
|
{
|
|
946
|
-
type: "button",
|
|
947
1009
|
onClick: () => setRoutePriority(r),
|
|
948
1010
|
className: utils.cn(
|
|
949
|
-
|
|
1011
|
+
"cursor-pointer",
|
|
950
1012
|
routePriority === r ? activeBtn : notActiveBtn
|
|
951
1013
|
),
|
|
952
1014
|
children: t(`settings.routePresets.${r}`)
|
|
@@ -1014,168 +1076,31 @@ function useChainStrategies() {
|
|
|
1014
1076
|
}
|
|
1015
1077
|
return context;
|
|
1016
1078
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (
|
|
1025
|
-
const base = BigInt(10) ** BigInt(decimals);
|
|
1026
|
-
const int = bi / base;
|
|
1027
|
-
const frac = Number(bi % base) / Number(base);
|
|
1028
|
-
return Number(int) + frac;
|
|
1029
|
-
}
|
|
1030
|
-
function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
|
|
1031
|
-
if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
|
|
1032
|
-
const byChain = assetMatrix[assetSymbol.toUpperCase()];
|
|
1033
|
-
return byChain?.[chainKey];
|
|
1034
|
-
}
|
|
1035
|
-
const DEFAULT_SLIPPAGE_BPS = 50;
|
|
1036
|
-
const lower = (s) => (s ?? "").toLowerCase();
|
|
1037
|
-
const normSym = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
1038
|
-
function tonNorm(addr) {
|
|
1039
|
-
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;
|
|
1040
1087
|
try {
|
|
1041
1088
|
if (addr.includes(":")) {
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
urlSafe: true
|
|
1045
|
-
});
|
|
1089
|
+
core.Address.parseRaw(addr);
|
|
1090
|
+
return true;
|
|
1046
1091
|
}
|
|
1047
|
-
|
|
1092
|
+
core.Address.parse(addr);
|
|
1093
|
+
return true;
|
|
1048
1094
|
} catch {
|
|
1049
|
-
return
|
|
1095
|
+
return false;
|
|
1050
1096
|
}
|
|
1051
|
-
}
|
|
1052
|
-
const isEvmAddress = (a) => /^0x[0-9a-fA-F]{40}$/.test(a ?? "");
|
|
1053
|
-
const isTronAddress = (a) => /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(a ?? "");
|
|
1054
|
-
const isZeroAddr = (a) => (
|
|
1055
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1056
|
-
!!a && /^0x0{40}$/i.test(a) || /^0x[eE]{4}e{36}$/i.test(a)
|
|
1057
|
-
);
|
|
1097
|
+
};
|
|
1058
1098
|
function isAddressValidForChain(chainKey, addr) {
|
|
1059
1099
|
if (!chainKey || !addr) return false;
|
|
1060
|
-
if (chainKey === "ton") return
|
|
1100
|
+
if (chainKey === "ton") return isTonAddress(addr);
|
|
1061
1101
|
if (chainKey === "tron") return isTronAddress(addr);
|
|
1062
1102
|
return isEvmAddress(addr);
|
|
1063
1103
|
}
|
|
1064
|
-
function addrForApi(chainKey, addr) {
|
|
1065
|
-
if (chainKey === "ton") return tonNorm(addr);
|
|
1066
|
-
return addr;
|
|
1067
|
-
}
|
|
1068
|
-
function isNativeAddrEqual(chain, tokenAddr) {
|
|
1069
|
-
if (!chain) return false;
|
|
1070
|
-
if (!tokenAddr) return false;
|
|
1071
|
-
if (isZeroAddr(tokenAddr)) return true;
|
|
1072
|
-
const nativeAddr = chain.nativeCurrency?.address;
|
|
1073
|
-
if (!nativeAddr) return false;
|
|
1074
|
-
if (chain.chainKey === "ton") {
|
|
1075
|
-
const a = tonNorm(tokenAddr);
|
|
1076
|
-
const b = tonNorm(nativeAddr);
|
|
1077
|
-
return !!a && !!b && a === b;
|
|
1078
|
-
}
|
|
1079
|
-
return lower(nativeAddr) === lower(tokenAddr);
|
|
1080
|
-
}
|
|
1081
|
-
function findNativeMeta(tokens, chain) {
|
|
1082
|
-
if (!chain) return { decimals: 18, priceUsd: void 0 };
|
|
1083
|
-
const sym = normSym(chain.nativeCurrency?.symbol);
|
|
1084
|
-
if (!sym) {
|
|
1085
|
-
return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1086
|
-
}
|
|
1087
|
-
const sameChain = tokens?.find(
|
|
1088
|
-
(t) => t.chainKey === chain.chainKey && normSym(t.symbol) === sym
|
|
1089
|
-
) ?? void 0;
|
|
1090
|
-
if (sameChain)
|
|
1091
|
-
return { decimals: sameChain.decimals, priceUsd: sameChain.price?.usd };
|
|
1092
|
-
const anyChain = tokens?.find((t) => normSym(t.symbol) === sym);
|
|
1093
|
-
if (anyChain)
|
|
1094
|
-
return { decimals: anyChain.decimals, priceUsd: anyChain.price?.usd };
|
|
1095
|
-
return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1096
|
-
}
|
|
1097
|
-
function lookupTokenMeta(tokens, chains, chainKey, tokenAddr) {
|
|
1098
|
-
if (!chainKey) return { decimals: 18, priceUsd: void 0 };
|
|
1099
|
-
const chain = chains?.find((c) => c.chainKey === chainKey);
|
|
1100
|
-
const hit = tokens?.find((t) => {
|
|
1101
|
-
if (t.chainKey !== chainKey) return false;
|
|
1102
|
-
if (chainKey === "ton") {
|
|
1103
|
-
const a = tonNorm(t.address);
|
|
1104
|
-
const b = tonNorm(tokenAddr);
|
|
1105
|
-
return !!a && !!b && a === b;
|
|
1106
|
-
}
|
|
1107
|
-
return lower(t.address) === lower(tokenAddr);
|
|
1108
|
-
}) ?? void 0;
|
|
1109
|
-
if (hit) return { decimals: hit.decimals, priceUsd: hit.price?.usd };
|
|
1110
|
-
if (isNativeAddrEqual(chain, tokenAddr)) {
|
|
1111
|
-
return findNativeMeta(tokens, chain);
|
|
1112
|
-
}
|
|
1113
|
-
return { decimals: chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1114
|
-
}
|
|
1115
|
-
function computeFeesUsdFromArray(fees, tokens, chains) {
|
|
1116
|
-
if (!fees?.length) return { totalUsd: 0 };
|
|
1117
|
-
let total = 0;
|
|
1118
|
-
let protocolFeeUsd = 0;
|
|
1119
|
-
let messageFeeUsd = 0;
|
|
1120
|
-
const byType = /* @__PURE__ */ new Map();
|
|
1121
|
-
for (const f of fees) {
|
|
1122
|
-
let usd = Number(f.usd ?? 0);
|
|
1123
|
-
if (!usd) {
|
|
1124
|
-
const { decimals, priceUsd } = lookupTokenMeta(
|
|
1125
|
-
tokens,
|
|
1126
|
-
chains,
|
|
1127
|
-
f.chainKey,
|
|
1128
|
-
f.token
|
|
1129
|
-
);
|
|
1130
|
-
const human = fromLD(String(f.amount ?? "0"), decimals);
|
|
1131
|
-
usd = (priceUsd ?? 0) * human;
|
|
1132
|
-
}
|
|
1133
|
-
total += usd;
|
|
1134
|
-
const type = (f.type ?? "other").toLowerCase();
|
|
1135
|
-
byType.set(type, (byType.get(type) ?? 0) + usd);
|
|
1136
|
-
if (type === "protocol" || type === "service") {
|
|
1137
|
-
protocolFeeUsd += usd;
|
|
1138
|
-
} else if (type === "message" || type === "gas" || type === "network") {
|
|
1139
|
-
messageFeeUsd += usd;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
const serviceUsd = byType.get("protocol") ?? byType.get("service") ?? void 0;
|
|
1143
|
-
const blockchainUsd = byType.get("gas") ?? byType.get("network") ?? byType.get("message") ?? void 0;
|
|
1144
|
-
return {
|
|
1145
|
-
totalUsd: total,
|
|
1146
|
-
protocolFeeUsd: protocolFeeUsd > 0 ? protocolFeeUsd : void 0,
|
|
1147
|
-
messageFeeUsd: messageFeeUsd > 0 ? messageFeeUsd : void 0,
|
|
1148
|
-
serviceUsd,
|
|
1149
|
-
blockchainUsd
|
|
1150
|
-
};
|
|
1151
|
-
}
|
|
1152
|
-
function dollarsFromNativeFees(feeNative, feeLzToken, chain, tokens) {
|
|
1153
|
-
let total = 0;
|
|
1154
|
-
if (feeNative && chain) {
|
|
1155
|
-
const { decimals, priceUsd } = findNativeMeta(tokens, chain);
|
|
1156
|
-
const human = fromLD(String(feeNative), decimals);
|
|
1157
|
-
total += (priceUsd ?? 0) * human;
|
|
1158
|
-
}
|
|
1159
|
-
if (feeLzToken) {
|
|
1160
|
-
const lz = tokens?.find((t) => normSym(t.symbol) === "LZ");
|
|
1161
|
-
if (lz?.price?.usd && lz.decimals != null) {
|
|
1162
|
-
const human = fromLD(String(feeLzToken), lz.decimals);
|
|
1163
|
-
total += lz.price.usd * human;
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
return total;
|
|
1167
|
-
}
|
|
1168
|
-
function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
|
|
1169
|
-
if (!fees?.length || !dstTokenAddr || !dstChainKey) return "0";
|
|
1170
|
-
let acc = 0n;
|
|
1171
|
-
for (const f of fees) {
|
|
1172
|
-
if (f.chainKey !== dstChainKey) continue;
|
|
1173
|
-
const same = dstChainKey === "ton" ? tonNorm(f.token) === tonNorm(dstTokenAddr) : lower(f.token) === lower(dstTokenAddr);
|
|
1174
|
-
if (!same) continue;
|
|
1175
|
-
acc += BigInt(f.amount ?? "0");
|
|
1176
|
-
}
|
|
1177
|
-
return acc.toString();
|
|
1178
|
-
}
|
|
1179
1104
|
function useBalances(chainKey, address, priorityTokenSymbol) {
|
|
1180
1105
|
const { chainRegistry } = useChainStrategies();
|
|
1181
1106
|
const { assetMatrix } = useTokensStore();
|
|
@@ -1237,10 +1162,92 @@ function useBalances(chainKey, address, priorityTokenSymbol) {
|
|
|
1237
1162
|
query
|
|
1238
1163
|
};
|
|
1239
1164
|
}
|
|
1240
|
-
|
|
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-2.5 px-5 py-3.5 bg-input rounded-md h-12.5 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-2.5 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-7.5 max-w-7.5 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();
|
|
1241
1249
|
const [query, setQuery] = require$$0.useState("");
|
|
1242
1250
|
const [tab, setTab] = require$$0.useState("my");
|
|
1243
|
-
const [isFocused, setIsFocused] = require$$0.useState(false);
|
|
1244
1251
|
const { srcAddress } = useAddresses();
|
|
1245
1252
|
const { fromChain, setFromChain, chains } = useChainsStore();
|
|
1246
1253
|
const { assetMatrix, selectedAssetSymbol } = useTokensStore();
|
|
@@ -1325,159 +1332,7 @@ function useTokenSelectData(items) {
|
|
|
1325
1332
|
const resetState = require$$0.useCallback(() => {
|
|
1326
1333
|
setQuery("");
|
|
1327
1334
|
setTab("my");
|
|
1328
|
-
setIsFocused(false);
|
|
1329
1335
|
}, []);
|
|
1330
|
-
return {
|
|
1331
|
-
query,
|
|
1332
|
-
setQuery,
|
|
1333
|
-
tab,
|
|
1334
|
-
setTab,
|
|
1335
|
-
isFocused,
|
|
1336
|
-
setIsFocused,
|
|
1337
|
-
effectiveTab,
|
|
1338
|
-
resetState,
|
|
1339
|
-
fromChain,
|
|
1340
|
-
setFromChain,
|
|
1341
|
-
selectedAssetSymbol,
|
|
1342
|
-
balancesQuery,
|
|
1343
|
-
groupedTokens,
|
|
1344
|
-
myTokens,
|
|
1345
|
-
getBalance,
|
|
1346
|
-
getTokenUsdValue,
|
|
1347
|
-
findFirstAvailableChain,
|
|
1348
|
-
hasAnyWallet
|
|
1349
|
-
};
|
|
1350
|
-
}
|
|
1351
|
-
const TokenRow = ({
|
|
1352
|
-
symbol,
|
|
1353
|
-
name,
|
|
1354
|
-
isSelected,
|
|
1355
|
-
hasAnyWallet,
|
|
1356
|
-
balance,
|
|
1357
|
-
usdValue,
|
|
1358
|
-
isBalanceLoading,
|
|
1359
|
-
onPick
|
|
1360
|
-
}) => {
|
|
1361
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1362
|
-
button.Button,
|
|
1363
|
-
{
|
|
1364
|
-
onClick: onPick,
|
|
1365
|
-
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" : ""}`,
|
|
1366
|
-
children: [
|
|
1367
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1368
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1369
|
-
TokenSymbol,
|
|
1370
|
-
{
|
|
1371
|
-
symbol,
|
|
1372
|
-
className: "size-7.5 max-w-7.5 rounded-full",
|
|
1373
|
-
alt: symbol
|
|
1374
|
-
}
|
|
1375
|
-
),
|
|
1376
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-1", children: [
|
|
1377
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-lg leading-4 truncate flex items-center gap-1", children: symbol }),
|
|
1378
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground truncate", children: name })
|
|
1379
|
-
] })
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__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: [
|
|
1382
|
-
/* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-5 w-16 rounded-md" }),
|
|
1383
|
-
/* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-3 w-12 rounded-md" })
|
|
1384
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1385
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-extrabold text-foreground text-lg leading-4 truncate", children: hasAnyWallet ? formatBalance(balance) : "—" }),
|
|
1386
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 text-muted-foreground", children: hasAnyWallet && balance > 0 && usdValue > 0 ? formatUsd(usdValue) : "—" })
|
|
1387
|
-
] }) })
|
|
1388
|
-
]
|
|
1389
|
-
}
|
|
1390
|
-
);
|
|
1391
|
-
};
|
|
1392
|
-
const HEADER_H = 30;
|
|
1393
|
-
const ROW_H = 50;
|
|
1394
|
-
const HEADER_TOP_GAP = 30;
|
|
1395
|
-
const VirtualizedTokenList = ({
|
|
1396
|
-
nodes,
|
|
1397
|
-
balancesLoading,
|
|
1398
|
-
hasAnyWallet,
|
|
1399
|
-
selectedAssetSymbol,
|
|
1400
|
-
getBalance,
|
|
1401
|
-
getTokenUsdValue,
|
|
1402
|
-
onPick
|
|
1403
|
-
}) => {
|
|
1404
|
-
const Row = ({ index, style }) => {
|
|
1405
|
-
const node = nodes[index];
|
|
1406
|
-
if (node.kind === "header") {
|
|
1407
|
-
const gap = index === 0 ? 0 : HEADER_TOP_GAP;
|
|
1408
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1409
|
-
"div",
|
|
1410
|
-
{
|
|
1411
|
-
style: { ...style, paddingTop: gap },
|
|
1412
|
-
className: "px-5 flex leading-4 text-base py-1.5 font-semibold text-muted-foreground uppercase",
|
|
1413
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: node.title })
|
|
1414
|
-
}
|
|
1415
|
-
);
|
|
1416
|
-
}
|
|
1417
|
-
const bal = getBalance(node.token.symbol);
|
|
1418
|
-
const usd = getTokenUsdValue(node.token.symbol, node.token.price?.usd);
|
|
1419
|
-
const isSelected = selectedAssetSymbol?.toUpperCase() === node.token.symbol.toUpperCase();
|
|
1420
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1421
|
-
TokenRow,
|
|
1422
|
-
{
|
|
1423
|
-
symbol: node.token.symbol,
|
|
1424
|
-
name: node.token.name,
|
|
1425
|
-
isSelected: !!isSelected,
|
|
1426
|
-
hasAnyWallet,
|
|
1427
|
-
balance: bal,
|
|
1428
|
-
usdValue: usd,
|
|
1429
|
-
isBalanceLoading: balancesLoading,
|
|
1430
|
-
onPick: () => onPick(node.token.symbol, node.willChangeSrc)
|
|
1431
|
-
}
|
|
1432
|
-
);
|
|
1433
|
-
};
|
|
1434
|
-
const getItemSize = (index) => {
|
|
1435
|
-
const node = nodes[index];
|
|
1436
|
-
if (node.kind === "header") {
|
|
1437
|
-
const gap = index === 0 ? 0 : HEADER_TOP_GAP;
|
|
1438
|
-
return HEADER_H + gap;
|
|
1439
|
-
}
|
|
1440
|
-
return ROW_H;
|
|
1441
|
-
};
|
|
1442
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1443
|
-
reactWindow.VariableSizeList,
|
|
1444
|
-
{
|
|
1445
|
-
height: 480,
|
|
1446
|
-
width: "100%",
|
|
1447
|
-
itemCount: nodes.length,
|
|
1448
|
-
itemSize: getItemSize,
|
|
1449
|
-
overscanCount: 8,
|
|
1450
|
-
style: { willChange: "transform", paddingBottom: "40px" },
|
|
1451
|
-
children: Row
|
|
1452
|
-
}
|
|
1453
|
-
);
|
|
1454
|
-
};
|
|
1455
|
-
const TokenSelectModal = ({
|
|
1456
|
-
isOpen,
|
|
1457
|
-
onClose,
|
|
1458
|
-
items,
|
|
1459
|
-
onChangeAsset
|
|
1460
|
-
}) => {
|
|
1461
|
-
const { t } = reactI18next.useTranslation();
|
|
1462
|
-
const {
|
|
1463
|
-
query,
|
|
1464
|
-
setQuery,
|
|
1465
|
-
tab,
|
|
1466
|
-
setTab,
|
|
1467
|
-
isFocused,
|
|
1468
|
-
setIsFocused,
|
|
1469
|
-
effectiveTab,
|
|
1470
|
-
resetState,
|
|
1471
|
-
setFromChain,
|
|
1472
|
-
selectedAssetSymbol,
|
|
1473
|
-
balancesQuery,
|
|
1474
|
-
groupedTokens,
|
|
1475
|
-
myTokens,
|
|
1476
|
-
getBalance,
|
|
1477
|
-
getTokenUsdValue,
|
|
1478
|
-
findFirstAvailableChain,
|
|
1479
|
-
hasAnyWallet
|
|
1480
|
-
} = useTokenSelectData(items);
|
|
1481
1336
|
const handleClose = require$$0.useCallback(() => {
|
|
1482
1337
|
resetState();
|
|
1483
1338
|
onClose();
|
|
@@ -1494,68 +1349,41 @@ const TokenSelectModal = ({
|
|
|
1494
1349
|
onChangeAsset(sym);
|
|
1495
1350
|
handleClose();
|
|
1496
1351
|
};
|
|
1497
|
-
const
|
|
1498
|
-
const out = [];
|
|
1352
|
+
const tokensToRender = require$$0.useMemo(() => {
|
|
1499
1353
|
if (effectiveTab === "my") {
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
token,
|
|
1505
|
-
willChangeSrc: false
|
|
1506
|
-
});
|
|
1507
|
-
}
|
|
1508
|
-
return out;
|
|
1354
|
+
return myTokens.map((token) => ({
|
|
1355
|
+
token,
|
|
1356
|
+
willChangeSrc: false
|
|
1357
|
+
}));
|
|
1509
1358
|
}
|
|
1510
1359
|
const mainTokens = [
|
|
1511
|
-
...groupedTokens.withBalance
|
|
1512
|
-
...groupedTokens.onSrcChain
|
|
1513
|
-
];
|
|
1514
|
-
for (const token of mainTokens) {
|
|
1515
|
-
out.push({
|
|
1516
|
-
kind: "token",
|
|
1517
|
-
key: `main:${token.symbol}`,
|
|
1360
|
+
...groupedTokens.withBalance.map((token) => ({
|
|
1518
1361
|
token,
|
|
1519
1362
|
willChangeSrc: false
|
|
1520
|
-
})
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
return out;
|
|
1538
|
-
}, [effectiveTab, myTokens, groupedTokens, t]);
|
|
1539
|
-
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: [
|
|
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: [
|
|
1540
1380
|
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectToken") }) }),
|
|
1541
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1542
|
-
|
|
1381
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1382
|
+
SearchInput,
|
|
1543
1383
|
{
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1548
|
-
input.Input,
|
|
1549
|
-
{
|
|
1550
|
-
placeholder: t("bridge.searchToken"),
|
|
1551
|
-
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",
|
|
1552
|
-
value: query,
|
|
1553
|
-
onChange: (e) => setQuery(e.target.value),
|
|
1554
|
-
onFocus: () => setIsFocused(true),
|
|
1555
|
-
onBlur: () => setIsFocused(false)
|
|
1556
|
-
}
|
|
1557
|
-
)
|
|
1558
|
-
]
|
|
1384
|
+
placeholder: t("bridge.searchToken"),
|
|
1385
|
+
value: query,
|
|
1386
|
+
onChange: setQuery
|
|
1559
1387
|
}
|
|
1560
1388
|
),
|
|
1561
1389
|
hasAnyWallet() && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
|
|
@@ -1578,20 +1406,52 @@ const TokenSelectModal = ({
|
|
|
1578
1406
|
}
|
|
1579
1407
|
)
|
|
1580
1408
|
] }),
|
|
1581
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-
|
|
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-3.5", children: t("bridge.noResults") }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1582
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") }),
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
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-1.5 font-semibold text-muted-foreground uppercase mt-7.5", 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
|
+
] })
|
|
1595
1455
|
] }) })
|
|
1596
1456
|
] }) });
|
|
1597
1457
|
};
|
|
@@ -1692,7 +1552,7 @@ const SelectTokenButton = ({
|
|
|
1692
1552
|
onClick,
|
|
1693
1553
|
token
|
|
1694
1554
|
}) => {
|
|
1695
|
-
const { t } =
|
|
1555
|
+
const { t } = useBridgeTranslation();
|
|
1696
1556
|
const label = require$$0.useMemo(() => {
|
|
1697
1557
|
return token?.symbol ?? t("bridge.selectToken");
|
|
1698
1558
|
}, [token, t]);
|
|
@@ -1722,7 +1582,7 @@ const SelectTokenButton = ({
|
|
|
1722
1582
|
);
|
|
1723
1583
|
};
|
|
1724
1584
|
const FormHeaderComponent = () => {
|
|
1725
|
-
const { t } =
|
|
1585
|
+
const { t } = useBridgeTranslation();
|
|
1726
1586
|
const { isOpen, onClose, onOpen } = useModal();
|
|
1727
1587
|
const {
|
|
1728
1588
|
isOpen: isOpenSettings,
|
|
@@ -1737,7 +1597,7 @@ const FormHeaderComponent = () => {
|
|
|
1737
1597
|
const sum = selectedAssetSymbol.toUpperCase();
|
|
1738
1598
|
return assets.find((a) => a.symbol.toUpperCase() === sum) ?? assets[0];
|
|
1739
1599
|
}, [assets, selectedAssetSymbol]);
|
|
1740
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(card.CardHeader, { className: "gap-y-0 flex justify-between items-center", children: [
|
|
1600
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(card.CardHeader, { className: "gap-y-0 flex flex-row justify-between items-center", children: [
|
|
1741
1601
|
/* @__PURE__ */ jsxRuntime.jsxs(card.CardTitle, { className: "flex items-center gap-2.5", children: [
|
|
1742
1602
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t("bridge.selectToken") }),
|
|
1743
1603
|
/* @__PURE__ */ jsxRuntime.jsx(SelectTokenButton, { token: current, onClick: onOpen })
|
|
@@ -1768,6 +1628,19 @@ const FormHeaderComponent = () => {
|
|
|
1768
1628
|
] });
|
|
1769
1629
|
};
|
|
1770
1630
|
const FormHeader = require$$0.memo(FormHeaderComponent);
|
|
1631
|
+
function toLD(human, decimals) {
|
|
1632
|
+
const [i = "0", f = ""] = human.replace(",", ".").split(".");
|
|
1633
|
+
const frac = (f + "0".repeat(decimals)).slice(0, decimals);
|
|
1634
|
+
return BigInt(i + frac).toString();
|
|
1635
|
+
}
|
|
1636
|
+
function fromLD(ld, decimals) {
|
|
1637
|
+
const bi = BigInt(ld || "0");
|
|
1638
|
+
if (decimals === 0) return Number(bi);
|
|
1639
|
+
const base = BigInt(10) ** BigInt(decimals);
|
|
1640
|
+
const int = bi / base;
|
|
1641
|
+
const frac = Number(bi % base) / Number(base);
|
|
1642
|
+
return Number(int) + frac;
|
|
1643
|
+
}
|
|
1771
1644
|
async function fetchQuotes(req) {
|
|
1772
1645
|
const params = {
|
|
1773
1646
|
srcChainKey: req.srcChainKey,
|
|
@@ -1826,6 +1699,131 @@ async function getQuotesByPriority(req) {
|
|
|
1826
1699
|
const priority = req.routePriority || RoutePriority.RECOMMENDED;
|
|
1827
1700
|
return selectQuoteByPriority(routes, priority);
|
|
1828
1701
|
}
|
|
1702
|
+
function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
|
|
1703
|
+
if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
|
|
1704
|
+
const byChain = assetMatrix[assetSymbol.toUpperCase()];
|
|
1705
|
+
return byChain?.[chainKey];
|
|
1706
|
+
}
|
|
1707
|
+
const DEFAULT_SLIPPAGE_BPS = 50;
|
|
1708
|
+
const lower = (s) => (s ?? "").toLowerCase();
|
|
1709
|
+
const normSym = (s) => (s ?? "").toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
|
|
1710
|
+
function tonNorm(addr) {
|
|
1711
|
+
if (!addr) return null;
|
|
1712
|
+
try {
|
|
1713
|
+
if (addr.includes(":")) {
|
|
1714
|
+
return core.Address.parseRaw(addr).toString({
|
|
1715
|
+
bounceable: false,
|
|
1716
|
+
urlSafe: true
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
return core.Address.parse(addr).toString({ bounceable: false, urlSafe: true });
|
|
1720
|
+
} catch {
|
|
1721
|
+
return null;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
const isZeroAddr = (a) => (
|
|
1725
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1726
|
+
!!a && /^0x0{40}$/i.test(a) || /^0x[eE]{4}e{36}$/i.test(a)
|
|
1727
|
+
);
|
|
1728
|
+
function addrForApi(chainKey, addr) {
|
|
1729
|
+
if (chainKey === "ton") return tonNorm(addr);
|
|
1730
|
+
return addr;
|
|
1731
|
+
}
|
|
1732
|
+
function isNativeAddrEqual(chain, tokenAddr) {
|
|
1733
|
+
if (!chain) return false;
|
|
1734
|
+
if (!tokenAddr) return false;
|
|
1735
|
+
if (isZeroAddr(tokenAddr)) return true;
|
|
1736
|
+
const nativeAddr = chain.nativeCurrency?.address;
|
|
1737
|
+
if (!nativeAddr) return false;
|
|
1738
|
+
if (chain.chainKey === "ton") {
|
|
1739
|
+
const a = tonNorm(tokenAddr);
|
|
1740
|
+
const b = tonNorm(nativeAddr);
|
|
1741
|
+
return !!a && !!b && a === b;
|
|
1742
|
+
}
|
|
1743
|
+
return lower(nativeAddr) === lower(tokenAddr);
|
|
1744
|
+
}
|
|
1745
|
+
function findNativeMeta(tokens, chain) {
|
|
1746
|
+
if (!chain) return { decimals: 18, priceUsd: void 0 };
|
|
1747
|
+
const sym = normSym(chain.nativeCurrency?.symbol);
|
|
1748
|
+
if (!sym) {
|
|
1749
|
+
return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1750
|
+
}
|
|
1751
|
+
const sameChain = tokens?.find(
|
|
1752
|
+
(t) => t.chainKey === chain.chainKey && normSym(t.symbol) === sym
|
|
1753
|
+
) ?? void 0;
|
|
1754
|
+
if (sameChain)
|
|
1755
|
+
return { decimals: sameChain.decimals, priceUsd: sameChain.price?.usd };
|
|
1756
|
+
const anyChain = tokens?.find((t) => normSym(t.symbol) === sym);
|
|
1757
|
+
if (anyChain)
|
|
1758
|
+
return { decimals: anyChain.decimals, priceUsd: anyChain.price?.usd };
|
|
1759
|
+
return { decimals: chain.chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1760
|
+
}
|
|
1761
|
+
function lookupTokenMeta(tokens, chains, chainKey, tokenAddr) {
|
|
1762
|
+
if (!chainKey) return { decimals: 18, priceUsd: void 0 };
|
|
1763
|
+
const chain = chains?.find((c) => c.chainKey === chainKey);
|
|
1764
|
+
const hit = tokens?.find((t) => {
|
|
1765
|
+
if (t.chainKey !== chainKey) return false;
|
|
1766
|
+
if (chainKey === "ton") {
|
|
1767
|
+
const a = tonNorm(t.address);
|
|
1768
|
+
const b = tonNorm(tokenAddr);
|
|
1769
|
+
return !!a && !!b && a === b;
|
|
1770
|
+
}
|
|
1771
|
+
return lower(t.address) === lower(tokenAddr);
|
|
1772
|
+
}) ?? void 0;
|
|
1773
|
+
if (hit) return { decimals: hit.decimals, priceUsd: hit.price?.usd };
|
|
1774
|
+
if (isNativeAddrEqual(chain, tokenAddr)) {
|
|
1775
|
+
return findNativeMeta(tokens, chain);
|
|
1776
|
+
}
|
|
1777
|
+
return { decimals: chainKey === "ton" ? 9 : 18, priceUsd: void 0 };
|
|
1778
|
+
}
|
|
1779
|
+
function computeFeesUsdFromArray(fees, tokens, chains) {
|
|
1780
|
+
if (!fees?.length) return { totalUsd: 0 };
|
|
1781
|
+
let total = 0;
|
|
1782
|
+
let protocolFeeUsd = 0;
|
|
1783
|
+
let messageFeeUsd = 0;
|
|
1784
|
+
const byType = /* @__PURE__ */ new Map();
|
|
1785
|
+
for (const f of fees) {
|
|
1786
|
+
let usd = Number(f.usd ?? 0);
|
|
1787
|
+
if (!usd) {
|
|
1788
|
+
const { decimals, priceUsd } = lookupTokenMeta(
|
|
1789
|
+
tokens,
|
|
1790
|
+
chains,
|
|
1791
|
+
f.chainKey,
|
|
1792
|
+
f.token
|
|
1793
|
+
);
|
|
1794
|
+
const human = fromLD(String(f.amount ?? "0"), decimals);
|
|
1795
|
+
usd = (priceUsd ?? 0) * human;
|
|
1796
|
+
}
|
|
1797
|
+
total += usd;
|
|
1798
|
+
const type = (f.type ?? "other").toLowerCase();
|
|
1799
|
+
byType.set(type, (byType.get(type) ?? 0) + usd);
|
|
1800
|
+
if (type === "protocol" || type === "service") {
|
|
1801
|
+
protocolFeeUsd += usd;
|
|
1802
|
+
} else if (type === "message" || type === "gas" || type === "network") {
|
|
1803
|
+
messageFeeUsd += usd;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
const serviceUsd = byType.get("protocol") ?? byType.get("service") ?? void 0;
|
|
1807
|
+
const blockchainUsd = byType.get("gas") ?? byType.get("network") ?? byType.get("message") ?? void 0;
|
|
1808
|
+
return {
|
|
1809
|
+
totalUsd: total,
|
|
1810
|
+
protocolFeeUsd: protocolFeeUsd > 0 ? protocolFeeUsd : void 0,
|
|
1811
|
+
messageFeeUsd: messageFeeUsd > 0 ? messageFeeUsd : void 0,
|
|
1812
|
+
serviceUsd,
|
|
1813
|
+
blockchainUsd
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
function sumFeeByTokenLD(fees, dstTokenAddr, dstChainKey) {
|
|
1817
|
+
if (!fees?.length || !dstTokenAddr || !dstChainKey) return "0";
|
|
1818
|
+
let acc = 0n;
|
|
1819
|
+
for (const f of fees) {
|
|
1820
|
+
if (f.chainKey !== dstChainKey) continue;
|
|
1821
|
+
const same = dstChainKey === "ton" ? tonNorm(f.token) === tonNorm(dstTokenAddr) : lower(f.token) === lower(dstTokenAddr);
|
|
1822
|
+
if (!same) continue;
|
|
1823
|
+
acc += BigInt(f.amount ?? "0");
|
|
1824
|
+
}
|
|
1825
|
+
return acc.toString();
|
|
1826
|
+
}
|
|
1829
1827
|
function useBridgeQuote() {
|
|
1830
1828
|
const { assetMatrix, selectedAssetSymbol } = useTokensStore();
|
|
1831
1829
|
const { fromChain, toChain } = useChainsStore();
|
|
@@ -2227,7 +2225,7 @@ const SelectNetworkButton = ({
|
|
|
2227
2225
|
onClick,
|
|
2228
2226
|
network
|
|
2229
2227
|
}) => {
|
|
2230
|
-
const { t } =
|
|
2228
|
+
const { t } = useBridgeTranslation();
|
|
2231
2229
|
const label = require$$0.useMemo(() => {
|
|
2232
2230
|
return network?.name ?? t("bridge.selectNetwork");
|
|
2233
2231
|
}, [network, t]);
|
|
@@ -2324,14 +2322,12 @@ const ChainSelectModal = ({
|
|
|
2324
2322
|
allowedItems,
|
|
2325
2323
|
onChangeChain
|
|
2326
2324
|
}) => {
|
|
2327
|
-
const { t } =
|
|
2325
|
+
const { t } = useBridgeTranslation();
|
|
2328
2326
|
const [query, setQuery] = require$$0.useState("");
|
|
2329
|
-
const [isFocused, setIsFocused] = require$$0.useState(false);
|
|
2330
2327
|
const { setFromChain, chains, fromChain, toChain } = useChainsStore();
|
|
2331
2328
|
const { assetMatrix, selectedAssetSymbol } = useTokensStore();
|
|
2332
2329
|
const handleClose = require$$0.useCallback(() => {
|
|
2333
2330
|
setQuery("");
|
|
2334
|
-
setIsFocused(false);
|
|
2335
2331
|
onClose();
|
|
2336
2332
|
}, [onClose]);
|
|
2337
2333
|
const findCompatibleSrcChain = require$$0.useCallback(
|
|
@@ -2391,7 +2387,7 @@ const ChainSelectModal = ({
|
|
|
2391
2387
|
button.Button,
|
|
2392
2388
|
{
|
|
2393
2389
|
onClick: () => onChainPick(chain, willChangeSrc),
|
|
2394
|
-
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-
|
|
2390
|
+
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-md transition-[300] ${isSelected ? "border border-ring" : ""}`,
|
|
2395
2391
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
2396
2392
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2397
2393
|
NetworkSymbol,
|
|
@@ -2407,26 +2403,16 @@ const ChainSelectModal = ({
|
|
|
2407
2403
|
chain.chainKey
|
|
2408
2404
|
);
|
|
2409
2405
|
};
|
|
2410
|
-
return /* @__PURE__ */ jsxRuntime.jsx(dialog.Dialog, { open: isOpen, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(dialog.DialogContent, { className: "!
|
|
2406
|
+
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: [
|
|
2411
2407
|
/* @__PURE__ */ jsxRuntime.jsx(dialog.DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(dialog.DialogTitle, { children: t("bridge.selectNetwork") }) }),
|
|
2412
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2413
|
-
|
|
2408
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2409
|
+
SearchInput,
|
|
2414
2410
|
{
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
{
|
|
2421
|
-
placeholder: t("bridge.searchDestinationChain"),
|
|
2422
|
-
className: "w-full outline-none leading-0 p-0 h-6 text-base text-foreground placeholder:text-muted-foreground bg-none dark:bg-transparent",
|
|
2423
|
-
value: query,
|
|
2424
|
-
onChange: (e) => setQuery(e.target.value),
|
|
2425
|
-
onFocus: () => setIsFocused(true),
|
|
2426
|
-
onBlur: () => setIsFocused(false)
|
|
2427
|
-
}
|
|
2428
|
-
)
|
|
2429
|
-
]
|
|
2411
|
+
placeholder: t("bridge.searchDestinationChain"),
|
|
2412
|
+
value: query,
|
|
2413
|
+
onChange: setQuery,
|
|
2414
|
+
containerClassName: "rounded-md",
|
|
2415
|
+
className: "text-foreground placeholder:text-muted-foreground"
|
|
2430
2416
|
}
|
|
2431
2417
|
),
|
|
2432
2418
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
@@ -2469,7 +2455,7 @@ const WalletButton = ({
|
|
|
2469
2455
|
wallet,
|
|
2470
2456
|
addressType
|
|
2471
2457
|
}) => {
|
|
2472
|
-
const { t } =
|
|
2458
|
+
const { t } = useBridgeTranslation();
|
|
2473
2459
|
const { onOpen } = useWalletSelectModal();
|
|
2474
2460
|
const { chainRegistry } = useChainStrategies();
|
|
2475
2461
|
const walletType = mapWalletToType(wallet);
|
|
@@ -2641,63 +2627,30 @@ const useCustomAddressStore = zustand.create((set) => ({
|
|
|
2641
2627
|
setCustomDstAddress: (address) => set({ customDstAddress: address }),
|
|
2642
2628
|
clearCustomDstAddress: () => set({ customDstAddress: void 0 })
|
|
2643
2629
|
}));
|
|
2644
|
-
const
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
bounceable: false,
|
|
2650
|
-
urlSafe: true
|
|
2651
|
-
});
|
|
2652
|
-
}
|
|
2653
|
-
return core.Address.parse(addr).toString({ bounceable: false, urlSafe: true });
|
|
2654
|
-
} catch {
|
|
2655
|
-
return null;
|
|
2656
|
-
}
|
|
2630
|
+
const useIsAddressValid = (address, chainKey) => {
|
|
2631
|
+
const isValid = require$$0.useMemo(() => {
|
|
2632
|
+
return isAddressValidForChain(chainKey, address);
|
|
2633
|
+
}, [address, chainKey]);
|
|
2634
|
+
return { isValid };
|
|
2657
2635
|
};
|
|
2658
|
-
const
|
|
2659
|
-
const
|
|
2636
|
+
const AnotherAddress = () => {
|
|
2637
|
+
const [enabled, setEnabled] = require$$0.useState(false);
|
|
2638
|
+
const [isFocused, setIsFocused] = require$$0.useState(false);
|
|
2639
|
+
const { t } = useBridgeTranslation();
|
|
2660
2640
|
const { toChain } = useChainsStore();
|
|
2661
|
-
const {
|
|
2662
|
-
const { setCustomDstAddress, clearCustomDstAddress } = useCustomAddressStore();
|
|
2641
|
+
const { setCustomDstAddress } = useCustomAddressStore();
|
|
2663
2642
|
const [value, setValue] = require$$0.useState("");
|
|
2664
|
-
const
|
|
2665
|
-
const
|
|
2666
|
-
const prevEnabledRef = require$$0.useRef(enabled);
|
|
2667
|
-
require$$0.useEffect(() => {
|
|
2668
|
-
const wasEnabled = prevEnabledRef.current;
|
|
2669
|
-
if (enabled && !wasEnabled) {
|
|
2670
|
-
prevDstRef.current = dstAddress;
|
|
2671
|
-
setValue(dstAddress ?? "");
|
|
2672
|
-
setInvalid(false);
|
|
2673
|
-
}
|
|
2674
|
-
if (!enabled && wasEnabled) {
|
|
2675
|
-
clearCustomDstAddress();
|
|
2676
|
-
setInvalid(false);
|
|
2677
|
-
}
|
|
2678
|
-
prevEnabledRef.current = enabled;
|
|
2679
|
-
}, [enabled]);
|
|
2643
|
+
const { isValid } = useIsAddressValid(value.trim(), toChain?.chainKey);
|
|
2644
|
+
const invalid = value.trim() && !isValid;
|
|
2680
2645
|
const pushToStoreIfValid = (raw) => {
|
|
2681
2646
|
if (!enabled) return;
|
|
2682
2647
|
const v = raw.trim();
|
|
2683
2648
|
if (!v) {
|
|
2684
2649
|
setCustomDstAddress(void 0);
|
|
2685
|
-
setInvalid(false);
|
|
2686
|
-
return;
|
|
2687
|
-
}
|
|
2688
|
-
const ck = toChain?.chainKey;
|
|
2689
|
-
if (!ck) {
|
|
2690
|
-
setInvalid(true);
|
|
2691
2650
|
return;
|
|
2692
2651
|
}
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
if (valid && valueForStore) {
|
|
2696
|
-
setInvalid(false);
|
|
2697
|
-
setCustomDstAddress(valueForStore);
|
|
2698
|
-
if (ck === "ton") setValue(valueForStore);
|
|
2699
|
-
} else {
|
|
2700
|
-
setInvalid(true);
|
|
2652
|
+
if (isValid) {
|
|
2653
|
+
setCustomDstAddress(v);
|
|
2701
2654
|
}
|
|
2702
2655
|
};
|
|
2703
2656
|
const onChange = (text) => {
|
|
@@ -2712,7 +2665,7 @@ const ToggleRow = ({ enabled, onToggle }) => {
|
|
|
2712
2665
|
} catch {
|
|
2713
2666
|
}
|
|
2714
2667
|
};
|
|
2715
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-lg
|
|
2668
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 flex flex-col rounded-b-lg bg-muted", children: [
|
|
2716
2669
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2717
2670
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm leading-4.5 font-medium text-muted-foreground", children: t("bridge.sendToAnotherAddress") }),
|
|
2718
2671
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2721,7 +2674,7 @@ const ToggleRow = ({ enabled, onToggle }) => {
|
|
|
2721
2674
|
className: "data-[state=unchecked]:bg-switch-inactive data-[state=checked]:bg-switch-active",
|
|
2722
2675
|
"aria-pressed": enabled,
|
|
2723
2676
|
checked: enabled,
|
|
2724
|
-
onClick:
|
|
2677
|
+
onClick: () => setEnabled((v) => !v)
|
|
2725
2678
|
}
|
|
2726
2679
|
)
|
|
2727
2680
|
] }),
|
|
@@ -2736,16 +2689,27 @@ const ToggleRow = ({ enabled, onToggle }) => {
|
|
|
2736
2689
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2737
2690
|
"div",
|
|
2738
2691
|
{
|
|
2739
|
-
className:
|
|
2692
|
+
className: utils.cn(
|
|
2693
|
+
"bg-input py-2 px-4 mt-2 w-full flex items-center gap-4 rounded-md justify-between border border-transparent transition-all",
|
|
2694
|
+
{
|
|
2695
|
+
"py-4": value,
|
|
2696
|
+
"border border-ring": isFocused,
|
|
2697
|
+
"border-destructive": invalid
|
|
2698
|
+
}
|
|
2699
|
+
),
|
|
2740
2700
|
children: [
|
|
2741
2701
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 w-full", children: [
|
|
2742
2702
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2743
2703
|
input.Input,
|
|
2744
2704
|
{
|
|
2745
|
-
className:
|
|
2746
|
-
|
|
2705
|
+
className: utils.cn(
|
|
2706
|
+
"p-0 h-auto text-base leading-5 font-semibold w-full bg-transparent dark:bg-transparent placeholder:text-muted-foreground/50 border-none"
|
|
2707
|
+
),
|
|
2708
|
+
placeholder: t("bridge.anotherAddressPlaceholder"),
|
|
2747
2709
|
type: "text",
|
|
2748
2710
|
value,
|
|
2711
|
+
onFocus: () => setIsFocused(true),
|
|
2712
|
+
onBlur: () => setIsFocused(false),
|
|
2749
2713
|
onChange: (e) => onChange(e.target.value)
|
|
2750
2714
|
}
|
|
2751
2715
|
),
|
|
@@ -2755,21 +2719,14 @@ const ToggleRow = ({ enabled, onToggle }) => {
|
|
|
2755
2719
|
defaultValue: "Check correctness before transfer"
|
|
2756
2720
|
}) }) })
|
|
2757
2721
|
] }),
|
|
2758
|
-
!value ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2759
|
-
button.Button,
|
|
2760
|
-
{
|
|
2761
|
-
variant: "default",
|
|
2762
|
-
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",
|
|
2763
|
-
onClick: onPaste,
|
|
2764
|
-
children: t("common.paste")
|
|
2765
|
-
}
|
|
2766
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2722
|
+
!value ? /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "secondary", size: "sm", onClick: onPaste, children: t("common.paste") }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2767
2723
|
button.Button,
|
|
2768
2724
|
{
|
|
2769
2725
|
variant: "ghost",
|
|
2770
|
-
|
|
2726
|
+
size: "sm",
|
|
2727
|
+
className: "rounded-full p-0 size-5 self-start",
|
|
2771
2728
|
onClick: () => setValue(""),
|
|
2772
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-
|
|
2729
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4" })
|
|
2773
2730
|
}
|
|
2774
2731
|
)
|
|
2775
2732
|
]
|
|
@@ -2882,7 +2839,7 @@ function getRouteDisplayName(route) {
|
|
|
2882
2839
|
return route.split(/[/\-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
2883
2840
|
}
|
|
2884
2841
|
const Details = () => {
|
|
2885
|
-
const { t } =
|
|
2842
|
+
const { t } = useBridgeTranslation();
|
|
2886
2843
|
const { selectedAssetSymbol, assetMatrix, tokens } = useTokensStore();
|
|
2887
2844
|
const { toChain, fromChain, chains } = useChainsStore();
|
|
2888
2845
|
const { quote, status } = useBridgeQuoteStore();
|
|
@@ -3528,7 +3485,7 @@ function useSilentValidations(amountString) {
|
|
|
3528
3485
|
return validationResult;
|
|
3529
3486
|
}
|
|
3530
3487
|
const SubmitButton = () => {
|
|
3531
|
-
const { t } =
|
|
3488
|
+
const { t } = useBridgeTranslation();
|
|
3532
3489
|
const { chainRegistry } = useChainStrategies();
|
|
3533
3490
|
const { srcAddress, dstAddress } = useAddresses();
|
|
3534
3491
|
const { quote, status, inputAmount, noRoute } = useBridgeQuoteStore();
|
|
@@ -3623,13 +3580,22 @@ const SubmitButton = () => {
|
|
|
3623
3580
|
}
|
|
3624
3581
|
};
|
|
3625
3582
|
const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
|
|
3626
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3583
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3584
|
+
button.Button,
|
|
3585
|
+
{
|
|
3586
|
+
onClick: handleClick,
|
|
3587
|
+
disabled,
|
|
3588
|
+
size: "lg",
|
|
3589
|
+
className: "w-full mt-4",
|
|
3590
|
+
children: label
|
|
3591
|
+
}
|
|
3592
|
+
);
|
|
3627
3593
|
};
|
|
3628
3594
|
function short(addr) {
|
|
3629
3595
|
return addr.slice(0, 4) + "…" + addr.slice(-4);
|
|
3630
3596
|
}
|
|
3631
3597
|
const WalletSelectModal = () => {
|
|
3632
|
-
const { t } =
|
|
3598
|
+
const { t } = useBridgeTranslation();
|
|
3633
3599
|
const { isOpen, onClose } = useWalletSelectModal();
|
|
3634
3600
|
const { connect, connectors, isPending } = wagmi.useConnect();
|
|
3635
3601
|
const { chainRegistry } = useChainStrategies();
|
|
@@ -3738,7 +3704,7 @@ const WalletSelectModal = () => {
|
|
|
3738
3704
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 font-semibold text-muted-foreground uppercase", children: t("wallets.connected") }),
|
|
3739
3705
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: connectedWallets.map((wallet) => {
|
|
3740
3706
|
const IconComponent = wallet.icon;
|
|
3741
|
-
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-
|
|
3707
|
+
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-md transition-[300]", children: [
|
|
3742
3708
|
/* @__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: [
|
|
3743
3709
|
/* @__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
3710
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
@@ -3779,7 +3745,7 @@ const WalletSelectModal = () => {
|
|
|
3779
3745
|
}
|
|
3780
3746
|
},
|
|
3781
3747
|
disabled: isEvmConnector ? isPending : !wallet.enabled,
|
|
3782
|
-
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-
|
|
3748
|
+
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-md transition-[300] disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3783
3749
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
3784
3750
|
/* @__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" }) }),
|
|
3785
3751
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
|
|
@@ -3866,7 +3832,7 @@ const ProgressStep = () => {
|
|
|
3866
3832
|
/* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
3867
3833
|
/* @__PURE__ */ jsxRuntime.jsx("span", {})
|
|
3868
3834
|
] }),
|
|
3869
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-display font-black relative z-10", children:
|
|
3835
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-display font-black relative z-10", children: i18n.t("transaction.inProgress") }),
|
|
3870
3836
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative mt-5 z-10", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute dot-vertical h-full left-5 top-0 bottom-0 z-0" }) })
|
|
3871
3837
|
] }) });
|
|
3872
3838
|
};
|
|
@@ -4123,10 +4089,10 @@ const FailedStep = () => {
|
|
|
4123
4089
|
/* @__PURE__ */ jsxRuntime.jsx(TransactionFailedVector, {}),
|
|
4124
4090
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "on-circle on-circle-failed-small under-noise" }),
|
|
4125
4091
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "on-circle on-circle-failed-big under-noise" }),
|
|
4126
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-display font-black relative z-10", children:
|
|
4092
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-display font-black relative z-10", children: i18n.t("transaction.failed") }),
|
|
4127
4093
|
current?.error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full space-y-2 mt-6 relative z-10", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: current.error }) })
|
|
4128
4094
|
] }),
|
|
4129
|
-
/* @__PURE__ */ jsxRuntime.jsx(card.CardFooter, { className: "flex-col gap-3 pb-10 px-8", children: /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", className: "w-full", onClick: reset, children:
|
|
4095
|
+
/* @__PURE__ */ jsxRuntime.jsx(card.CardFooter, { className: "flex-col gap-3 pb-10 px-8", children: /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", className: "w-full", onClick: reset, children: i18n.t("common.close") }) })
|
|
4130
4096
|
] });
|
|
4131
4097
|
};
|
|
4132
4098
|
const TransactionSuccessVector = (props) => {
|
|
@@ -5488,7 +5454,7 @@ var fireworksExports = requireFireworks();
|
|
|
5488
5454
|
const Fireworks = /* @__PURE__ */ getDefaultExportFromCjs(fireworksExports);
|
|
5489
5455
|
const SuccessStep = () => {
|
|
5490
5456
|
const { current, reset } = useTransactionStore();
|
|
5491
|
-
const { t } =
|
|
5457
|
+
const { t } = useBridgeTranslation();
|
|
5492
5458
|
const metadata = current?.metadata;
|
|
5493
5459
|
const srcTxHash = current?.srcTxHash;
|
|
5494
5460
|
const handleCopyHash = () => {
|
|
@@ -5707,7 +5673,7 @@ const useCountdown = (initialSeconds) => {
|
|
|
5707
5673
|
};
|
|
5708
5674
|
};
|
|
5709
5675
|
const ConfirmStep = () => {
|
|
5710
|
-
const { t } =
|
|
5676
|
+
const { t } = useBridgeTranslation();
|
|
5711
5677
|
const { formatTime } = useCountdown(90);
|
|
5712
5678
|
return /* @__PURE__ */ jsxRuntime.jsx(card.Card, { className: "flex flex-col border-none h-full bg-background overflow-hidden rounded-none md:rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs(card.CardContent, { className: "flex flex-col relative gap-4 py-10 px-8 flex-1 items-center justify-start text-center noise", children: [
|
|
5713
5679
|
/* @__PURE__ */ jsxRuntime.jsx(TransactionConfirmVector, {}),
|
|
@@ -5830,7 +5796,7 @@ class ChainStrategyRegistry {
|
|
|
5830
5796
|
async getBalances(chainKey, address, tokens, priorityToken) {
|
|
5831
5797
|
const strategy = this.getStrategy(chainKey);
|
|
5832
5798
|
if (!strategy) return {};
|
|
5833
|
-
return await strategy.getBalances(address, tokens, priorityToken);
|
|
5799
|
+
return await strategy.getBalances(address, tokens, chainKey, priorityToken);
|
|
5834
5800
|
}
|
|
5835
5801
|
isAddressValid(chainKey, address) {
|
|
5836
5802
|
const strategy = this.getStrategy(chainKey);
|
|
@@ -5941,14 +5907,9 @@ function parseTonAddress(address) {
|
|
|
5941
5907
|
}
|
|
5942
5908
|
return ton.Address.parse(address);
|
|
5943
5909
|
}
|
|
5944
|
-
async function getEvmBalances(publicClient, address, tokens, priorityToken) {
|
|
5910
|
+
async function getEvmBalances(publicClient, address, tokens, chainKey, priorityToken) {
|
|
5945
5911
|
const balances = {};
|
|
5946
5912
|
try {
|
|
5947
|
-
console.log("start getEvmBalances");
|
|
5948
|
-
console.log("publicClient:", publicClient);
|
|
5949
|
-
console.log("isAddress:", viem.isAddress(address));
|
|
5950
|
-
console.log("tokens:", tokens);
|
|
5951
|
-
console.log("priorityToken:", priorityToken);
|
|
5952
5913
|
if (!address || !viem.isAddress(address)) {
|
|
5953
5914
|
console.warn(`Invalid EVM address provided: ${address}`);
|
|
5954
5915
|
return balances;
|
|
@@ -5957,40 +5918,55 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
|
|
|
5957
5918
|
throw new Error("No public client provided");
|
|
5958
5919
|
}
|
|
5959
5920
|
const nativeTokens = tokens.filter((t) => isNativeAddress(t.address));
|
|
5960
|
-
const erc20Tokens = tokens.filter(
|
|
5921
|
+
const erc20Tokens = tokens.filter(
|
|
5922
|
+
(t) => !isNativeAddress(t.address) && viem.isAddress(t.address)
|
|
5923
|
+
);
|
|
5961
5924
|
if (priorityToken) {
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
const
|
|
5969
|
-
if (
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5925
|
+
if (priorityToken.chainKey !== chainKey) {
|
|
5926
|
+
console.debug(
|
|
5927
|
+
`Skipping priority token ${priorityToken.symbol}: chain mismatch (expected ${chainKey}, got ${priorityToken.chainKey})`
|
|
5928
|
+
);
|
|
5929
|
+
} else {
|
|
5930
|
+
try {
|
|
5931
|
+
const isPriorityNative = isNativeAddress(priorityToken.address);
|
|
5932
|
+
if (isPriorityNative) {
|
|
5933
|
+
const ethBalance = await publicClient.getBalance({
|
|
5934
|
+
address
|
|
5935
|
+
});
|
|
5936
|
+
const balance = parseFloat(
|
|
5937
|
+
viem.formatUnits(ethBalance, priorityToken.decimals)
|
|
5938
|
+
);
|
|
5939
|
+
if (balance > 0) {
|
|
5940
|
+
balances[priorityToken.symbol] = { balance, address };
|
|
5941
|
+
}
|
|
5942
|
+
} else if (viem.isAddress(priorityToken.address)) {
|
|
5943
|
+
const tokenBalance = await publicClient.readContract({
|
|
5944
|
+
address: priorityToken.address,
|
|
5945
|
+
abi: [
|
|
5946
|
+
{
|
|
5947
|
+
name: "balanceOf",
|
|
5948
|
+
type: "function",
|
|
5949
|
+
stateMutability: "view",
|
|
5950
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
5951
|
+
outputs: [{ name: "balance", type: "uint256" }]
|
|
5952
|
+
}
|
|
5953
|
+
],
|
|
5954
|
+
functionName: "balanceOf",
|
|
5955
|
+
args: [address]
|
|
5956
|
+
});
|
|
5957
|
+
const balance = parseFloat(
|
|
5958
|
+
viem.formatUnits(tokenBalance, priorityToken.decimals)
|
|
5959
|
+
);
|
|
5960
|
+
if (balance > 0) {
|
|
5961
|
+
balances[priorityToken.symbol] = { balance, address };
|
|
5962
|
+
}
|
|
5990
5963
|
}
|
|
5964
|
+
} catch (error) {
|
|
5965
|
+
console.debug(
|
|
5966
|
+
`Failed to get priority token balance for ${priorityToken.symbol}:`,
|
|
5967
|
+
error
|
|
5968
|
+
);
|
|
5991
5969
|
}
|
|
5992
|
-
} catch (error) {
|
|
5993
|
-
console.debug(`Failed to get priority token balance for ${priorityToken.symbol}:`, error);
|
|
5994
5970
|
}
|
|
5995
5971
|
}
|
|
5996
5972
|
for (const token of nativeTokens) {
|
|
@@ -6003,7 +5979,10 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
|
|
|
6003
5979
|
balances[token.symbol] = { balance, address };
|
|
6004
5980
|
}
|
|
6005
5981
|
} catch (error) {
|
|
6006
|
-
console.debug(
|
|
5982
|
+
console.debug(
|
|
5983
|
+
`Failed to get native balance for ${token.symbol}:`,
|
|
5984
|
+
error
|
|
5985
|
+
);
|
|
6007
5986
|
}
|
|
6008
5987
|
}
|
|
6009
5988
|
if (erc20Tokens.length > 0) {
|
|
@@ -6031,17 +6010,25 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
|
|
|
6031
6010
|
if (!token) return;
|
|
6032
6011
|
if (result.status === "success" && result.result !== void 0) {
|
|
6033
6012
|
try {
|
|
6034
|
-
const balance = parseFloat(
|
|
6013
|
+
const balance = parseFloat(
|
|
6014
|
+
viem.formatUnits(result.result, token.decimals)
|
|
6015
|
+
);
|
|
6035
6016
|
if (balance > 0) {
|
|
6036
6017
|
balances[token.symbol] = { balance, address };
|
|
6037
6018
|
}
|
|
6038
6019
|
} catch (error) {
|
|
6039
|
-
console.debug(
|
|
6020
|
+
console.debug(
|
|
6021
|
+
`Failed to parse balance for ${token.symbol}:`,
|
|
6022
|
+
error
|
|
6023
|
+
);
|
|
6040
6024
|
}
|
|
6041
6025
|
}
|
|
6042
6026
|
});
|
|
6043
6027
|
} catch (error) {
|
|
6044
|
-
console.warn(
|
|
6028
|
+
console.warn(
|
|
6029
|
+
"Multicall failed, falling back to individual calls:",
|
|
6030
|
+
error
|
|
6031
|
+
);
|
|
6045
6032
|
for (const token of erc20Tokens) {
|
|
6046
6033
|
try {
|
|
6047
6034
|
const tokenBalance = await publicClient.readContract({
|
|
@@ -6075,7 +6062,7 @@ async function getEvmBalances(publicClient, address, tokens, priorityToken) {
|
|
|
6075
6062
|
}
|
|
6076
6063
|
return balances;
|
|
6077
6064
|
}
|
|
6078
|
-
async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
|
|
6065
|
+
async function getTonBalances(address, tokens, chainKey, customTonClient, tonApiKey) {
|
|
6079
6066
|
const balances = {};
|
|
6080
6067
|
try {
|
|
6081
6068
|
if (!isTonFriendlyAddress(address)) {
|
|
@@ -6234,13 +6221,18 @@ class EvmChainStrategy {
|
|
|
6234
6221
|
getConnectLabel(t) {
|
|
6235
6222
|
return t("wallets.connectEvmWallet");
|
|
6236
6223
|
}
|
|
6237
|
-
async getBalances(address, tokens, priorityToken) {
|
|
6224
|
+
async getBalances(address, tokens, chainKey, priorityToken) {
|
|
6238
6225
|
if (!this.publicClient) {
|
|
6239
6226
|
console.warn("No publicClient available for balance query");
|
|
6240
6227
|
return {};
|
|
6241
6228
|
}
|
|
6242
|
-
|
|
6243
|
-
|
|
6229
|
+
return await getEvmBalances(
|
|
6230
|
+
this.publicClient,
|
|
6231
|
+
address,
|
|
6232
|
+
tokens,
|
|
6233
|
+
chainKey,
|
|
6234
|
+
priorityToken
|
|
6235
|
+
);
|
|
6244
6236
|
}
|
|
6245
6237
|
isAddressValid(address) {
|
|
6246
6238
|
if (!address) return false;
|
|
@@ -6596,10 +6588,11 @@ class TonChainStrategy {
|
|
|
6596
6588
|
getConnectLabel(t) {
|
|
6597
6589
|
return t("wallets.connectTonWallet");
|
|
6598
6590
|
}
|
|
6599
|
-
async getBalances(address, tokens) {
|
|
6591
|
+
async getBalances(address, tokens, chainKey) {
|
|
6600
6592
|
return await getTonBalances(
|
|
6601
6593
|
address,
|
|
6602
6594
|
tokens,
|
|
6595
|
+
chainKey,
|
|
6603
6596
|
this.config.tonClient,
|
|
6604
6597
|
this.config.tonApiKey
|
|
6605
6598
|
);
|
|
@@ -6682,12 +6675,12 @@ class TonChainStrategy {
|
|
|
6682
6675
|
payload: msg.payload
|
|
6683
6676
|
})
|
|
6684
6677
|
);
|
|
6685
|
-
const
|
|
6678
|
+
const transaction2 = {
|
|
6686
6679
|
validUntil: Math.floor(Date.now() / 1e3) + TON_CONFIG.validUntil,
|
|
6687
6680
|
messages: tonMessages
|
|
6688
6681
|
};
|
|
6689
6682
|
const result = await this.config.tonConnectUI.sendTransaction(
|
|
6690
|
-
|
|
6683
|
+
transaction2
|
|
6691
6684
|
);
|
|
6692
6685
|
return {
|
|
6693
6686
|
chainKey: "ton",
|
|
@@ -6808,7 +6801,6 @@ class TronChainStrategy {
|
|
|
6808
6801
|
__publicField(this, "config");
|
|
6809
6802
|
this.config = config;
|
|
6810
6803
|
}
|
|
6811
|
-
// ========== Identity ==========
|
|
6812
6804
|
canHandle(chainKey) {
|
|
6813
6805
|
return chainKey.toLowerCase() === "tron";
|
|
6814
6806
|
}
|
|
@@ -6818,7 +6810,6 @@ class TronChainStrategy {
|
|
|
6818
6810
|
getName() {
|
|
6819
6811
|
return "TRON Chain Strategy";
|
|
6820
6812
|
}
|
|
6821
|
-
// ========== Wallet Management ==========
|
|
6822
6813
|
async connect() {
|
|
6823
6814
|
const tronWeb = this.getTronWeb();
|
|
6824
6815
|
if (!tronWeb && (typeof window === "undefined" || !window.tronLink)) {
|
|
@@ -6849,7 +6840,6 @@ class TronChainStrategy {
|
|
|
6849
6840
|
getConnectLabel(t) {
|
|
6850
6841
|
return t("wallets.connectTronWallet");
|
|
6851
6842
|
}
|
|
6852
|
-
// ========== Balance & Validation ==========
|
|
6853
6843
|
async getBalances(address, tokens) {
|
|
6854
6844
|
const tronWeb = this.getTronWeb();
|
|
6855
6845
|
if (!tronWeb) return {};
|
|
@@ -6859,7 +6849,6 @@ class TronChainStrategy {
|
|
|
6859
6849
|
if (!address) return false;
|
|
6860
6850
|
return /^T[1-9A-HJ-NP-Za-km-z]{33}$/.test(address);
|
|
6861
6851
|
}
|
|
6862
|
-
// ========== Gas Estimation ==========
|
|
6863
6852
|
async estimateGasRequirement(params) {
|
|
6864
6853
|
const {
|
|
6865
6854
|
selectedToken,
|
|
@@ -7506,7 +7495,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7506
7495
|
require$$0.useEffect(() => {
|
|
7507
7496
|
setTronConnected(!!tronConnected);
|
|
7508
7497
|
}, [tronConnected, setTronConnected]);
|
|
7509
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BridgeI18nProvider, { defaultLanguage: props.defaultLanguage, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7510
7499
|
ChainStrategyProvider,
|
|
7511
7500
|
{
|
|
7512
7501
|
evmWallet: {
|
|
@@ -7531,7 +7520,7 @@ const EvaaBridgeWithProviders = (props) => {
|
|
|
7531
7520
|
tonApiKey: props.tonApiKey,
|
|
7532
7521
|
children: /* @__PURE__ */ jsxRuntime.jsx(EvaaBridgeContent, { ...props })
|
|
7533
7522
|
}
|
|
7534
|
-
);
|
|
7523
|
+
) });
|
|
7535
7524
|
};
|
|
7536
7525
|
const EvaaBridgeContent = ({
|
|
7537
7526
|
className,
|
|
@@ -7539,10 +7528,9 @@ const EvaaBridgeContent = ({
|
|
|
7539
7528
|
onAmountChange,
|
|
7540
7529
|
onChainChange
|
|
7541
7530
|
} = {}) => {
|
|
7542
|
-
const { t } =
|
|
7531
|
+
const { t } = useBridgeTranslation();
|
|
7543
7532
|
useTokensRequest();
|
|
7544
7533
|
useChainsRequest();
|
|
7545
|
-
const [sendToAnother, setSendToAnother] = require$$0.useState(false);
|
|
7546
7534
|
const swap = useSwapModel();
|
|
7547
7535
|
const { fromChain, toChain } = swap;
|
|
7548
7536
|
const { selectedAssetSymbol, assetMatrix } = useTokensStore();
|
|
@@ -7670,13 +7658,7 @@ const EvaaBridgeContent = ({
|
|
|
7670
7658
|
onSelect: handleToChainChange
|
|
7671
7659
|
}
|
|
7672
7660
|
),
|
|
7673
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7674
|
-
ToggleRow,
|
|
7675
|
-
{
|
|
7676
|
-
enabled: sendToAnother,
|
|
7677
|
-
onToggle: () => setSendToAnother((v) => !v)
|
|
7678
|
-
}
|
|
7679
|
-
),
|
|
7661
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnotherAddress, {}),
|
|
7680
7662
|
/* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {})
|
|
7681
7663
|
] }),
|
|
7682
7664
|
/* @__PURE__ */ jsxRuntime.jsx(card.CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(Details, {}) })
|
|
@@ -7751,7 +7733,6 @@ exports.addrForApi = addrForApi;
|
|
|
7751
7733
|
exports.buildAssetMatrix = buildAssetMatrix;
|
|
7752
7734
|
exports.calculateMinReceived = calculateMinReceived;
|
|
7753
7735
|
exports.computeFeesUsdFromArray = computeFeesUsdFromArray;
|
|
7754
|
-
exports.dollarsFromNativeFees = dollarsFromNativeFees;
|
|
7755
7736
|
exports.findNativeMeta = findNativeMeta;
|
|
7756
7737
|
exports.formatBalance = formatBalance;
|
|
7757
7738
|
exports.formatHash = formatHash;
|
|
@@ -7770,10 +7751,7 @@ exports.getQuotesByPriority = getQuotesByPriority;
|
|
|
7770
7751
|
exports.getTokens = getTokens;
|
|
7771
7752
|
exports.getTonBalances = getTonBalances;
|
|
7772
7753
|
exports.getTronBalances = getTronBalances;
|
|
7773
|
-
exports.isAddressValidForChain = isAddressValidForChain;
|
|
7774
|
-
exports.isEvmAddress = isEvmAddress;
|
|
7775
7754
|
exports.isNativeAddrEqual = isNativeAddrEqual;
|
|
7776
|
-
exports.isTronAddress = isTronAddress;
|
|
7777
7755
|
exports.isZeroAddr = isZeroAddr;
|
|
7778
7756
|
exports.listAssetsForSelect = listAssetsForSelect;
|
|
7779
7757
|
exports.lookupTokenMeta = lookupTokenMeta;
|