UNPKG

@sky-mavis/tanto-widget

Version:
105 lines 3.73 kB
import {jsx}from'@emotion/react/jsx-runtime';import {useMutation}from'@tanstack/react-query';import {useState,useRef,useCallback,useMemo}from'react';import {v4}from'uuid';import {useAccount,useSignMessage,useDisconnect}from'wagmi';import {useAccountSwitch}from'../../hooks/useAccountSwitch.mjs';import {authEventEmitter}from'../../hooks/useAuthEffect.mjs';import {mutation}from'../../services/queries.mjs';import {delay}from'../../utils/common.mjs';import {TantoWidgetError,TantoWidgetErrorCodes}from'../../utils/errors.mjs';import {generateSiweMessage}from'../../utils/siwe.mjs';import {isWCConnector,isWaypointConnector}from'../../utils/walletDetection.mjs';import {useTantoConfig}from'../tanto/useTantoConfig.mjs';import {AuthContext}from'./AuthContext.mjs';import {useWaypointMessageHandler}from'./useWaypointMessageHandler.mjs';function AuthProvider({ children }) { const { createAccountOnConnect: enableAuth = false, clientId, __internal_baseUrl } = useTantoConfig(); const { address, chainId, connector } = useAccount(); const { signMessageAsync } = useSignMessage(); const { disconnect } = useDisconnect(); const [isSigningIn, setIsSigningIn] = useState(false); const [error, setError] = useState(null); const currentSignInRef = useRef(null); const { mutateAsync: generateNonce } = useMutation(mutation.generateNonce()); const { mutateAsync: createAccount } = useMutation(mutation.createAccount()); const reset = useCallback(() => { setIsSigningIn(false); setError(null); currentSignInRef.current = null; }, []); const signIn = useCallback(async () => { if (!enableAuth || !address || !chainId || isSigningIn) return; const sessionId = v4(); currentSignInRef.current = sessionId; setIsSigningIn(true); setError(null); try { // Wait for WC (in case of connect to metamask) switch chain if (isWCConnector(connector?.id)) await delay(1_000); if (isWaypointConnector(connector?.id)) return; const { nonce, expirationTime, issuedAt, notBefore } = await generateNonce({ baseUrl: __internal_baseUrl, address, clientId }); const message = generateSiweMessage({ address, chainId, nonce, expirationTime, issuedAt, notBefore }); const signature = await signMessageAsync({ message }); if (currentSignInRef.current !== sessionId) return; const { idToken } = await createAccount({ baseUrl: __internal_baseUrl, message, signature, clientId }); authEventEmitter.emit('success', { address, chainId, token: idToken }); } catch (error) { if (currentSignInRef.current !== sessionId) return; const authError = error instanceof Error ? error : new TantoWidgetError(TantoWidgetErrorCodes.CREATE_ACCOUNT_FAILED, 'Failed to create account'); console.debug('Auth error:', authError); setError(authError); authEventEmitter.emit('failed', { error: authError }); disconnect(); } finally { setIsSigningIn(false); } }, [enableAuth, address, chainId, isSigningIn, connector?.id, generateNonce, signMessageAsync, createAccount, clientId, disconnect]); useAccountSwitch(signIn); useWaypointMessageHandler(enableAuth); const contextValue = useMemo(() => ({ enable: enableAuth, error, isSigningIn, signIn, reset }), [enableAuth, error, isSigningIn, signIn, reset]); return jsx(AuthContext.Provider, { value: contextValue, children: children }); }export{AuthProvider};