diff --git a/.changeset/three-wombats-tease.md b/.changeset/three-wombats-tease.md
new file mode 100644
index 00000000000..bcdaf3d5005
--- /dev/null
+++ b/.changeset/three-wombats-tease.md
@@ -0,0 +1,24 @@
+---
+"thirdweb": minor
+---
+
+Add `useWalletDetailsModal` hook to open Wallet Details Modal without using `` component
+
+```tsx
+import { createThirdwebClient } from "thirdweb";
+import { useWalletDetailsModal } from "thirdweb/react";
+
+const client = createThirdwebClient({
+ clientId: "",
+});
+
+function Example() {
+ const { open } = useWalletDetailsModal();
+
+ function handleClick() {
+ open({ client, theme: "light" });
+ }
+
+ return ;
+}
+```
diff --git a/packages/thirdweb/src/exports/react.ts b/packages/thirdweb/src/exports/react.ts
index 9976fef1f1e..f988fc23bf3 100644
--- a/packages/thirdweb/src/exports/react.ts
+++ b/packages/thirdweb/src/exports/react.ts
@@ -135,3 +135,8 @@ export {
useWalletInfo,
useWalletImage,
} from "../react/web/ui/hooks/useWalletInfo.js";
+
+export {
+ useWalletDetailsModal,
+ type UseWalletDetailsModalOptions,
+} from "../react/web/ui/ConnectWallet/Details.js";
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx
index 33d577444b1..493115cb1af 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx
@@ -294,6 +294,8 @@ function ConnectButtonInner(
chains={props?.chains || []}
chain={props.chain}
switchButton={props.switchButton}
+ client={props.client}
+ connectLocale={locale}
/>
);
}
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButtonProps.ts b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButtonProps.ts
index c8efc774b8f..a1d687759c9 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButtonProps.ts
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButtonProps.ts
@@ -132,20 +132,6 @@ export type ConnectButton_detailsModalOptions = {
*/
networkSelector?: NetworkSelectorProps;
- /**
- * Hide the "Switch to Personal wallet" option in the Connect Wallet details modal which is shown when wallet is connected to either Smart Wallet or Safe.
- *
- * By default it is `false`
- * @example
- * ```tsx
- *
- * ```
- */
- hideSwitchToPersonalWallet?: boolean;
-
/**
* Hide the "Disconnect Wallet" button in the `ConnectButton` Details Modal.
*
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx
index 4ddb6bded02..885eebaf090 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx
@@ -10,9 +10,10 @@ import {
TextAlignJustifyIcon,
} from "@radix-ui/react-icons";
import { useQuery } from "@tanstack/react-query";
-import { useEffect, useState } from "react";
+import { useContext, useEffect, useState } from "react";
import { ethereum } from "../../../../chains/chain-definitions/ethereum.js";
import type { Chain } from "../../../../chains/types.js";
+import type { ThirdwebClient } from "../../../../client/client.js";
import { getContract } from "../../../../contract/contract.js";
import { resolveAvatar } from "../../../../extensions/ens/resolve-avatar.js";
import { resolveName } from "../../../../extensions/ens/resolve-name.js";
@@ -24,7 +25,6 @@ import {
useChainsQuery,
} from "../../../core/hooks/others/useChainQuery.js";
import { useWalletBalance } from "../../../core/hooks/others/useWalletBalance.js";
-import { useConnectUI } from "../../../core/hooks/others/useWalletConnectionCtx.js";
import {
useActiveAccount,
useActiveWallet,
@@ -32,6 +32,7 @@ import {
useDisconnect,
useSwitchActiveWalletChain,
} from "../../../core/hooks/wallets/wallet-hooks.js";
+import { SetRootElementContext } from "../../../core/providers/RootElementContext.js";
import { shortenString } from "../../../core/utils/addresses.js";
import { hasSmartAccount } from "../../utils/isSmartWallet.js";
import { ChainIcon } from "../components/ChainIcon.js";
@@ -45,7 +46,10 @@ import { WalletImage } from "../components/WalletImage.js";
import { Container, Line } from "../components/basic.js";
import { Button, IconButton } from "../components/buttons.js";
import { Link, Text } from "../components/text.js";
-import { useCustomTheme } from "../design-system/CustomThemeProvider.js";
+import {
+ CustomThemeProvider,
+ useCustomTheme,
+} from "../design-system/CustomThemeProvider.js";
import { fadeInAnimation } from "../design-system/animations.js";
import { StyledButton } from "../design-system/elements.js";
import {
@@ -56,12 +60,17 @@ import {
radius,
spacing,
} from "../design-system/index.js";
+import type { LocaleId } from "../types.js";
import type {
ConnectButtonProps,
ConnectButton_detailsButtonOptions,
ConnectButton_detailsModalOptions,
+ PayUIOptions,
} from "./ConnectButtonProps.js";
-import { NetworkSelectorContent } from "./NetworkSelector.js";
+import {
+ NetworkSelectorContent,
+ type NetworkSelectorProps,
+} from "./NetworkSelector.js";
import { onModalUnmount } from "./constants.js";
import type { SupportedTokens } from "./defaultTokens.js";
import { FundsIcon } from "./icons/FundsIcon.js";
@@ -69,6 +78,8 @@ import { KeyIcon } from "./icons/KeyIcon.js";
import { SmartWalletBadgeIcon } from "./icons/SmartAccountBadgeIcon.js";
import { WalletIcon } from "./icons/WalletIcon.js";
import { genericTokenIcon } from "./icons/dataUris.js";
+import { getConnectLocale } from "./locale/getConnectLocale.js";
+import type { ConnectLocale } from "./locale/types.js";
import { LazyBuyScreen } from "./screens/Buy/LazyBuyScreen.js";
import { BuyTxHistory } from "./screens/Buy/tx-history/BuyTxHistory.js";
import { PrivateKey } from "./screens/PrivateKey.js";
@@ -103,102 +114,67 @@ export const ConnectedWalletDetails: React.FC<{
chains: Chain[];
chain?: Chain;
switchButton: ConnectButtonProps["switchButton"];
+ connectLocale: ConnectLocale;
+ client: ThirdwebClient;
}> = (props) => {
- const { connectLocale: locale, client } = useConnectUI();
+ const { connectLocale: locale, client } = props;
+ const setRootEl = useContext(SetRootElementContext);
const activeWallet = useActiveWallet();
- const activeAccount = useActiveAccount();
const walletChain = useActiveWalletChain();
- const chainQuery = useChainQuery(walletChain);
- const { disconnect } = useDisconnect();
- // prefetch chains metadata with low concurrency
- useChainsQuery(props.chains, 5);
- const tokenAddress =
- walletChain && props.detailsButton?.displayBalanceToken
- ? props.detailsButton.displayBalanceToken[Number(walletChain.id)]
- : undefined;
+ useChainsQuery(props.chains, 5);
- const balanceQuery = useWalletBalance({
- chain: walletChain ? walletChain : undefined,
- tokenAddress,
- address: activeAccount?.address,
+ const { ensAvatarQuery, addressOrENS, balanceQuery } = useWalletInfo(
client,
- });
-
- const [screen, setScreen] = useState("main");
- const [isOpen, setIsOpen] = useState(false);
-
- const ensNameQuery = useQuery({
- queryKey: ["ens-name", activeAccount?.address],
- enabled: !!activeAccount?.address,
- queryFn: () =>
- resolveName({
- client,
- address: activeAccount?.address || "",
- resolverChain: ethereum,
- }),
- });
-
- const ensAvatarQuery = useQuery({
- queryKey: ["ens-avatar", ensNameQuery.data],
- enabled: !!ensNameQuery.data,
- queryFn: async () =>
- resolveAvatar({
- client,
- name: ensNameQuery.data || "",
- }),
- });
-
- // const personalAccount = (activeWallet as WalletWithPersonalAccount)
- // ?.personalAccount;
-
- // const smartWallet = activeWallet
- // ? personalAccountToSmartAccountMap.get(activeWallet.getAccount())
- // : undefined;
-
- const disableSwitchChain = !activeWallet?.switchChain;
-
- // const isActuallyMetaMask =
- // activeWallet && activeWallet instanceof MetaMaskWallet;
-
- const shortAddress = activeAccount?.address
- ? shortenString(activeAccount.address, false)
- : "";
-
- const addressOrENS = ensNameQuery.data || shortAddress;
+ props.detailsButton?.displayBalanceToken,
+ );
- useEffect(() => {
- if (!isOpen) {
- onModalUnmount(() => {
- setScreen("main");
- });
- }
- }, [isOpen]);
+ function closeModal() {
+ setRootEl(null);
+ }
- // if (activeWallet && "isSmartWallet" in activeWallet) {
- // avatarOrWalletIconUrl = smartWalletMetadata.iconUrl;
- // }
+ function openModal() {
+ setRootEl(
+ ,
+ );
+ }
const isNetworkMismatch =
props.chain && walletChain && walletChain.id !== props.chain.id;
- // Note: Must wrap the `SwitchNetworkButton` in a fragment to avoid warning from radix-ui
- // Note: Must wrap the `detailsButton.render` in an container element
- const trigger = props.detailsButton?.render ? (
-
- ) : props.chain && isNetworkMismatch ? (
- <>
+ if (props.detailsButton?.render) {
+ return (
+ // biome-ignore lint/a11y/useKeyWithClickEvents: ok
+
+ );
+ }
+
+ if (props.chain && isNetworkMismatch) {
+ return (
- >
- ) : (
+ );
+ }
+
+ return (
{ensAvatarQuery.data ? (
{/* Address */}
- {/* activeWallet?.id === "local" ? (
-
- {locale.guest}
-
- ) : */}
{addressOrENS ? (
);
+};
+
+function DetailsModal(props: {
+ client: ThirdwebClient;
+ locale: ConnectLocale;
+ detailsModal?: ConnectButton_detailsModalOptions;
+ theme: "light" | "dark" | Theme;
+ supportedTokens?: SupportedTokens;
+ closeModal: () => void;
+ onDisconnect: () => void;
+ chains: Chain[];
+ displayBalanceToken?: Record;
+}) {
+ const [screen, setScreen] = useState("main");
+ const { disconnect } = useDisconnect();
+ const [isOpen, setIsOpen] = useState(true);
+
+ const { client, locale } = props;
+ const { ensAvatarQuery, addressOrENS, balanceQuery } = useWalletInfo(
+ client,
+ props.displayBalanceToken,
+ );
+
+ const activeWallet = useActiveWallet();
+ const activeAccount = useActiveAccount();
+ const walletChain = useActiveWalletChain();
+ const chainQuery = useChainQuery(walletChain);
+
+ const disableSwitchChain = !activeWallet?.switchChain;
+
+ function closeModal() {
+ setIsOpen(false);
+ onModalUnmount(() => {
+ props.closeModal();
+ });
+ }
+
+ function handleDisconnect() {
+ setIsOpen(false);
+ props.closeModal();
+ props.onDisconnect();
+ }
const networkSwitcherButton = (
-
+
{(activeWallet?.id === "embedded" || activeWallet?.id === "inApp") && (
-
+
)}
{/* Address */}
@@ -535,7 +543,10 @@ export const ConnectedWalletDetails: React.FC<{
)} */}
- setIsOpen(false)} />
+
{/* Request Testnet funds */}
{(props.detailsModal?.showTestnetFaucet ?? false) &&
@@ -577,7 +588,7 @@ export const ConnectedWalletDetails: React.FC<{
)} */}
{props.detailsModal?.footer && (
- setIsOpen(false)} />
+
)}
@@ -594,7 +605,7 @@ export const ConnectedWalletDetails: React.FC<{
onClick={() => {
if (activeWallet) {
disconnect(activeWallet);
- props.onDisconnect();
+ handleDisconnect();
}
}}
>
@@ -625,9 +636,7 @@ export const ConnectedWalletDetails: React.FC<{
isEmbed={false}
onBack={() => setScreen("main")}
client={client}
- onDone={() => {
- setIsOpen(false);
- }}
+ onDone={closeModal}
/>
);
}
@@ -642,9 +651,7 @@ export const ConnectedWalletDetails: React.FC<{
? [walletChain, ...props.chains]
: props.chains
}
- closeModal={() => {
- setIsOpen(false);
- }}
+ closeModal={closeModal}
networkSelector={props.detailsModal?.networkSelector}
onBack={() => {
setScreen("main");
@@ -683,6 +690,8 @@ export const ConnectedWalletDetails: React.FC<{
onBack={() => {
setScreen("main");
}}
+ client={client}
+ connectLocale={locale}
/>
);
}
@@ -695,6 +704,8 @@ export const ConnectedWalletDetails: React.FC<{
onBack={() => {
setScreen("main");
}}
+ client={client}
+ connectLocale={locale}
/>
);
}
@@ -711,19 +722,27 @@ export const ConnectedWalletDetails: React.FC<{
connectLocale={locale}
payOptions={props.detailsModal?.payOptions || {}}
theme={typeof props.theme === "string" ? props.theme : props.theme.type}
- onDone={() => {
- setIsOpen(false);
- }}
+ onDone={closeModal}
/>
);
}
return (
-
- {content}
-
+
+ {
+ if (!_open) {
+ closeModal();
+ }
+ }}
+ >
+ {content}
+
+
);
-};
+}
const WalletInfoButton = /* @__PURE__ */ StyledButton(() => {
const theme = useCustomTheme();
@@ -814,40 +833,15 @@ const StyledChevronRightIcon = /* @__PURE__ */ styled(
};
});
-// function AccountSwitcher(props: { wallet: Wallet; name: string }) {
-// const { connect } = useConnect();
-// const locale = useTWLocale().connectWallet;
-// const activeWallet = useActiveWallet();
-
-// return (
-// {
-// // remove the current active account as "connected"
-// if (activeWallet) {
-// connectionManager.removeConnectedWallet(activeWallet);
-// }
-// // set as connected and active
-// connect(props.wallet);
-// }}
-// style={{
-// fontSize: fontSize.sm,
-// }}
-// >
-//
-//
-// {locale.switchTo} {props.name}
-//
-//
-// );
-// }
-
-function ConnectedToSmartWallet() {
+function ConnectedToSmartWallet(props: {
+ client: ThirdwebClient;
+ connectLocale: ConnectLocale;
+}) {
const activeAccount = useActiveAccount();
const activeWallet = useActiveWallet();
const isSmartWallet = hasSmartAccount(activeWallet);
const chain = useActiveWalletChain();
- const { client, connectLocale: locale } = useConnectUI();
+ const { client, connectLocale: locale } = props;
const [isSmartWalletDeployed, setIsSmartWalletDeployed] = useState(false);
@@ -912,8 +906,10 @@ function ConnectedToSmartWallet() {
return null;
}
-function InAppWalletUserInfo() {
- const { client } = useConnectUI();
+function InAppWalletUserInfo(props: {
+ client: ThirdwebClient;
+}) {
+ const { client } = props;
const account = useActiveAccount();
const userInfoQuery = useQuery({
@@ -961,10 +957,11 @@ function SwitchNetworkButton(props: {
className?: string;
switchNetworkBtnTitle?: string;
targetChain: Chain;
+ connectLocale: ConnectLocale;
}) {
const switchChain = useSwitchActiveWalletChain();
const [switching, setSwitching] = useState(false);
- const locale = useConnectUI().connectLocale;
+ const locale = props.connectLocale;
const switchNetworkBtnTitle =
props.switchNetworkBtnTitle ?? locale.switchNetwork;
@@ -1003,9 +1000,10 @@ function SwitchNetworkButton(props: {
function SwitchMetamaskAccount(props: {
closeModal: () => void;
+ connectLocale: ConnectLocale;
}) {
const wallet = useActiveWallet();
- const connectLocale = useConnectUI().connectLocale;
+ const connectLocale = props.connectLocale;
if (wallet?.id !== "io.metamask") {
return null;
@@ -1033,3 +1031,265 @@ function SwitchMetamaskAccount(props: {
);
}
+
+export type UseWalletDetailsModalOptions = {
+ /**
+ * A client is the entry point to the thirdweb SDK.
+ * It is required for all other actions.
+ * You can create a client using the `createThirdwebClient` function. Refer to the [Creating a Client](https://portal.thirdweb.com/typescript/v5/client) documentation for more information.
+ *
+ * You must provide a `clientId` or `secretKey` in order to initialize a client. Pass `clientId` if you want for client-side usage and `secretKey` for server-side usage.
+ *
+ * ```tsx
+ * import { createThirdwebClient } from "thirdweb";
+ *
+ * const client = createThirdwebClient({
+ * clientId: "",
+ * })
+ * ```
+ */
+ client: ThirdwebClient;
+ /**
+ * Set the theme for the Wallet Details Modal. By default it is set to `"dark"`
+ *
+ * theme can be set to either `"dark"`, `"light"` or a custom theme object.
+ * You can also import [`lightTheme`](https://portal.thirdweb.com/references/typescript/v5/lightTheme)
+ * or [`darkTheme`](https://portal.thirdweb.com/references/typescript/v5/darkTheme)
+ * functions from `thirdweb/react` to use the default themes as base and overrides parts of it.
+ * @example
+ * ```ts
+ * import { lightTheme } from "thirdweb/react";
+ *
+ * const customTheme = lightTheme({
+ * colors: {
+ * modalBg: 'red'
+ * }
+ * })
+ *
+ * ```
+ */
+ theme?: "light" | "dark" | Theme;
+ /**
+ * Customize the tokens shown in the "Send Funds" screen in Details Modal for various networks.
+ *
+ * By default, The "Send Funds" screen shows a few popular tokens for default chains and the native token. For other chains it only shows the native token.
+ * @example
+ *
+ * supportedTokens prop allows you to customize this list as shown below which shows "Dai Stablecoin" when users wallet is connected to the "Base" mainnet.
+ *
+ * ```tsx
+ * import { ConnectButton } from 'thirdweb/react';
+ *
+ * function Example() {
+ * return (
+ *
+ * );
+ * }
+ * ```
+ */
+ supportedTokens?: SupportedTokens;
+ /**
+ * By default - ConnectButton UI uses the `en-US` locale for english language users.
+ *
+ * You can customize the language used in the ConnectButton UI by setting the `locale` prop.
+ *
+ * Refer to the [`LocaleId`](https://portal.thirdweb.com/references/typescript/v5/LocaleId) type for supported locales.
+ */
+ locale?: LocaleId;
+ /**
+ * Array of chains that your app supports. They will be displayed in the network selector in the screen.
+ *
+ * This is only relevant if your app is a multi-chain app and works across multiple blockchains.
+ * If your app only works on a single blockchain, you should only specify the `chain` prop.
+ *
+ * You can create a `Chain` object using the [`defineChain`](https://portal.thirdweb.com/references/typescript/v5/defineChain) function.
+ * At minimum, you need to pass the `id` of the blockchain to `defineChain` function to create a `Chain` object.
+ *
+ * ```tsx
+ * import { defineChain } from "thirdweb/react";
+ *
+ * const polygon = defineChain({
+ * id: 137,
+ * });
+ * ```
+ */
+ chains?: Chain[];
+ /**
+ * Show a "Request Testnet funds" link in Wallet Details Modal when user is connected to a testnet.
+ *
+ * By default it is `false`, If you want to show the "Request Testnet funds" link when user is connected to a testnet, set this prop to `true`
+ */
+ showTestnetFaucet?: boolean;
+
+ /**
+ * customize the Network selector shown in the Wallet Details Modal
+ */
+ networkSelector?: NetworkSelectorProps;
+
+ /**
+ * Hide the "Disconnect Wallet" button in the Wallet Details Modal.
+ *
+ * By default it is `false`
+ */
+ hideDisconnect?: boolean;
+
+ /**
+ * Render custom UI at the bottom of the Details Modal
+ */
+ footer?: (props: { close: () => void }) => JSX.Element;
+
+ /**
+ * Configure options for thirdweb Pay.
+ *
+ * thirdweb Pay allows users to buy tokens using crypto or fiat currency.
+ */
+ payOptions?: PayUIOptions;
+
+ /**
+ * Display the balance of a token instead of the native token in `ConnectButton` details button.
+ * @example
+ * ```tsx
+ * const displayBalanceToken = {
+ * // show USDC balance when connected to Ethereum mainnet or Polygon
+ * [ethereum.id]: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
+ * [polygon.id]: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
+ * }
+ * ```
+ */
+ displayBalanceToken?: Record;
+};
+
+/**
+ * Hook to open the Wallet Details Modal that shows various information about the connected wallet and allows users to perform various actions like sending funds, receiving funds, switching networks, Buying tokens, etc.
+ *
+ * @example
+ * ```tsx
+ * import { createThirdwebClient } from "thirdweb";
+ * import { useWalletDetailsModal } from "thirdweb/react";
+ *
+ * const client = createThirdwebClient({
+ * clientId: "",
+ * });
+ *
+ * function Example() {
+ * const { open } = useWalletDetailsModal();
+ *
+ * function handleClick() {
+ * open({ client, theme: 'light' });
+ * }
+ *
+ * return
+ * }
+ * ```
+ */
+export function useWalletDetailsModal() {
+ const account = useActiveAccount();
+ const setRootEl = useContext(SetRootElementContext);
+
+ function closeModal() {
+ setRootEl(null);
+ }
+
+ function openModal(props: UseWalletDetailsModalOptions) {
+ if (!account) {
+ throw new Error("Wallet is not connected.");
+ }
+
+ getConnectLocale(props.locale || "en_US")
+ .then((locale) => {
+ setRootEl(
+ ,
+ );
+ })
+ .catch(() => {
+ closeModal();
+ });
+ }
+
+ return {
+ open: openModal,
+ };
+}
+
+function useWalletInfo(
+ client: ThirdwebClient,
+ displayBalanceToken?: Record,
+) {
+ const walletChain = useActiveWalletChain();
+
+ const tokenAddress =
+ walletChain && displayBalanceToken
+ ? displayBalanceToken[Number(walletChain.id)]
+ : undefined;
+
+ const activeAccount = useActiveAccount();
+ const ensNameQuery = useQuery({
+ queryKey: ["ens-name", activeAccount?.address],
+ enabled: !!activeAccount?.address,
+ queryFn: () =>
+ resolveName({
+ client,
+ address: activeAccount?.address || "",
+ resolverChain: ethereum,
+ }),
+ });
+
+ const ensAvatarQuery = useQuery({
+ queryKey: ["ens-avatar", ensNameQuery.data],
+ enabled: !!ensNameQuery.data,
+ queryFn: async () =>
+ resolveAvatar({
+ client,
+ name: ensNameQuery.data || "",
+ }),
+ });
+
+ const shortAddress = activeAccount?.address
+ ? shortenString(activeAccount.address, false)
+ : "";
+
+ const balanceQuery = useWalletBalance({
+ chain: walletChain ? walletChain : undefined,
+ tokenAddress,
+ address: activeAccount?.address,
+ client,
+ });
+
+ const addressOrENS = ensNameQuery.data || shortAddress;
+
+ return {
+ ensNameQuery,
+ ensAvatarQuery,
+ addressOrENS,
+ shortAddress,
+ balanceQuery,
+ };
+}
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx
index 4ac8f03ee15..1a14962eb02 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx
@@ -1,5 +1,5 @@
+import type { ThirdwebClient } from "../../../../../client/client.js";
import type { WalletId } from "../../../../../wallets/wallet-types.js";
-import { useConnectUI } from "../../../../core/hooks/others/useWalletConnectionCtx.js";
import { useActiveAccount } from "../../../../core/hooks/wallets/wallet-hooks.js";
import { shortenString } from "../../../../core/utils/addresses.js";
import { CopyIcon } from "../../components/CopyIcon.js";
@@ -12,6 +12,7 @@ import { useCustomTheme } from "../../design-system/CustomThemeProvider.js";
import { StyledButton } from "../../design-system/elements.js";
import { iconSize, radius, spacing } from "../../design-system/index.js";
import { useClipboard } from "../../hooks/useCopyClipboard.js";
+import type { ConnectLocale } from "../locale/types.js";
/**
*
@@ -20,11 +21,13 @@ import { useClipboard } from "../../hooks/useCopyClipboard.js";
export function ReceiveFunds(props: {
walletId?: WalletId;
onBack: () => void;
+ connectLocale: ConnectLocale;
+ client: ThirdwebClient;
}) {
const account = useActiveAccount();
const address = account?.address;
const { hasCopied, onCopy } = useClipboard(address || "");
- const { connectLocale, client } = useConnectUI();
+ const { connectLocale, client } = props;
const locale = connectLocale.receiveFundsScreen;
return (
diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx
index ceac841e604..dae96c0f5f6 100644
--- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx
+++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx
@@ -3,7 +3,6 @@ import { useMemo, useState } from "react";
import type { ThirdwebClient } from "../../../../../client/client.js";
import { isAddress } from "../../../../../utils/address.js";
import { useWalletBalance } from "../../../../core/hooks/others/useWalletBalance.js";
-import { useConnectUI } from "../../../../core/hooks/others/useWalletConnectionCtx.js";
import {
useActiveAccount,
useActiveWalletChain,
@@ -20,6 +19,7 @@ import { StyledDiv } from "../../design-system/elements.js";
import { fontSize, iconSize, spacing } from "../../design-system/index.js";
import { useSendToken } from "../../hooks/useSendToken.js";
import { type SupportedTokens, defaultTokens } from "../defaultTokens.js";
+import type { ConnectLocale } from "../locale/types.js";
import { TokenSelector } from "./TokenSelector.js";
import { formatTokenBalance } from "./formatTokenBalance.js";
import { type ERC20OrNativeToken, NATIVE_TOKEN } from "./nativeToken.js";
@@ -32,11 +32,13 @@ type TXError = Error & { data?: { message?: string } };
export function SendFunds(props: {
supportedTokens?: SupportedTokens;
onBack: () => void;
+ connectLocale: ConnectLocale;
+ client: ThirdwebClient;
}) {
const [screen, setScreen] = useState<"base" | "tokenSelector">("base");
const activeChain = useActiveWalletChain();
const chainId = activeChain?.id;
- const { connectLocale, client } = useConnectUI();
+ const { connectLocale, client } = props;
let defaultToken: ERC20OrNativeToken = NATIVE_TOKEN;
const supportedTokens = props.supportedTokens || defaultTokens;
@@ -95,6 +97,7 @@ export function SendFunds(props: {
setAmount={setAmount}
onBack={props.onBack}
client={client}
+ connectLocale={connectLocale}
/>
);
}
@@ -111,8 +114,9 @@ function SendFundsForm(props: {
setAmount: (value: string) => void;
onBack: () => void;
client: ThirdwebClient;
+ connectLocale: ConnectLocale;
}) {
- const locale = useConnectUI().connectLocale.sendFundsScreen;
+ const locale = props.connectLocale.sendFundsScreen;
const tokenAddress =
props.token && "address" in props.token ? props.token.address : undefined;
@@ -145,7 +149,7 @@ function SendFundsForm(props: {
const showInvalidAddressError = receiverAddress && !isValidReceiverAddress;
- const sendTokenMutation = useSendToken();
+ const sendTokenMutation = useSendToken(props.client);
function getErrorMessage(error?: TXError) {
const message = error?.data?.message || error?.message;
diff --git a/packages/thirdweb/src/react/web/ui/hooks/useSendToken.ts b/packages/thirdweb/src/react/web/ui/hooks/useSendToken.ts
index 660fd6431a8..31ed2e6e7bb 100644
--- a/packages/thirdweb/src/react/web/ui/hooks/useSendToken.ts
+++ b/packages/thirdweb/src/react/web/ui/hooks/useSendToken.ts
@@ -1,11 +1,11 @@
import { useMutation } from "@tanstack/react-query";
+import type { ThirdwebClient } from "../../../../client/client.js";
import { getContract } from "../../../../contract/contract.js";
import { transfer } from "../../../../extensions/erc20/write/transfer.js";
import { waitForReceipt } from "../../../../transaction/actions/wait-for-tx-receipt.js";
import { prepareTransaction } from "../../../../transaction/prepare-transaction.js";
import { toWei } from "../../../../utils/units.js";
import { useSendTransactionCore } from "../../../core/hooks/contract/useSendTransaction.js";
-import { useConnectUI } from "../../../core/hooks/others/useWalletConnectionCtx.js";
import { useActiveWalletChain } from "../../../core/hooks/wallets/wallet-hooks.js";
// Q: Should we expose this hook?
@@ -14,10 +14,9 @@ import { useActiveWalletChain } from "../../../core/hooks/wallets/wallet-hooks.j
* Send Native or ERC20 tokens from active wallet to given address.
* @internal
*/
-export function useSendToken() {
+export function useSendToken(client: ThirdwebClient) {
const sendTransaction = useSendTransactionCore();
const activeChain = useActiveWalletChain();
- const { client } = useConnectUI();
return useMutation({
async mutationFn(option: {
diff --git a/packages/thirdweb/src/react/web/wallets/shared/ScanScreen.tsx b/packages/thirdweb/src/react/web/wallets/shared/ScanScreen.tsx
index 9cdccbaef36..020b10bfbb0 100644
--- a/packages/thirdweb/src/react/web/wallets/shared/ScanScreen.tsx
+++ b/packages/thirdweb/src/react/web/wallets/shared/ScanScreen.tsx
@@ -1,8 +1,8 @@
"use client";
import { CheckIcon, CopyIcon } from "@radix-ui/react-icons";
import { useState } from "react";
+import type { ThirdwebClient } from "../../../../client/client.js";
import type { WalletId } from "../../../../wallets/wallet-types.js";
-import { useConnectUI } from "../../../core/hooks/others/useWalletConnectionCtx.js";
import { AccentFailIcon } from "../../ui/ConnectWallet/icons/AccentFailIcon.js";
import { QRCode } from "../../ui/components/QRCode.js";
import { Spacer } from "../../ui/components/Spacer.js";
@@ -29,8 +29,10 @@ export const ScanScreen: React.FC<{
getStartedLink: string;
error: boolean;
onRetry: () => void;
+ connectModalSize: "compact" | "wide";
+ client: ThirdwebClient;
}> = (props) => {
- const { connectModal, client } = useConnectUI();
+ const { connectModalSize, client } = props;
const [linkCopied, setLinkCopied] = useState(false);
return (
@@ -133,7 +135,7 @@ export const ScanScreen: React.FC<{
{props.onGetStarted && (