forked from cerc-io/laconic-wallet
Use page for handling sign requests (#42)
* Use sign request page instead of modal * Fix context * Remove multiple if statements * Change metadata * Remove sign modal * Make review changes * Remove state --------- Co-authored-by: Adw8 <adwait@deepstacksoft.com>
This commit is contained in:
parent
a4e0dc5406
commit
05be6008de
52
App.tsx
52
App.tsx
@ -15,7 +15,6 @@ import HomeScreen from './components/HomeScreen';
|
|||||||
import SignRequest from './components/SignRequest';
|
import SignRequest from './components/SignRequest';
|
||||||
import InvalidPath from './components/InvalidPath';
|
import InvalidPath from './components/InvalidPath';
|
||||||
import PairingModal from './components/PairingModal';
|
import PairingModal from './components/PairingModal';
|
||||||
import SignModal from './components/SignModal';
|
|
||||||
import WalletConnect from './components/WalletConnect';
|
import WalletConnect from './components/WalletConnect';
|
||||||
import { StackParamsList } from './types';
|
import { StackParamsList } from './types';
|
||||||
import useInitialization, {
|
import useInitialization, {
|
||||||
@ -23,6 +22,8 @@ import useInitialization, {
|
|||||||
} from './utils/wallet-connect/WalletConnectUtils';
|
} from './utils/wallet-connect/WalletConnectUtils';
|
||||||
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib';
|
import { EIP155_SIGNING_METHODS } from './utils/wallet-connect/EIP155Lib';
|
||||||
import { AccountsContext } from './context/AccountsContext';
|
import { AccountsContext } from './context/AccountsContext';
|
||||||
|
import { getSignParamsMessage } from './utils/wallet-connect/Helpers';
|
||||||
|
import { navigationRef, navigateTo } from './utils/RootNavigation';
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator<StackParamsList>();
|
const Stack = createNativeStackNavigator<StackParamsList>();
|
||||||
|
|
||||||
@ -37,8 +38,13 @@ const App = (): React.JSX.Element => {
|
|||||||
SignClientTypes.EventArguments['session_proposal'] | undefined
|
SignClientTypes.EventArguments['session_proposal'] | undefined
|
||||||
>();
|
>();
|
||||||
const [requestSession, setRequestSession] = useState<any>();
|
const [requestSession, setRequestSession] = useState<any>();
|
||||||
const [requestEventData, setRequestEventData] = useState<any>();
|
|
||||||
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(
|
const onSessionProposal = useCallback(
|
||||||
(proposal: SignClientTypes.EventArguments['session_proposal']) => {
|
(proposal: SignClientTypes.EventArguments['session_proposal']) => {
|
||||||
@ -52,6 +58,8 @@ const App = (): React.JSX.Element => {
|
|||||||
async (requestEvent: SignClientTypes.EventArguments['session_request']) => {
|
async (requestEvent: SignClientTypes.EventArguments['session_request']) => {
|
||||||
const { topic, params } = requestEvent;
|
const { topic, params } = requestEvent;
|
||||||
const { request } = params;
|
const { request } = params;
|
||||||
|
const address = request.params[1];
|
||||||
|
const message = getSignParamsMessage(request.params);
|
||||||
const requestSessionData =
|
const requestSessionData =
|
||||||
web3wallet.engine.signClient.session.get(topic);
|
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.ETH_SIGN:
|
||||||
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
||||||
setRequestSession(requestSessionData);
|
setRequestSession(requestSessionData);
|
||||||
setRequestEventData(requestEvent);
|
if (address && message) {
|
||||||
setSignModalVisible(true);
|
navigateTo('SignRequest', {
|
||||||
|
network: 'eth',
|
||||||
|
address,
|
||||||
|
message,
|
||||||
|
requestEvent,
|
||||||
|
requestSession,
|
||||||
|
});
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[],
|
[requestSession],
|
||||||
);
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
web3wallet?.on('session_proposal', onSessionProposal);
|
web3wallet?.on('session_proposal', onSessionProposal);
|
||||||
web3wallet?.on('session_request', onSessionRequest);
|
web3wallet?.on('session_request', onSessionRequest);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
web3wallet?.off('session_proposal', onSessionProposal);
|
||||||
|
web3wallet?.off('session_request', onSessionRequest);
|
||||||
|
};
|
||||||
//TODO: Investigate dependancies
|
//TODO: Investigate dependancies
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentEthAddresses = useMemo(() => {
|
|
||||||
if (accounts.ethAccounts.length > 0) {
|
|
||||||
return accounts.ethAccounts.map(account => account.address);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}, [accounts]);
|
|
||||||
|
|
||||||
const linking = {
|
const linking = {
|
||||||
prefixes: ['https://www.laconic-wallet.com'],
|
prefixes: ['https://www.laconic-wallet.com'],
|
||||||
config: {
|
config: {
|
||||||
@ -92,7 +104,7 @@ const App = (): React.JSX.Element => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationContainer linking={linking}>
|
<NavigationContainer linking={linking} ref={navigationRef}>
|
||||||
<Stack.Navigator>
|
<Stack.Navigator>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="Laconic"
|
name="Laconic"
|
||||||
@ -114,7 +126,7 @@ const App = (): React.JSX.Element => {
|
|||||||
name="SignRequest"
|
name="SignRequest"
|
||||||
component={SignRequest}
|
component={SignRequest}
|
||||||
options={{
|
options={{
|
||||||
title: 'Sign Message?',
|
title: 'Sign this message?',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
@ -140,14 +152,6 @@ const App = (): React.JSX.Element => {
|
|||||||
setCurrentProposal={setCurrentProposal}
|
setCurrentProposal={setCurrentProposal}
|
||||||
currentEthAddresses={currentEthAddresses}
|
currentEthAddresses={currentEthAddresses}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SignModal
|
|
||||||
visible={signModalVisible}
|
|
||||||
setModalVisible={setSignModalVisible}
|
|
||||||
requestEvent={requestEventData}
|
|
||||||
requestSession={requestSession}
|
|
||||||
currentEthAddresses={currentEthAddresses}
|
|
||||||
/>
|
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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 (
|
|
||||||
<Modal visible={visible} animationType="slide" transparent>
|
|
||||||
<View style={styles.container}>
|
|
||||||
<View style={styles.modalContentContainer}>
|
|
||||||
<Text variant="titleLarge">Sign this message?</Text>
|
|
||||||
|
|
||||||
<Image
|
|
||||||
style={styles.dappLogo}
|
|
||||||
source={{
|
|
||||||
uri: requestIcon,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Text>{requestName}</Text>
|
|
||||||
<Text variant="bodyMedium">{requestURL}</Text>
|
|
||||||
|
|
||||||
<View style={styles.messageBody}>
|
|
||||||
<Text variant="bodyLarge">{message}</Text>
|
|
||||||
</View>
|
|
||||||
<Text>Chains: {chainID}</Text>
|
|
||||||
|
|
||||||
<View style={styles.flexRow}>
|
|
||||||
<Button mode="outlined" onPress={() => onReject()}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<View style={styles.space} />
|
|
||||||
<Button mode="contained" onPress={() => onApprove()}>
|
|
||||||
Accept
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SignModal;
|
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { Alert, View } from 'react-native';
|
import { Alert, View } from 'react-native';
|
||||||
import { ActivityIndicator, Button, Text } from 'react-native-paper';
|
import { ActivityIndicator, Button, Text } from 'react-native-paper';
|
||||||
|
|
||||||
@ -13,6 +13,11 @@ import AccountDetails from './AccountDetails';
|
|||||||
import styles from '../styles/stylesheet';
|
import styles from '../styles/stylesheet';
|
||||||
import { signMessage } from '../utils/sign-message';
|
import { signMessage } from '../utils/sign-message';
|
||||||
import { retrieveSingleAccount } from '../utils/accounts';
|
import { retrieveSingleAccount } from '../utils/accounts';
|
||||||
|
import {
|
||||||
|
approveEIP155Request,
|
||||||
|
rejectEIP155Request,
|
||||||
|
} from '../utils/wallet-connect/EIP155Requests';
|
||||||
|
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
|
||||||
|
|
||||||
type SignRequestProps = NativeStackScreenProps<StackParamsList, 'SignRequest'>;
|
type SignRequestProps = NativeStackScreenProps<StackParamsList, 'SignRequest'>;
|
||||||
|
|
||||||
@ -20,7 +25,7 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
const [account, setAccount] = useState<Account>();
|
const [account, setAccount] = useState<Account>();
|
||||||
const [message, setMessage] = useState<string>('');
|
const [message, setMessage] = useState<string>('');
|
||||||
const [network, setNetwork] = useState<string>('');
|
const [network, setNetwork] = useState<string>('');
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const navigation =
|
const navigation =
|
||||||
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
||||||
@ -36,7 +41,9 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
);
|
);
|
||||||
if (!requestAccount) {
|
if (!requestAccount) {
|
||||||
navigation.navigate('InvalidPath');
|
navigation.navigate('InvalidPath');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestAccount && requestAccount !== account) {
|
if (requestAccount && requestAccount !== account) {
|
||||||
setAccount(requestAccount);
|
setAccount(requestAccount);
|
||||||
}
|
}
|
||||||
@ -66,7 +73,6 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoaded(true);
|
|
||||||
if (route.path) {
|
if (route.path) {
|
||||||
const sanitizedRoute = sanitizePath(route.path);
|
const sanitizedRoute = sanitizePath(route.path);
|
||||||
sanitizedRoute &&
|
sanitizedRoute &&
|
||||||
@ -76,11 +82,28 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
route.params?.address,
|
route.params?.address,
|
||||||
route.params?.message,
|
route.params?.message,
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
setLoaded(false);
|
route.params &&
|
||||||
|
retrieveData(
|
||||||
|
route.params?.network,
|
||||||
|
route.params?.address,
|
||||||
|
route.params?.message,
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
}, [route]);
|
}, [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) {
|
if (!account) {
|
||||||
throw new Error('Account is not valid');
|
throw new Error('Account is not valid');
|
||||||
}
|
}
|
||||||
@ -91,17 +114,36 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
accountId: account.counterId,
|
accountId: account.counterId,
|
||||||
});
|
});
|
||||||
Alert.alert('Signature', signedMessage);
|
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 () => {
|
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');
|
navigation.navigate('Laconic');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!loaded ? (
|
{isLoading ? (
|
||||||
|
<ActivityIndicator />
|
||||||
|
) : (
|
||||||
<View style={styles.appContainer}>
|
<View style={styles.appContainer}>
|
||||||
<AccountDetails account={account} />
|
<AccountDetails account={account} />
|
||||||
<View style={styles.requestMessage}>
|
<View style={styles.requestMessage}>
|
||||||
@ -119,8 +161,6 @@ const SignRequest = ({ route }: SignRequestProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
|
||||||
<ActivityIndicator />
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
9
types.ts
9
types.ts
@ -4,7 +4,14 @@ export type StackParamsList = {
|
|||||||
Laconic: undefined;
|
Laconic: undefined;
|
||||||
SignMessage: { selectedNetwork: string; accountInfo: Account } | undefined;
|
SignMessage: { selectedNetwork: string; accountInfo: Account } | undefined;
|
||||||
SignRequest:
|
SignRequest:
|
||||||
| { network: string; address: string; message: string }
|
| {
|
||||||
|
network: string;
|
||||||
|
address: string;
|
||||||
|
message: string;
|
||||||
|
// TODO: remove any
|
||||||
|
requestEvent?: any;
|
||||||
|
requestSession?: any;
|
||||||
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
InvalidPath: undefined;
|
InvalidPath: undefined;
|
||||||
WalletConnect: undefined;
|
WalletConnect: undefined;
|
||||||
|
14
utils/RootNavigation.ts
Normal file
14
utils/RootNavigation.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {
|
||||||
|
CommonActions,
|
||||||
|
createNavigationContainerRef,
|
||||||
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
|
import { StackParamsList } from '../types';
|
||||||
|
|
||||||
|
export const navigationRef = createNavigationContainerRef<StackParamsList>();
|
||||||
|
|
||||||
|
export function navigateTo(routeName: string, params?: object) {
|
||||||
|
if (navigationRef.isReady()) {
|
||||||
|
navigationRef.dispatch(CommonActions.navigate(routeName, params));
|
||||||
|
}
|
||||||
|
}
|
@ -5,27 +5,20 @@ import { SignClientTypes } from '@walletconnect/types';
|
|||||||
import { getSdkError } from '@walletconnect/utils';
|
import { getSdkError } from '@walletconnect/utils';
|
||||||
|
|
||||||
import { EIP155_SIGNING_METHODS } from './EIP155Lib';
|
import { EIP155_SIGNING_METHODS } from './EIP155Lib';
|
||||||
import { getSignParamsMessage, getAccountNumberFromParams } from './Helpers';
|
import { getSignParamsMessage } from './Helpers';
|
||||||
import { signEthMessage } from '../sign-message';
|
import { signEthMessage } from '../sign-message';
|
||||||
import { Account } from '../../types';
|
|
||||||
|
|
||||||
export async function approveEIP155Request(
|
export async function approveEIP155Request(
|
||||||
requestEvent: SignClientTypes.EventArguments['session_request'],
|
requestEvent: SignClientTypes.EventArguments['session_request'],
|
||||||
currentEthAddresses: string[],
|
counterId: number | undefined,
|
||||||
ethAccounts: Account[],
|
|
||||||
) {
|
) {
|
||||||
const { params, id } = requestEvent;
|
const { params, id } = requestEvent;
|
||||||
const { request } = params;
|
const { request } = params;
|
||||||
const counterId = await getAccountNumberFromParams(
|
|
||||||
currentEthAddresses,
|
|
||||||
ethAccounts,
|
|
||||||
params,
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (request.method) {
|
switch (request.method) {
|
||||||
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
||||||
const message = getSignParamsMessage(request.params);
|
const message = getSignParamsMessage(request.params);
|
||||||
const signedMessage = await signEthMessage(message, counterId);
|
const signedMessage =
|
||||||
|
counterId && (await signEthMessage(message, counterId));
|
||||||
return formatJsonRpcResult(id, signedMessage);
|
return formatJsonRpcResult(id, signedMessage);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -28,10 +28,10 @@ export async function createWeb3Wallet() {
|
|||||||
web3wallet = await Web3Wallet.init({
|
web3wallet = await Web3Wallet.init({
|
||||||
core,
|
core,
|
||||||
metadata: {
|
metadata: {
|
||||||
name: 'Web3Wallet React Native Tutorial',
|
name: 'Laconic Wallet',
|
||||||
description: 'ReactNative Web3Wallet',
|
description: 'ReactNative Laconic Wallet',
|
||||||
url: 'https://walletconnect.com/',
|
url: 'https://wallet.laconic.com/',
|
||||||
icons: ['https://avatars.githubusercontent.com/u/37784886'],
|
icons: ['https://avatars.githubusercontent.com/u/92608123'],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user