import { type JSX, useEffect, useState } from "react"; import { Linking, StyleSheet, TouchableOpacity, View } from "react-native"; import type { ThirdwebClient } from "../../../../client/client.js"; import { getContract } from "../../../../contract/contract.js"; import { isContractDeployed } from "../../../../utils/bytecode/is-contract-deployed.js"; import { formatNumber } from "../../../../utils/formatNumber.js"; import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js"; import { isSmartWallet } from "../../../../wallets/smart/is-smart-wallet.js"; import type { Theme } from "../../../core/design-system/index.js"; import { useSiweAuth } from "../../../core/hooks/auth/useSiweAuth.js"; import type { ConnectButtonProps } from "../../../core/hooks/connection/ConnectButtonProps.js"; import { useChainName } from "../../../core/hooks/others/useChainQuery.js"; import { useActiveAccount } from "../../../core/hooks/wallets/useActiveAccount.js"; import { useActiveWallet } from "../../../core/hooks/wallets/useActiveWallet.js"; import { useActiveWalletChain } from "../../../core/hooks/wallets/useActiveWalletChain.js"; import { useDisconnect } from "../../../core/hooks/wallets/useDisconnect.js"; import { useConnectedWalletDetails } from "../../../core/utils/wallet.js"; import { fontSize, radius, spacing } from "../../design-system/index.js"; import { Address } from "../components/Address.js"; import { ThemedButton } from "../components/button.js"; import { ChainIcon } from "../components/ChainIcon.js"; import { type ContainerType, Header } from "../components/Header.js"; import { RNImage } from "../components/RNImage.js"; import { Skeleton } from "../components/Skeleton.js"; import { Spacer } from "../components/spacer.js"; import { ThemedText } from "../components/text.js"; import { ThemedView } from "../components/view.js"; import { WalletImage } from "../components/WalletImage.js"; import { CLOSE_ICON, COINS_ICON, EXIT_ICON, RECEIVE_ICON, SEND_ICON, SMART_WALLET_ICON, } from "../icons/svgs.js"; import { ReceiveScreen } from "./ReceiveScreen.js"; import { SendScreen } from "./SendScreen.js"; import { TokenListScreen } from "./TokenListScreen.js"; type ConnectedModalState = | { screen: "account"; } | { screen: "send" } | { screen: "receive" } | { screen: "view_funds" }; type ConnectedModalProps = ConnectButtonProps & { theme: Theme; wallet: Wallet; account: Account; onClose?: () => void; containerType: ContainerType; }; type ConnectedModalPropsInner = ConnectedModalProps & { setModalState: (state: ConnectedModalState) => void; }; export function ConnectedModal(props: ConnectedModalProps) { const { theme, containerType, client } = props; const [modalState, setModalState] = useState({ screen: "account", }); let content: JSX.Element; switch (modalState.screen) { case "send": { content = ( setModalState({ screen: "account" })} onClose={props.onClose} supportedTokens={props.supportedTokens} theme={theme} /> ); break; } case "receive": { content = ( setModalState({ screen: "account" })} onClose={props.onClose} theme={theme} wallet={props.wallet} /> ); break; } case "view_funds": { content = ( <>
setModalState({ screen: "account" })} onClose={props.onClose} theme={theme} title="View Funds" /> ); break; } default: { content = ( <> {props.onClose && ( )} ); } } return ( {content} ); } const AccountHeader = (props: ConnectedModalProps) => { const { account, wallet, theme, client } = props; const walletChain = useActiveWalletChain(); const { pfp, name, balanceQuery } = useConnectedWalletDetails( props.client, walletChain, account, props.detailsButton?.displayBalanceToken, ); return (
{balanceQuery.data ? ( {formatNumber(Number(balanceQuery.data.displayValue), 5)}{" "} {balanceQuery.data?.symbol} ) : ( )} ); }; const WalletActionsRow = (props: ConnectedModalPropsInner) => { const { theme, setModalState } = props; return ( setModalState({ screen: "send" })} style={styles.walletActionButton} theme={theme} variant="secondary" > Send setModalState({ screen: "receive" })} style={styles.walletActionButton} theme={theme} variant="secondary" > Receive {/** TODO (rn) Buy button here */} ); }; const WalletMenu = (props: ConnectedModalPropsInner) => { return ( {/* TODO (rn) implement transactions screen */} {/* */} ); }; const ChainSwitcher = (props: ConnectedModalPropsInner) => { const { client, wallet, theme } = props; const chain = wallet.getChain(); const { name } = useChainName(chain); return ( {name ? ( {name} ) : ( )} ); }; const ViewFunds = (props: ConnectedModalPropsInner) => { const { theme, setModalState } = props; return ( setModalState({ screen: "view_funds" })} style={styles.walletMenuRow} > View Funds ); }; const DisconnectWallet = (props: ConnectedModalProps) => { const { wallet, account, theme, onClose, onDisconnect } = props; const { disconnect } = useDisconnect(); const siweAuth = useSiweAuth(wallet, account, props.auth); return ( { onClose?.(); disconnect(wallet); if (siweAuth.isLoggedIn) { siweAuth.doLogout(); } onDisconnect?.({ wallet, account, }); }} style={styles.walletMenuRow} > Disconnect Wallet ); }; function SmartAccountBadge(props: { theme: Theme; client: ThirdwebClient }) { const activeAccount = useActiveAccount(); const activeWallet = useActiveWallet(); const isSW = isSmartWallet(activeWallet); const chain = useActiveWalletChain(); const { client, theme } = props; const [isSmartWalletDeployed, setIsSmartWalletDeployed] = useState(false); useEffect(() => { if (activeAccount && isSW && activeAccount.address && chain) { const contract = getContract({ address: activeAccount.address, chain, client, }); isContractDeployed(contract).then((isDeployed) => { setIsSmartWalletDeployed(isDeployed); }); } else { setIsSmartWalletDeployed(false); } }, [activeAccount, chain, client, isSW]); const content = ( Smart Account ); if (chain && activeAccount && isSW) { return ( <> {isSmartWalletDeployed ? ( Linking.openURL( `https://thirdweb.com/${chain.id}/${activeAccount.address}/account`, ) } > {content} ) : ( {content} )} ); } return null; } const styles = StyleSheet.create({ accountHeaderContainer: { alignItems: "center", flexDirection: "column", justifyContent: "center", paddingHorizontal: spacing.lg, }, embedContainer: { backgroundColor: "transparent", flex: 1, flexDirection: "column", width: "100%", }, modalContainer: { borderTopLeftRadius: radius.lg, borderTopRightRadius: radius.lg, flex: 1, flexDirection: "column", width: "100%", }, walletActionButton: { flex: 1, gap: spacing.smd, padding: spacing.smd }, walletActionRowContainer: { alignItems: "center", flexDirection: "row", gap: spacing.md, justifyContent: "space-evenly", paddingHorizontal: spacing.lg, }, walletMenuContainer: { flexDirection: "column", gap: spacing.lg, paddingHorizontal: spacing.lg, }, walletMenuRow: { alignItems: "center", flexDirection: "row", gap: spacing.md, justifyContent: "flex-start", }, });