import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Image, ScrollView, View } from 'react-native'; import { ActivityIndicator, Button, Text, Appbar } from 'react-native-paper'; import { providers, BigNumber } from 'ethers'; import { useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp, NativeStackScreenProps, } from '@react-navigation/native-stack'; import { getHeaderTitle } from '@react-navigation/elements'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; import { calculateFee, GasPrice, SigningStargateClient, } from '@cosmjs/stargate'; import { Account, StackParamsList } from '../types'; import AccountDetails from '../components/AccountDetails'; import styles from '../styles/stylesheet'; import { retrieveSingleAccount } from '../utils/accounts'; import { approveWalletConnectRequest, rejectWalletConnectRequest, } from '../utils/wallet-connect/WalletConnectRequests'; import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; import { EIP155_CHAINS } from '../utils/wallet-connect/EIP155Data'; import DataBox from '../components/DataBox'; import { getPathKey } from '../utils/misc'; import { COSMOS_TESTNET_CHAINS } from '../utils/wallet-connect/COSMOSData'; import { COSMOS_DENOM } from '../utils/constants'; type SignRequestProps = NativeStackScreenProps< StackParamsList, 'ApproveTransaction' >; const ApproveTransaction = ({ route }: SignRequestProps) => { const requestSession = route.params.requestSessionData; const requestName = requestSession.peer.metadata.name; const requestIcon = requestSession.peer.metadata.icons[0]; const requestURL = requestSession.peer.metadata.url; const network = route.params.network; const transaction = route.params.transaction; const requestEvent = route.params.requestEvent; const chainId = requestEvent.params.chainId; const [account, setAccount] = useState(); const [isLoading, setIsLoading] = useState(true); const [balance, setBalance] = useState(''); const [isTxLoading, setIsTxLoading] = useState(false); const [cosmosStargateClient, setCosmosStargateClient] = useState(); const provider = useMemo(() => { if (network === 'eth') { return new providers.JsonRpcProvider(EIP155_CHAINS[chainId].rpc); } }, [chainId, network]); const navigation = useNavigation>(); const retrieveData = useCallback( async (requestAddress: string) => { const requestAccount = await retrieveSingleAccount( network, requestAddress, ); if (!requestAccount) { navigation.navigate('InvalidPath'); return; } setAccount(requestAccount); setIsLoading(false); }, [navigation, network], ); const gasFees = useMemo(() => { if (network === 'eth') { return BigNumber.from(transaction.gasLimit) .mul(BigNumber.from(transaction.gasPrice)) .toString(); } else { const gasPrice = GasPrice.fromString(transaction.gasPrice!.toString()); const cosmosFees = calculateFee(Number(transaction.gasLimit), gasPrice); return cosmosFees.amount[0].amount; } }, [transaction, network]); useEffect(() => { retrieveData(transaction.from!); }, [retrieveData, transaction]); const acceptRequestHandler = async () => { setIsTxLoading(true); if (!account) { throw new Error('account not found'); } const response = await approveWalletConnectRequest( requestEvent, account, network, '', network === 'eth' ? provider : cosmosStargateClient, ); const { topic } = requestEvent; await web3wallet!.respondSessionRequest({ topic, response }); setIsTxLoading(false); navigation.navigate('Laconic'); }; const rejectRequestHandler = async () => { const response = rejectWalletConnectRequest(requestEvent); const { topic } = requestEvent; await web3wallet!.respondSessionRequest({ topic, response, }); navigation.navigate('Laconic'); }; useEffect(() => { const getAccountBalance = async (account: Account) => { if (network === 'eth') { const fetchedBalance = provider && (await provider.getBalance(account.address)); setBalance(fetchedBalance ? fetchedBalance.toString() : '0'); } else { const cosmosBalance = await cosmosStargateClient?.getBalance( account.address, COSMOS_DENOM, ); setBalance(cosmosBalance?.amount!); } }; if (account) { getAccountBalance(account); } }, [account, provider, network, cosmosStargateClient]); useEffect(() => { navigation.setOptions({ // eslint-disable-next-line react/no-unstable-nested-components header: ({ options, back }) => { const title = getHeaderTitle(options, 'Approve Transaction'); return ( {back && ( { await rejectRequestHandler(); navigation.navigate('Laconic'); }} /> )} ); }, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [navigation, route.name]); useEffect(() => { if (network !== 'cosmos') { return; } const setClient = async () => { if (!account) { return; } const cosmosPrivKey = (await getPathKey('cosmos', account.counterId)) .privKey; const sender = await DirectSecp256k1Wallet.fromKey( Buffer.from(cosmosPrivKey.split('0x')[1], 'hex'), ); const client = await SigningStargateClient.connectWithSigner( COSMOS_TESTNET_CHAINS[chainId as string].rpc, sender, ); setCosmosStargateClient(client); }; setClient(); }, [account, chainId, network]); return ( <> {isLoading ? ( ) : ( {requestIcon && ( )} {requestName} {requestURL} From {transaction && ( {network === 'eth' && ( )} )} )} ); }; export default ApproveTransaction;