@rash2x/bridge-widget 0.1.3 → 0.1.5

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.
@@ -44,10 +44,11 @@ const reactWindow = require("react-window");
44
44
  const SwitchPrimitive = require("@radix-ui/react-switch");
45
45
  const lucideReact = require("lucide-react");
46
46
  const AccordionPrimitive = require("@radix-ui/react-accordion");
47
- const connectkit = require("connectkit");
48
47
  const i18next = require("i18next");
49
48
  const sonner = require("sonner");
50
49
  const ethers = require("ethers");
50
+ const viem = require("viem");
51
+ const ton = require("@ton/ton");
51
52
  const tronwalletAdapters = require("@tronweb3/tronwallet-adapters");
52
53
  function _interopNamespaceDefault(e) {
53
54
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -551,7 +552,7 @@ function cn(...inputs) {
551
552
  return tailwindMerge.twMerge(clsx.clsx(inputs));
552
553
  }
553
554
  const buttonVariants = classVarianceAuthority.cva(
554
- "inline-flex items-center rounded-full justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
555
+ "inline-flex items-center rounded-full text-lg justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
555
556
  {
556
557
  variants: {
557
558
  variant: {
@@ -824,19 +825,6 @@ const Tip = (props) => {
824
825
  /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: text }) })
825
826
  ] });
826
827
  };
827
- function toLD(human, decimals) {
828
- const [i = "0", f = ""] = human.replace(",", ".").split(".");
829
- const frac = (f + "0".repeat(decimals)).slice(0, decimals);
830
- return BigInt(i + frac).toString();
831
- }
832
- function fromLD(ld, decimals) {
833
- const bi = BigInt(ld || "0");
834
- if (decimals === 0) return Number(bi);
835
- const base = BigInt(10) ** BigInt(decimals);
836
- const int = bi / base;
837
- const frac = Number(bi % base) / Number(base);
838
- return Number(int) + frac;
839
- }
840
828
  async function getChains() {
841
829
  const res = await fetch("https://stargate.finance/api/v1/chains", {
842
830
  credentials: "same-origin"
@@ -884,49 +872,16 @@ async function getDestTokens(srcChainKey, srcTokenAddr) {
884
872
  });
885
873
  return unique;
886
874
  }
887
- const isTonFriendly = (a) => !!a && /^[A-Za-z0-9_-]{48,}$/.test(a);
888
- function normalizeTickerSymbol(s) {
875
+ function normalizeTickerSymbol$1(s) {
889
876
  return s.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
890
877
  }
891
- async function getSwapBalances(accountFriendly) {
892
- if (!isTonFriendly(accountFriendly)) throw new Error("Invalid TON address");
893
- const accRes = await fetch(
894
- `https://tonapi.io/v2/accounts/${accountFriendly}`
895
- );
896
- if (!accRes.ok) throw new Error(`TON account fetch failed: ${accRes.status}`);
897
- const acc = await accRes.json();
898
- const ton = fromLD(String(acc?.balance ?? "0"), 9);
899
- const result = {
900
- TON: { balance: ton, address: "ton-native" }
901
- };
902
- const jetsRes = await fetch(
903
- `https://tonapi.io/v2/accounts/${accountFriendly}/jettons?limit=200`
904
- );
905
- if (!jetsRes.ok) return result;
906
- const jets = await jetsRes.json();
907
- const items = jets?.balances ?? jets?.jettons ?? jets?.items ?? [];
908
- for (const it of items) {
909
- const rawSym = (it?.jetton?.symbol ?? it?.symbol ?? "").toString();
910
- if (!rawSym) continue;
911
- const symUpper = rawSym.toUpperCase();
912
- const symNorm = normalizeTickerSymbol(symUpper);
913
- const master = (it?.jetton?.address ?? it?.address ?? "").toString();
914
- const decimals = Number(it?.jetton?.decimals ?? it?.decimals ?? 9) || 9;
915
- const raw = (it?.balance ?? "0").toString();
916
- const human = fromLD(raw, decimals);
917
- const entry = { balance: human, address: master };
918
- result[symUpper] = entry;
919
- if (symNorm !== symUpper) result[symNorm] = entry;
920
- }
921
- return result;
922
- }
923
878
  const BASE_URL$1 = "https://icons-ckg.pages.dev/stargate-light/tokens";
924
879
  const TokenSymbol = ({
925
880
  symbol,
926
881
  className = "w-4 h-4",
927
882
  alt
928
883
  }) => {
929
- const normalizedSymbol = normalizeTickerSymbol(symbol).toLowerCase();
884
+ const normalizedSymbol = normalizeTickerSymbol$1(symbol).toLowerCase();
930
885
  const src = `${BASE_URL$1}/${normalizedSymbol}.svg`;
931
886
  return /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: alt ?? symbol, className });
932
887
  };
@@ -1340,6 +1295,19 @@ function useChainStrategies() {
1340
1295
  }
1341
1296
  return context;
1342
1297
  }
1298
+ function toLD(human, decimals) {
1299
+ const [i = "0", f = ""] = human.replace(",", ".").split(".");
1300
+ const frac = (f + "0".repeat(decimals)).slice(0, decimals);
1301
+ return BigInt(i + frac).toString();
1302
+ }
1303
+ function fromLD(ld, decimals) {
1304
+ const bi = BigInt(ld || "0");
1305
+ if (decimals === 0) return Number(bi);
1306
+ const base = BigInt(10) ** BigInt(decimals);
1307
+ const int = bi / base;
1308
+ const frac = Number(bi % base) / Number(base);
1309
+ return Number(int) + frac;
1310
+ }
1343
1311
  function resolveTokenOnChainFromMatrix$2(assetMatrix, assetSymbol, chainKey) {
1344
1312
  if (!assetMatrix || !assetSymbol || !chainKey) return void 0;
1345
1313
  const byChain = assetMatrix[assetSymbol.toUpperCase()];
@@ -1521,18 +1489,19 @@ function useBalances(chainKey, address) {
1521
1489
  const data = query.data;
1522
1490
  if (data) {
1523
1491
  for (const [sum, v] of Object.entries(data)) {
1524
- map.set(normalizeTickerSymbol(sum), Number(v.balance ?? 0));
1492
+ map.set(normalizeTickerSymbol$1(sum), Number(v.balance ?? 0));
1525
1493
  }
1526
1494
  }
1527
1495
  return map;
1528
1496
  }, [query.data]);
1529
1497
  const getBalance = require$$0.useCallback(
1530
- (symbol) => balanceBySymbol.get(normalizeTickerSymbol(symbol)) ?? 0,
1498
+ (symbol) => balanceBySymbol.get(normalizeTickerSymbol$1(symbol)) ?? 0,
1531
1499
  [balanceBySymbol]
1532
1500
  );
1533
1501
  const isLoading = query.isLoading || query.isFetching;
1502
+ const balances = require$$0.useMemo(() => query.data || {}, [query.data]);
1534
1503
  return {
1535
- balances: query.data || {},
1504
+ balances,
1536
1505
  getBalance,
1537
1506
  isLoading,
1538
1507
  query
@@ -1986,17 +1955,17 @@ const RefreshButton = () => {
1986
1955
  return /* @__PURE__ */ jsxRuntime.jsx(
1987
1956
  Button,
1988
1957
  {
1989
- className: `cursor-pointer py-1.5 h-8.5 hover:scale-110 shadow-none px-8.5 hover:bg-secondary bg-secondary !rounded-40 ${spinning ? "opacity-70" : ""}`,
1990
1958
  onClick: handleRefresh,
1991
1959
  disabled: spinning,
1960
+ variant: "secondary",
1961
+ size: "sm",
1992
1962
  children: /* @__PURE__ */ jsxRuntime.jsx(
1993
1963
  ReloadIcon,
1994
1964
  {
1995
1965
  style: {
1996
1966
  transform: `rotate(${turns * 180}deg)`,
1997
1967
  transition: "transform 300ms linear"
1998
- },
1999
- className: "size-4 text-foreground m-1 will-change-transform"
1968
+ }
2000
1969
  }
2001
1970
  )
2002
1971
  }
@@ -2004,7 +1973,6 @@ const RefreshButton = () => {
2004
1973
  };
2005
1974
  const SelectTokenButton = ({
2006
1975
  onClick,
2007
- className,
2008
1976
  token
2009
1977
  }) => {
2010
1978
  const { t } = reactI18next.useTranslation();
@@ -2015,7 +1983,8 @@ const SelectTokenButton = ({
2015
1983
  Button,
2016
1984
  {
2017
1985
  onClick,
2018
- className: `cursor-pointer hover:scale-[1.1] p-1.5 h-8.5 pr-3 !pl-1.5 bg-secondary hover:bg-secondary shadow-none rounded-full flex items-center justify-between gap-3 w-fit shrink-0 ${className ?? ""}`,
1986
+ size: "sm",
1987
+ variant: "secondary",
2019
1988
  type: "button",
2020
1989
  "aria-label": label,
2021
1990
  children: [
@@ -2035,6 +2004,75 @@ const SelectTokenButton = ({
2035
2004
  }
2036
2005
  );
2037
2006
  };
2007
+ function Card({ className, ...props }) {
2008
+ return /* @__PURE__ */ jsxRuntime.jsx(
2009
+ "div",
2010
+ {
2011
+ "data-slot": "card",
2012
+ className: cn(
2013
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
2014
+ className
2015
+ ),
2016
+ ...props
2017
+ }
2018
+ );
2019
+ }
2020
+ function CardHeader({ className, ...props }) {
2021
+ return /* @__PURE__ */ jsxRuntime.jsx(
2022
+ "div",
2023
+ {
2024
+ "data-slot": "card-header",
2025
+ className: cn(
2026
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
2027
+ className
2028
+ ),
2029
+ ...props
2030
+ }
2031
+ );
2032
+ }
2033
+ function CardTitle({ className, ...props }) {
2034
+ return /* @__PURE__ */ jsxRuntime.jsx(
2035
+ "div",
2036
+ {
2037
+ "data-slot": "card-title",
2038
+ className: cn("leading-none font-semibold", className),
2039
+ ...props
2040
+ }
2041
+ );
2042
+ }
2043
+ function CardAction({ className, ...props }) {
2044
+ return /* @__PURE__ */ jsxRuntime.jsx(
2045
+ "div",
2046
+ {
2047
+ "data-slot": "card-action",
2048
+ className: cn(
2049
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
2050
+ className
2051
+ ),
2052
+ ...props
2053
+ }
2054
+ );
2055
+ }
2056
+ function CardContent({ className, ...props }) {
2057
+ return /* @__PURE__ */ jsxRuntime.jsx(
2058
+ "div",
2059
+ {
2060
+ "data-slot": "card-content",
2061
+ className: cn("px-6", className),
2062
+ ...props
2063
+ }
2064
+ );
2065
+ }
2066
+ function CardFooter({ className, ...props }) {
2067
+ return /* @__PURE__ */ jsxRuntime.jsx(
2068
+ "div",
2069
+ {
2070
+ "data-slot": "card-footer",
2071
+ className: cn("flex items-center px-6 [.border-t]:pt-6", className),
2072
+ ...props
2073
+ }
2074
+ );
2075
+ }
2038
2076
  const FormHeaderComponent = ({ modalContainer }) => {
2039
2077
  const { t } = reactI18next.useTranslation();
2040
2078
  const { isOpen, onClose, onOpen } = useModal();
@@ -2051,29 +2089,14 @@ const FormHeaderComponent = ({ modalContainer }) => {
2051
2089
  const sum = selectedAssetSymbol.toUpperCase();
2052
2090
  return assets.find((a) => a.symbol.toUpperCase() === sum) ?? assets[0];
2053
2091
  }, [assets, selectedAssetSymbol]);
2054
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2055
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2056
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
2057
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t("bridge.selectToken") }),
2058
- /* @__PURE__ */ jsxRuntime.jsx(SelectTokenButton, { token: current, onClick: onOpen })
2059
- ] }),
2060
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
2061
- /* @__PURE__ */ jsxRuntime.jsx(RefreshButton, {}),
2062
- /* @__PURE__ */ jsxRuntime.jsx(
2063
- Button,
2064
- {
2065
- className: "cursor-pointer py-1.5 h-8.5 hover:scale-110 shadow-none px-8.5 hover:bg-secondary bg-secondary !rounded-40",
2066
- onClick: onOpenSettings,
2067
- children: /* @__PURE__ */ jsxRuntime.jsx(
2068
- BoltIcon,
2069
- {
2070
- className: "size-4 text-foreground m-1",
2071
- stroke: "currentColor"
2072
- }
2073
- )
2074
- }
2075
- )
2076
- ] })
2092
+ return /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "gap-y-0", children: [
2093
+ /* @__PURE__ */ jsxRuntime.jsxs(CardTitle, { className: "flex items-center gap-2.5", children: [
2094
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-normal leading-3.5 text-muted-foreground", children: t("bridge.selectToken") }),
2095
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTokenButton, { token: current, onClick: onOpen })
2096
+ ] }),
2097
+ /* @__PURE__ */ jsxRuntime.jsxs(CardAction, { className: "flex items-center gap-2.5", children: [
2098
+ /* @__PURE__ */ jsxRuntime.jsx(RefreshButton, {}),
2099
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onOpenSettings, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsx(BoltIcon, { stroke: "currentColor" }) })
2077
2100
  ] }),
2078
2101
  /* @__PURE__ */ jsxRuntime.jsx(
2079
2102
  TokenSelectModal,
@@ -3763,7 +3786,9 @@ function useBridgeTransaction() {
3763
3786
  function useGasEstimate(amountNum) {
3764
3787
  const { fromChain } = useChainsStore();
3765
3788
  const { selectedAssetSymbol, tokens } = useTokensStore();
3766
- const { getSourceGasReserveHuman } = useSettingsStore();
3789
+ const getSourceGasReserveHuman = useSettingsStore(
3790
+ (state) => state.getSourceGasReserveHuman
3791
+ );
3767
3792
  const { srcAddress } = useAddresses();
3768
3793
  const { balances, isLoading: balancesLoading } = useBalances(
3769
3794
  fromChain?.chainKey,
@@ -3771,59 +3796,44 @@ function useGasEstimate(amountNum) {
3771
3796
  );
3772
3797
  const { chainRegistry } = useChainStrategies();
3773
3798
  const balancesKnown = !balancesLoading;
3774
- const [gasRequirement, setGasRequirement] = require$$0.useState(
3775
- null
3776
- );
3777
- require$$0.useEffect(() => {
3778
- let cancelled = false;
3779
- async function estimateGas() {
3780
- if (!fromChain) {
3781
- setGasRequirement(null);
3782
- return;
3783
- }
3784
- const strategy = chainRegistry.getStrategy(fromChain.chainKey);
3785
- if (!strategy) {
3786
- setGasRequirement(null);
3787
- return;
3788
- }
3789
- try {
3790
- const selectedToken = tokens?.find(
3791
- (t) => t.symbol.toUpperCase() === selectedAssetSymbol?.toUpperCase()
3792
- ) || null;
3793
- const nativeTokenSymbol = fromChain.nativeCurrency?.symbol ?? "";
3794
- const nativeDecimals = fromChain.nativeCurrency?.decimals || 18;
3795
- const reserveFallback = getSourceGasReserveHuman(fromChain.chainKey);
3796
- const result = await strategy.estimateGasRequirement({
3797
- selectedToken,
3798
- nativeTokenSymbol,
3799
- amount: amountNum,
3800
- balances,
3801
- nativeDecimals,
3802
- reserveFallback
3803
- });
3804
- if (!cancelled) {
3805
- setGasRequirement(result);
3806
- }
3807
- } catch (error) {
3808
- console.error("Error estimating gas:", error);
3809
- if (!cancelled) {
3810
- setGasRequirement(null);
3811
- }
3812
- }
3813
- }
3814
- estimateGas();
3815
- return () => {
3816
- cancelled = true;
3817
- };
3818
- }, [
3819
- fromChain,
3820
- selectedAssetSymbol,
3821
- tokens,
3822
- amountNum,
3823
- balances,
3824
- chainRegistry,
3825
- getSourceGasReserveHuman
3826
- ]);
3799
+ const strategy = require$$0.useMemo(() => {
3800
+ if (!fromChain) return null;
3801
+ return chainRegistry.getStrategy(fromChain.chainKey);
3802
+ }, [fromChain, chainRegistry]);
3803
+ const { data: gasRequirement } = reactQuery.useQuery({
3804
+ queryKey: [
3805
+ "gas-estimate",
3806
+ fromChain?.chainKey,
3807
+ selectedAssetSymbol,
3808
+ amountNum,
3809
+ balances
3810
+ ],
3811
+ queryFn: async () => {
3812
+ if (!fromChain || !strategy) {
3813
+ return null;
3814
+ }
3815
+ const selectedToken = tokens?.find(
3816
+ (t) => t.symbol.toUpperCase() === selectedAssetSymbol?.toUpperCase()
3817
+ ) || null;
3818
+ const nativeTokenSymbol = fromChain.nativeCurrency?.symbol ?? "";
3819
+ const nativeDecimals = fromChain.nativeCurrency?.decimals || 18;
3820
+ const reserveFallback = getSourceGasReserveHuman(fromChain.chainKey);
3821
+ const result = await strategy.estimateGasRequirement({
3822
+ selectedToken,
3823
+ nativeTokenSymbol,
3824
+ amount: amountNum,
3825
+ balances,
3826
+ nativeDecimals,
3827
+ reserveFallback
3828
+ });
3829
+ return result;
3830
+ },
3831
+ enabled: !!fromChain && !!strategy,
3832
+ staleTime: 3e4,
3833
+ gcTime: 5 * 6e4,
3834
+ refetchOnWindowFocus: false,
3835
+ retry: 1
3836
+ });
3827
3837
  return {
3828
3838
  nativeSym: gasRequirement?.nativeSym || "",
3829
3839
  nativeBalance: gasRequirement?.nativeBalance || 0,
@@ -3972,7 +3982,7 @@ function useSilentValidations(amountString) {
3972
3982
  ]);
3973
3983
  return validationResult;
3974
3984
  }
3975
- function useTransferAction() {
3985
+ const SubmitButton = () => {
3976
3986
  const { t } = reactI18next.useTranslation();
3977
3987
  const { chainRegistry } = useChainStrategies();
3978
3988
  const { srcAddress, dstAddress } = useAddresses();
@@ -4048,7 +4058,7 @@ function useTransferAction() {
4048
4058
  maximumAmountFormatted,
4049
4059
  chainRegistry
4050
4060
  ]);
4051
- const onClick = async () => {
4061
+ const handleClick = async () => {
4052
4062
  if (isBusy) return;
4053
4063
  if (missingSrc && srcChainKey) {
4054
4064
  onOpen("src");
@@ -4068,24 +4078,7 @@ function useTransferAction() {
4068
4078
  }
4069
4079
  };
4070
4080
  const disabled = isBusy || amountNum <= 0 || status === "loading" || isBalanceLoading || hasInsufficientBalance || hasAmountTooLarge || !gas.hasEnoughGas || noRoute || !isValidForTransfer;
4071
- return {
4072
- // состояния
4073
- isBusy,
4074
- canTransfer,
4075
- missingSrc,
4076
- missingDst,
4077
- hasEnoughGas: gas.hasEnoughGas,
4078
- noRoute,
4079
- // представление
4080
- label,
4081
- disabled,
4082
- // действие
4083
- onClick
4084
- };
4085
- }
4086
- const SubmitButton = () => {
4087
- const { label, disabled, onClick } = useTransferAction();
4088
- return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick, disabled, size: "lg", children: label });
4081
+ return /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: handleClick, disabled, className: "w-full", children: label });
4089
4082
  };
4090
4083
  function short(addr) {
4091
4084
  return addr.slice(0, 4) + "…" + addr.slice(-4);
@@ -4095,6 +4088,7 @@ const WalletSelectModal = ({
4095
4088
  }) => {
4096
4089
  const { t } = reactI18next.useTranslation();
4097
4090
  const { isOpen, onClose } = useWalletSelectModal();
4091
+ const { connect, connectors, isPending } = wagmi.useConnect();
4098
4092
  const { chainRegistry } = useChainStrategies();
4099
4093
  const tonWallet = chainRegistry.getStrategyByType("ton");
4100
4094
  const metaMaskWallet = chainRegistry.getStrategyByType("evm");
@@ -4127,7 +4121,13 @@ const WalletSelectModal = ({
4127
4121
  onDisconnect: () => tronWallet.disconnect()
4128
4122
  });
4129
4123
  }
4130
- const isWalletConnected = (walletId) => connectedWallets.some((w) => w.id === walletId);
4124
+ const isWalletConnected = (walletId) => {
4125
+ const isEvmConnector = connectors.some((c) => c.id === walletId);
4126
+ if (isEvmConnector && metaMaskWallet?.isConnected()) {
4127
+ return true;
4128
+ }
4129
+ return connectedWallets.some((w) => w.id === walletId);
4130
+ };
4131
4131
  const tonWallets = [
4132
4132
  {
4133
4133
  id: "ton",
@@ -4136,14 +4136,15 @@ const WalletSelectModal = ({
4136
4136
  enabled: true
4137
4137
  }
4138
4138
  ];
4139
- const evmWallets = [
4140
- {
4141
- id: "metamask",
4142
- name: t("wallets.metaMask"),
4143
- icon: MetaMaskIcon,
4144
- enabled: true
4145
- }
4146
- ];
4139
+ const evmWallets = connectors.filter(
4140
+ (connector) => connector.id === "walletConnect" || connector.id === "metaMaskSDK"
4141
+ ).map((connector) => ({
4142
+ id: connector.id,
4143
+ name: connector.name,
4144
+ icon: MetaMaskIcon,
4145
+ // You can add a WalletConnect icon here
4146
+ enabled: true
4147
+ }));
4147
4148
  const tronWallets = [
4148
4149
  {
4149
4150
  id: "tronlink",
@@ -4173,9 +4174,6 @@ const WalletSelectModal = ({
4173
4174
  case "ton":
4174
4175
  await tonWallet?.connect();
4175
4176
  break;
4176
- case "metamask":
4177
- await metaMaskWallet?.connect();
4178
- break;
4179
4177
  case "tronlink":
4180
4178
  await tronWallet?.connect();
4181
4179
  break;
@@ -4200,56 +4198,47 @@ const WalletSelectModal = ({
4200
4198
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: t("wallets.connected") }),
4201
4199
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: connectedWallets.map((wallet) => {
4202
4200
  const IconComponent = wallet.icon;
4203
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsxs(
4204
- Button,
4205
- {
4206
- 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]",
4207
- children: [
4208
- /* @__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: [
4209
- /* @__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" }) }),
4210
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
4211
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: short(wallet.address) }),
4212
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: wallet.name })
4213
- ] })
4214
- ] }) }),
4215
- /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: () => {
4201
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsxs(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: [
4202
+ /* @__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: [
4203
+ /* @__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" }) }),
4204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
4205
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: short(wallet.address) }),
4206
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs leading-3 font-semibold text-muted-foreground", children: wallet.name })
4207
+ ] })
4208
+ ] }) }),
4209
+ /* @__PURE__ */ jsxRuntime.jsx(
4210
+ "div",
4211
+ {
4212
+ onClick: () => {
4216
4213
  wallet.onDisconnect();
4217
4214
  onClose();
4218
- }, className: "text-sm font-medium text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(ExitIcon, { className: "text-[#808080] size-6" }) })
4219
- ]
4220
- }
4221
- ) }, wallet.id);
4215
+ },
4216
+ className: "text-sm font-medium text-muted-foreground",
4217
+ children: /* @__PURE__ */ jsxRuntime.jsx(ExitIcon, { className: "text-[#808080] size-6" })
4218
+ }
4219
+ )
4220
+ ] }) }, wallet.id);
4222
4221
  }) })
4223
4222
  ] }),
4224
4223
  categories.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4225
4224
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-2 leading-4 text-base font-semibold text-muted-foreground uppercase", children: category.title }),
4226
4225
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: category.wallets.map((wallet) => {
4227
4226
  const IconComponent = wallet.icon;
4228
- if (wallet.id === "metamask") {
4229
- return /* @__PURE__ */ jsxRuntime.jsx("div", { id: wallet.id, children: /* @__PURE__ */ jsxRuntime.jsx(connectkit.ConnectKitButton.Custom, { children: ({ isConnecting, show }) => {
4230
- return /* @__PURE__ */ jsxRuntime.jsx(
4231
- Button,
4232
- {
4233
- type: "button",
4234
- onClick: show,
4235
- disabled: isConnecting,
4236
- 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",
4237
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
4238
- /* @__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" }) }),
4239
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start min-w-0", children: [
4240
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-extrabold text-foreground text-sm leading-4 truncate", children: wallet.name }),
4241
- 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") })
4242
- ] })
4243
- ] })
4244
- }
4245
- );
4246
- } }) }, wallet.id);
4247
- }
4227
+ const isEvmConnector = category.title === t("wallets.evmWallets");
4228
+ const connector = isEvmConnector ? connectors.find((c) => c.id === wallet.id) : null;
4248
4229
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: /* @__PURE__ */ jsxRuntime.jsx(
4249
4230
  Button,
4250
4231
  {
4251
- onClick: () => handleWalletSelect(wallet.id),
4252
- disabled: !wallet.enabled,
4232
+ type: "button",
4233
+ onClick: () => {
4234
+ if (connector) {
4235
+ connect({ connector });
4236
+ onClose();
4237
+ } else {
4238
+ handleWalletSelect(wallet.id);
4239
+ }
4240
+ },
4241
+ disabled: isEvmConnector ? isPending : !wallet.enabled,
4253
4242
  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",
4254
4243
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
4255
4244
  /* @__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" }) }),
@@ -4265,39 +4254,6 @@ const WalletSelectModal = ({
4265
4254
  ] })
4266
4255
  ] }) });
4267
4256
  };
4268
- function Card({ className, ...props }) {
4269
- return /* @__PURE__ */ jsxRuntime.jsx(
4270
- "div",
4271
- {
4272
- "data-slot": "card",
4273
- className: cn(
4274
- "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
4275
- className
4276
- ),
4277
- ...props
4278
- }
4279
- );
4280
- }
4281
- function CardContent({ className, ...props }) {
4282
- return /* @__PURE__ */ jsxRuntime.jsx(
4283
- "div",
4284
- {
4285
- "data-slot": "card-content",
4286
- className: cn("px-6", className),
4287
- ...props
4288
- }
4289
- );
4290
- }
4291
- function CardFooter({ className, ...props }) {
4292
- return /* @__PURE__ */ jsxRuntime.jsx(
4293
- "div",
4294
- {
4295
- "data-slot": "card-footer",
4296
- className: cn("flex items-center px-6 [.border-t]:pt-6", className),
4297
- ...props
4298
- }
4299
- );
4300
- }
4301
4257
  const TransactionProgressVector = (props) => {
4302
4258
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "200", height: "200", viewBox: "0 0 200 200", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
4303
4259
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6361,6 +6317,49 @@ class ChainStrategyRegistry {
6361
6317
  await strategy.disconnect();
6362
6318
  }
6363
6319
  }
6320
+ const EVM_CONFIG = {
6321
+ usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
6322
+ gasEstimates: {
6323
+ approve: 65000n,
6324
+ bridge: 300000n
6325
+ },
6326
+ gasBuffer: 1.2,
6327
+ // 20% buffer
6328
+ timeout: 3e5,
6329
+ // 5 minutes (increased for slower networks)
6330
+ requiredConfirmations: 3
6331
+ // Wait for 3 confirmations for reorg protection
6332
+ };
6333
+ const TON_CONFIG = {
6334
+ apiUrl: "https://toncenter.com/api/v2",
6335
+ timeout: 36e4,
6336
+ // 6 minutes
6337
+ validUntil: 600
6338
+ // 10 minutes
6339
+ };
6340
+ const TRON_CONFIG = {
6341
+ timeout: 12e4,
6342
+ // 2 minutes (for 19 confirmations)
6343
+ feeLimit: 1e8,
6344
+ // 100 TRX in sun
6345
+ requiredConfirmations: 19,
6346
+ // TRON standard: 19 blocks for confirmation
6347
+ pollingInterval: 3e3
6348
+ // 3 seconds between checks
6349
+ };
6350
+ let tonClientInstance = null;
6351
+ function getTonClient(customClient, apiKey) {
6352
+ if (customClient) {
6353
+ return customClient;
6354
+ }
6355
+ if (!tonClientInstance) {
6356
+ tonClientInstance = new ton.TonClient({
6357
+ endpoint: `${TON_CONFIG.apiUrl}/jsonRPC`,
6358
+ apiKey
6359
+ });
6360
+ }
6361
+ return tonClientInstance;
6362
+ }
6364
6363
  function isNativeAddress(addr) {
6365
6364
  if (!addr) return false;
6366
6365
  const a = addr.toLowerCase();
@@ -6386,44 +6385,72 @@ function formatUnitsFromBigIntStr(valueStr, decimals) {
6386
6385
  const tail = s.slice(s.length - decimals).replace(/0+$/, "");
6387
6386
  return Number(tail ? `${head}.${tail}` : head);
6388
6387
  }
6389
- async function getEvmBalances(address, tokens) {
6388
+ function isTonFriendlyAddress(address) {
6389
+ return !!address && /^[A-Za-z0-9_-]{48,}$/.test(address);
6390
+ }
6391
+ function normalizeTickerSymbol(symbol) {
6392
+ return symbol.toUpperCase().replace(/₮/g, "T").replace(/[^A-Z0-9]/g, "");
6393
+ }
6394
+ function parseTonAddress(address) {
6395
+ if (address.startsWith("0x")) {
6396
+ const hex = address.slice(2);
6397
+ return ton.Address.parseRaw(`0:${hex}`);
6398
+ }
6399
+ if (address.includes(":")) {
6400
+ return ton.Address.parseRaw(address);
6401
+ }
6402
+ return ton.Address.parse(address);
6403
+ }
6404
+ async function getEvmBalances(publicClient, address, tokens) {
6390
6405
  const balances = {};
6391
6406
  try {
6392
- if (!address || !ethers.ethers.isAddress(address)) {
6407
+ console.log("start getEvmBalances");
6408
+ console.log("publicClient:", publicClient);
6409
+ console.log("isAddress:", viem.isAddress(address));
6410
+ console.log("tokens:", tokens);
6411
+ if (!address || !viem.isAddress(address)) {
6393
6412
  console.warn(`Invalid EVM address provided: ${address}`);
6394
6413
  return balances;
6395
6414
  }
6396
- if (typeof window === "undefined" || !window.ethereum) {
6397
- throw new Error("No ethereum provider found");
6415
+ if (!publicClient) {
6416
+ throw new Error("No public client provided");
6398
6417
  }
6399
- const provider = new ethers.ethers.BrowserProvider(window.ethereum);
6400
6418
  for (const token of tokens) {
6401
6419
  try {
6402
6420
  let balance = 0;
6403
6421
  const isNative = isNativeAddress(token.address);
6404
6422
  if (isNative) {
6405
- const ethBalance = await provider.getBalance(address);
6406
- balance = parseFloat(ethers.ethers.formatUnits(ethBalance, token.decimals));
6423
+ const ethBalance = await publicClient.getBalance({
6424
+ address
6425
+ });
6426
+ balance = parseFloat(viem.formatUnits(ethBalance, token.decimals));
6407
6427
  } else {
6408
- if (!ethers.ethers.isAddress(token.address)) {
6428
+ if (!viem.isAddress(token.address)) {
6409
6429
  continue;
6410
6430
  }
6411
- const code = await provider.getCode(token.address);
6412
- if (code === "0x") {
6431
+ const bytecode = await publicClient.getBytecode({
6432
+ address: token.address
6433
+ });
6434
+ if (!bytecode || bytecode === "0x") {
6413
6435
  continue;
6414
6436
  }
6415
- const contract = new ethers.ethers.Contract(
6416
- token.address,
6417
- [
6418
- "function balanceOf(address owner) view returns (uint256)",
6419
- "function decimals() view returns (uint8)"
6420
- ],
6421
- provider
6422
- );
6423
6437
  try {
6424
- const tokenBalance = await contract.balanceOf(address);
6438
+ const tokenBalance = await publicClient.readContract({
6439
+ address: token.address,
6440
+ abi: [
6441
+ {
6442
+ name: "balanceOf",
6443
+ type: "function",
6444
+ stateMutability: "view",
6445
+ inputs: [{ name: "owner", type: "address" }],
6446
+ outputs: [{ name: "balance", type: "uint256" }]
6447
+ }
6448
+ ],
6449
+ functionName: "balanceOf",
6450
+ args: [address]
6451
+ });
6425
6452
  balance = parseFloat(
6426
- ethers.ethers.formatUnits(tokenBalance, token.decimals)
6453
+ viem.formatUnits(tokenBalance, token.decimals)
6427
6454
  );
6428
6455
  } catch {
6429
6456
  continue;
@@ -6446,6 +6473,68 @@ async function getEvmBalances(address, tokens) {
6446
6473
  }
6447
6474
  return balances;
6448
6475
  }
6476
+ async function getTonBalances(address, tokens, customTonClient, tonApiKey) {
6477
+ const balances = {};
6478
+ try {
6479
+ if (!isTonFriendlyAddress(address)) {
6480
+ console.warn(`Invalid TON address provided: ${address}`);
6481
+ return balances;
6482
+ }
6483
+ const client = getTonClient(customTonClient, tonApiKey);
6484
+ const accountAddress = ton.Address.parse(address);
6485
+ console.log(address);
6486
+ console.log(tokens);
6487
+ try {
6488
+ const balance = await client.getBalance(accountAddress);
6489
+ const tonBalance = Number(balance) / 1e9;
6490
+ console.log("tonBalance", tonBalance);
6491
+ if (tonBalance > 0) {
6492
+ balances.TON = { balance: tonBalance, address: "ton-native" };
6493
+ }
6494
+ } catch (error) {
6495
+ console.warn("Failed to get native TON balance:", error);
6496
+ }
6497
+ for (const token of tokens) {
6498
+ try {
6499
+ if (isNativeAddress(token.address) || token.symbol.toUpperCase() === "TON") {
6500
+ continue;
6501
+ }
6502
+ const jettonMasterAddress = parseTonAddress(token.address);
6503
+ const jettonWalletAddress = await client.runMethod(
6504
+ jettonMasterAddress,
6505
+ "get_wallet_address",
6506
+ [
6507
+ {
6508
+ type: "slice",
6509
+ cell: ton.beginCell().storeAddress(accountAddress).endCell()
6510
+ }
6511
+ ]
6512
+ );
6513
+ const jettonWalletAddr = jettonWalletAddress.stack.readAddress();
6514
+ const jettonData = await client.runMethod(
6515
+ jettonWalletAddr,
6516
+ "get_wallet_data"
6517
+ );
6518
+ const jettonBalance = jettonData.stack.readBigNumber();
6519
+ const humanBalance = Number(jettonBalance) / Math.pow(10, token.decimals);
6520
+ if (humanBalance > 0) {
6521
+ const symbolUpper = token.symbol.toUpperCase();
6522
+ const symbolNorm = normalizeTickerSymbol(symbolUpper);
6523
+ const entry = { balance: humanBalance, address: token.address };
6524
+ balances[symbolUpper] = entry;
6525
+ if (symbolNorm !== symbolUpper) {
6526
+ balances[symbolNorm] = entry;
6527
+ }
6528
+ }
6529
+ } catch (error) {
6530
+ console.debug(`Failed to get balance for ${token.symbol}:`, error);
6531
+ }
6532
+ }
6533
+ } catch (error) {
6534
+ console.error("Failed to get TON balances:", error);
6535
+ }
6536
+ return balances;
6537
+ }
6449
6538
  async function getTronBalances(tronWeb, address, tokens) {
6450
6539
  const balances = {};
6451
6540
  try {
@@ -6489,30 +6578,6 @@ async function getTronBalances(tronWeb, address, tokens) {
6489
6578
  }
6490
6579
  return balances;
6491
6580
  }
6492
- const EVM_CONFIG = {
6493
- usdtAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
6494
- gasEstimates: {
6495
- approve: 65000n,
6496
- bridge: 300000n
6497
- },
6498
- gasBuffer: 1.2,
6499
- // 20% buffer
6500
- timeout: 12e4
6501
- // 2 minutes
6502
- };
6503
- const TON_CONFIG = {
6504
- apiUrl: "https://toncenter.com/api/v2",
6505
- timeout: 36e4,
6506
- // 6 minutes
6507
- validUntil: 600
6508
- // 10 minutes
6509
- };
6510
- const TRON_CONFIG = {
6511
- timeout: 6e4,
6512
- // 1 minute
6513
- feeLimit: 1e8
6514
- // 100 TRX in sun
6515
- };
6516
6581
  const ERC20_ABI = [
6517
6582
  "function approve(address spender, uint256 amount) returns (bool)",
6518
6583
  "function allowance(address owner, address spender) view returns (uint256)",
@@ -6523,12 +6588,13 @@ class EvmChainStrategy {
6523
6588
  constructor(config) {
6524
6589
  __publicField(this, "config");
6525
6590
  __publicField(this, "provider");
6591
+ __publicField(this, "publicClient");
6526
6592
  this.config = config;
6593
+ this.publicClient = config.publicClient;
6527
6594
  if (config.walletClient) {
6528
6595
  this.provider = new ethers.BrowserProvider(config.walletClient.transport);
6529
6596
  }
6530
6597
  }
6531
- // ========== Identity ==========
6532
6598
  canHandle(chainKey) {
6533
6599
  const key = chainKey.toLowerCase();
6534
6600
  return key !== "ton" && key !== "tron";
@@ -6539,7 +6605,6 @@ class EvmChainStrategy {
6539
6605
  getName() {
6540
6606
  return "EVM Chain Strategy";
6541
6607
  }
6542
- // ========== Wallet Management ==========
6543
6608
  async connect() {
6544
6609
  }
6545
6610
  async disconnect() {
@@ -6563,15 +6628,17 @@ class EvmChainStrategy {
6563
6628
  getConnectLabel(t) {
6564
6629
  return t("wallets.connectEvmWallet");
6565
6630
  }
6566
- // ========== Balance & Validation ==========
6567
6631
  async getBalances(address, tokens) {
6568
- return await getEvmBalances(address, tokens);
6632
+ if (!this.publicClient) {
6633
+ console.warn("No publicClient available for balance query");
6634
+ return {};
6635
+ }
6636
+ return await getEvmBalances(this.publicClient, address, tokens);
6569
6637
  }
6570
6638
  isAddressValid(address) {
6571
6639
  if (!address) return false;
6572
6640
  return /^0x[0-9a-fA-F]{40}$/.test(address);
6573
6641
  }
6574
- // ========== Gas Estimation ==========
6575
6642
  async estimateGasRequirement(params) {
6576
6643
  const provider = this.provider;
6577
6644
  const {
@@ -6618,7 +6685,6 @@ class EvmChainStrategy {
6618
6685
  isNativeSelected
6619
6686
  };
6620
6687
  }
6621
- // ========== Transaction Execution ==========
6622
6688
  validateSteps(steps) {
6623
6689
  if (!steps || steps.length === 0) {
6624
6690
  throw new InvalidStepsError("evm", "No transaction steps provided");
@@ -6680,17 +6746,14 @@ class EvmChainStrategy {
6680
6746
  if (!provider) {
6681
6747
  throw new ProviderNotAvailableError("evm");
6682
6748
  }
6683
- const deadline = Date.now() + EVM_CONFIG.timeout;
6684
- let receipt = null;
6685
- while (Date.now() < deadline) {
6686
- try {
6687
- receipt = await provider.getTransactionReceipt(txHash);
6688
- if (receipt) break;
6689
- } catch (e) {
6690
- console.debug("Error fetching receipt:", e);
6691
- }
6692
- await new Promise((r) => setTimeout(r, 2500));
6693
- }
6749
+ console.log(
6750
+ `Waiting for ${EVM_CONFIG.requiredConfirmations} confirmations for tx: ${txHash}`
6751
+ );
6752
+ const receipt = await provider.waitForTransaction(
6753
+ txHash,
6754
+ EVM_CONFIG.requiredConfirmations,
6755
+ EVM_CONFIG.timeout
6756
+ );
6694
6757
  if (!receipt) {
6695
6758
  const error = new TransactionTimeoutError("evm", txHash);
6696
6759
  return {
@@ -6705,11 +6768,35 @@ class EvmChainStrategy {
6705
6768
  error: error.message
6706
6769
  };
6707
6770
  }
6708
- console.log("EVM transaction confirmed on-chain");
6771
+ console.log(
6772
+ `EVM transaction confirmed in block ${receipt.blockNumber} with ${EVM_CONFIG.requiredConfirmations} confirmations`
6773
+ );
6709
6774
  return {
6710
6775
  completed: true
6711
6776
  };
6712
6777
  } catch (error) {
6778
+ if (error && typeof error === "object" && "code" in error && error.code === "TRANSACTION_REPLACED") {
6779
+ console.log(
6780
+ `Transaction was replaced: ${"reason" in error ? String(error.reason) : "unknown"}`
6781
+ );
6782
+ if ("receipt" in error && error.receipt) {
6783
+ const replacementReceipt = error.receipt;
6784
+ if (replacementReceipt.status === 1) {
6785
+ console.log(
6786
+ `Replacement transaction succeeded in block ${replacementReceipt.blockNumber}`
6787
+ );
6788
+ return {
6789
+ completed: true
6790
+ };
6791
+ } else {
6792
+ const chainError2 = new TransactionRevertedError("evm", txHash);
6793
+ return {
6794
+ completed: false,
6795
+ error: chainError2.message
6796
+ };
6797
+ }
6798
+ }
6799
+ }
6713
6800
  const chainError = toChainStrategyError(
6714
6801
  error,
6715
6802
  "evm",
@@ -6721,7 +6808,6 @@ class EvmChainStrategy {
6721
6808
  };
6722
6809
  }
6723
6810
  }
6724
- // ========== Private Helper Methods ==========
6725
6811
  async executeTransaction(step) {
6726
6812
  const provider = this.provider;
6727
6813
  const signer = await provider?.getSigner();
@@ -6824,13 +6910,52 @@ class EvmChainStrategy {
6824
6910
  return false;
6825
6911
  }
6826
6912
  }
6913
+ /**
6914
+ * Check if a block has reached finality status (optional, for critical transactions)
6915
+ * This is more stringent than confirmations and protects against long-range reorgs
6916
+ *
6917
+ * Usage: Call this method after waitForCompletion if you need additional security
6918
+ * for high-value transactions. The method checks if the block has been marked as
6919
+ * "finalized" by the Ethereum consensus layer (2/3 of validators).
6920
+ *
6921
+ * @param blockNumber - The block number to check for finality
6922
+ * @returns true if the block is finalized, false otherwise
6923
+ */
6924
+ async checkFinality(blockNumber) {
6925
+ try {
6926
+ const provider = this.provider;
6927
+ if (!provider) {
6928
+ return false;
6929
+ }
6930
+ const finalizedBlock = await provider.getBlock("finalized");
6931
+ if (!finalizedBlock) {
6932
+ console.debug(
6933
+ "Finalized block not available (pre-merge or unsupported)"
6934
+ );
6935
+ return false;
6936
+ }
6937
+ const isFinalized = blockNumber <= finalizedBlock.number;
6938
+ if (isFinalized) {
6939
+ console.log(
6940
+ `Block ${blockNumber} has reached finality (finalized block: ${finalizedBlock.number})`
6941
+ );
6942
+ } else {
6943
+ console.debug(
6944
+ `Block ${blockNumber} not yet finalized (finalized block: ${finalizedBlock.number})`
6945
+ );
6946
+ }
6947
+ return isFinalized;
6948
+ } catch (error) {
6949
+ console.debug("Error checking finality:", error);
6950
+ return false;
6951
+ }
6952
+ }
6827
6953
  }
6828
6954
  class TonChainStrategy {
6829
6955
  constructor(config) {
6830
6956
  __publicField(this, "config");
6831
6957
  this.config = config;
6832
6958
  }
6833
- // ========== Identity ==========
6834
6959
  canHandle(chainKey) {
6835
6960
  return chainKey.toLowerCase() === "ton";
6836
6961
  }
@@ -6840,7 +6965,6 @@ class TonChainStrategy {
6840
6965
  getName() {
6841
6966
  return "TON Chain Strategy";
6842
6967
  }
6843
- // ========== Wallet Management ==========
6844
6968
  async connect() {
6845
6969
  await this.config.tonConnectUI?.openModal();
6846
6970
  }
@@ -6865,17 +6989,26 @@ class TonChainStrategy {
6865
6989
  getConnectLabel(t) {
6866
6990
  return t("wallets.connectTonWallet");
6867
6991
  }
6868
- // ========== Balance & Validation ==========
6869
- async getBalances(address) {
6870
- return await getSwapBalances(address);
6992
+ async getBalances(address, tokens) {
6993
+ return await getTonBalances(
6994
+ address,
6995
+ tokens,
6996
+ this.config.tonClient,
6997
+ this.config.tonApiKey
6998
+ );
6871
6999
  }
6872
7000
  isAddressValid(address) {
6873
7001
  if (!address) return false;
6874
7002
  return true;
6875
7003
  }
6876
- // ========== Gas Estimation ==========
6877
7004
  async estimateGasRequirement(params) {
6878
- const { selectedToken, nativeTokenSymbol, amount, balances, reserveFallback } = params;
7005
+ const {
7006
+ selectedToken,
7007
+ nativeTokenSymbol,
7008
+ amount,
7009
+ balances,
7010
+ reserveFallback
7011
+ } = params;
6879
7012
  const nativeSym = nativeTokenSymbol.toUpperCase();
6880
7013
  const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
6881
7014
  const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
@@ -6897,7 +7030,6 @@ class TonChainStrategy {
6897
7030
  isNativeSelected
6898
7031
  };
6899
7032
  }
6900
- // ========== Transaction Execution ==========
6901
7033
  validateSteps(steps) {
6902
7034
  if (!steps || steps.length === 0) {
6903
7035
  throw new InvalidStepsError("ton", "No transaction steps provided");
@@ -6950,19 +7082,17 @@ class TonChainStrategy {
6950
7082
  const result = await this.config.tonConnectUI.sendTransaction(
6951
7083
  transaction
6952
7084
  );
6953
- const hash = this.getTxHash(result.boc);
6954
7085
  return {
6955
7086
  chainKey: "ton",
6956
- hash
7087
+ hash: result.boc
6957
7088
  };
6958
7089
  } catch (error) {
6959
7090
  throw toChainStrategyError(error, "ton", "transaction");
6960
7091
  }
6961
7092
  }
6962
- async waitForCompletion(txHash, context) {
7093
+ async waitForCompletion(txHash) {
6963
7094
  try {
6964
7095
  const confirmed = await this.checkTonTransaction(
6965
- context.srcAddress,
6966
7096
  txHash,
6967
7097
  TON_CONFIG.timeout
6968
7098
  );
@@ -6992,39 +7122,78 @@ class TonChainStrategy {
6992
7122
  };
6993
7123
  }
6994
7124
  }
6995
- // ========== Private Helper Methods ==========
6996
- getTxHash(boc) {
6997
- const cell = core.Cell.fromBase64(boc);
6998
- const buffer = cell.hash();
6999
- return buffer.toString("hex");
7125
+ getNormalizedExtMessageHash(message) {
7126
+ if (message.info.type !== "external-in") {
7127
+ throw new Error(`Expected external-in message, got ${message.info.type}`);
7128
+ }
7129
+ const normalizedInfo = {
7130
+ ...message.info,
7131
+ src: void 0,
7132
+ importFee: 0n
7133
+ };
7134
+ const normalizedMessage = {
7135
+ ...message,
7136
+ info: normalizedInfo,
7137
+ init: null
7138
+ };
7139
+ return core.beginCell().store(core.storeMessage(normalizedMessage, { forceRef: true })).endCell().hash();
7000
7140
  }
7001
- async checkTonTransaction(address, txHash, timeoutMs = 36e4) {
7141
+ async checkTonTransaction(bocBase64, timeoutMs = 36e4) {
7002
7142
  const deadline = Date.now() + timeoutMs;
7003
- const normalizedHash = txHash.toLowerCase();
7004
- while (Date.now() < deadline) {
7005
- try {
7006
- const response = await fetch(
7007
- `${TON_CONFIG.apiUrl}/getTransactions?address=${address}&limit=20`
7143
+ const client = getTonClient(this.config.tonClient, this.config.tonApiKey);
7144
+ try {
7145
+ const inMessage = core.loadMessage(core.Cell.fromBase64(bocBase64).beginParse());
7146
+ if (inMessage.info.type !== "external-in") {
7147
+ console.debug(
7148
+ "Expected external-in message, got:",
7149
+ inMessage.info.type
7008
7150
  );
7009
- if (!response.ok) {
7010
- console.debug("TonCenter API error:", response.status);
7011
- await new Promise((r) => setTimeout(r, 3e3));
7012
- continue;
7013
- }
7014
- const data = await response.json();
7015
- const transactions = data.result || [];
7016
- for (const tx of transactions) {
7017
- const txIdHash = tx.transaction_id?.hash;
7018
- if (txIdHash && txIdHash.toLowerCase() === normalizedHash) {
7019
- return true;
7151
+ return false;
7152
+ }
7153
+ const accountAddress = inMessage.info.dest;
7154
+ const targetMessageHash = this.getNormalizedExtMessageHash(inMessage);
7155
+ let lt = void 0;
7156
+ let hash = void 0;
7157
+ while (Date.now() < deadline) {
7158
+ try {
7159
+ const transactions = await client.getTransactions(accountAddress, {
7160
+ lt,
7161
+ hash,
7162
+ limit: 10,
7163
+ archival: true
7164
+ });
7165
+ if (transactions.length === 0) {
7166
+ await new Promise((r) => setTimeout(r, 3e3));
7167
+ lt = void 0;
7168
+ hash = void 0;
7169
+ continue;
7170
+ }
7171
+ for (const tx of transactions) {
7172
+ if (tx.inMessage?.info.type === "external-in") {
7173
+ const txInMessageHash = this.getNormalizedExtMessageHash(
7174
+ tx.inMessage
7175
+ );
7176
+ if (txInMessageHash.equals(targetMessageHash)) {
7177
+ console.debug("Transaction found by in-message hash");
7178
+ return true;
7179
+ }
7180
+ }
7020
7181
  }
7182
+ const lastTx = transactions[transactions.length - 1];
7183
+ lt = lastTx.lt.toString();
7184
+ hash = lastTx.hash().toString("base64");
7185
+ } catch (error) {
7186
+ console.debug("Error fetching transactions:", error);
7187
+ await new Promise((r) => setTimeout(r, 3e3));
7188
+ lt = void 0;
7189
+ hash = void 0;
7021
7190
  }
7022
- } catch (e) {
7023
- console.debug("TonCenter polling error:", e);
7024
7191
  }
7025
- await new Promise((r) => setTimeout(r, 3e3));
7192
+ return false;
7193
+ } catch (error) {
7194
+ console.debug("Error parsing BOC or checking transaction:", error);
7195
+ return false;
7026
7196
  }
7027
- return false;
7028
7197
  }
7029
7198
  }
7030
7199
  class TronChainStrategy {
@@ -7085,7 +7254,13 @@ class TronChainStrategy {
7085
7254
  }
7086
7255
  // ========== Gas Estimation ==========
7087
7256
  async estimateGasRequirement(params) {
7088
- const { selectedToken, nativeTokenSymbol, amount, balances, reserveFallback } = params;
7257
+ const {
7258
+ selectedToken,
7259
+ nativeTokenSymbol,
7260
+ amount,
7261
+ balances,
7262
+ reserveFallback
7263
+ } = params;
7089
7264
  const nativeSym = nativeTokenSymbol.toUpperCase();
7090
7265
  const isNativeSelected = nativeSym === (selectedToken?.symbol ?? "").toUpperCase();
7091
7266
  const nativeBalance = Number(balances[nativeSym]?.balance ?? 0);
@@ -7107,7 +7282,6 @@ class TronChainStrategy {
7107
7282
  isNativeSelected
7108
7283
  };
7109
7284
  }
7110
- // ========== Transaction Execution ==========
7111
7285
  validateSteps(steps) {
7112
7286
  console.log("validateSteps");
7113
7287
  if (!steps?.length) {
@@ -7142,7 +7316,10 @@ class TronChainStrategy {
7142
7316
  if (String(step.chainKey).toLowerCase() !== "tron") continue;
7143
7317
  const tx = step.transaction;
7144
7318
  if (!tx) {
7145
- throw new InvalidTransactionDataError("tron", "Missing transaction data");
7319
+ throw new InvalidTransactionDataError(
7320
+ "tron",
7321
+ "Missing transaction data"
7322
+ );
7146
7323
  }
7147
7324
  const hexData = typeof tx?.data === "string" ? tx.data : "";
7148
7325
  const parsed = this.parseTronStep(step, tx, hexData);
@@ -7193,13 +7370,19 @@ class TronChainStrategy {
7193
7370
  break;
7194
7371
  }
7195
7372
  default:
7196
- throw new InvalidStepsError("tron", "Unsupported TRON parsed tx kind");
7373
+ throw new InvalidStepsError(
7374
+ "tron",
7375
+ "Unsupported TRON parsed tx kind"
7376
+ );
7197
7377
  }
7198
7378
  const { txid } = await this.signAndBroadcast(tronWeb, unsigned);
7199
7379
  lastTxId = txid;
7200
7380
  }
7201
7381
  if (!lastTxId) {
7202
- throw new TransactionFailedError("tron", "No TRON transaction was executed");
7382
+ throw new TransactionFailedError(
7383
+ "tron",
7384
+ "No TRON transaction was executed"
7385
+ );
7203
7386
  }
7204
7387
  return { hash: lastTxId, chainKey: "tron" };
7205
7388
  }
@@ -7209,47 +7392,84 @@ class TronChainStrategy {
7209
7392
  if (!tronWeb) {
7210
7393
  throw new ProviderNotAvailableError("tron");
7211
7394
  }
7395
+ console.log(
7396
+ `Waiting for ${TRON_CONFIG.requiredConfirmations} confirmations for TRON tx: ${txHash}`
7397
+ );
7212
7398
  const deadline = Date.now() + TRON_CONFIG.timeout;
7213
- while (Date.now() < deadline) {
7399
+ let txBlockNumber = null;
7400
+ while (Date.now() < deadline && !txBlockNumber) {
7214
7401
  try {
7215
7402
  const info = await tronWeb.trx.getTransactionInfo(txHash);
7216
- console.log("TRON transaction info:", info);
7217
- if (info) {
7403
+ if (info && info.blockNumber) {
7218
7404
  const result = info.receipt?.result;
7219
- if (result === "SUCCESS") {
7220
- console.log("TRON transaction confirmed on-chain");
7405
+ if (result !== "SUCCESS") {
7406
+ const msg = this.hexToAscii(info.resMessage) || null;
7407
+ let reason = msg;
7408
+ const cr = info.contractResult?.[0];
7409
+ if (cr && /^0x?08c379a0/i.test(cr)) {
7410
+ try {
7411
+ const clean = cr.replace(/^0x/, "");
7412
+ const len = parseInt(clean.slice(8 + 64, 8 + 64 + 64), 16);
7413
+ const strHex = clean.slice(
7414
+ 8 + 64 + 64,
7415
+ 8 + 64 + 64 + len * 2
7416
+ );
7417
+ const str = this.hexToAscii("0x" + strHex);
7418
+ if (str) reason = str;
7419
+ } catch (e) {
7420
+ console.debug("TRON revert string decode error", e);
7421
+ }
7422
+ }
7423
+ const error2 = new TransactionRevertedError(
7424
+ "tron",
7425
+ txHash,
7426
+ reason || "Unknown error"
7427
+ );
7221
7428
  return {
7222
- completed: true
7429
+ completed: false,
7430
+ error: error2.message
7223
7431
  };
7224
7432
  }
7225
- const msg = this.hexToAscii(info.resMessage) || null;
7226
- let reason = msg;
7227
- const cr = info.contractResult?.[0];
7228
- if (cr && /^0x?08c379a0/i.test(cr)) {
7229
- try {
7230
- const clean = cr.replace(/^0x/, "");
7231
- const len = parseInt(clean.slice(8 + 64, 8 + 64 + 64), 16);
7232
- const strHex = clean.slice(8 + 64 + 64, 8 + 64 + 64 + len * 2);
7233
- const str = this.hexToAscii("0x" + strHex);
7234
- if (str) reason = str;
7235
- } catch (e) {
7236
- console.debug("TRON revert string decode error", e);
7237
- }
7433
+ txBlockNumber = info.blockNumber;
7434
+ console.log(`TRON transaction found in block ${txBlockNumber}`);
7435
+ }
7436
+ } catch (e) {
7437
+ console.debug("TRON getTransactionInfo error:", e);
7438
+ }
7439
+ if (!txBlockNumber) {
7440
+ await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
7441
+ }
7442
+ }
7443
+ if (!txBlockNumber) {
7444
+ const error2 = new TransactionTimeoutError("tron", txHash);
7445
+ return {
7446
+ completed: false,
7447
+ error: error2.message
7448
+ };
7449
+ }
7450
+ let confirmations = 0;
7451
+ while (Date.now() < deadline) {
7452
+ try {
7453
+ const currentBlock = await tronWeb.trx.getCurrentBlock();
7454
+ const currentBlockNumber = currentBlock?.block_header?.raw_data?.number;
7455
+ if (currentBlockNumber) {
7456
+ confirmations = currentBlockNumber - txBlockNumber;
7457
+ if (confirmations >= TRON_CONFIG.requiredConfirmations) {
7458
+ console.log(
7459
+ `TRON transaction confirmed in block ${txBlockNumber} with ${confirmations} confirmations`
7460
+ );
7461
+ return {
7462
+ completed: true
7463
+ };
7238
7464
  }
7239
- const error2 = new TransactionRevertedError(
7240
- "tron",
7241
- txHash,
7242
- reason || "Unknown error"
7465
+ console.log(
7466
+ `TRON transaction confirmations: ${confirmations}/${TRON_CONFIG.requiredConfirmations}`
7243
7467
  );
7244
- return {
7245
- completed: false,
7246
- error: error2.message
7247
- };
7248
7468
  }
7249
7469
  } catch (e) {
7250
- console.debug("TRON getTransactionInfo error:", e);
7470
+ console.debug("TRON getCurrentBlock error:", e);
7251
7471
  }
7252
- await new Promise((r) => setTimeout(r, 3e3));
7472
+ await new Promise((r) => setTimeout(r, TRON_CONFIG.pollingInterval));
7253
7473
  }
7254
7474
  const error = new TransactionTimeoutError("tron", txHash);
7255
7475
  return {
@@ -7257,14 +7477,17 @@ class TronChainStrategy {
7257
7477
  error: error.message
7258
7478
  };
7259
7479
  } catch (error) {
7260
- const chainError = toChainStrategyError(error, "tron", "waitForCompletion");
7480
+ const chainError = toChainStrategyError(
7481
+ error,
7482
+ "tron",
7483
+ "waitForCompletion"
7484
+ );
7261
7485
  return {
7262
7486
  completed: false,
7263
7487
  error: chainError.message
7264
7488
  };
7265
7489
  }
7266
7490
  }
7267
- // ========== Private Helper Methods ==========
7268
7491
  getTronWeb() {
7269
7492
  return typeof window !== "undefined" ? window.tronWeb : void 0;
7270
7493
  }
@@ -7317,7 +7540,10 @@ class TronChainStrategy {
7317
7540
  amount: this.extractAmountFromTxData(tx.data)
7318
7541
  };
7319
7542
  }
7320
- throw new InvalidTransactionDataError("tron", "Cannot parse approve transaction");
7543
+ throw new InvalidTransactionDataError(
7544
+ "tron",
7545
+ "Cannot parse approve transaction"
7546
+ );
7321
7547
  }
7322
7548
  if (step?.type === "transfer" || step?.type === "bridge") {
7323
7549
  const s = step;
@@ -7347,7 +7573,10 @@ class TronChainStrategy {
7347
7573
  feeLimit: raw2.feeLimit
7348
7574
  };
7349
7575
  }
7350
- throw new InvalidTransactionDataError("tron", "Cannot parse transfer/bridge transaction");
7576
+ throw new InvalidTransactionDataError(
7577
+ "tron",
7578
+ "Cannot parse transfer/bridge transaction"
7579
+ );
7351
7580
  }
7352
7581
  if (tx?.to && tx?.value && !tx?.data) {
7353
7582
  const v = BigInt(tx.value.toString());
@@ -7367,19 +7596,28 @@ class TronChainStrategy {
7367
7596
  feeLimit: raw.feeLimit
7368
7597
  };
7369
7598
  }
7370
- throw new InvalidTransactionDataError("tron", `Unsupported TRON step type: ${step?.type ?? "unknown"}`);
7599
+ throw new InvalidTransactionDataError(
7600
+ "tron",
7601
+ `Unsupported TRON step type: ${step?.type ?? "unknown"}`
7602
+ );
7371
7603
  }
7372
7604
  extractSpenderFromTxData(data) {
7373
7605
  const clean = data.replace(/^0x/, "");
7374
7606
  if (clean.length < 74) {
7375
- throw new InvalidTransactionDataError("tron", "Invalid transaction data length");
7607
+ throw new InvalidTransactionDataError(
7608
+ "tron",
7609
+ "Invalid transaction data length"
7610
+ );
7376
7611
  }
7377
7612
  return "41" + clean.slice(32, 72);
7378
7613
  }
7379
7614
  extractAmountFromTxData(data) {
7380
7615
  const clean = data.replace(/^0x/, "");
7381
7616
  if (clean.length < 138) {
7382
- throw new InvalidTransactionDataError("tron", "Invalid transaction data length");
7617
+ throw new InvalidTransactionDataError(
7618
+ "tron",
7619
+ "Invalid transaction data length"
7620
+ );
7383
7621
  }
7384
7622
  const amountHex = clean.slice(72, 136);
7385
7623
  return BigInt("0x" + amountHex).toString();
@@ -7387,7 +7625,10 @@ class TronChainStrategy {
7387
7625
  extractRecipientFromTxData(data) {
7388
7626
  const clean = data.replace(/^0x/, "");
7389
7627
  if (clean.length < 74) {
7390
- throw new InvalidTransactionDataError("tron", "Invalid transaction data length");
7628
+ throw new InvalidTransactionDataError(
7629
+ "tron",
7630
+ "Invalid transaction data length"
7631
+ );
7391
7632
  }
7392
7633
  return "41" + clean.slice(32, 72);
7393
7634
  }
@@ -7462,7 +7703,6 @@ class TronChainStrategy {
7462
7703
  return null;
7463
7704
  }
7464
7705
  }
7465
- // ========== Transaction Builders ==========
7466
7706
  async buildApprove(tronWeb, p) {
7467
7707
  const res = await tronWeb.transactionBuilder.triggerSmartContract(
7468
7708
  p.token,
@@ -7475,7 +7715,10 @@ class TronChainStrategy {
7475
7715
  p.from
7476
7716
  );
7477
7717
  if (!res?.transaction) {
7478
- throw new TransactionFailedError("tron", "Failed to build approve transaction");
7718
+ throw new TransactionFailedError(
7719
+ "tron",
7720
+ "Failed to build approve transaction"
7721
+ );
7479
7722
  }
7480
7723
  return res.transaction;
7481
7724
  }
@@ -7491,7 +7734,10 @@ class TronChainStrategy {
7491
7734
  p.from
7492
7735
  );
7493
7736
  if (!res?.transaction) {
7494
- throw new TransactionFailedError("tron", "Failed to build transfer transaction");
7737
+ throw new TransactionFailedError(
7738
+ "tron",
7739
+ "Failed to build transfer transaction"
7740
+ );
7495
7741
  }
7496
7742
  return res.transaction;
7497
7743
  }
@@ -7511,12 +7757,13 @@ class TronChainStrategy {
7511
7757
  p.from
7512
7758
  );
7513
7759
  if (!res?.transaction) {
7514
- throw new TransactionFailedError("tron", "Failed to build raw call transaction");
7760
+ throw new TransactionFailedError(
7761
+ "tron",
7762
+ "Failed to build raw call transaction"
7763
+ );
7515
7764
  }
7516
7765
  return res.transaction;
7517
7766
  }
7518
- // ========== Transaction Sender ==========
7519
- /* eslint-disable @typescript-eslint/no-explicit-any */
7520
7767
  async signAndBroadcast(tronWeb, unsignedTx) {
7521
7768
  const signed = await tronWeb.trx.sign(unsignedTx);
7522
7769
  const sent = await tronWeb.trx.sendRawTransaction(signed);
@@ -7528,33 +7775,77 @@ class TronChainStrategy {
7528
7775
  }
7529
7776
  return { txid: sent.txid };
7530
7777
  }
7778
+ /**
7779
+ * Check if a transaction has been solidified (confirmed by solidityNode)
7780
+ * This is an additional check for critical transactions to ensure they are
7781
+ * truly confirmed and available through the solidityNode API.
7782
+ *
7783
+ * Usage: Call this method after waitForCompletion for high-value transactions
7784
+ * to get additional assurance that the transaction is solidified.
7785
+ *
7786
+ * @param txHash - Transaction hash to check
7787
+ * @returns true if the transaction is solidified, false otherwise
7788
+ */
7789
+ async checkSolidified(txHash) {
7790
+ try {
7791
+ const tronWeb = this.getTronWeb();
7792
+ if (!tronWeb) {
7793
+ return false;
7794
+ }
7795
+ const info = await tronWeb.trx.getTransactionInfo(txHash);
7796
+ if (!info || !info.blockNumber) {
7797
+ console.debug(
7798
+ "Transaction not yet solidified (no blockNumber in info)"
7799
+ );
7800
+ return false;
7801
+ }
7802
+ const result = info.receipt?.result;
7803
+ if (result === "SUCCESS") {
7804
+ console.log(
7805
+ `Transaction ${txHash} is solidified in block ${info.blockNumber}`
7806
+ );
7807
+ return true;
7808
+ }
7809
+ console.debug(`Transaction solidified but result is: ${result}`);
7810
+ return false;
7811
+ } catch (error) {
7812
+ console.debug("Error checking solidified status:", error);
7813
+ return false;
7814
+ }
7815
+ }
7531
7816
  }
7532
7817
  function ChainStrategyProvider({
7533
7818
  children,
7534
7819
  evmWallet,
7535
7820
  tonWallet,
7536
- tronWallet
7821
+ tronWallet,
7822
+ tonClient,
7823
+ tonApiKey
7537
7824
  }) {
7538
7825
  const evmStrategy = require$$0.useMemo(
7539
7826
  () => new EvmChainStrategy({
7540
7827
  evmAddress: evmWallet.address,
7541
7828
  evmIsConnected: evmWallet.isConnected,
7542
7829
  evmDisconnect: evmWallet.disconnect,
7543
- walletClient: evmWallet.walletClient
7830
+ walletClient: evmWallet.walletClient,
7831
+ publicClient: evmWallet.publicClient
7544
7832
  }),
7545
7833
  [
7546
7834
  evmWallet.address,
7547
7835
  evmWallet.isConnected,
7548
7836
  evmWallet.disconnect,
7549
- evmWallet.walletClient
7837
+ evmWallet.walletClient,
7838
+ evmWallet.publicClient
7550
7839
  ]
7551
7840
  );
7552
7841
  const tonStrategy = require$$0.useMemo(
7553
7842
  () => new TonChainStrategy({
7554
7843
  tonConnectUI: tonWallet.tonConnectUI,
7555
- tonAddress: tonWallet.address
7844
+ tonAddress: tonWallet.address,
7845
+ tonClient,
7846
+ tonApiKey
7556
7847
  }),
7557
- [tonWallet.tonConnectUI, tonWallet.address]
7848
+ [tonWallet.tonConnectUI, tonWallet.address, tonClient, tonApiKey]
7558
7849
  );
7559
7850
  const tronStrategy = require$$0.useMemo(
7560
7851
  () => new TronChainStrategy({
@@ -7576,9 +7867,12 @@ function ChainStrategyProvider({
7576
7867
  () => new ChainStrategyRegistry([evmStrategy, tonStrategy, tronStrategy]),
7577
7868
  [evmStrategy, tonStrategy, tronStrategy]
7578
7869
  );
7579
- const value = {
7580
- chainRegistry
7581
- };
7870
+ const value = require$$0.useMemo(
7871
+ () => ({
7872
+ chainRegistry
7873
+ }),
7874
+ [chainRegistry]
7875
+ );
7582
7876
  return /* @__PURE__ */ jsxRuntime.jsx(ChainStrategyContext.Provider, { value, children });
7583
7877
  }
7584
7878
  const EvaaBridgeWithProviders = (props) => {
@@ -7587,6 +7881,7 @@ const EvaaBridgeWithProviders = (props) => {
7587
7881
  const { address: evmAddress, isConnected: evmIsConnected } = wagmi.useAccount();
7588
7882
  const { disconnect: evmDisconnect } = wagmi.useDisconnect();
7589
7883
  const { data: walletClient } = wagmi.useWalletClient();
7884
+ const publicClient = wagmi.usePublicClient();
7590
7885
  const {
7591
7886
  address: tronAddress,
7592
7887
  connected: tronConnected,
@@ -7611,7 +7906,8 @@ const EvaaBridgeWithProviders = (props) => {
7611
7906
  address: evmAddress,
7612
7907
  isConnected: evmIsConnected,
7613
7908
  disconnect: evmDisconnect,
7614
- walletClient
7909
+ walletClient,
7910
+ publicClient
7615
7911
  },
7616
7912
  tonWallet: {
7617
7913
  tonConnectUI,
@@ -7624,6 +7920,8 @@ const EvaaBridgeWithProviders = (props) => {
7624
7920
  connect: tronConnect,
7625
7921
  disconnect: tronDisconnect
7626
7922
  },
7923
+ tonClient: props.tonClient,
7924
+ tonApiKey: props.tonApiKey,
7627
7925
  children: /* @__PURE__ */ jsxRuntime.jsx(EvaaBridgeContent, { ...props })
7628
7926
  }
7629
7927
  );
@@ -7728,16 +8026,16 @@ const EvaaBridgeContent = ({
7728
8026
  }, [chains, assetMatrix, allowedFromChains]);
7729
8027
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7730
8028
  /* @__PURE__ */ jsxRuntime.jsxs(
7731
- "section",
8029
+ Card,
7732
8030
  {
7733
8031
  className: cn(
7734
- "p-5 bg-card max-w-md w-full rounded-3xl mx-auto flex flex-col gap-4 relative",
8032
+ "max-w-md w-full mx-auto flex flex-col relative",
7735
8033
  className
7736
8034
  ),
7737
8035
  ref: modalContainerRef,
7738
8036
  children: [
7739
8037
  /* @__PURE__ */ jsxRuntime.jsx(FormHeader, { modalContainer: modalContainerRef.current }),
7740
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-[1px]", children: [
8038
+ /* @__PURE__ */ jsxRuntime.jsxs(CardContent, { className: "space-y-[1px]", children: [
7741
8039
  /* @__PURE__ */ jsxRuntime.jsx(
7742
8040
  SwapSection,
7743
8041
  {
@@ -7775,10 +8073,10 @@ const EvaaBridgeContent = ({
7775
8073
  enabled: sendToAnother,
7776
8074
  onToggle: () => setSendToAnother((v) => !v)
7777
8075
  }
7778
- )
8076
+ ),
8077
+ /* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {})
7779
8078
  ] }),
7780
- /* @__PURE__ */ jsxRuntime.jsx(SubmitButton, {}),
7781
- /* @__PURE__ */ jsxRuntime.jsx(ReceiveRow, {})
8079
+ /* @__PURE__ */ jsxRuntime.jsx(CardFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(ReceiveRow, {}) })
7782
8080
  ]
7783
8081
  }
7784
8082
  ),
@@ -7866,8 +8164,8 @@ exports.getQuoteAmounts = getQuoteAmounts;
7866
8164
  exports.getQuoteDetails = getQuoteDetails;
7867
8165
  exports.getQuoteFees = getQuoteFees;
7868
8166
  exports.getQuotesByPriority = getQuotesByPriority;
7869
- exports.getSwapBalances = getSwapBalances;
7870
8167
  exports.getTokens = getTokens;
8168
+ exports.getTonBalances = getTonBalances;
7871
8169
  exports.getTronBalances = getTronBalances;
7872
8170
  exports.isAddressValidForChain = isAddressValidForChain;
7873
8171
  exports.isEvmAddress = isEvmAddress;
@@ -7876,7 +8174,7 @@ exports.isTronAddress = isTronAddress;
7876
8174
  exports.isZeroAddr = isZeroAddr;
7877
8175
  exports.listAssetsForSelect = listAssetsForSelect;
7878
8176
  exports.lookupTokenMeta = lookupTokenMeta;
7879
- exports.normalizeTickerSymbol = normalizeTickerSymbol;
8177
+ exports.normalizeTickerSymbol = normalizeTickerSymbol$1;
7880
8178
  exports.pollUntilDelivered = pollUntilDelivered;
7881
8179
  exports.resolveTokenOnChain = resolveTokenOnChain;
7882
8180
  exports.resolveTokenOnChainFromMatrix = resolveTokenOnChainFromMatrix$2;