diff --git a/App.tsx b/App.tsx index b304288..48b63d8 100644 --- a/App.tsx +++ b/App.tsx @@ -15,7 +15,6 @@ import HomeScreen from './components/HomeScreen'; import SignRequest from './components/SignRequest'; import InvalidPath from './components/InvalidPath'; import PairingModal from './components/PairingModal'; -import SignModal from './components/SignModal'; import WalletConnect from './components/WalletConnect'; import { StackParamsList } from './types'; import useInitialization, { @@ -23,6 +22,8 @@ import useInitialization, { } from './utils/wallet-connect/WalletConnectUtils'; import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib'; import { AccountsContext } from './context/AccountsContext'; +import { getSignParamsMessage } from './utils/wallet-connect/Helpers'; +import { navigationRef, navigateTo } from './utils/RootNavigation'; const Stack = createNativeStackNavigator(); @@ -37,8 +38,13 @@ const App = (): React.JSX.Element => { SignClientTypes.EventArguments['session_proposal'] | undefined >(); const [requestSession, setRequestSession] = useState(); - const [requestEventData, setRequestEventData] = useState(); - const [signModalVisible, setSignModalVisible] = useState(false); + + const currentEthAddresses = useMemo(() => { + if (accounts.ethAccounts.length > 0) { + return accounts.ethAccounts.map(account => account.address); + } + return []; + }, [accounts]); const onSessionProposal = useCallback( (proposal: SignClientTypes.EventArguments['session_proposal']) => { @@ -52,6 +58,8 @@ const App = (): React.JSX.Element => { async (requestEvent: SignClientTypes.EventArguments['session_request']) => { const { topic, params } = requestEvent; const { request } = params; + const address = request.params[1]; + const message = getSignParamsMessage(request.params); const requestSessionData = web3wallet.engine.signClient.session.get(topic); @@ -59,27 +67,31 @@ const App = (): React.JSX.Element => { case EIP155_SIGNING_METHODS.ETH_SIGN: case EIP155_SIGNING_METHODS.PERSONAL_SIGN: setRequestSession(requestSessionData); - setRequestEventData(requestEvent); - setSignModalVisible(true); + if (address && message) { + navigateTo('SignRequest', { + network: 'eth', + address, + message, + requestEvent, + requestSession, + }); + } return; } }, - [], + [requestSession], ); useEffect(() => { web3wallet?.on('session_proposal', onSessionProposal); web3wallet?.on('session_request', onSessionRequest); + + return () => { + web3wallet?.off('session_proposal', onSessionProposal); + web3wallet?.off('session_request', onSessionRequest); + }; //TODO: Investigate dependancies }); - const currentEthAddresses = useMemo(() => { - if (accounts.ethAccounts.length > 0) { - return accounts.ethAccounts.map(account => account.address); - } - - return []; - }, [accounts]); - const linking = { prefixes: ['https://www.laconic-wallet.com'], config: { @@ -92,7 +104,7 @@ const App = (): React.JSX.Element => { }; return ( - + { name="SignRequest" component={SignRequest} options={{ - title: 'Sign Message?', + title: 'Sign this message?', }} /> { setCurrentProposal={setCurrentProposal} currentEthAddresses={currentEthAddresses} /> - - ); }; diff --git a/components/SignModal.tsx b/components/SignModal.tsx deleted file mode 100644 index 4c4d70f..0000000 --- a/components/SignModal.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useContext } from 'react'; -import { Button, Text } from 'react-native-paper'; -import { Image, Modal, View } from 'react-native'; - -import { getSignParamsMessage } from '../utils/wallet-connect/Helpers'; -import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; -import { - approveEIP155Request, - rejectEIP155Request, -} from '../utils/wallet-connect/EIP155Requests'; - -import styles from '../styles/stylesheet'; -import { SignModalProps } from '../types'; -import { AccountsContext } from '../context/AccountsContext'; - -const SignModal = ({ - visible, - setModalVisible, - requestEvent, - requestSession, - currentEthAddresses, -}: SignModalProps) => { - const { accounts } = useContext(AccountsContext); - - if (!requestEvent || !requestSession) { - return null; - } - - const chainID = requestEvent?.params?.chainId?.toUpperCase(); - const message = getSignParamsMessage(requestEvent?.params?.request?.params); - - const requestName = requestSession?.peer?.metadata?.name; - const requestIcon = requestSession?.peer?.metadata?.icons[0]; - const requestURL = requestSession?.peer?.metadata?.url; - - const { topic } = requestEvent; - - const onApprove = async () => { - if (requestEvent) { - const response = await approveEIP155Request( - requestEvent, - currentEthAddresses, - accounts.ethAccounts, - ); - await web3wallet.respondSessionRequest({ - topic, - response, - }); - setModalVisible(false); - } - }; - - const onReject = async () => { - if (requestEvent) { - const response = rejectEIP155Request(requestEvent); - await web3wallet.respondSessionRequest({ - topic, - response, - }); - setModalVisible(false); - } - }; - - return ( - - - - Sign this message? - - - - {requestName} - {requestURL} - - - {message} - - Chains: {chainID} - - - - - - - - - - ); -}; - -export default SignModal; diff --git a/components/SignRequest.tsx b/components/SignRequest.tsx index ea735df..5d7f7ab 100644 --- a/components/SignRequest.tsx +++ b/components/SignRequest.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { Alert, View } from 'react-native'; import { ActivityIndicator, Button, Text } from 'react-native-paper'; @@ -13,6 +13,11 @@ import AccountDetails from './AccountDetails'; import styles from '../styles/stylesheet'; import { signMessage } from '../utils/sign-message'; import { retrieveSingleAccount } from '../utils/accounts'; +import { + approveEIP155Request, + rejectEIP155Request, +} from '../utils/wallet-connect/EIP155Requests'; +import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils'; type SignRequestProps = NativeStackScreenProps; @@ -20,7 +25,7 @@ const SignRequest = ({ route }: SignRequestProps) => { const [account, setAccount] = useState(); const [message, setMessage] = useState(''); const [network, setNetwork] = useState(''); - const [loaded, setLoaded] = useState(false); + const [isLoading, setIsLoading] = useState(true); const navigation = useNavigation>(); @@ -36,7 +41,9 @@ const SignRequest = ({ route }: SignRequestProps) => { ); if (!requestAccount) { navigation.navigate('InvalidPath'); + return; } + if (requestAccount && requestAccount !== account) { setAccount(requestAccount); } @@ -66,7 +73,6 @@ const SignRequest = ({ route }: SignRequestProps) => { }; useEffect(() => { - setLoaded(true); if (route.path) { const sanitizedRoute = sanitizePath(route.path); sanitizedRoute && @@ -76,11 +82,28 @@ const SignRequest = ({ route }: SignRequestProps) => { route.params?.address, route.params?.message, ); + return; } - setLoaded(false); + route.params && + retrieveData( + route.params?.network, + route.params?.address, + route.params?.message, + ); + setIsLoading(false); }, [route]); - const signMessageHandler = async () => { + const handleEIP155Request = async () => { + const { requestEvent } = route.params || {}; + const response = await approveEIP155Request( + requestEvent, + account?.counterId, + ); + const { topic } = requestEvent; + await web3wallet.respondSessionRequest({ topic, response }); + }; + + const handleIntent = async () => { if (!account) { throw new Error('Account is not valid'); } @@ -91,17 +114,36 @@ const SignRequest = ({ route }: SignRequestProps) => { accountId: account.counterId, }); Alert.alert('Signature', signedMessage); - navigation.navigate('Laconic'); } }; + const signMessageHandler = async () => { + if (route.params?.requestEvent) { + await handleEIP155Request(); + } else { + await handleIntent(); + } + + navigation.navigate('Laconic'); + }; + const rejectRequestHandler = async () => { + if (route.params?.requestEvent) { + const response = rejectEIP155Request(route.params?.requestEvent); + const { topic } = route.params?.requestEvent; + await web3wallet.respondSessionRequest({ + topic, + response, + }); + } navigation.navigate('Laconic'); }; return ( <> - {!loaded ? ( + {isLoading ? ( + + ) : ( @@ -119,8 +161,6 @@ const SignRequest = ({ route }: SignRequestProps) => { - ) : ( - )} ); diff --git a/types.ts b/types.ts index f294a82..98e76da 100644 --- a/types.ts +++ b/types.ts @@ -4,7 +4,14 @@ export type StackParamsList = { Laconic: undefined; SignMessage: { selectedNetwork: string; accountInfo: Account } | undefined; SignRequest: - | { network: string; address: string; message: string } + | { + network: string; + address: string; + message: string; + // TODO: remove any + requestEvent?: any; + requestSession?: any; + } | undefined; InvalidPath: undefined; WalletConnect: undefined; diff --git a/utils/RootNavigation.ts b/utils/RootNavigation.ts new file mode 100644 index 0000000..10b50c5 --- /dev/null +++ b/utils/RootNavigation.ts @@ -0,0 +1,14 @@ +import { + CommonActions, + createNavigationContainerRef, +} from '@react-navigation/native'; + +import { StackParamsList } from '../types'; + +export const navigationRef = createNavigationContainerRef(); + +export function navigateTo(routeName: string, params?: object) { + if (navigationRef.isReady()) { + navigationRef.dispatch(CommonActions.navigate(routeName, params)); + } +} diff --git a/utils/wallet-connect/EIP155Requests.ts b/utils/wallet-connect/EIP155Requests.ts index 414c127..bdb207b 100644 --- a/utils/wallet-connect/EIP155Requests.ts +++ b/utils/wallet-connect/EIP155Requests.ts @@ -5,27 +5,20 @@ import { SignClientTypes } from '@walletconnect/types'; import { getSdkError } from '@walletconnect/utils'; import { EIP155_SIGNING_METHODS } from './EIP155Lib'; -import { getSignParamsMessage, getAccountNumberFromParams } from './Helpers'; +import { getSignParamsMessage } from './Helpers'; import { signEthMessage } from '../sign-message'; -import { Account } from '../../types'; export async function approveEIP155Request( requestEvent: SignClientTypes.EventArguments['session_request'], - currentEthAddresses: string[], - ethAccounts: Account[], + counterId: number | undefined, ) { const { params, id } = requestEvent; const { request } = params; - const counterId = await getAccountNumberFromParams( - currentEthAddresses, - ethAccounts, - params, - ); - switch (request.method) { case EIP155_SIGNING_METHODS.PERSONAL_SIGN: const message = getSignParamsMessage(request.params); - const signedMessage = await signEthMessage(message, counterId); + const signedMessage = + counterId && (await signEthMessage(message, counterId)); return formatJsonRpcResult(id, signedMessage); default: diff --git a/utils/wallet-connect/WalletConnectUtils.tsx b/utils/wallet-connect/WalletConnectUtils.tsx index 800fead..eb60607 100644 --- a/utils/wallet-connect/WalletConnectUtils.tsx +++ b/utils/wallet-connect/WalletConnectUtils.tsx @@ -28,10 +28,10 @@ export async function createWeb3Wallet() { web3wallet = await Web3Wallet.init({ core, metadata: { - name: 'Web3Wallet React Native Tutorial', - description: 'ReactNative Web3Wallet', - url: 'https://walletconnect.com/', - icons: ['https://avatars.githubusercontent.com/u/37784886'], + name: 'Laconic Wallet', + description: 'ReactNative Laconic Wallet', + url: 'https://wallet.laconic.com/', + icons: ['https://avatars.githubusercontent.com/u/92608123'], }, }); }