forked from cerc-io/laconic-wallet
* Display decoded message received while using signDirect method * Fix permission dialog not exiting after clicking outside * Handle review changes * Remove optional chaining in while checking for signDirect method
213 lines
6.5 KiB
TypeScript
213 lines
6.5 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react';
|
|
import { Button, Snackbar, Text } from 'react-native-paper';
|
|
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
import { TxBody, AuthInfo } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
|
|
|
|
import { SignClientTypes } from '@walletconnect/types';
|
|
import { useNavigation } from '@react-navigation/native';
|
|
import {
|
|
NativeStackNavigationProp,
|
|
createNativeStackNavigator,
|
|
} from '@react-navigation/native-stack';
|
|
|
|
import SignMessage from './components/SignMessage';
|
|
import HomeScreen from './components/HomeScreen';
|
|
import SignRequest from './components/SignRequest';
|
|
import InvalidPath from './components/InvalidPath';
|
|
import PairingModal from './components/PairingModal';
|
|
import AddSession from './components/AddSession';
|
|
import WalletConnect from './components/WalletConnect';
|
|
import { StackParamsList } from './types';
|
|
import { web3wallet } from './utils/wallet-connect/WalletConnectUtils';
|
|
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib';
|
|
import { getSignParamsMessage } from './utils/wallet-connect/Helpers';
|
|
import { useWalletConnect } from './context/WalletConnectContext';
|
|
|
|
const Stack = createNativeStackNavigator<StackParamsList>();
|
|
|
|
const App = (): React.JSX.Element => {
|
|
const navigation =
|
|
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
|
|
|
const { requestSession, setRequestSession, setActiveSessions } =
|
|
useWalletConnect();
|
|
|
|
const [modalVisible, setModalVisible] = useState(false);
|
|
const [toastVisible, setToastVisible] = useState(false);
|
|
const [currentProposal, setCurrentProposal] = useState<
|
|
SignClientTypes.EventArguments['session_proposal'] | undefined
|
|
>();
|
|
|
|
const onSessionProposal = useCallback(
|
|
(proposal: SignClientTypes.EventArguments['session_proposal']) => {
|
|
setModalVisible(true);
|
|
setCurrentProposal(proposal);
|
|
},
|
|
[],
|
|
);
|
|
|
|
const onSessionRequest = useCallback(
|
|
async (requestEvent: SignClientTypes.EventArguments['session_request']) => {
|
|
const { topic, params } = requestEvent;
|
|
const { request } = params;
|
|
|
|
const requestSessionData =
|
|
web3wallet.engine.signClient.session.get(topic);
|
|
|
|
setRequestSession(requestSessionData);
|
|
|
|
switch (request.method) {
|
|
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
|
navigation.navigate('SignRequest', {
|
|
network: 'eth',
|
|
address: request.params[1],
|
|
message: getSignParamsMessage(request.params),
|
|
requestEvent,
|
|
requestSession,
|
|
});
|
|
|
|
break;
|
|
case 'cosmos_signDirect':
|
|
const message = {
|
|
txbody: TxBody.toJSON(
|
|
TxBody.decode(
|
|
Uint8Array.from(
|
|
Buffer.from(request.params.signDoc.bodyBytes, 'hex'),
|
|
),
|
|
),
|
|
),
|
|
authInfo: AuthInfo.toJSON(
|
|
AuthInfo.decode(
|
|
Uint8Array.from(
|
|
Buffer.from(request.params.signDoc.authInfoBytes, 'hex'),
|
|
),
|
|
),
|
|
),
|
|
};
|
|
navigation.navigate('SignRequest', {
|
|
network: 'cosmos',
|
|
address: request.params.signerAddress,
|
|
message: JSON.stringify(message, undefined, 2),
|
|
requestEvent,
|
|
requestSession,
|
|
});
|
|
|
|
break;
|
|
case 'cosmos_signAmino':
|
|
navigation.navigate('SignRequest', {
|
|
network: 'cosmos',
|
|
address: request.params.signerAddress,
|
|
message: request.params.signDoc.memo,
|
|
requestEvent,
|
|
requestSession,
|
|
});
|
|
|
|
break;
|
|
default:
|
|
throw new Error('Invalid method');
|
|
}
|
|
},
|
|
[requestSession, setRequestSession, navigation],
|
|
);
|
|
|
|
const onSessionDelete = useCallback(() => {
|
|
let sessions = web3wallet?.getActiveSessions();
|
|
setActiveSessions(sessions);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
web3wallet?.on('session_proposal', onSessionProposal);
|
|
web3wallet?.on('session_request', onSessionRequest);
|
|
web3wallet?.on('session_delete', onSessionDelete);
|
|
return () => {
|
|
web3wallet?.off('session_proposal', onSessionProposal);
|
|
web3wallet?.off('session_request', onSessionRequest);
|
|
web3wallet?.off('session_delete', onSessionDelete);
|
|
};
|
|
//TODO: Investigate dependencies
|
|
});
|
|
|
|
return (
|
|
<>
|
|
<Stack.Navigator>
|
|
<Stack.Screen
|
|
name="Laconic"
|
|
component={HomeScreen}
|
|
options={{
|
|
headerTitle: () => <Text variant="titleLarge">Laconic Wallet</Text>,
|
|
headerBackVisible: false,
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="SignMessage"
|
|
component={SignMessage}
|
|
options={{
|
|
headerTitle: () => <Text variant="titleLarge">Sign Message</Text>,
|
|
}}
|
|
initialParams={{ selectedNetwork: 'Ethereum' }}
|
|
/>
|
|
<Stack.Screen
|
|
name="SignRequest"
|
|
component={SignRequest}
|
|
options={{
|
|
headerTitle: () => (
|
|
<Text variant="titleLarge">Sign this message?</Text>
|
|
),
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="InvalidPath"
|
|
component={InvalidPath}
|
|
options={{
|
|
headerTitle: () => <Text variant="titleLarge">Bad Request</Text>,
|
|
headerBackVisible: false,
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="WalletConnect"
|
|
component={WalletConnect}
|
|
options={{
|
|
headerTitle: () => <Text variant="titleLarge">WalletConnect</Text>,
|
|
headerRight: () => (
|
|
<Button
|
|
onPress={() => {
|
|
navigation.navigate('AddSession');
|
|
}}>
|
|
{<Icon name={'qrcode-scan'} size={20} />}
|
|
</Button>
|
|
),
|
|
}}
|
|
/>
|
|
|
|
<Stack.Screen
|
|
name="AddSession"
|
|
component={AddSession}
|
|
options={{
|
|
title: 'New session',
|
|
}}
|
|
/>
|
|
</Stack.Navigator>
|
|
<PairingModal
|
|
visible={modalVisible}
|
|
setModalVisible={setModalVisible}
|
|
currentProposal={currentProposal}
|
|
setCurrentProposal={setCurrentProposal}
|
|
setToastVisible={setToastVisible}
|
|
/>
|
|
<Snackbar
|
|
visible={toastVisible}
|
|
onDismiss={() => setToastVisible(false)}
|
|
action={{
|
|
label: 'Ok',
|
|
onPress: () => {
|
|
setToastVisible(false);
|
|
},
|
|
}}>
|
|
Session approved
|
|
</Snackbar>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default App;
|