import { JsonRpcSigner , Web3Provider } from '@ethersproject/providers' ; import { AbstractConnector } from '@web3-react/abstract-connector' ; import { useWeb3React } from '@web3-react/core' ; import Button from 'components/core/Button/Button' ; import colors from 'components/core/colors' ; import { BodyRegular , TitleMedium } from 'components/core/Text/Text' ; import useFetcher from 'contexts/swr/useFetcher' ; import { useAuthenticatedUserAddresses } from 'hooks/api/users/useUser' ; import { useCallback , useEffect , useMemo , useState } from 'react' ; import styled from 'styled-components' ; import { isWeb3Error , Web3Error } from 'types/Error' ; import Spacer from 'components/core/Spacer/Spacer' ; import { ADDRESS_ALREADY_CONNECTED , INITIAL , CONFIRM_ADDRESS , PROMPT_SIGNATURE , PendingState , WalletName , METAMASK , } from 'types/Wallet' ; import { useModal } from 'contexts/modal/ModalContext' ; import ManageWalletsModal from 'scenes/Modals/ManageWalletsModal' ; import Mixpanel from 'utils/mixpanel' ; import { addWallet , fetchNonce } from '../authRequestUtils' ; import { DEFAULT_WALLET_TYPE_ID , signMessageWithEOA } from '../walletUtils' ; type Props = { pendingWallet : AbstractConnector ; userFriendlyWalletName : string ; setDetectedError : ( error : Web3Error ) => void ; walletName : WalletName ; } ; function AddWalletPendingDefault ( { pendingWallet , userFriendlyWalletName , setDetectedError , walletName , } ) { const { library , account } = useWeb3React < Web3Provider > ( ) ; const signer = useMemo ( ( ) => ( library && account ? library . getSigner ( account ) : undefined ) , [ library , account ] ) ; const [ pendingState , setPendingState ] = useState < PendingState > ( INITIAL ) ; const [ isConnecting , setIsConnecting ] = useState ( false ) ; const fetcher = useFetcher ( ) ; const authenticatedUserAddresses = useAuthenticatedUserAddresses ( ) ; const { showModal } = useModal ( ) ; const openManageWalletsModal = useCallback ( ( address ) => { showModal ( < ManageWalletsModal newAddress = { address } / > ) ; } , [ showModal ] ) ; /**
     * Add Wallet Pipeline:
     * 1. Fetch nonce from server with provided wallet address
     * 2. Sign nonce with wallet (metamask / walletconnect / etc.)
     * 3. Add wallet address to user's account
     */ const attemptAddWallet = useCallback ( async ( address , signer ) => { try { setIsConnecting ( true ) ; setPendingState ( PROMPT_SIGNATURE ) ; const { nonce , user_exists : userExists } = await fetchNonce ( address , fetcher ) ; if ( userExists ) { throw { code : 'EXISTING_USER' } as Web3Error ; } const signature = await signMessageWithEOA ( address , nonce , signer , pendingWallet ) ; const payload = { signature , address , wallet_type : DEFAULT_WALLET_TYPE_ID , } ; const { signatureValid } = await addWallet ( payload , fetcher ) ; Mixpanel . trackConnectWallet ( userFriendlyWalletName , 'Add Wallet' ) ; openManageWalletsModal ( address ) ; setIsConnecting ( false ) ; return signatureValid ; } catch ( error ) { setIsConnecting ( false ) ; if ( isWeb3Error ( error ) ) { setDetectedError ( error ) ; } if ( error instanceof Error ) { const web3Error = { code : 'AUTHENTICATION_ERROR' , ... error } ; setDetectedError ( web3Error ) ; } } } , [ fetcher , openManageWalletsModal , pendingWallet , userFriendlyWalletName , setDetectedError ] ) ; const isMetamask = useMemo ( ( ) => walletName === METAMASK , [ walletName ] ) ; useEffect ( ( ) => { async function authenticate ( ) { if ( account && signer ) { if ( authenticatedUserAddresses . includes ( account . toLowerCase ( ) ) ) { setPendingState ( ADDRESS_ALREADY_CONNECTED ) ; return ; } if ( isMetamask ) { setPendingState ( CONFIRM_ADDRESS ) ; } else { await attemptAddWallet ( account . toLowerCase ( ) , signer ) ; } } } void authenticate ( ) ; } , [ account , signer , authenticatedUserAddresses , attemptAddWallet , isMetamask ] ) ; if ( pendingState === ADDRESS_ALREADY_CONNECTED && account ) { return ( < div > < TitleMedium > Connect with { userFriendlyWalletName } < /TitleMedium> < Spacer height = { 8 } / > < BodyRegular color = { colors . gray50 } > The following address is already connected to this account : < /BodyRegular> < Spacer height = { 8 } / > < BodyRegular color = { colors . black } > { account . toLowerCase ( ) } < /BodyRegular> { isMetamask && ( < > < Spacer height = { 8 } /> < BodyRegular color = { colors . gray50 } > If you want to connect a different address via Metamask , please switch accounts in the extension and try again . < /BodyRegular> < />)} < /div>); } if ( pendingState === CONFIRM_ADDRESS && account && signer ) { return ( < div > < TitleMedium > Connect with { userFriendlyWalletName } < /TitleMedium> < Spacer height = { 8 } / > < BodyRegular color = { colors . gray50 } > Confirm the following wallet address : < /BodyRegular> < Spacer height = { 8 } / > < BodyRegular color = { colors . black } > { account ?. toLowerCase ( ) } < /BodyRegular> < Spacer height = { 16 } / > < BodyRegular color = { colors . gray50 } > If you want to connect a different address via Metamask , please switch accounts in the extension and try again . < /BodyRegular> < Spacer height = { 24 } / > < StyledButton text = { isConnecting ? 'Connecting...' : 'Confirm' } onClick = { async ( ) => attemptAddWallet ( account . toLowerCase ( ) , signer ) } disabled = { isConnecting } / > < /div>); } if ( pendingState === PROMPT_SIGNATURE ) { return ( < div > < TitleMedium > Connect with { userFriendlyWalletName } < /TitleMedium> < Spacer height = { 8 } / > < BodyRegular color = { colors . gray50 } > Sign the message with your wallet . < /BodyRegular> < /div>); } return ( < div > < TitleMedium > Connect with { userFriendlyWalletName } < /TitleMedium> < Spacer height = { 8 } / > < BodyRegular color = { colors . gray50 } > Approve your wallet to connect to Gallery . < /BodyRegular> < /div>); } const StyledButton = styled ( Button ) `
  align-self: flex-end;
  padding: 16px;
  width: 100%;
  height: 100%;
` ; export default AddWalletPendingDefault ;