Use context for maintaining accounts state (#41)

* Use context for maintaining accounts state

* Remove custom hook from context
This commit is contained in:
shreerang6921 2024-03-06 17:44:13 +05:30 committed by GitHub
parent 19e39281a6
commit a4e0dc5406
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 87 additions and 58 deletions

31
App.tsx
View File

@ -1,4 +1,10 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, {
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from 'react';
import { SignClientTypes } from '@walletconnect/types'; import { SignClientTypes } from '@walletconnect/types';
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer } from '@react-navigation/native';
@ -16,13 +22,15 @@ import useInitialization, {
web3wallet, web3wallet,
} 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 { retrieveAccounts } from './utils/accounts'; import { AccountsContext } from './context/AccountsContext';
const Stack = createNativeStackNavigator<StackParamsList>(); const Stack = createNativeStackNavigator<StackParamsList>();
const App = (): React.JSX.Element => { const App = (): React.JSX.Element => {
useInitialization(); useInitialization();
const { accounts } = useContext(AccountsContext);
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
//TODO: Remove any //TODO: Remove any
const [currentProposal, setCurrentProposal] = useState< const [currentProposal, setCurrentProposal] = useState<
@ -31,7 +39,6 @@ const App = (): React.JSX.Element => {
const [requestSession, setRequestSession] = useState<any>(); const [requestSession, setRequestSession] = useState<any>();
const [requestEventData, setRequestEventData] = useState<any>(); const [requestEventData, setRequestEventData] = useState<any>();
const [signModalVisible, setSignModalVisible] = useState(false); const [signModalVisible, setSignModalVisible] = useState(false);
const [currentEthAddresses, setCurrentEthAddresses] = useState<string[]>([]);
const onSessionProposal = useCallback( const onSessionProposal = useCallback(
(proposal: SignClientTypes.EventArguments['session_proposal']) => { (proposal: SignClientTypes.EventArguments['session_proposal']) => {
@ -65,19 +72,13 @@ const App = (): React.JSX.Element => {
//TODO: Investigate dependancies //TODO: Investigate dependancies
}); });
useEffect(() => { const currentEthAddresses = useMemo(() => {
const fetchEthAccounts = async () => { if (accounts.ethAccounts.length > 0) {
const { ethLoadedAccounts } = await retrieveAccounts(); return accounts.ethAccounts.map(account => account.address);
}
if (ethLoadedAccounts) { return [];
const ethAddreses = ethLoadedAccounts.map(account => account.address); }, [accounts]);
setCurrentEthAddresses(ethAddreses);
}
};
fetchEthAccounts();
// TODO: Use context to maintain accounts state
}, [modalVisible]);
const linking = { const linking = {
prefixes: ['https://www.laconic-wallet.com'], prefixes: ['https://www.laconic-wallet.com'],

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useContext, useState } from 'react';
import { ScrollView, TouchableOpacity, View } from 'react-native'; import { ScrollView, TouchableOpacity, View } from 'react-native';
import { Button, List, Text, useTheme } from 'react-native-paper'; import { Button, List, Text, useTheme } from 'react-native-paper';
@ -10,16 +10,18 @@ import { addAccount } from '../utils/accounts';
import styles from '../styles/stylesheet'; import styles from '../styles/stylesheet';
import HDPathDialog from './HDPathDialog'; import HDPathDialog from './HDPathDialog';
import AccountDetails from './AccountDetails'; import AccountDetails from './AccountDetails';
import { AccountsContext } from '../context/AccountsContext';
const Accounts = ({ const Accounts = ({
network, network,
accounts,
updateAccounts,
currentIndex, currentIndex,
updateIndex: updateId, updateIndex: updateId,
}: AccountsProps) => { }: AccountsProps) => {
const navigation = const navigation =
useNavigation<NativeStackNavigationProp<StackParamsList>>(); useNavigation<NativeStackNavigationProp<StackParamsList>>();
const { accounts, setAccounts } = useContext(AccountsContext);
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const [isAccountCreating, setIsAccountCreating] = useState(false); const [isAccountCreating, setIsAccountCreating] = useState(false);
const [hdDialog, setHdDialog] = useState(false); const [hdDialog, setHdDialog] = useState(false);
@ -28,6 +30,25 @@ const Accounts = ({
const handlePress = () => setExpanded(!expanded); const handlePress = () => setExpanded(!expanded);
const updateAccounts = (account: Account) => {
switch (network) {
case 'eth':
setAccounts({
...accounts,
ethAccounts: [...accounts.ethAccounts, account],
});
break;
case 'cosmos':
setAccounts({
...accounts,
cosmosAccounts: [...accounts.cosmosAccounts, account],
});
break;
default:
console.error('Select a valid network!');
}
};
const addAccountHandler = async () => { const addAccountHandler = async () => {
setIsAccountCreating(true); setIsAccountCreating(true);
const newAccount = await addAccount(network); const newAccount = await addAccount(network);

View File

@ -1,17 +1,19 @@
import React, { useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { View, ActivityIndicator } from 'react-native'; import { View, ActivityIndicator } from 'react-native';
import { Button, Text } from 'react-native-paper'; import { Button, Text } from 'react-native-paper';
import { createWallet, resetWallet, retrieveAccounts } from '../utils/accounts'; import { createWallet, resetWallet, retrieveAccounts } from '../utils/accounts';
import { DialogComponent } from './Dialog'; import { DialogComponent } from './Dialog';
import { NetworkDropdown } from './NetworkDropdown'; import { NetworkDropdown } from './NetworkDropdown';
import { Account, AccountsState } from '../types';
import Accounts from './Accounts'; import Accounts from './Accounts';
import CreateWallet from './CreateWallet'; import CreateWallet from './CreateWallet';
import ResetWalletDialog from './ResetWalletDialog'; import ResetWalletDialog from './ResetWalletDialog';
import styles from '../styles/stylesheet'; import styles from '../styles/stylesheet';
import { AccountsContext } from '../context/AccountsContext';
const HomeScreen = () => { const HomeScreen = () => {
const { accounts, setAccounts } = useContext(AccountsContext);
const [isWalletCreated, setIsWalletCreated] = useState<boolean>(false); const [isWalletCreated, setIsWalletCreated] = useState<boolean>(false);
const [isWalletCreating, setIsWalletCreating] = useState<boolean>(false); const [isWalletCreating, setIsWalletCreating] = useState<boolean>(false);
const [walletDialog, setWalletDialog] = useState<boolean>(false); const [walletDialog, setWalletDialog] = useState<boolean>(false);
@ -20,10 +22,6 @@ const HomeScreen = () => {
const [currentIndex, setCurrentIndex] = useState<number>(0); const [currentIndex, setCurrentIndex] = useState<number>(0);
const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(false); const [isAccountsFetched, setIsAccountsFetched] = useState<boolean>(false);
const [phrase, setPhrase] = useState(''); const [phrase, setPhrase] = useState('');
const [accounts, setAccounts] = useState<AccountsState>({
ethAccounts: [],
cosmosAccounts: [],
});
const hideWalletDialog = () => setWalletDialog(false); const hideWalletDialog = () => setWalletDialog(false);
const hideResetDialog = () => setResetWalletDialog(false); const hideResetDialog = () => setResetWalletDialog(false);
@ -64,25 +62,6 @@ const HomeScreen = () => {
setCurrentIndex(index); setCurrentIndex(index);
}; };
const updateAccounts = (account: Account) => {
switch (network) {
case 'eth':
setAccounts({
...accounts,
ethAccounts: [...accounts.ethAccounts, account],
});
break;
case 'cosmos':
setAccounts({
...accounts,
cosmosAccounts: [...accounts.cosmosAccounts, account],
});
break;
default:
console.error('Select a valid network!');
}
};
useEffect(() => { useEffect(() => {
const fetchAccounts = async () => { const fetchAccounts = async () => {
if (isAccountsFetched) { if (isAccountsFetched) {
@ -104,7 +83,7 @@ const HomeScreen = () => {
}; };
fetchAccounts(); fetchAccounts();
}, [isAccountsFetched]); }, [isAccountsFetched, setAccounts]);
return ( return (
<View style={styles.appContainer}> <View style={styles.appContainer}>
@ -122,10 +101,8 @@ const HomeScreen = () => {
<View style={styles.accountComponent}> <View style={styles.accountComponent}>
<Accounts <Accounts
network={network} network={network}
accounts={accounts}
currentIndex={currentIndex} currentIndex={currentIndex}
updateIndex={updateIndex} updateIndex={updateIndex}
updateAccounts={updateAccounts}
/> />
</View> </View>
<View style={styles.resetContainer}> <View style={styles.resetContainer}>

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useContext } from 'react';
import { Button, Text } from 'react-native-paper'; import { Button, Text } from 'react-native-paper';
import { Image, Modal, View } from 'react-native'; import { Image, Modal, View } from 'react-native';
@ -11,6 +11,7 @@ import {
import styles from '../styles/stylesheet'; import styles from '../styles/stylesheet';
import { SignModalProps } from '../types'; import { SignModalProps } from '../types';
import { AccountsContext } from '../context/AccountsContext';
const SignModal = ({ const SignModal = ({
visible, visible,
@ -19,6 +20,8 @@ const SignModal = ({
requestSession, requestSession,
currentEthAddresses, currentEthAddresses,
}: SignModalProps) => { }: SignModalProps) => {
const { accounts } = useContext(AccountsContext);
if (!requestEvent || !requestSession) { if (!requestEvent || !requestSession) {
return null; return null;
} }
@ -37,6 +40,7 @@ const SignModal = ({
const response = await approveEIP155Request( const response = await approveEIP155Request(
requestEvent, requestEvent,
currentEthAddresses, currentEthAddresses,
accounts.ethAccounts,
); );
await web3wallet.respondSessionRequest({ await web3wallet.respondSessionRequest({
topic, topic,

View File

@ -0,0 +1,25 @@
import React, { createContext, useState } from 'react';
import { AccountsState } from '../types';
const AccountsContext = createContext<{
accounts: AccountsState;
setAccounts: (account: AccountsState) => void;
}>({
accounts: { ethAccounts: [], cosmosAccounts: [] },
setAccounts: () => {},
});
const AccountsProvider = ({ children }: { children: any }) => {
const [accounts, setAccounts] = useState<AccountsState>({
ethAccounts: [],
cosmosAccounts: [],
});
return (
<AccountsContext.Provider value={{ accounts, setAccounts }}>
{children}
</AccountsContext.Provider>
);
};
export { AccountsContext, AccountsProvider };

View File

@ -4,12 +4,15 @@ import { AppRegistry } from 'react-native';
import { PaperProvider } from 'react-native-paper'; import { PaperProvider } from 'react-native-paper';
import App from './App'; import App from './App';
import { AccountsProvider } from './context/AccountsContext';
import { name as appName } from './app.json'; import { name as appName } from './app.json';
export default function Main() { export default function Main() {
return ( return (
<PaperProvider> <PaperProvider>
<App /> <AccountsProvider>
<App />
</AccountsProvider>
</PaperProvider> </PaperProvider>
); );
} }

View File

@ -25,13 +25,8 @@ export type WalletDetails = {
export type AccountsProps = { export type AccountsProps = {
network: string; network: string;
accounts: {
ethAccounts: Account[];
cosmosAccounts: Account[];
};
currentIndex: number; currentIndex: number;
updateIndex: (index: number) => void; updateIndex: (index: number) => void;
updateAccounts: (account: Account) => void;
}; };
export type NetworkDropdownProps = { export type NetworkDropdownProps = {

View File

@ -7,15 +7,18 @@ import { getSdkError } from '@walletconnect/utils';
import { EIP155_SIGNING_METHODS } from './EIP155Lib'; import { EIP155_SIGNING_METHODS } from './EIP155Lib';
import { getSignParamsMessage, getAccountNumberFromParams } from './Helpers'; import { getSignParamsMessage, getAccountNumberFromParams } 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[], currentEthAddresses: string[],
ethAccounts: Account[],
) { ) {
const { params, id } = requestEvent; const { params, id } = requestEvent;
const { request } = params; const { request } = params;
const counterId = await getAccountNumberFromParams( const counterId = await getAccountNumberFromParams(
currentEthAddresses, currentEthAddresses,
ethAccounts,
params, params,
); );

View File

@ -1,9 +1,10 @@
// Taken from https://medium.com/walletconnect/how-to-build-a-wallet-in-react-native-with-the-web3wallet-sdk-b6f57bf02f9a // Taken from https://medium.com/walletconnect/how-to-build-a-wallet-in-react-native-with-the-web3wallet-sdk-b6f57bf02f9a
import { retrieveAccounts } from '../accounts';
import { EIP155_CHAINS, TEIP155Chain } from './EIP155Lib';
import { utils } from 'ethers'; import { utils } from 'ethers';
import { Account } from '../../types';
import { EIP155_CHAINS, TEIP155Chain } from './EIP155Lib';
/** /**
* Truncates string (in the middle) via given lenght value * Truncates string (in the middle) via given lenght value
*/ */
@ -67,6 +68,7 @@ export function getSignTypedDataParamsData(params: string[]) {
*/ */
export async function getAccountNumberFromParams( export async function getAccountNumberFromParams(
addresses: string[], addresses: string[],
ethAccounts: Account[],
params: any, params: any,
) { ) {
const paramsString = JSON.stringify(params); const paramsString = JSON.stringify(params);
@ -78,9 +80,7 @@ export async function getAccountNumberFromParams(
} }
}); });
const { ethLoadedAccounts } = await retrieveAccounts(); const currentAccount = ethAccounts!.find(
const currentAccount = ethLoadedAccounts!.find(
account => account.address === address, account => account.address === address,
); );