diff --git a/src/screens/WalletEmbed.tsx b/src/screens/WalletEmbed.tsx index 2a8d2f9..8dcf038 100644 --- a/src/screens/WalletEmbed.tsx +++ b/src/screens/WalletEmbed.tsx @@ -5,6 +5,7 @@ import { Text, TextInput, } from 'react-native-paper'; +import { BigNumber } from 'ethers'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { @@ -13,22 +14,31 @@ import { SigningStargateClient, } from '@cosmjs/stargate'; -import { createWallet, retrieveAccounts } from '../utils/accounts'; +import { createWallet, retrieveAccounts, retrieveSingleAccount } from '../utils/accounts'; import AccountDetails from '../components/AccountDetails'; import styles from '../styles/stylesheet'; -import { retrieveSingleAccount } from '../utils/accounts'; import DataBox from '../components/DataBox'; import { getPathKey } from '../utils/misc'; import { useNetworks } from '../context/NetworksContext'; import TxErrorDialog from '../components/TxErrorDialog'; -import { BigNumber } from 'ethers'; import { MEMO } from '../screens/ApproveTransfer'; +import { Account, NetworksDataState } from '../types'; + +type TransactionDetails = { + chainId: string; + fromAddress: string; + toAddress: string; + amount: string; + account: Account + balance: string; + requestedNetwork: NetworksDataState +}; export const WalletEmbed = () => { const [isTxRequested, setIsTxRequested] = useState(false); - const [transactionDetails, setTransactionDetails] = useState(null); - const [fees, setFees] = useState(''); - const [gasLimit, setGasLimit] = useState(''); + const [transactionDetails, setTransactionDetails] = useState(null); + const [fees, setFees] = useState(''); + const [gasLimit, setGasLimit] = useState(''); const [isTxLoading, setIsTxLoading] = useState(false); const [txError, setTxError] = useState(null); const txEventRef = useRef(null); @@ -36,7 +46,7 @@ export const WalletEmbed = () => { const { networksData } = useNetworks(); const getAccountsData = useCallback(async (chainId: string) => { - const targetNetwork = networksData.find(network => network.chainId === "laconic-testnet-2"); + const targetNetwork = networksData.find(network => network.chainId === chainId); if (!targetNetwork) { return ''; @@ -53,11 +63,8 @@ export const WalletEmbed = () => { }, [networksData]); - const getAddressesFromData = (accountsData: string): string[] => { - return accountsData - ? accountsData.split(',') - : []; - }; + const getAddressesFromData = (accountsData: string): string[] => + accountsData?.split(',') || []; const sendMessage = ( source: Window | null, @@ -114,81 +121,81 @@ export const WalletEmbed = () => { }; }, [networksData, getAccountsData]); - const handleTxRequested = async (event: MessageEvent) => { - if (event.data.type !== 'REQUEST_TX') return; + const handleTxRequested = useCallback( + async (event: MessageEvent) => { + try { + if (event.data.type !== 'REQUEST_TX') return; - txEventRef.current = event; + txEventRef.current = event; - const { chainId, fromAddress, toAddress, amount } = event.data; - const network = networksData.find( - net => net.chainId === chainId - ); + const { chainId, fromAddress, toAddress, amount } = event.data; + const network = networksData.find(net => net.chainId === chainId); - if (!network) { - console.error('Network not found'); - return; - } + if (!network) { + console.error('Network not found'); + throw new Error('Requested network not supported.'); + } - const account = await retrieveSingleAccount(network.namespace, network.chainId, fromAddress); - if (!account) { - throw new Error('Account not found'); - } + const account = await retrieveSingleAccount(network.namespace, network.chainId, fromAddress); + if (!account) { + throw new Error('Account not found for the requested address.'); + } - const cosmosPrivKey = ( - await getPathKey(`${network.namespace}:${chainId}`, account.index) - ).privKey; - const sender = await DirectSecp256k1Wallet.fromKey( - Buffer.from(cosmosPrivKey.split('0x')[1], 'hex'), - network.addressPrefix - ); + const cosmosPrivKey = ( + await getPathKey(`${network.namespace}:${chainId}`, account.index) + ).privKey; - const client = await SigningStargateClient.connectWithSigner( - network.rpcUrl!, - sender - ); + const sender = await DirectSecp256k1Wallet.fromKey( + Buffer.from(cosmosPrivKey.split('0x')[1], 'hex'), + network.addressPrefix + ); - const balance = await client?.getBalance( - account.address, - network!.nativeDenom!.toLowerCase(), - ); + const client = await SigningStargateClient.connectWithSigner(network.rpcUrl!, sender); - const sendMsg = { - typeUrl: '/cosmos.bank.v1beta1.MsgSend', - value: { - fromAddress: fromAddress, - toAddress: toAddress, - amount: [ - { - amount: String(amount), - denom: network.nativeDenom!, + const balance = await client.getBalance( + account.address, + network.nativeDenom!.toLowerCase() + ); + + const sendMsg = { + typeUrl: '/cosmos.bank.v1beta1.MsgSend', + value: { + fromAddress: fromAddress, + toAddress: toAddress, + amount: [ + { + amount: String(amount), + denom: network.nativeDenom!, + }, + ], }, - ], - }, - }; + }; - const gasEstimation = await client.simulate(fromAddress, [sendMsg], MEMO); - const gasLimit = - String( - Math.round(gasEstimation * Number(process.env.REACT_APP_GAS_ADJUSTMENT)), - ) - setGasLimit(gasLimit); - - const gasPrice = GasPrice.fromString(network.gasPrice! + network.nativeDenom); - const cosmosFees = calculateFee(Number(gasLimit), gasPrice); - setFees(cosmosFees.amount[0].amount); + const gasEstimation = await client.simulate(fromAddress, [sendMsg], MEMO); + const gasLimit = String( + Math.round(gasEstimation * Number(process.env.REACT_APP_GAS_ADJUSTMENT)) + ); + setGasLimit(gasLimit); - setTransactionDetails({ - chainId, - fromAddress, - toAddress, - amount, - account, - balance: balance.amount, - requestedNetwork: network, - }); + const gasPrice = GasPrice.fromString(`${network.gasPrice}${network.nativeDenom}`); + const cosmosFees = calculateFee(Number(gasLimit), gasPrice); + setFees(cosmosFees.amount[0].amount); - setIsTxRequested(true); - }; + setTransactionDetails({ + chainId, + fromAddress, + toAddress, + amount, + account, + balance: balance.amount, + requestedNetwork: network, + }); + + setIsTxRequested(true); + } catch (error) { + console.error('Error processing transaction request:', error); + } + }, [networksData]); useEffect(() => { window.addEventListener('message', handleTxRequested); @@ -198,44 +205,44 @@ export const WalletEmbed = () => { const acceptRequestHandler = async () => { try { setIsTxLoading(true); - const { chainId, fromAddress, toAddress, amount, requestedNetwork } = - transactionDetails; - + if (!transactionDetails) { + throw new Error('Tx details not set'); + } const balanceBigNum = BigNumber.from(transactionDetails.balance); - const amountBigNum = BigNumber.from(String(amount)); + const amountBigNum = BigNumber.from(String(transactionDetails.amount)); if (amountBigNum.gte(balanceBigNum)) { throw new Error('Insufficient funds'); } const cosmosPrivKey = ( - await getPathKey(`${requestedNetwork.namespace}:${chainId}`, transactionDetails.account.index) + await getPathKey(`${transactionDetails.requestedNetwork.namespace}:${transactionDetails.chainId}`, transactionDetails.account.index) ).privKey; const sender = await DirectSecp256k1Wallet.fromKey( Buffer.from(cosmosPrivKey.split('0x')[1], 'hex'), - requestedNetwork.addressPrefix + transactionDetails.requestedNetwork.addressPrefix ); const client = await SigningStargateClient.connectWithSigner( - requestedNetwork.rpcUrl!, + transactionDetails.requestedNetwork.rpcUrl!, sender ); const fee = calculateFee( Number(gasLimit), - GasPrice.fromString(`${requestedNetwork.gasPrice}${requestedNetwork.nativeDenom}`) + GasPrice.fromString(`${transactionDetails.requestedNetwork.gasPrice}${transactionDetails.requestedNetwork.nativeDenom}`) ); const txResult = await client.sendTokens( - fromAddress, - toAddress, - [{ amount: String(amount), denom: requestedNetwork.nativeDenom }], + transactionDetails.fromAddress, + transactionDetails.toAddress, + [{ amount: String(transactionDetails.amount), denom: transactionDetails.requestedNetwork.nativeDenom! }], fee ); const event = txEventRef.current; if (event?.source) { - sendMessage(event.source as Window, 'TRANSACTION_SUCCESS', txResult.transactionHash, '*'); + sendMessage(event.source as Window, 'TRANSACTION_SUCCESS', txResult.transactionHash, event.origin); } else { console.error('No event source available to send message'); }