diff --git a/packages/thirdweb/src/exports/react.ts b/packages/thirdweb/src/exports/react.ts index 243afcb505d..659e70588e3 100644 --- a/packages/thirdweb/src/exports/react.ts +++ b/packages/thirdweb/src/exports/react.ts @@ -121,4 +121,10 @@ export { type PayEmbedProps, type PayEmbedConnectOptions, } from "../react/web/ui/PayEmbed.js"; + +export { + PayEmbedUI, + type PayEmbedUIProps, +} from "../react/web/ui/PayEmbedUI.js"; + export type { PayUIOptions } from "../react/web/ui/ConnectWallet/ConnectButtonProps.js"; diff --git a/packages/thirdweb/src/react/web/hooks/useSendTransaction.tsx b/packages/thirdweb/src/react/web/hooks/useSendTransaction.tsx index ce4709f29b5..b69e3fbb5ea 100644 --- a/packages/thirdweb/src/react/web/hooks/useSendTransaction.tsx +++ b/packages/thirdweb/src/react/web/hooks/useSendTransaction.tsx @@ -5,7 +5,12 @@ import type { GaslessOptions } from "../../../transaction/actions/gasless/types. import type { PreparedTransaction } from "../../../transaction/prepare-transaction.js"; import type { Wallet } from "../../../wallets/interfaces/wallet.js"; import { useSendTransactionCore } from "../../core/hooks/contract/useSendTransaction.js"; -import { useActiveWallet } from "../../core/hooks/wallets/wallet-hooks.js"; +import { + useActiveAccount, + useActiveWallet, + useActiveWalletChain, + useSwitchActiveWalletChain, +} from "../../core/hooks/wallets/wallet-hooks.js"; import { SetRootElementContext } from "../../core/providers/RootElementContext.js"; import type { PayUIOptions } from "../ui/ConnectWallet/ConnectButtonProps.js"; import type { SupportedTokens } from "../ui/ConnectWallet/defaultTokens.js"; @@ -182,7 +187,11 @@ function ModalContent(props: ModalProps) { "buy", ); - if (!localeQuery.data) { + const account = useActiveAccount(); + const activeChain = useActiveWalletChain(); + const switchChain = useSwitchActiveWalletChain(); + + if (!localeQuery.data || !account || !activeChain) { return ; } @@ -202,6 +211,9 @@ function ModalContent(props: ModalProps) { }} isBuyForTx={true} isEmbed={false} + account={account} + activeChain={activeChain} + switchChain={switchChain} /> ); } @@ -226,6 +238,9 @@ function ModalContent(props: ModalProps) { onDone={() => { setScreen("execute-tx"); }} + account={account} + activeChain={activeChain} + switchChain={switchChain} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx index dfba3ded8c0..45c9de8d9fb 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx @@ -6,6 +6,8 @@ import { useSiweAuth } from "../../../core/hooks/auth/useSiweAuth.js"; import { AutoConnect } from "../../../core/hooks/connection/useAutoConnect.js"; import { useActiveAccount, + useActiveWallet, + useActiveWalletChain, useActiveWalletConnectionStatus, } from "../../../core/hooks/wallets/wallet-hooks.js"; import { ConnectUIContext } from "../../../core/providers/wallet-connection.js"; @@ -135,6 +137,9 @@ function ConnectButtonInner( }, ) { const activeAccount = useActiveAccount(); + const activeChain = useActiveWalletChain(); + const activeWallet = useActiveWallet(); + const siweAuth = useSiweAuth(props.auth); const [showSignatureModal, setShowSignatureModal] = useState(false); @@ -173,7 +178,7 @@ function ConnectButtonInner( return tokens; }, [props.supportedTokens]); - if (!activeAccount) { + if (!activeAccount || !activeChain || !activeWallet) { // Connect Wallet button return ( ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx index 638c3404f21..b22b93e1880 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx @@ -16,6 +16,7 @@ import { getContract } from "../../../../contract/contract.js"; import { resolveAvatar } from "../../../../extensions/ens/resolve-avatar.js"; import { resolveName } from "../../../../extensions/ens/resolve-name.js"; import { isContractDeployed } from "../../../../utils/bytecode/is-contract-deployed.js"; +import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js"; import { useChainQuery, useChainsQuery, @@ -97,24 +98,26 @@ export const ConnectedWalletDetails: React.FC<{ chains: Chain[]; chain?: Chain; switchButton: ConnectButtonProps["switchButton"]; + activeWallet: Wallet; + activeChain: Chain; + activeAccount: Account; }> = (props) => { const { connectLocale: locale, client } = useConnectUI(); + const { activeChain, activeWallet, activeAccount } = props; + const switchChain = useSwitchActiveWalletChain(); - const activeWallet = useActiveWallet(); - const activeAccount = useActiveAccount(); - const walletChain = useActiveWalletChain(); - const chainQuery = useChainQuery(walletChain); + const chainQuery = useChainQuery(activeChain); 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)] + activeChain && props.detailsButton?.displayBalanceToken + ? props.detailsButton.displayBalanceToken[Number(activeChain.id)] : undefined; const balanceQuery = useWalletBalance({ - chain: walletChain ? walletChain : undefined, + chain: activeChain, tokenAddress, address: activeAccount?.address, client, @@ -174,8 +177,7 @@ export const ConnectedWalletDetails: React.FC<{ // avatarOrWalletIconUrl = smartWalletMetadata.iconUrl; // } - const isNetworkMismatch = - props.chain && walletChain && walletChain.id !== props.chain.id; + const isNetworkMismatch = props.chain && activeChain.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 @@ -293,7 +295,7 @@ export const ConnectedWalletDetails: React.FC<{ ) : ( - {chainQuery.data?.name || `Unknown chain #${walletChain?.id}`} + {chainQuery.data?.name || `Unknown chain #${activeChain?.id}`} )} @@ -604,6 +606,9 @@ export const ConnectedWalletDetails: React.FC<{ onDone={() => { setIsOpen(false); }} + account={activeAccount} + activeChain={activeChain} + switchChain={switchChain} /> ); } @@ -613,9 +618,8 @@ export const ConnectedWalletDetails: React.FC<{ c.id === walletChain.id) === undefined - ? [walletChain, ...props.chains] + props.chains.find((c) => c.id === activeChain.id) === undefined + ? [activeChain, ...props.chains] : props.chains } closeModal={() => { @@ -697,6 +701,9 @@ export const ConnectedWalletDetails: React.FC<{ onDone={() => { setIsOpen(false); }} + account={activeAccount} + activeChain={activeChain} + switchChain={switchChain} /> ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx index cc9df7e0c72..9e89f764e7e 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx @@ -14,10 +14,6 @@ import { import { useWalletBalance } from "../../../../../core/hooks/others/useWalletBalance.js"; import { useBuyWithCryptoQuote } from "../../../../../core/hooks/pay/useBuyWithCryptoQuote.js"; import { useBuyWithFiatQuote } from "../../../../../core/hooks/pay/useBuyWithFiatQuote.js"; -import { - useActiveAccount, - useActiveWalletChain, -} from "../../../../../core/hooks/wallets/wallet-hooks.js"; import { LoadingScreen } from "../../../../wallets/shared/LoadingScreen.js"; import { Drawer, @@ -65,7 +61,7 @@ import { useBuySupportedSources, } from "./swap/useSwapSupportedChains.js"; -// NOTE: Must not use useConnectUI here because this UI can be used outside connect ui +// NOTE: Can not use any wallet hooks or Context export type BuyScreenProps = { onBack?: () => void; @@ -79,6 +75,9 @@ export type BuyScreenProps = { onDone: () => void; connectButton?: React.ReactNode; isEmbed: boolean; + account: Account | null; + activeChain: Chain | null; + switchChain: (chain: Chain) => Promise; }; /** @@ -114,6 +113,9 @@ type BuyScreenContentProps = { onDone: () => void; connectButton?: React.ReactNode; isEmbed: boolean; + account: Account | null; + activeChain: Chain | null; + switchChain: (chain: Chain) => Promise; }; function useBuyScreenStates(options: { @@ -166,11 +168,15 @@ function useBuyScreenStates(options: { * @internal */ function BuyScreenContent(props: BuyScreenContentProps) { - const { client, supportedDestinations, connectLocale, payOptions, buyForTx } = - props; - - const account = useActiveAccount(); - const activeChain = useActiveWalletChain(); + const { + client, + supportedDestinations, + connectLocale, + payOptions, + buyForTx, + activeChain, + account, + } = props; // prefetch chains metadata for destination chains useChainsQuery(supportedDestinations.map((x) => x.chain) || [], 50); @@ -489,6 +495,8 @@ function BuyScreenContent(props: BuyScreenContentProps) { // currently disabled because we are only using Stripe }} account={account} + activeChain={activeChain} + switchChain={props.switchChain} /> )} @@ -547,6 +555,7 @@ function SwapScreenContent( showFromTokenSelector: () => void; account: Account; activeChain: Chain; + switchChain: (chain: Chain) => Promise; }, ) { const { @@ -650,6 +659,8 @@ function SwapScreenContent( }); quoteQuery.refetch(); }} + activeChain={props.activeChain} + switchChain={props.switchChain} /> ), }); @@ -691,6 +702,7 @@ function SwapScreenContent( prefillSource?.allowEdits?.chain === false && prefillSource?.allowEdits?.token === false } + account={account} /> + ) : (