diff --git a/src/ui/hooks/useWeb3.ts b/src/ui/hooks/useWeb3.ts index c9ff12e7..98a978d4 100644 --- a/src/ui/hooks/useWeb3.ts +++ b/src/ui/hooks/useWeb3.ts @@ -1,16 +1,17 @@ -import { useEffect } from 'react'; +import { useMemo } from 'react'; +import Web3 from 'web3'; + +import { EVM_ENDPOINT } from '@/constant'; import { useNetworkStore } from '../stores/networkStore'; -import { useProviderStore } from '../stores/providerStore'; export const useWeb3 = () => { - const { currentNetwork: network } = useNetworkStore(); - - const providerStore = useProviderStore(); - - useEffect(() => { - providerStore.setWeb3Instance(network); - }, [network, providerStore]); + const { currentNetwork } = useNetworkStore(); + const network = currentNetwork || 'mainnet'; + const web3instance = useMemo(() => { + const provider = new Web3.providers.HttpProvider(EVM_ENDPOINT[network]); + return new Web3(provider); + }, [network]); - return providerStore.web3Instance; + return web3instance; }; diff --git a/src/ui/views/Send/SendToEVM/EvmToEvmConfirmation.tsx b/src/ui/views/Send/SendToEVM/EvmToEvmConfirmation.tsx index dc9b819b..d6698a17 100644 --- a/src/ui/views/Send/SendToEVM/EvmToEvmConfirmation.tsx +++ b/src/ui/views/Send/SendToEVM/EvmToEvmConfirmation.tsx @@ -6,7 +6,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import { type TransactionState } from '@/shared/types/transaction-types'; -import { ensureEvmAddressPrefix } from '@/shared/utils/address'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; @@ -24,6 +24,7 @@ interface EvmConfirmationProps { handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } +const returnNothing = { doit: true }; const EvmToEvmConfirmation = ({ transactionState, @@ -48,7 +49,11 @@ const EvmToEvmConfirmation = ({ const web3Instance = useWeb3(); useEffect(() => { - if (isConfirmationOpen && web3Instance) { + if ( + isConfirmationOpen && + web3Instance && + isValidEthereumAddress(transactionState.selectedToken?.address) + ) { const contractInstance = new web3Instance.eth.Contract( erc20ABI, transactionState.selectedToken.address @@ -82,7 +87,7 @@ const EvmToEvmConfirmation = ({ const startCount = useCallback(() => { let count = 0; let intervalId; - if (transactionState.toAddress) { + if (isConfirmationOpen && transactionState.toAddress) { intervalId = setInterval(function () { count++; if (count === 7) { @@ -90,10 +95,10 @@ const EvmToEvmConfirmation = ({ } setCount(count); }, 500); - } else if (!transactionState.toAddress) { + } else if (!isConfirmationOpen || !transactionState.toAddress) { clearInterval(intervalId); } - }, [transactionState.toAddress]); + }, [transactionState.toAddress, isConfirmationOpen]); const getPending = useCallback(async () => { const pending = await wallet.getPendingTx(); @@ -126,7 +131,7 @@ const EvmToEvmConfirmation = ({ let address, gas, value, data; - if (transactionState.coinInfo.unit.toLowerCase() === 'flow') { + if (transactionState.selectedToken.symbol.toLowerCase() === 'flow') { address = transactionState.toAddress; gas = '1'; // const amountBN = new BN(transactionState.amount).multipliedBy(new BN(10).pow(18)); @@ -164,21 +169,7 @@ const EvmToEvmConfirmation = ({ setFailed(true); setErrorMessage(err.message); } - }, [ - transactionState.amount, - transactionState.selectedToken.decimals, - transactionState.selectedToken.address, - transactionState.selectedToken.symbol, - transactionState.coinInfo.unit, - transactionState.coinInfo.coin, - transactionState.coinInfo.icon, - transactionState.toAddress, - transactionState.toContact, - erc20Contract?.methods, - wallet, - handleCloseIconClicked, - history, - ]); + }, [transactionState, erc20Contract, wallet, handleCloseIconClicked, history]); const transferTokens = useCallback(async () => { try { @@ -229,212 +220,224 @@ const EvmToEvmConfirmation = ({ } }, [transactionState]); - const renderContent = () => ( - - + - - - {tid ? ( - - - {chrome.i18n.getMessage('Transaction_created')} - - - ) : ( - - {!sending - ? chrome.i18n.getMessage('Confirmation') - : chrome.i18n.getMessage('Processing')} - - )} - - - - - - - - - - {colorArray.map((color, index) => ( - - {count === index ? ( - - ) : ( + + + + {tid ? ( + sx={{ + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + alignItems: 'center', + }} + > + + {chrome.i18n.getMessage('Transaction_created')} + + + ) : ( + + {!sending + ? chrome.i18n.getMessage('Confirmation') + : chrome.i18n.getMessage('Processing')} + )} + + + + + + + + + + + {colorArray.map((color, index) => ( + + {count === index ? ( + + ) : ( + + )} + + ))} - ))} - - - + + - - - - - {transactionState.coinInfo.coin} - - - - {transactionState.amount} {transactionState.coinInfo.unit} - - - - - $ {transactionState.fiatAmount} - - - - - - - - {/* */} - - - {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} - - - - - - - ); + + + + $ {transactionState.fiatAmount} + + + - return ( - isConfirmationOpen && ( - <> - + + + {/* */} + + + {chrome.i18n.getMessage('Your_address_is_currently_processing_another_transaction')} + + + + + + + + setErrorCode(null)} /> + ); }; diff --git a/src/ui/views/Send/SendToEVM/FlowToEVMConfirmation.tsx b/src/ui/views/Send/SendToEVM/FlowToEVMConfirmation.tsx index 5390f7cd..6701512e 100644 --- a/src/ui/views/Send/SendToEVM/FlowToEVMConfirmation.tsx +++ b/src/ui/views/Send/SendToEVM/FlowToEVMConfirmation.tsx @@ -5,24 +5,30 @@ import BN from 'bignumber.js'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { type TransactionState } from '@/shared/types/transaction-types'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; -import { useTransactionStore } from '@/ui/stores/transactionStore'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import IconNext from 'ui/FRWAssets/svg/next.svg'; -import { LLSpinner, LLProfile, FRWProfile, FRWTargetProfile } from 'ui/FRWComponent'; -import { useWallet } from 'ui/utils'; +import { LLSpinner, LLProfile, FRWTargetProfile } from 'ui/FRWComponent'; +import { stripFinalAmount, useWallet } from 'ui/utils'; interface ToEthConfirmationProps { isConfirmationOpen: boolean; - data: any; + transactionState: TransactionState; handleCloseIconClicked: () => void; handleCancelBtnClicked: () => void; handleAddBtnClicked: () => void; } -const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { +const FlowToEVMConfirmation = ({ + transactionState, + isConfirmationOpen, + handleCloseIconClicked, + handleCancelBtnClicked, + handleAddBtnClicked, +}: ToEthConfirmationProps) => { const wallet = useWallet(); const history = useHistory(); const [sending, setSending] = useState(false); @@ -35,7 +41,7 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { const [count, setCount] = useState(0); const { sufficient: isSufficient, sufficientAfterAction } = useStorageCheck({ transferAmount: 0, - coin: props.data?.coinInfo?.coin, + coin: transactionState?.coinInfo?.coin, // the transfer is within the EVM network, the flag should be false movingBetweenEVMAndFlow: false, }); @@ -56,7 +62,7 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { const startCount = useCallback(() => { let count = 0; let intervalId; - if (props.data.contact.address) { + if (transactionState.toAddress) { intervalId = setInterval(function () { count++; if (count === 7) { @@ -64,10 +70,10 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { } setCount(count); }, 500); - } else if (!props.data.contact.address) { + } else if (!transactionState.toAddress) { clearInterval(intervalId); } - }, [props?.data?.contact?.address]); + }, [transactionState.toAddress]); const getPending = useCallback(async () => { const pending = await wallet.getPendingTx(); @@ -81,20 +87,22 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { }, []); const transferFlowFromCadenceToEvm = useCallback(async () => { - const amount = new BN(props.data.amount).decimalPlaces(8, BN.ROUND_DOWN).toString(); - + const amount = new BN(transactionState.amount).decimalPlaces(8, BN.ROUND_DOWN).toString(); + if (stripFinalAmount(amount, 8) !== stripFinalAmount(transactionState.amount, 8)) { + throw new Error('Amount entered does not match required precision'); + } wallet - .transferFlowEvm(props.data.contact.address, amount) + .transferFlowEvm(transactionState.toAddress, amount) .then(async (txId) => { - await wallet.setRecent(props.data.contact); + await wallet.setRecent(transactionState.toContact); wallet.listenTransaction( txId, true, - `${props.data.amount} ${props.data.coinInfo.coin} Sent`, - `You have sent ${props.data.amount} ${props.data.tokenSymbol} to ${props.data.contact.contact_name}. \nClick to view this transaction.`, - props.data.coinInfo.icon + `${transactionState.amount} ${transactionState.coinInfo.coin} Sent`, + `You have sent ${transactionState.amount} ${transactionState.selectedToken?.symbol} to ${transactionState.toContact?.contact_name}. \nClick to view this transaction.`, + transactionState.coinInfo.icon ); - props.handleCloseIconClicked(); + handleCloseIconClicked(); await wallet.setDashIndex(0); setSending(false); setTid(txId); @@ -105,33 +113,35 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { setFailed(true); }); // Depending on history is probably not great - }, [history, props, wallet]); + }, [history, transactionState, wallet, handleCloseIconClicked]); const transferFTFromCadenceToEvm = useCallback(async () => { setSending(true); - const value = new BN(props.data.amount).decimalPlaces(8, BN.ROUND_DOWN).toString(); - - const address = props.data.selectedToken!.address.startsWith('0x') - ? props.data.selectedToken!.address.slice(2) - : props.data.selectedToken!.address; + const amount = new BN(transactionState.amount).decimalPlaces(8, BN.ROUND_DOWN).toString(); + if (stripFinalAmount(amount, 8) !== stripFinalAmount(transactionState.amount, 8)) { + throw new Error('Amount entered does not match required precision'); + } + const address = transactionState.selectedToken!.address.startsWith('0x') + ? transactionState.selectedToken!.address.slice(2) + : transactionState.selectedToken!.address; wallet .transferFTToEvmV2( - `A.${address}.${props.data.selectedToken!.contractName}.Vault`, - value, - props.data.contact.address + `A.${address}.${transactionState.selectedToken!.contractName}.Vault`, + amount, + transactionState.toAddress ) .then(async (txId) => { - await wallet.setRecent(props.data.contact); + await wallet.setRecent(transactionState.toContact); wallet.listenTransaction( txId, true, - `${props.data.amount} ${props.data.coinInfo.coin} Sent`, - `You have sent ${props.data.amount} ${props.data.tokenSymbol} to ${props.data.contact.contact_name}. \nClick to view this transaction.`, - props.data.coinInfo.icon + `${transactionState.amount} ${transactionState.coinInfo.coin} Sent`, + `You have sent ${transactionState.amount} ${transactionState.selectedToken?.symbol} to ${transactionState.toContact?.contact_name}. \nClick to view this transaction.`, + transactionState.coinInfo.icon ); - props.handleCloseIconClicked(); + handleCloseIconClicked(); await wallet.setDashIndex(0); setSending(false); setTid(txId); @@ -143,12 +153,22 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { setFailed(true); }); // Depending on history is probably not great - }, [history, props, wallet]); + }, [ + handleCloseIconClicked, + history, + transactionState.amount, + transactionState.coinInfo.coin, + transactionState.coinInfo.icon, + transactionState.selectedToken, + transactionState.toAddress, + transactionState.toContact, + wallet, + ]); const transferTokens = useCallback(async () => { try { setSending(true); - switch (props.data.currentTxState) { + switch (transactionState.currentTxState) { case 'FlowFromCadenceToEvm': await transferFlowFromCadenceToEvm(); break; @@ -156,13 +176,13 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { await transferFTFromCadenceToEvm(); break; default: - throw new Error(`Unsupported transaction state: ${props.data.currentTxState}`); + throw new Error(`Unsupported transaction state: ${transactionState.currentTxState}`); } } catch (error) { console.error('Transaction failed:', error); setFailed(true); } - }, [transferFlowFromCadenceToEvm, transferFTFromCadenceToEvm, props.data.currentTxState]); + }, [transferFlowFromCadenceToEvm, transferFTFromCadenceToEvm, transactionState.currentTxState]); const transactionDoneHandler = useCallback( (request) => { @@ -232,7 +252,7 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { )} - + @@ -240,10 +260,10 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { - {props.data.childType && props.data.childType !== 'evm' ? ( - + {transactionState.fromNetwork === 'Evm' ? ( + ) : ( - + )} { ))} - + { }} > - + {transactionState.coinInfo.icon && ( + + )} - {props.data.coinInfo.coin} + {transactionState.coinInfo.coin} - {props.data.amount} {props.data.coinInfo.unit} + {transactionState.amount} {transactionState.coinInfo.unit} @@ -301,7 +326,7 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { color="info" sx={{ fontSize: '14px', fontWeight: 'semi-bold', textAlign: 'end' }} > - $ {props.data.secondAmount} + $ {transactionState.fiatAmount} @@ -375,7 +400,7 @@ const FlowToEVMConfirmation = (props: ToEthConfirmationProps) => { <> void; handleMaxClick: () => void; }) => { - console.log('SendEth '); const history = useHistory(); const wallet = useWallet(); const { currentNetwork: network } = useNetworkStore(); const [isConfirmationOpen, setConfirmationOpen] = useState(false); const [validated, setValidated] = useState(null); - // TODO: move this to some store - const web3Instance = useMemo(() => { - const provider = new Web3.providers.HttpProvider(EVM_ENDPOINT[network]); - return new Web3(provider); - }, [network]); - - const [erc20Contract, setErc20Contract] = useState(null); - - const updateContractInfo = useCallback( - async (address: string, symbol: string) => { - // Update the contract instance - let contractAddress = '0x7cd84a6b988859202cbb3e92830fff28813b9341'; - if (symbol.toLowerCase() !== 'flow') { - contractAddress = address; - } - const contractInstance = new web3Instance.eth.Contract(erc20ABI, contractAddress); - - setErc20Contract(contractInstance); - }, - [web3Instance] - ); - const checkAddress = useCallback(async () => { //wallet controller api try { @@ -103,18 +80,8 @@ const SendEth = ({ }, [transactionState.toAddress]); useEffect(() => { - console.log('SendEth useEffect '); - updateContractInfo( - transactionState.selectedToken.address, - transactionState.selectedToken.symbol - ); checkAddress(); - }, [ - updateContractInfo, - checkAddress, - transactionState.selectedToken.address, - transactionState.selectedToken.symbol, - ]); + }, [checkAddress]); return (
@@ -131,7 +98,7 @@ const SendEth = ({ /> */} - {validated ? ( + {validated !== null && validated ? ( <> ) : ( setConfirmationOpen(false)} handleCancelBtnClicked={() => setConfirmationOpen(false)} handleAddBtnClicked={() => { diff --git a/src/ui/views/Send/TransferAmount.tsx b/src/ui/views/Send/TransferAmount.tsx index ad71f7fb..b02dad14 100644 --- a/src/ui/views/Send/TransferAmount.tsx +++ b/src/ui/views/Send/TransferAmount.tsx @@ -110,7 +110,6 @@ const useStyles = makeStyles(() => ({ height: '25px', }, })); - const TransferAmount = ({ transactionState, handleAmountChange, @@ -132,17 +131,11 @@ const TransferAmount = ({ (option) => { const selectCoin = coinStore.coins.find((coin) => coin.unit === option); if (selectCoin) { - // Debounce only the state updates, not the render - const updateStates = debounce(() => { - handleTokenChange(option); - }, 300); - - updateStates(); return ; } return null; }, - [coinStore, handleTokenChange] + [coinStore] ); return ( @@ -215,9 +208,10 @@ const TransferAmount = ({