Created
August 18, 2024 11:51
-
-
Save athallarizky/fb4612a614c7b47d195e11ca107d5c89 to your computer and use it in GitHub Desktop.
useWallet.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, { useCallback, useMemo, useEffect, useState } from 'react'; | |
| import { useAccount, useDisconnect, useSignMessage } from 'wagmi'; | |
| import useFetch from 'use-http'; | |
| // Zustand Store | |
| import { useStore, useWeb3AuthStore } from 'store'; | |
| // Helper | |
| import { encryptWallet } from 'utils/helper'; | |
| import { useToken } from './useHttp'; | |
| interface WalletContextObject { | |
| handleDisconnect: () => void; | |
| isFetchingAuth: boolean; | |
| signStatus: 'idle' | 'error' | 'loading' | 'success'; | |
| accountStatus: 'connecting' | 'reconnecting' | 'connected' | 'disconnected'; | |
| } | |
| type WalletProviderProps = { | |
| children?: React.ReactNode; | |
| }; | |
| export const WalletContext = React.createContext<WalletContextObject>({} as WalletContextObject); | |
| export const WalletProvider: React.FC<WalletProviderProps> = ({ children }) => { | |
| const { post: doLogin } = useFetch('/authorization/handheld/v2/login', { | |
| data: [], | |
| }); | |
| const { address, isConnected, status: accountStatus, isDisconnected } = useAccount(); | |
| const { disconnect } = useDisconnect(); | |
| const [isFetchingAuth, setIsFetchingAuth] = useState<boolean>(false); | |
| /** Zustand Store */ | |
| const { setWallet, setLoggedIn, setProfile, setWalletSignature, cleanStore, wallet } = useStore(); | |
| const { actions } = useWeb3AuthStore(); | |
| const signMessageText = ` | |
| Welcome to Kometh! | |
| Please sign this message to log in. | |
| This won't cost you any ETH. | |
| Your authentication status will reset after 24 hours. | |
| If you're connecting a hardware wallet, | |
| you'll need to sign the message on your device, too.`; | |
| const { | |
| data: signData, | |
| status: signStatus, | |
| signMessage, | |
| } = useSignMessage({ | |
| message: signMessageText, | |
| }); | |
| const { createToken } = useToken(); | |
| const revokeAccess = useCallback(() => { | |
| cleanStore(); | |
| disconnect(); | |
| setIsFetchingAuth(false); | |
| }, [address]); | |
| const isDifferentAccount = useMemo(() => { | |
| if (wallet && address) { | |
| return Boolean(address?.toLowerCase() !== wallet?.toLowerCase()); | |
| } | |
| return undefined; | |
| }, [address, wallet]); | |
| const fetchLogin = useCallback(async addressWallet => { | |
| setIsFetchingAuth(true); | |
| try { | |
| if (addressWallet) { | |
| const store = JSON.parse(localStorage.getItem('store')); | |
| const { state } = store; | |
| let currToken = state?.token; | |
| if (!state?.token) { | |
| currToken = await createToken(); | |
| } | |
| /** | |
| * encrypting wallet | |
| */ | |
| const encryptedWallet = await encryptWallet(currToken, addressWallet?.toLowerCase()); | |
| const response = await doLogin({ | |
| wallet_address: encryptedWallet, | |
| }); | |
| const { data } = response; | |
| if (data?.is_active) { | |
| setWallet(data?.wallet_address); | |
| setProfile(data); | |
| setLoggedIn(true); | |
| setIsFetchingAuth(false); | |
| signMessage(); | |
| } else { | |
| revokeAccess(); | |
| } | |
| } else { | |
| revokeAccess(); | |
| } | |
| } catch (error) { | |
| revokeAccess(); | |
| } | |
| }, []); | |
| const handleDisconnect = useCallback(() => { | |
| revokeAccess(); | |
| disconnect(); | |
| actions.clearUserInformationState(); | |
| // onClose(); | |
| }, [isDisconnected]); | |
| useEffect(() => { | |
| if (isConnected) { | |
| if (wallet) { | |
| if (isDifferentAccount) { | |
| fetchLogin(address); | |
| } | |
| } else { | |
| fetchLogin(address); | |
| } | |
| } | |
| }, [isConnected, address]); | |
| useEffect(() => { | |
| if (signStatus === 'success') { | |
| setWalletSignature(signData); | |
| const htmlTag = document.documentElement as HTMLElement; | |
| htmlTag.style.overflow = 'auto'; | |
| } else if (signStatus === 'error') { | |
| revokeAccess(); | |
| } | |
| }, [signStatus]); | |
| return ( | |
| <> | |
| <WalletContext.Provider | |
| value={{ | |
| handleDisconnect, | |
| isFetchingAuth, | |
| signStatus, | |
| accountStatus, | |
| }} | |
| > | |
| {children} | |
| </WalletContext.Provider> | |
| </> | |
| ); | |
| }; | |
| WalletProvider.defaultProps = { | |
| children: undefined, | |
| }; | |
| export const useWallet = () => { | |
| const { handleDisconnect, isFetchingAuth, signStatus, accountStatus } = React.useContext(WalletContext); | |
| return { | |
| handleDisconnect, | |
| isFetchingAuth, | |
| signStatus, | |
| accountStatus, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment