diff --git a/contracts/src/bridge/frontend/src/components/modules/bridge/index.tsx b/contracts/src/bridge/frontend/src/components/modules/bridge/index.tsx index 6fb15af949..a1c75f3d68 100644 --- a/contracts/src/bridge/frontend/src/components/modules/bridge/index.tsx +++ b/contracts/src/bridge/frontend/src/components/modules/bridge/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React from "react"; import { CardHeader, CardTitle, @@ -58,6 +58,13 @@ export default function Dashboard() { const onSubmit = React.useCallback( async (data: any) => { + if (amount > fromTokenBalance) { + setError("amount", { + type: "manual", + message: "Amount must be less than balance", + }); + return; + } try { setLoading(true); const transactionData = { ...data, receiver: receiver || address }; @@ -143,10 +150,8 @@ export default function Dashboard() { React.useEffect(() => { const storedReceiver = handleStorage.get("tenBridgeReceiver"); - if (storedReceiver) { - setValue("receiver", storedReceiver); - } - }, []); + setValue("receiver", storedReceiver ? storedReceiver : address); + }, [address]); React.useEffect(() => { const fetchTokenBalance = async (token: Token) => { @@ -169,7 +174,13 @@ export default function Dashboard() { fetchTokenBalance(selectedToken); } } - }, [fromChain, token, amount, receiver, provider, isL1ToL2]); + }, [fromChain, token, amount, receiver, provider, isL1ToL2, walletConnected]); + + React.useEffect(() => { + setValue("fromChain", isL1ToL2 ? L1CHAINS[0].value : L2CHAINS[0].value); + setValue("toChain", isL1ToL2 ? L2CHAINS[0].value : L1CHAINS[0].value); + setValue("token", isL1ToL2 ? L1TOKENS[0].value : L2TOKENS[0].value); + }, [isL1ToL2]); return (
diff --git a/contracts/src/bridge/frontend/src/components/providers/wallet-provider.tsx b/contracts/src/bridge/frontend/src/components/providers/wallet-provider.tsx index fb1a8d45be..16d9118ede 100644 --- a/contracts/src/bridge/frontend/src/components/providers/wallet-provider.tsx +++ b/contracts/src/bridge/frontend/src/components/providers/wallet-provider.tsx @@ -25,50 +25,37 @@ const WalletProvider = ({ children }: WalletConnectionProviderProps) => { const [address, setAddress] = useState(""); const [isL1ToL2, setIsL1ToL2] = useState(true); - useEffect(() => { - const storedAddress = handleStorage.get("walletAddress"); - const storedIsL1ToL2 = handleStorage.get("isL1ToL2") === "true"; - - if (storedAddress) { - setAddress(storedAddress); - setIsWalletConnected(true); - setIsL1ToL2(storedIsL1ToL2); - } + const initializeProvider = async () => { + const detectedProvider = await getEthereumProvider(); + setProvider(detectedProvider); - const initializeProvider = async () => { - const detectedProvider = await getEthereumProvider(); - setProvider(detectedProvider); + const newSigner = initializeSigner(provider); + setSigner(newSigner); - const chainId = await detectedProvider.request({ - method: requestMethods.getChainId, - }); - - const isL1 = chainId === WalletNetwork.L1_SEPOLIA; - setIsL1ToL2(isL1); - }; + const chainId = await detectedProvider.send(requestMethods.getChainId, []); - initializeProvider(); - }, []); + const isL1 = chainId === WalletNetwork.L1_SEPOLIA; + setIsL1ToL2(isL1); + }; const connectWallet = async () => { try { const detectedProvider = await getEthereumProvider(); setProvider(detectedProvider); - const chainId = await detectedProvider.request({ - method: requestMethods.getChainId, - }); + const accounts = await detectedProvider.send( + requestMethods.connectAccounts, + [] + ); - const isL1 = chainId === WalletNetwork.L1_SEPOLIA; - setIsL1ToL2(isL1); + const newSigner = initializeSigner(detectedProvider); + setSigner(newSigner); - const accounts = await detectedProvider.request({ - method: requestMethods.connectAccounts, - }); setIsWalletConnected(true); setAddress(accounts[0]); handleStorage.save("walletAddress", accounts[0]); - handleStorage.save("isL1ToL2", isL1.toString()); + handleStorage.save("isL1ToL2", isL1ToL2.toString()); + toast({ title: "Connected", description: "Connected to wallet! Account: " + accounts[0], @@ -94,6 +81,9 @@ const WalletProvider = ({ children }: WalletConnectionProviderProps) => { setIsWalletConnected(false); handleStorage.remove("walletAddress"); handleStorage.remove("isL1ToL2"); + handleStorage.remove("tenBridgeReceiver"); + window.location.reload(); + toast({ title: "Disconnected", description: "Disconnected from wallet", @@ -111,14 +101,17 @@ const WalletProvider = ({ children }: WalletConnectionProviderProps) => { }; useEffect(() => { - if (provider) { - const newSigner = initializeSigner(provider); - setSigner(newSigner); + const storedAddress = handleStorage.get("walletAddress"); + const storedIsL1ToL2 = handleStorage.get("isL1ToL2") === "true"; - const cleanup = setupEventListeners(provider, setAddress); - return cleanup; + if (storedAddress) { + setAddress(storedAddress); + setIsWalletConnected(true); + setIsL1ToL2(storedIsL1ToL2); } - }, [provider]); + + initializeProvider(); + }, []); const switchNetwork = async () => { if (!provider) { @@ -133,13 +126,15 @@ const WalletProvider = ({ children }: WalletConnectionProviderProps) => { const desiredNetwork = isL1ToL2 ? WalletNetwork.L2_TEN_TESTNET : WalletNetwork.L1_SEPOLIA; - await provider.request({ - method: requestMethods.switchNetwork, - params: [{ chainId: desiredNetwork }], - }); + + await provider.request(requestMethods.switchNetwork, [ + { chainId: desiredNetwork }, + ]); + const isL1 = desiredNetwork === WalletNetwork.L1_SEPOLIA; setIsL1ToL2(isL1); handleStorage.save("isL1ToL2", isL1.toString()); + toast({ title: "Network Switched", description: `Switched to ${ @@ -167,6 +162,16 @@ const WalletProvider = ({ children }: WalletConnectionProviderProps) => { } }; + useEffect(() => { + if (provider) { + const newSigner = initializeSigner(provider); + setSigner(newSigner); + + const cleanup = setupEventListeners(provider, setAddress); + return cleanup; + } + }, [provider]); + const value = { provider, signer, diff --git a/contracts/src/bridge/frontend/src/hooks/useContract.ts b/contracts/src/bridge/frontend/src/hooks/useContract.ts index 87b65a0f26..5276d92ade 100644 --- a/contracts/src/bridge/frontend/src/hooks/useContract.ts +++ b/contracts/src/bridge/frontend/src/hooks/useContract.ts @@ -4,7 +4,7 @@ import Bridge from "../../artifacts/IBridge.sol/IBridge.json"; import ManagementContractAbi from "../../artifacts/ManagementContract.sol/ManagementContract.json"; import IMessageBusAbi from "../../artifacts/IMessageBus.sol/IMessageBus.json"; import { useWalletStore } from "../components/providers/wallet-provider"; -import { showToast, toast } from "../components/ui/use-toast"; +import { toast } from "../components/ui/use-toast"; import { ContractState, ToastType } from "../types"; import { useGeneralService } from "../services/useGeneralService"; import { StandardMerkleTree } from "@openzeppelin/merkle-tree"; @@ -26,64 +26,56 @@ export const useContract = () => { }, [obscuroConfig, isObscuroConfigLoading]); useEffect(() => { - if (isObscuroConfigLoading) { - return; - } - if (!obscuroConfig) { - showToast(ToastType.DESTRUCTIVE, "Config not found"); - return; - } + const setupContracts = async () => { + if (!memoizedConfig || !provider || !signer) { + return; + } - if (!memoizedConfig) { - showToast(ToastType.DESTRUCTIVE, "Config not found"); - return; - } + const l1BridgeAddress = memoizedConfig.ImportantContracts.L1Bridge; + const l2BridgeAddress = memoizedConfig.ImportantContracts.L2Bridge; + const l1MessageBusAddress = memoizedConfig.MessageBusAddress; + const l2MessageBusAddress = memoizedConfig.L2MessageBusAddress; + const managementContractAddress = + memoizedConfig.ManagementContractAddress; + + const wallet = new ethers.Wallet(privateKey as string, provider); + + const address = isL1ToL2 ? l1BridgeAddress : l2BridgeAddress; + const messageBusAddress = isL1ToL2 + ? l1MessageBusAddress + : l2MessageBusAddress; + + const bridgeContract = new ethers.Contract(address, Bridge.abi, wallet); + const messageBusContract = new ethers.Contract( + messageBusAddress, + IMessageBusAbi, + wallet + ); + const managementContract = new ethers.Contract( + managementContractAddress, + ManagementContractAbi, + wallet + ); - const l1BridgeAddress = memoizedConfig.ImportantContracts.L1Bridge; - const l2BridgeAddress = memoizedConfig.ImportantContracts.L2Bridge; - const l1MessageBusAddress = memoizedConfig.MessageBusAddress; - const l2MessageBusAddress = memoizedConfig.L2MessageBusAddress; - const managementContractAddress = memoizedConfig.ManagementContractAddress; + setContractState({ + bridgeContract, + managementContract, + messageBusContract, + wallet, + messageBusAddress, + }); + }; - if (!provider) { - showToast(ToastType.DESTRUCTIVE, "Provider not found"); - return; - } - const p = new ethers.providers.Web3Provider(provider); - const wallet = new ethers.Wallet(privateKey as string, p); - const address = isL1ToL2 ? l1BridgeAddress : l2BridgeAddress; - const messageBusAddress = isL1ToL2 - ? l1MessageBusAddress - : l2MessageBusAddress; - const bridgeContract = new ethers.Contract( - address as string, - Bridge.abi, - wallet - ); - const messageBusContract = new ethers.Contract( - messageBusAddress as string, - IMessageBusAbi, - wallet - ); - const managementContract = new ethers.Contract( - managementContractAddress as string, - ManagementContractAbi, - wallet - ); - setContractState({ - bridgeContract, - managementContract, - messageBusContract, - wallet, - messageBusAddress, - }); - }, [isObscuroConfigLoading, memoizedConfig, provider, isL1ToL2]); + setupContracts(); + }, [memoizedConfig, provider, isL1ToL2, signer]); const sendNative = async (receiver: string, value: string) => { const { bridgeContract, managementContract, messageBusContract, wallet } = contractState; if (!bridgeContract || !signer || !wallet || !managementContract) { + console.error("Contract or signer not found"); + console.log("🚀 ~ sendNative ~ signer", signer, provider); throw new Error("Contract or signer not found"); } @@ -308,8 +300,7 @@ export const useContract = () => { } try { - const p = new ethers.providers.Web3Provider(provider); - const balance = await p.getBalance(walletAddress); + const balance = await provider.getBalance(walletAddress); return ethers.utils.formatEther(balance); } catch (error) { console.error("Error checking Ether balance:", error); @@ -328,14 +319,13 @@ export const useContract = () => { } try { - const p = new ethers.providers.Web3Provider(provider); const tokenContract = new ethers.Contract( tokenAddress, [ "function balanceOf(address owner) view returns (uint256)", "function decimals() view returns (uint8)", ], - p + provider ); const balance = await tokenContract.balanceOf(walletAddress); @@ -356,8 +346,6 @@ export const useContract = () => { } try { - const p = new ethers.providers.Web3Provider(provider); - const topics = [ ethers.utils.id("ValueTransfer(address,address,uint256)"), ethers.utils.hexZeroPad(userAddress, 32), @@ -369,7 +357,7 @@ export const useContract = () => { fromBlock: 5868682, }; - return await p.getLogs(filter); + return await provider.getLogs(filter); } catch (error) { console.error("Error fetching transactions:", error); throw error; diff --git a/contracts/src/bridge/frontend/src/lib/utils/walletEvents.ts b/contracts/src/bridge/frontend/src/lib/utils/walletEvents.ts index a4d810117f..28d4b4fa3c 100644 --- a/contracts/src/bridge/frontend/src/lib/utils/walletEvents.ts +++ b/contracts/src/bridge/frontend/src/lib/utils/walletEvents.ts @@ -1,4 +1,4 @@ -import { ethers } from "ethers"; +import { ethereum } from "."; export const setupEventListeners = ( provider: any, @@ -23,5 +23,9 @@ export const setupEventListeners = ( }; export const initializeSigner = (provider: any) => { - return new ethers.providers.Web3Provider(provider).getSigner(); + if (!provider) { + return null; + } + + return provider.getSigner(); }; diff --git a/contracts/src/bridge/frontend/src/lib/utils/walletUtils.ts b/contracts/src/bridge/frontend/src/lib/utils/walletUtils.ts index 19f45ade28..2aaf14a95c 100644 --- a/contracts/src/bridge/frontend/src/lib/utils/walletUtils.ts +++ b/contracts/src/bridge/frontend/src/lib/utils/walletUtils.ts @@ -1,8 +1,9 @@ import detectEthereumProvider from "@metamask/detect-provider"; import { ethers } from "ethers"; +import { ethereum } from "."; export const getEthereumProvider = async () => { - const provider = await detectEthereumProvider(); + const provider = new ethers.providers.Web3Provider(ethereum); if (!provider) { throw new Error("No Ethereum provider detected"); }