From 8ea863c86912c244db0c474856ba1ff9a6c639d7 Mon Sep 17 00:00:00 2001 From: Jennifer Echenim Date: Wed, 21 Aug 2024 23:14:24 +0400 Subject: [PATCH] - handle unknown account error - add loading state to wallet store --- .../src/components/modules/bridge/index.tsx | 28 ++++---- .../bridge-frontend/src/hooks/useContract.ts | 12 ++-- .../src/lib/utils/contractUtils.ts | 7 +- .../src/stores/wallet-store.ts | 70 ++++++++++++------- tools/bridge-frontend/src/types/index.ts | 1 + 5 files changed, 67 insertions(+), 51 deletions(-) diff --git a/tools/bridge-frontend/src/components/modules/bridge/index.tsx b/tools/bridge-frontend/src/components/modules/bridge/index.tsx index a2a0829238..89bcd0fc88 100644 --- a/tools/bridge-frontend/src/components/modules/bridge/index.tsx +++ b/tools/bridge-frontend/src/components/modules/bridge/index.tsx @@ -30,8 +30,14 @@ import { handleStorage } from "@/src/lib/utils/walletUtils"; import useWalletStore from "@/src/stores/wallet-store"; export default function Dashboard() { - const { provider, address, walletConnected, switchNetwork, isL1ToL2 } = - useWalletStore(); + const { + provider, + address, + walletConnected, + switchNetwork, + isL1ToL2, + loading, + } = useWalletStore(); const { getNativeBalance, getTokenBalance, sendERC20, sendNative } = useContract(); const intervalId = React.useRef(null); @@ -60,7 +66,6 @@ export default function Dashboard() { const [fromChain, toChain, token, receiver, amount] = textValues; const [fromTokenBalance, setFromTokenBalance] = React.useState(0); - const [loading, setLoading] = React.useState(false); const [open, setOpen] = React.useState(false); const onSubmit = React.useCallback( @@ -73,7 +78,6 @@ export default function Dashboard() { return; } try { - setLoading(true); const transactionData = { ...data, receiver: receiver || address }; toast({ title: "Bridge Transaction", @@ -111,8 +115,6 @@ export default function Dashboard() { }`, variant: ToastType.DESTRUCTIVE, }); - } finally { - setLoading(false); } }, // eslint-disable-next-line react-hooks/exhaustive-deps @@ -139,7 +141,6 @@ export default function Dashboard() { async (event: any) => { event.preventDefault(); try { - setLoading(true); switchNetwork(); } catch (error) { console.error("Network switch failed", error); @@ -150,8 +151,6 @@ export default function Dashboard() { }`, variant: ToastType.DESTRUCTIVE, }); - } finally { - setLoading(false); } }, [switchNetwork] @@ -167,7 +166,6 @@ export default function Dashboard() { const fetchTokenBalance = async () => { if (!token || !address) return; - setLoading(true); try { const selectedToken = tokens.find((t: IToken) => t.value === token); if (!selectedToken) return; @@ -179,8 +177,6 @@ export default function Dashboard() { setFromTokenBalance(balance); } catch (error) { console.error("Failed to fetch balance:", error); - } finally { - setLoading(false); } }; @@ -232,25 +228,25 @@ export default function Dashboard() { fromChains={fromChains} tokens={tokens} fromTokenBalance={fromTokenBalance} - loading={loading} + loading={loading || formState.isSubmitting} setAmount={setAmount} walletConnected={walletConnected} /> diff --git a/tools/bridge-frontend/src/hooks/useContract.ts b/tools/bridge-frontend/src/hooks/useContract.ts index f659c5d679..b698acf5b4 100644 --- a/tools/bridge-frontend/src/hooks/useContract.ts +++ b/tools/bridge-frontend/src/hooks/useContract.ts @@ -38,8 +38,11 @@ export const useContract = () => { ManagementContractAddress, } = memoizedConfig; - let prov = new ethers.providers.Web3Provider(provider); - const walletInstance = new ethers.Wallet(privateKey as string, prov); + let ethersProvider = new ethers.providers.Web3Provider(provider); + const walletInstance = new ethers.Wallet( + privateKey as string, + ethersProvider + ); const isL1 = isL1ToL2; const bridgeAddress = isL1 ? L1Bridge : L2Bridge; const messageBusAddress = isL1 ? MessageBusAddress : L2MessageBusAddress; @@ -193,11 +196,6 @@ export const useContract = () => { } if (!signer || !provider) { - toast({ - title: "Signer or provider not found", - description: "Confirm that your active account is connected", - variant: ToastType.DESTRUCTIVE, - }); return handleError(null, "Signer or provider not found"); } diff --git a/tools/bridge-frontend/src/lib/utils/contractUtils.ts b/tools/bridge-frontend/src/lib/utils/contractUtils.ts index 7170eb2590..355d392018 100644 --- a/tools/bridge-frontend/src/lib/utils/contractUtils.ts +++ b/tools/bridge-frontend/src/lib/utils/contractUtils.ts @@ -3,7 +3,12 @@ import { ethers } from "ethers"; const handleError = (error: any, customMessage: string) => { console.error(customMessage, error); - throw new Error(customMessage); + if (error?.message?.includes("unknown account")) { + throw new Error( + "Ensure your wallet is unlocked and an account is connected" + ); + } + throw new Error(error); }; const constructMerkleTree = (leafEntries: any[], msgHash: string) => { diff --git a/tools/bridge-frontend/src/stores/wallet-store.ts b/tools/bridge-frontend/src/stores/wallet-store.ts index 42e1efa195..fdc1d58818 100644 --- a/tools/bridge-frontend/src/stores/wallet-store.ts +++ b/tools/bridge-frontend/src/stores/wallet-store.ts @@ -10,7 +10,7 @@ import { initializeSigner, setupEventListeners, } from "@/src/lib/utils/walletEvents"; -import { currentNetwork } from "../lib/utils"; +import { currentNetwork } from "@/src/lib/utils"; const useWalletStore = create((set, get) => ({ provider: null, @@ -19,32 +19,43 @@ const useWalletStore = create((set, get) => ({ walletConnected: false, isL1ToL2: true, isWrongNetwork: false, + loading: true, initializeProvider: async () => { - const detectedProvider = await getEthereumProvider(); - const newSigner = initializeSigner(detectedProvider); - - //@ts-ignore - const chainId = await detectedProvider?.request({ - method: requestMethods.getChainId, - params: [], - }); - - const isL1 = chainId === currentNetwork.l1; - const expectedChainId = isL1 ? currentNetwork.l1 : currentNetwork.l2; - - set({ - provider: detectedProvider, - signer: newSigner, - isL1ToL2: isL1, - isWrongNetwork: chainId !== expectedChainId, - }); - - const cleanup = setupEventListeners(detectedProvider, (address: string) => { - set({ address }); - }); - - return cleanup; + try { + set({ loading: true }); + const detectedProvider = await getEthereumProvider(); + const newSigner = initializeSigner(detectedProvider); + + //@ts-ignore + const chainId = await detectedProvider?.request({ + method: requestMethods.getChainId, + params: [], + }); + + const isL1 = chainId === currentNetwork.l1; + const expectedChainId = isL1 ? currentNetwork.l1 : currentNetwork.l2; + + set({ + provider: detectedProvider, + signer: newSigner, + isL1ToL2: isL1, + isWrongNetwork: chainId !== expectedChainId, + }); + + const cleanup = setupEventListeners( + detectedProvider, + (address: string) => { + set({ address }); + } + ); + + return cleanup; + } catch (error) { + console.error("Error initializing provider:", error); + } finally { + set({ loading: false }); + } }, connectWallet: async () => { @@ -117,6 +128,7 @@ const useWalletStore = create((set, get) => ({ switchNetwork: async () => { const { provider, isL1ToL2 } = get(); + if (!provider) { toast({ title: "Error", @@ -126,6 +138,8 @@ const useWalletStore = create((set, get) => ({ return; } + set({ loading: true }); + const desiredNetwork = isL1ToL2 ? currentNetwork.l2 : currentNetwork.l1; try { @@ -146,8 +160,8 @@ const useWalletStore = create((set, get) => ({ console.error("Error switching network:", error); if (error.code === 4902) { toast({ - title: "Network Not Found", - description: "Network not found in wallet", + title: "Network not found", + description: error.message || "Network not found in wallet", variant: ToastType.INFO, }); } else { @@ -157,6 +171,8 @@ const useWalletStore = create((set, get) => ({ variant: ToastType.DESTRUCTIVE, }); } + } finally { + set({ loading: false }); } }, diff --git a/tools/bridge-frontend/src/types/index.ts b/tools/bridge-frontend/src/types/index.ts index a9b124584d..5034f34e7e 100644 --- a/tools/bridge-frontend/src/types/index.ts +++ b/tools/bridge-frontend/src/types/index.ts @@ -199,6 +199,7 @@ export interface IWalletState { walletConnected: boolean; isL1ToL2: boolean; isWrongNetwork: boolean; + loading: boolean; initializeProvider: () => void; connectWallet: () => void; disconnectWallet: () => void;