From 9696fcb93f4744a6ed3c1eefa78202b09fb08011 Mon Sep 17 00:00:00 2001 From: simodrws Date: Wed, 2 Aug 2023 18:45:17 +0200 Subject: [PATCH] feat: wip authenticate --- src/refactor/masa/use-masa-loading.ts | 42 +++ src/refactor/masanew.stories.tsx | 16 +- .../ui/components/modals/ModalLoading.tsx | 11 + .../modals/authenticate/auth-view.tsx | 14 +- .../modals/authenticate/authenticate.tsx | 281 ++++++++---------- .../modals/authenticate/connected-view.tsx | 13 +- .../authenticate/use-authenticate-modal.ts | 107 +++++++ .../wallet-client/wallet/use-wallet.ts | 13 + 8 files changed, 318 insertions(+), 179 deletions(-) create mode 100644 src/refactor/masa/use-masa-loading.ts create mode 100644 src/refactor/ui/components/modals/ModalLoading.tsx create mode 100644 src/refactor/ui/components/modals/authenticate/use-authenticate-modal.ts diff --git a/src/refactor/masa/use-masa-loading.ts b/src/refactor/masa/use-masa-loading.ts new file mode 100644 index 00000000..935cd71f --- /dev/null +++ b/src/refactor/masa/use-masa-loading.ts @@ -0,0 +1,42 @@ +import { useMemo } from 'react'; +import { useMasaClient } from '../masa-client/use-masa-client'; +import { useCreditScores } from './use-credit-scores'; +import { useGreen } from './use-green'; +import { useIdentity } from './use-identity'; +import { useSession } from './use-session'; +import { useSoulNames } from './use-soulnames'; +import { useWallet } from '../wallet-client/wallet/use-wallet'; + +export const useMasaLoading = () => { + const { isLoadingSigner, isConnecting } = useWallet(); + const { isLoadingSession } = useSession(); + const { isLoadingIdentity } = useIdentity(); + const { isLoadingSoulnames } = useSoulNames(); + const { isLoadingCreditScores } = useCreditScores(); + const { isLoadingGreens } = useGreen(); + const { sdk: masa } = useMasaClient(); + + const isLoading = useMemo( + () => + isLoadingSession || + isLoadingIdentity || + isLoadingSoulnames || + isLoadingCreditScores || + isLoadingGreens || + isLoadingSigner || + isConnecting || + !masa, + [ + isLoadingSession, + isLoadingIdentity, + isLoadingSoulnames, + isLoadingCreditScores, + isLoadingGreens, + masa, + isLoadingSigner, + isConnecting, + ] + ); + + return isLoading; +}; diff --git a/src/refactor/masanew.stories.tsx b/src/refactor/masanew.stories.tsx index a2ae9092..acf70da0 100644 --- a/src/refactor/masanew.stories.tsx +++ b/src/refactor/masanew.stories.tsx @@ -26,9 +26,7 @@ import { CreateIdentityModal, } from './ui/components/modals'; import { useGreenModal } from './ui/components/modals/create-green/use-green-modal'; -import CreateSoulnameModal, { - openCreateSoulnameModal, -} from './ui/components/modals/create-soulname/CreateSoulnameModal'; +import { openCreateSoulnameModal } from './ui/components/modals/create-soulname/CreateSoulnameModal'; import { useWalletClient } from './wallet-client/wallet-client-provider'; import { openAuthenticateModal } from './ui/components/modals/authenticate/authenticate'; import { SupportedNetworks } from '@masa-finance/masa-sdk'; @@ -159,6 +157,7 @@ const WalletInfo = () => { openChainModal, openAccountModal, disconnect, + shortAddress, // disconnectAsync, isLoadingSigner, isLoadingBalance, @@ -173,6 +172,7 @@ const WalletInfo = () => {

Wallet

  • address: {String(address)}
  • previousAddress: {String(previousAddress)}
  • +
  • shortAddress: {String(shortAddress)}
  • activeConnector: {String(connector?.name)}
  • isConnected: {String(isConnected)}
  • isConnecting: {String(isConnecting)}
  • @@ -503,12 +503,12 @@ const ModalFlow = () => { disabled={!!hasSession} onClick={() => openAuthenticateModal({ - onAuthenticate: () => console.log('AUTHENTICATE SUCCESS'), - onClose: () => console.log('AUTHENTICATE CLOSED'), - onError: () => console.log('AUTHENTICATE ERROR'), - closeOnSuccess: false, + onAuthenticateSuccess: () => console.log('AUTHENTICATE SUCCESS'), + // onClose: () => console.log('AUTHENTICATE CLOSED'), + onAuthenticateError: () => console.log('AUTHENTICATE ERROR'), + // closeOnSuccess: false, // TODO: Didn't know how to handle this type, lets fix is later - next: CreateSoulnameModal as any, + // next: CreateSoulnameModal as any, }) } > diff --git a/src/refactor/ui/components/modals/ModalLoading.tsx b/src/refactor/ui/components/modals/ModalLoading.tsx new file mode 100644 index 00000000..d006b3d6 --- /dev/null +++ b/src/refactor/ui/components/modals/ModalLoading.tsx @@ -0,0 +1,11 @@ +import React, { ReactNode } from 'react'; +import { Spinner } from '../spinner'; + +export const ModalLoading = ({ titleText }: { titleText?: ReactNode }) => ( +
    +
    +

    {titleText}

    + +
    +
    +); diff --git a/src/refactor/ui/components/modals/authenticate/auth-view.tsx b/src/refactor/ui/components/modals/authenticate/auth-view.tsx index e5faf537..61764f86 100644 --- a/src/refactor/ui/components/modals/authenticate/auth-view.tsx +++ b/src/refactor/ui/components/modals/authenticate/auth-view.tsx @@ -4,7 +4,7 @@ interface AuthViewProps { message: string | undefined; handleClipboard: () => void; copied: boolean; - shortAddress: string; + shortAddress?: string; loginSessionAsync: () => void; isLoadingSigner?: boolean; hasSession: boolean | undefined | null; @@ -23,8 +23,8 @@ const AuthView = ({ isConnected, switchWallet, }: AuthViewProps): JSX.Element => ( -
    -
    +
    +

    Wallet connected!

    {message}

    @@ -39,8 +39,8 @@ const AuthView = ({ {copied ? 'Copied!' : shortAddress}

    -
    -
    + +
    - -
    + + ); export default AuthView; diff --git a/src/refactor/ui/components/modals/authenticate/authenticate.tsx b/src/refactor/ui/components/modals/authenticate/authenticate.tsx index 5830b2fb..68b3c0a5 100644 --- a/src/refactor/ui/components/modals/authenticate/authenticate.tsx +++ b/src/refactor/ui/components/modals/authenticate/authenticate.tsx @@ -1,217 +1,180 @@ -import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import NiceModal, { useModal } from '@ebay/nice-modal-react'; -import { Spinner } from '../../spinner'; +// import { useAsync } from 'react-use'; import { useWallet } from '../../../../wallet-client/wallet/use-wallet'; import { useSession } from '../../../../masa/use-session'; -import { useConfig } from '../../../../base-provider'; import { Modal } from '../modal'; -import AuthView from './auth-view'; import ConnectedView from './connected-view'; +import { useAuthenticateModal } from './use-authenticate-modal'; +import { ModalLoading } from '../ModalLoading'; export interface AuthenticateProps { - onAuthenticate?: (payload: unknown) => void; - onClose?: () => void; - onError?: () => void; - next?: FC; - closeOnSuccess?: boolean; + onAuthenticateSuccess?: () => void; + onAuthenticateError?: () => void; + // onClose?: () => void; + // next?: FC; + // closeOnSuccess?: boolean; } export const Authenticate = ({ - onAuthenticate, - onClose, - onError, - closeOnSuccess, - next, + onAuthenticateSuccess, + onAuthenticateError, }: AuthenticateProps): JSX.Element => { const modal = useModal(); const { address, - hasAddress, + shortAddress, disconnect, - isConnected, - signer, openConnectModal, isLoadingSigner, } = useWallet(); - const { isLoadingSession, hasSession, loginSessionAsync } = useSession(); - const { company } = useConfig(); + const { isLoadingSession } = useSession(); - const needsWalletConnection = !hasSession && !isConnected && !hasAddress; - const showAuthenticateView = - isConnected && !hasSession && signer && hasAddress; - const showConnectedView = hasSession && hasAddress; + // const needsWalletConnection = !hasSession && !isConnected && !hasAddress; + // const showAuthenticateView = + // isConnected && !hasSession && signer && hasAddress; + // const showConnectedView = hasSession && hasAddress; const [copied, setCopied] = useState(false); - const handleLoginSession = useCallback(async () => { - const result = await loginSessionAsync?.(); - - if (!result) { - return onError?.(); - } - - if (result && result.address) { - onAuthenticate?.(result); - - if (closeOnSuccess) { - await modal.hide(); - return onClose?.(); - } - - if (next) { - await modal.hide(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - await NiceModal.show(next); - } - } - return result; - }, [ - loginSessionAsync, - onError, - onAuthenticate, - closeOnSuccess, - next, - modal, - onClose, - ]); - - const switchWallet = useCallback(() => { + const switchWallet = useCallback(async () => { disconnect?.(); - }, [disconnect]); - - const copy = useMemo(() => { - switch (company) { - case 'Masa': { - return { - titleText: 'Starting your soulbound journey', - message: `Your wallet is now connected. Start your soulbound journey by minting a Masa Soulbound Identity and claiming a unique Masa Soul Name.`, - }; - } - case 'Celo': { - return { - titleText: 'Starting your soulbound journey', - message: `Your wallet is now connected. Start your journey by minting a Prosperity Passport and claiming a unique .celo domain name.`, - }; - } - case 'Base': { - return { - titleText: 'Starting your soulbound journey', - mesage: - 'Your wallet is now connected. Start your Base Camp journey by claiming a unique .base domain name.', - }; - } - case 'Base Universe': { - return { - titleText: 'Starting your soulbound journey', - message: - 'Your wallet is now connected. Start your Base Universe journey by claiming a unique .bu domain name.', - }; - } - default: { - return { - titleText: 'Starting your soulbound journey', - message: `Your wallet is now connected. Start your soulbound journey by minting a Masa Soulbound Identity and claiming a unique Masa Soul Name.`, - }; - } - } - }, [company]); - - const shortAddress = useMemo(() => { - if (!address) return ''; - - // eslint-disable-next-line unicorn/prefer-string-slice - return `${address?.slice(0, 2) ?? ''}...${address.substring( - address.length - 4, - address.length - )}`; - }, [address]); + await modal?.hide(); + openConnectModal?.(); + }, [modal, disconnect, openConnectModal]); const handleClipboard = useCallback(() => { if (address) { - void navigator.clipboard.writeText(address); + void navigator?.clipboard?.writeText?.(address); setCopied(true); } }, [address]); - useEffect(() => { - if (needsWalletConnection) { - modal.remove(); - openConnectModal?.(); - } - }, [ - modal, - openConnectModal, - isConnected, - hasSession, - hasAddress, - modal.visible, + const { + isAuthenticating, + onAuthenticateStart, + successMessage, needsWalletConnection, - ]); + showAuthenticateView, + showConnectedView, + showSwitchWalletButton, + } = useAuthenticateModal({ + onAuthenticateError, + onAuthenticateSuccess, + }); + + // useAsync(async () => { + // if (needsWalletConnection) { + // modal.remove(); + // openConnectModal?.(); + // } + // }, [modal, needsWalletConnection, openConnectModal]); + + if (needsWalletConnection) { + return <>No Modal; + } if (isLoadingSigner) { - return ; + return ( + + BRUDER + + + ); } - return ( - - {showAuthenticateView && ( - - )} - {showConnectedView && ( + if (showConnectedView) { + return ( + - )} - - ); + + ); + } + + if (showAuthenticateView) { + +
    +
    +

    + {isAuthenticating ? 'Signing you in ...' : 'Wallet connected!'} +

    +

    {successMessage}

    + +

    + You are connected with the following wallet + {}} + > + {copied ? 'Copied!' : shortAddress} + +

    +
    +
    + + +
    +

    + Want to use a different wallet? + {showSwitchWalletButton && ( + + {}} + > + Switch Wallet + + + )} +

    +
    +
    +
    +
    ; + } + + return <>ERROR; }; export const AuthenticateModal = NiceModal.create( ({ - onAuthenticate, - onClose, - onError, - closeOnSuccess, - next, + onAuthenticateSuccess, + // onClose, + onAuthenticateError, }: AuthenticateProps) => ( ) ); export const openAuthenticateModal = ({ - onAuthenticate, - onClose, - onError, - closeOnSuccess, - next, + onAuthenticateSuccess, + onAuthenticateError, }: AuthenticateProps) => NiceModal.show(AuthenticateModal, { - onAuthenticate, - onClose, - onError, - closeOnSuccess, - next, + onAuthenticateSuccess, + onAuthenticateError, }); export default AuthenticateModal; diff --git a/src/refactor/ui/components/modals/authenticate/connected-view.tsx b/src/refactor/ui/components/modals/authenticate/connected-view.tsx index c2f697b7..c8cf2239 100644 --- a/src/refactor/ui/components/modals/authenticate/connected-view.tsx +++ b/src/refactor/ui/components/modals/authenticate/connected-view.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from 'react'; import type { NiceModalHandler } from '@ebay/nice-modal-react'; import { Spinner } from '../../spinner'; +import { Modal } from '../modal'; interface ConnectedViewProps { titleText: string; @@ -29,12 +30,14 @@ const ConnectedView = ({ }, [isLoadingSession, modal]); return ( -
    -
    -

    {titleText}

    - + +
    +
    +

    {titleText}

    + +
    -
    + ); }; diff --git a/src/refactor/ui/components/modals/authenticate/use-authenticate-modal.ts b/src/refactor/ui/components/modals/authenticate/use-authenticate-modal.ts new file mode 100644 index 00000000..753c9f62 --- /dev/null +++ b/src/refactor/ui/components/modals/authenticate/use-authenticate-modal.ts @@ -0,0 +1,107 @@ +import { useMemo } from 'react'; +import { useAsyncFn } from 'react-use'; +import { useWallet } from '../../../../wallet-client/wallet/use-wallet'; +import { useSession } from '../../../../masa/use-session'; +import { useConfig } from '../../../../base-provider'; + +export const useAuthenticateModal = ({ + onAuthenticateSuccess, + onAuthenticateError, +}: { + onAuthenticateSuccess?: () => void; + onAuthenticateError?: () => void; + onClose?: () => void; +}) => { + const { hasAddress, isConnected, signer } = useWallet(); + + const { hasSession, loginSession } = useSession(); + const { company } = useConfig(); + + const needsWalletConnection = useMemo( + () => !hasSession && !isConnected && !hasAddress, + [hasSession, isConnected, hasAddress] + ); + const showAuthenticateView = useMemo( + () => isConnected && !hasSession && signer && hasAddress, + [isConnected, hasSession, signer, hasAddress] + ); + const showConnectedView = useMemo( + () => hasSession && hasAddress, + [hasSession, hasAddress] + ); + + const successMessage = useMemo(() => { + switch (company) { + case 'Masa': { + return `Your wallet is now connected. Start your soulbound journey by minting + a Masa Soulbound Identity and claiming a unique Masa Soul Name.`; + } + case 'Celo': { + return `Your wallet is now connected. Start your journey by minting a Prosperity Passport and claiming a unique .celo domain name.`; + } + case 'Base': { + return 'Your wallet is now connected. Start your Base Camp journey by claiming a unique .base domain name.'; + } + case 'Base Universe': { + return 'Your wallet is now connected. Start your Base Universe journey by claiming a unique .bu domain name.'; + } + case 'Brozo': { + return 'Your wallet is connected. Start your Brozo journey by minting a unique .bro domain name.'; + } + default: { + return `Your wallet is now connected. Start your soulbound journey by minting + a Masa Soulbound Identity and claiming a unique Masa Soul Name.`; + } + } + }, [company]); + + const [{ loading: isAuthenticating }, onAuthenticateStart] = + useAsyncFn(async () => { + const result = await loginSession?.(); + + if (!result) { + onAuthenticateError?.(); + return result; + } + + if (result && result.address) { + onAuthenticateSuccess?.(); + + // if (closeOnSuccess) { + // await modal.hide(); + // return onClose?.(); + // } + + // if (next) { + // await modal.hide(); + + // await NiceModal.show(next); + // } + } + return result; + }, [ + loginSession, + // onError, + onAuthenticateError, + onAuthenticateSuccess, + // closeOnSuccess, + // next, + // modal, + // onClose, + ]); + + const showSwitchWalletButton = useMemo( + () => !hasSession && isConnected, + [hasSession, isConnected] + ); + return { + needsWalletConnection, + showAuthenticateView, + showConnectedView, + successMessage, + + isAuthenticating, + onAuthenticateStart, + showSwitchWalletButton, + }; +}; diff --git a/src/refactor/wallet-client/wallet/use-wallet.ts b/src/refactor/wallet-client/wallet/use-wallet.ts index 8ba49405..90a68217 100644 --- a/src/refactor/wallet-client/wallet/use-wallet.ts +++ b/src/refactor/wallet-client/wallet/use-wallet.ts @@ -36,6 +36,16 @@ const useWallet = () => { address, }); + const shortAddress = useMemo(() => { + if (!address) return ''; + + // eslint-disable-next-line unicorn/prefer-string-slice + return `${address?.slice(0, 2) ?? ''}...${address.substring( + address.length - 4, + address.length + )}`; + }, [address]); + // useEffect(() => console.log({ provider, signer }), [provider, signer]); useEffect(() => { @@ -72,6 +82,7 @@ const useWallet = () => { const useWalletValue = useMemo( () => ({ address, + shortAddress, hasAddress, walletName, previousAddress, @@ -95,6 +106,7 @@ const useWallet = () => { }), [ address, + shortAddress, hasAddress, walletName, previousAddress, @@ -124,6 +136,7 @@ const useWallet = () => { walletName?: string; previousAddress?: `0x${string}`; compareAddress?: `0x${string}`; + shortAddress?: `0x${string}`; provider?: Provider; signer?: Signer; connector?: Connector;