diff --git a/tools/walletextension/frontend/src/api/ethRequests.ts b/tools/walletextension/frontend/src/api/ethRequests.ts index 38e7d07347..b4f5f2eecc 100644 --- a/tools/walletextension/frontend/src/api/ethRequests.ts +++ b/tools/walletextension/frontend/src/api/ethRequests.ts @@ -48,8 +48,9 @@ export const switchToTenNetwork = async () => { }); return 0; - } catch (error: any) { - return error.code; + } catch (switchError: any) { + showToast(ToastType.DESTRUCTIVE, `switchToTenNetwork: ${switchError.code}`); + return switchError.code; } }; @@ -83,14 +84,9 @@ export const getSignature = async (account: string, data: any) => { }; export const getToken = async (provider: ethers.providers.Web3Provider) => { - if (!provider) { - showToast( - ToastType.DESTRUCTIVE, - "No provider found. Please try again later." - ); + if (!provider.send) { return null; } - try { if (await isTenChain()) { const token = await provider.send(requestMethods.getStorageAt, [ diff --git a/tools/walletextension/frontend/src/components/layouts/footer.tsx b/tools/walletextension/frontend/src/components/layouts/footer.tsx index 9f8caca5c5..035216c2a4 100644 --- a/tools/walletextension/frontend/src/components/layouts/footer.tsx +++ b/tools/walletextension/frontend/src/components/layouts/footer.tsx @@ -11,9 +11,9 @@ export default function Footer() { const { version } = useWalletConnection(); return ( -
-
-
+
+
+ -
+

Version: {version || "Unknown"}

diff --git a/tools/walletextension/frontend/src/components/modules/home/connected.tsx b/tools/walletextension/frontend/src/components/modules/home/connected.tsx index 1238595a92..e180ad1670 100644 --- a/tools/walletextension/frontend/src/components/modules/home/connected.tsx +++ b/tools/walletextension/frontend/src/components/modules/home/connected.tsx @@ -57,7 +57,7 @@ const Connected = () => { ) : ( accounts.map((account: Account, i: number) => ( - + diff --git a/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx b/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx index 2210b49183..352106394d 100644 --- a/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx +++ b/tools/walletextension/frontend/src/components/providers/wallet-provider.tsx @@ -5,7 +5,7 @@ import { Account, } from "../../types/interfaces/WalletInterfaces"; import { showToast } from "../ui/use-toast"; -import { ethereum } from "../../lib/utils"; +import { ethereum, isValidTokenFormat } from "../../lib/utils"; import { accountIsAuthenticated, fetchVersion, @@ -44,25 +44,23 @@ export const WalletConnectionProvider = ({ const [provider, setProvider] = useState({} as ethers.providers.Web3Provider); const initialize = async () => { + if (!provider) { + return showToast( + ToastType.INFO, + "Provider is required to initialize wallet connection." + ); + } + try { - if (!ethereum) { - showToast( - ToastType.DESTRUCTIVE, - "Please install Metamask to connect your wallet." - ); - return; - } - const providerInstance = new ethers.providers.Web3Provider(ethereum); - setProvider(providerInstance); - await ethService.checkIfMetamaskIsLoaded(providerInstance); + await ethService.checkIfMetamaskIsLoaded(provider); - const fetchedToken = await getToken(providerInstance); + const fetchedToken = await getToken(provider); setToken(fetchedToken); const status = await ethService.isUserConnectedToTenChain(fetchedToken); setWalletConnected(status); - const accounts = await ethService.getAccounts(providerInstance); + const accounts = await ethService.getAccounts(provider); setAccounts(accounts || null); setVersion(await fetchVersion()); } catch (error) { @@ -105,7 +103,7 @@ export const WalletConnectionProvider = ({ } else { showToast(ToastType.DESTRUCTIVE, "Account authentication failed."); } - } catch (error) { + } catch (error: any) { showToast(ToastType.DESTRUCTIVE, "Account authentication failed."); } }; @@ -135,26 +133,48 @@ export const WalletConnectionProvider = ({ ); return; } + const token = await getToken(provider); + + if (!isValidTokenFormat(token)) { + showToast( + ToastType.INFO, + "Invalid token format. Please refresh the page." + ); + setAccounts([]); + setWalletConnected(false); + return; + } + + setToken(token); try { const accounts = await ethService.getAccounts(provider); - const token = await getToken(provider); - setToken(token); let updatedAccounts: Account[] = []; - updatedAccounts = await Promise.all( - accounts!.map(async (account) => { - await ethService.authenticateWithGateway(token, account.name); - const { status } = await accountIsAuthenticated(token, account.name); - return { - ...account, - connected: status, - }; - }) + if (!accounts || accounts.length === 0) { + setAccounts([]); + } else { + updatedAccounts = await Promise.all( + accounts!.map(async (account) => { + await ethService.authenticateWithGateway(token, account.name); + const { status } = await accountIsAuthenticated( + token, + account.name + ); + return { + ...account, + connected: status, + }; + }) + ); + showToast(ToastType.INFO, "Accounts authenticated with gateway!"); + setAccounts(updatedAccounts); + } + } catch (error: any) { + showToast( + ToastType.DESTRUCTIVE, + `Error fetching user accounts: ${error?.message}` ); - setAccounts(updatedAccounts || null); - } catch (error) { - showToast(ToastType.DESTRUCTIVE, "Error fetching user accounts."); } finally { setWalletConnected(true); setLoading(false); @@ -162,8 +182,23 @@ export const WalletConnectionProvider = ({ }; useEffect(() => { - initialize(); - // eslint-disable-next-line react-hooks/exhaustive-deps + if (ethereum && ethereum.isMetaMask) { + const providerInstance = new ethers.providers.Web3Provider(ethereum); + setProvider(providerInstance); + initialize(); + + ethereum.on("accountsChanged", () => { + fetchUserAccounts(); + }); + } + + return () => { + if (ethereum && ethereum.removeListener) { + ethereum.removeListener("accountsChanged", () => { + fetchUserAccounts(); + }); + } + }; }, []); const walletConnectionContextValue: WalletConnectionContextType = { diff --git a/tools/walletextension/frontend/src/services/ethService.ts b/tools/walletextension/frontend/src/services/ethService.ts index 32127a0fd6..e5a8bcebe6 100644 --- a/tools/walletextension/frontend/src/services/ethService.ts +++ b/tools/walletextension/frontend/src/services/ethService.ts @@ -96,7 +96,7 @@ const ethService = { }) ); updatedAccounts = await Promise.all(authenticationPromise); - showToast(ToastType.SUCCESS, "Account authentication status updated!"); + showToast(ToastType.INFO, "Account authentication status updated!"); return updatedAccounts; }, @@ -135,6 +135,7 @@ const ethService = { } catch (error) { console.error(error); showToast(ToastType.DESTRUCTIVE, "An error occurred. Please try again."); + throw error; } }, diff --git a/tools/walletextension/frontend/src/services/useGatewayService.ts b/tools/walletextension/frontend/src/services/useGatewayService.ts index 3eb5fa355f..474b5283b0 100644 --- a/tools/walletextension/frontend/src/services/useGatewayService.ts +++ b/tools/walletextension/frontend/src/services/useGatewayService.ts @@ -2,11 +2,16 @@ import { ToastType } from "@/types/interfaces"; import { joinTestnet } from "../api/gateway"; import { useWalletConnection } from "../components/providers/wallet-provider"; import { showToast } from "../components/ui/use-toast"; -import {SWITCHED_CODE, tenGatewayAddress, tenGatewayVersion} from "../lib/constants"; +import { + SWITCHED_CODE, + tenGatewayAddress, + tenGatewayVersion, +} from "../lib/constants"; import { isTenChain, isValidTokenFormat } from "../lib/utils"; import { addNetworkToMetaMask, connectAccounts, + getToken, switchToTenNetwork, } from "@/api/ethRequests"; @@ -28,37 +33,43 @@ const useGatewayService = () => { }; const connectToTenTestnet = async () => { + showToast(ToastType.INFO, "Connecting to Obscuro Testnet..."); setLoading(true); try { if (await isTenChain()) { if (!token || !isValidTokenFormat(token)) { showToast( ToastType.DESTRUCTIVE, - "Existing Ten network detected in MetaMask. Please remove before hitting begin" + "Existing Obscuro Testnet detected in MetaMask. Please remove before hitting begin" ); return; } } - + showToast(ToastType.INFO, "Switching to Obscuro Testnet..."); const switched = await switchToTenNetwork(); - - if (switched === SWITCHED_CODE || (token && !isValidTokenFormat(token))) { + showToast(ToastType.SUCCESS, `Switched to Obscuro Testnet: ${switched}`); + // SWITCHED_CODE=4902; error 4902 means that the chain does not exist + if ( + switched === SWITCHED_CODE || + !isValidTokenFormat(await getToken(provider)) + ) { + showToast(ToastType.INFO, "Adding Obscuro Testnet..."); const user = await joinTestnet(); const rpcUrls = [ `${tenGatewayAddress}/${tenGatewayVersion}/?token=${user}`, ]; await addNetworkToMetaMask(rpcUrls); + showToast(ToastType.SUCCESS, "Added Obscuro Testnet"); } if (!(await isMetamaskConnected())) { showToast(ToastType.INFO, "No accounts found, connecting..."); await connectAccounts(); - showToast(ToastType.SUCCESS, "Connected to Ten Network"); + showToast(ToastType.SUCCESS, "Connected to Obscuro Testnet"); } - await fetchUserAccounts(); } catch (error: any) { - showToast(ToastType.DESTRUCTIVE, `${error}`); + showToast(ToastType.DESTRUCTIVE, `${error?.message}`); throw error; } finally { setLoading(false);