diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js --- a/lib/types/siwe-types.js +++ b/lib/types/siwe-types.js @@ -115,3 +115,9 @@ +validate: (signature: string, provider?: any) => Promise, +toMessage: () => string, }; + +export type SIWEResult = { + +address: string, + +message: string, + +signature: string, +}; diff --git a/native/account/fullscreen-siwe-panel.react.js b/native/account/fullscreen-siwe-panel.react.js --- a/native/account/fullscreen-siwe-panel.react.js +++ b/native/account/fullscreen-siwe-panel.react.js @@ -1,8 +1,9 @@ // @flow import * as React from 'react'; -import { ActivityIndicator, View } from 'react-native'; +import { Alert, ActivityIndicator, View } from 'react-native'; +import { useSIWEServerCall } from './siwe-hooks.js'; import SIWEPanel from './siwe-panel.react.js'; type Props = { @@ -21,7 +22,21 @@ [], ); - const { onClose, closing } = props; + const { onClose } = props; + const siweServerCallParams = React.useMemo(() => { + const onServerCallFailure = () => { + Alert.alert( + 'Unknown error', + 'Uhh... try again?', + [{ text: 'OK', onPress: onClose }], + { cancelable: false }, + ); + }; + return { onFailure: onServerCallFailure }; + }, [onClose]); + const siweServerCall = useSIWEServerCall(siweServerCallParams); + + const { closing } = props; return ( <> {activity} @@ -29,6 +44,7 @@ closing={closing} onClosed={onClose} onClosing={onClose} + onSuccessfulWalletSignature={siweServerCall} setLoading={setLoading} /> diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js --- a/native/account/registration/connect-ethereum.react.js +++ b/native/account/registration/connect-ethereum.react.js @@ -94,6 +94,9 @@ [panelState], ); + const onSkip = React.useCallback(() => {}, []); + const onSuccessfulWalletSignature = React.useCallback(() => {}, []); + let siwePanel; if (panelState !== 'closed') { siwePanel = ( @@ -101,13 +104,12 @@ onClosing={onPanelClosing} onClosed={onPanelClosed} closing={panelState === 'closing'} + onSuccessfulWalletSignature={onSuccessfulWalletSignature} setLoading={siwePanelSetLoading} /> ); } - const onSkip = React.useCallback(() => {}, []); - return ( <> diff --git a/native/account/siwe-hooks.js b/native/account/siwe-hooks.js new file mode 100644 --- /dev/null +++ b/native/account/siwe-hooks.js @@ -0,0 +1,71 @@ +// @flow + +import * as React from 'react'; + +import { siweAuth, siweAuthActionTypes } from 'lib/actions/siwe-actions.js'; +import type { LogInStartingPayload } from 'lib/types/account-types.js'; +import { + useServerCall, + useDispatchActionPromise, +} from 'lib/utils/action-utils.js'; + +import { NavContext } from '../navigation/navigation-context.js'; +import { useSelector } from '../redux/redux-utils.js'; +import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors.js'; + +type SIWEServerCallParams = { + +message: string, + +signature: string, + ... +}; +type UseSIWEServerCallParams = { + +onFailure: () => mixed, +}; +function useSIWEServerCall( + params: UseSIWEServerCallParams, +): SIWEServerCallParams => Promise { + const { onFailure } = params; + + const siweAuthCall = useServerCall(siweAuth); + + const callSIWE = React.useCallback( + async (message, signature, extraInfo) => { + try { + return await siweAuthCall({ + message, + signature, + ...extraInfo, + }); + } catch (e) { + onFailure(); + throw e; + } + }, + [onFailure, siweAuthCall], + ); + + const navContext = React.useContext(NavContext); + const logInExtraInfo = useSelector(state => + nativeLogInExtraInfoSelector({ + redux: state, + navContext, + }), + ); + + const dispatchActionPromise = useDispatchActionPromise(); + return React.useCallback( + async ({ message, signature }) => { + const extraInfo = await logInExtraInfo(); + + dispatchActionPromise( + siweAuthActionTypes, + callSIWE(message, signature, extraInfo), + undefined, + ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), + ); + }, + [logInExtraInfo, dispatchActionPromise, callSIWE], + ); +} + +export { useSIWEServerCall }; diff --git a/native/account/siwe-panel.react.js b/native/account/siwe-panel.react.js --- a/native/account/siwe-panel.react.js +++ b/native/account/siwe-panel.react.js @@ -9,21 +9,17 @@ import { getSIWENonce, getSIWENonceActionTypes, - siweAuth, siweAuthActionTypes, } from 'lib/actions/siwe-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import type { LogInStartingPayload } from 'lib/types/account-types.js'; -import type { SIWEWebViewMessage } from 'lib/types/siwe-types.js'; +import type { SIWEWebViewMessage, SIWEResult } from 'lib/types/siwe-types.js'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; import { commCoreModule } from '../native-modules.js'; -import { NavContext } from '../navigation/navigation-context.js'; import { useSelector } from '../redux/redux-utils.js'; -import { nativeLogInExtraInfoSelector } from '../selectors/account-selectors.js'; import { defaultLandingURLPrefix } from '../utils/url-utils.js'; const commSIWE = `${defaultLandingURLPrefix}/siwe`; @@ -37,21 +33,13 @@ type Props = { +onClosed: () => mixed, +onClosing: () => mixed, + +onSuccessfulWalletSignature: SIWEResult => mixed, +closing: boolean, +setLoading: boolean => mixed, }; function SIWEPanel(props: Props): React.Node { - const navContext = React.useContext(NavContext); const dispatchActionPromise = useDispatchActionPromise(); const getSIWENonceCall = useServerCall(getSIWENonce); - const siweAuthCall = useServerCall(siweAuth); - - const logInExtraInfo = useSelector(state => - nativeLogInExtraInfoSelector({ - redux: state, - navContext, - }), - ); const getSIWENonceCallFailed = useSelector( state => getSIWENonceLoadingStatusSelector(state) === 'error', @@ -117,42 +105,8 @@ snapToIndex?.(0); }, [snapToIndex, snapPoints]); - const callSIWE = React.useCallback( - async (message, signature, extraInfo) => { - try { - return await siweAuthCall({ - message, - signature, - ...extraInfo, - }); - } catch (e) { - Alert.alert( - 'Unknown error', - 'Uhh... try again?', - [{ text: 'OK', onPress: onClosing }], - { cancelable: false }, - ); - throw e; - } - }, - [onClosing, siweAuthCall], - ); - - const handleSIWE = React.useCallback( - async ({ message, signature }) => { - const extraInfo = await logInExtraInfo(); - - dispatchActionPromise( - siweAuthActionTypes, - callSIWE(message, signature, extraInfo), - undefined, - ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), - ); - }, - [logInExtraInfo, dispatchActionPromise, callSIWE], - ); const closeBottomSheet = bottomSheetRef.current?.close; - const { closing } = props; + const { closing, onSuccessfulWalletSignature } = props; const disableOnClose = React.useRef(false); const handleMessage = React.useCallback( async event => { @@ -162,7 +116,7 @@ if (address && signature) { disableOnClose.current = true; closeBottomSheet?.(); - await handleSIWE({ message, signature }); + await onSuccessfulWalletSignature({ address, message, signature }); } } else if (data.type === 'siwe_closed') { onClosing(); @@ -171,7 +125,7 @@ setWalletConnectModalOpen(data.state === 'open'); } }, - [handleSIWE, onClosing, closeBottomSheet], + [onSuccessfulWalletSignature, onClosing, closeBottomSheet], ); const prevClosingRef = React.useRef(); React.useEffect(() => {