From 0b519553adeeee3764828191a677a3397db30849 Mon Sep 17 00:00:00 2001 From: Usame Algan Date: Mon, 6 Nov 2023 09:46:07 +0100 Subject: [PATCH] fix: Add social login option to onboard module --- src/hooks/wallets/mpc/useSocialWallet.ts | 24 ------------- src/pages/_app.tsx | 3 ++ src/services/mpc/PasswordRecoveryModal.tsx | 42 ++++++++++++++++++++++ src/services/mpc/SocialLoginModule.ts | 36 +++++++++++++++---- 4 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 src/services/mpc/PasswordRecoveryModal.tsx diff --git a/src/hooks/wallets/mpc/useSocialWallet.ts b/src/hooks/wallets/mpc/useSocialWallet.ts index 4d2dd700ef..d98998ffdd 100644 --- a/src/hooks/wallets/mpc/useSocialWallet.ts +++ b/src/hooks/wallets/mpc/useSocialWallet.ts @@ -13,23 +13,6 @@ import useMpc from './useMPC' const { getStore, setStore, useStore } = new ExternalStore() -// Listen to onboard modal open and hide the social login button -const hideOnboardButton = () => { - const onboardRoot = document.querySelector('onboard-v2')?.shadowRoot - if (!onboardRoot) return - - const hideSocialLoginButton = () => { - const walletButtons = onboardRoot.querySelectorAll('.wallet-button-container') || [] - const socialButton = Array.from(walletButtons).find((el) => el.textContent?.includes(ONBOARD_MPC_MODULE_LABEL)) - socialButton?.remove() - } - - const observer = new MutationObserver(hideSocialLoginButton) - observer.observe(onboardRoot, { childList: true }) - - return () => observer.disconnect() -} - export const useInitSocialWallet = () => { const mpcCoreKit = useMpc() const onboard = useOnboard() @@ -71,13 +54,6 @@ export const useInitSocialWallet = () => { setStore(new SocialWalletService(mpcCoreKit)) } }, [mpcCoreKit]) - - // Hide social login when onboard pops up - // @FIXME the button should work but atm it doesn't - useEffect(() => { - if (!onboard) return - return hideOnboardButton() - }, [onboard]) } export const getSocialWalletService = getStore diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index ec90253c7a..e7b3d6d3d7 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,3 +1,4 @@ +import PasswordRecoveryModal from '@/services/mpc/PasswordRecoveryModal' import Sentry from '@/services/sentry' // needs to be imported first import type { ReactNode } from 'react' import { type ReactElement } from 'react' @@ -126,6 +127,8 @@ const WebCoreApp = ({ + + diff --git a/src/services/mpc/PasswordRecoveryModal.tsx b/src/services/mpc/PasswordRecoveryModal.tsx new file mode 100644 index 0000000000..7a7e1d08ab --- /dev/null +++ b/src/services/mpc/PasswordRecoveryModal.tsx @@ -0,0 +1,42 @@ +import { PasswordRecovery } from '@/components/common/SocialSigner/PasswordRecovery' +import TxModalDialog from '@/components/common/TxModalDialog' +import useSocialWallet from '@/hooks/wallets/mpc/useSocialWallet' +import ExternalStore from '@/services/ExternalStore' + +const { useStore: useCloseCallback, setStore: setCloseCallback } = new ExternalStore<() => void>() + +export const open = (cb: () => void) => { + setCloseCallback(() => cb) +} + +export const close = () => { + setCloseCallback(undefined) +} + +const PasswordRecoveryModal = () => { + const socialWalletService = useSocialWallet() + const closeCallback = useCloseCallback() + const open = !!closeCallback + + const handleClose = () => { + closeCallback?.() + setCloseCallback(undefined) + close() + } + + const recoverPassword = async (password: string, storeDeviceFactor: boolean) => { + if (!socialWalletService) return + + await socialWalletService.recoverAccountWithPassword(password, storeDeviceFactor) + } + + if (!open) return null + + return ( + + + + ) +} + +export default PasswordRecoveryModal diff --git a/src/services/mpc/SocialLoginModule.ts b/src/services/mpc/SocialLoginModule.ts index f9921000b3..e6b2e2fb8c 100644 --- a/src/services/mpc/SocialLoginModule.ts +++ b/src/services/mpc/SocialLoginModule.ts @@ -1,7 +1,10 @@ import { _getMPCCoreKitInstance } from '@/hooks/wallets/mpc/useMPC' +import { getSocialWalletService } from '@/hooks/wallets/mpc/useSocialWallet' import { getWeb3ReadOnly } from '@/hooks/wallets/web3' +import * as PasswordRecoveryModal from '@/services/mpc/PasswordRecoveryModal' import { type WalletInit, ProviderRpcError } from '@web3-onboard/common' import { type EIP1193Provider } from '@web3-onboard/core' +import { COREKIT_STATUS } from '@web3auth/mpc-core-kit' const getMPCProvider = () => _getMPCCoreKitInstance()?.provider @@ -37,26 +40,44 @@ function MpcModule(): WalletInit { web3.on(event, listener) }, request: (request) => { - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { try { - const web3 = assertDefined(getMPCProvider()) - const web3ReadOnly = assertDefined(getWeb3ReadOnly()) /* * We have to fallback to web3ReadOnly for eth_estimateGas because the provider by Web3Auth does not expose / implement it. */ if ('eth_estimateGas' === request.method) { + const web3ReadOnly = assertDefined(getWeb3ReadOnly()) + web3ReadOnly ?.send(request.method, request.params ?? []) .then(resolve) .catch(reject) + return } - /* - * If the provider is defined we already have access to the accounts. So we can just reply with the current account. - */ if ('eth_requestAccounts' === request.method) { - web3.request({ method: 'eth_accounts' }).then(resolve).catch(reject) + try { + // If the provider is defined we already have access to the accounts. + const web3 = assertDefined(getMPCProvider()) + web3.request({ method: 'eth_accounts' }).then(resolve).catch(reject) + } catch (e) { + // Otherwise try to log in the user + const socialWalletService = getSocialWalletService() + if (!socialWalletService) throw Error('Social Login not ready') + + const status = await socialWalletService.loginAndCreate() + + if (status === COREKIT_STATUS.REQUIRED_SHARE) { + PasswordRecoveryModal.open(() => { + const web3 = assertDefined(getMPCProvider()) + web3.request({ method: 'eth_accounts' }).then(resolve).catch(reject) + }) + } else { + const web3 = assertDefined(getMPCProvider()) + web3.request({ method: 'eth_accounts' }).then(resolve).catch(reject) + } + } return } @@ -66,6 +87,7 @@ function MpcModule(): WalletInit { return } + const web3 = assertDefined(getMPCProvider()) // Default: we call the inner provider web3.request(request).then(resolve).catch(reject) return