forked from cerc-io/laconic-wallet
Use context for maintaining accounts state (#41)
* Use context for maintaining accounts state * Remove custom hook from context
This commit is contained in:
parent
19e39281a6
commit
a4e0dc5406
31
App.tsx
31
App.tsx
@ -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'],
|
||||||
|
@ -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);
|
||||||
|
@ -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}>
|
||||||
|
@ -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,
|
||||||
|
25
context/AccountsContext.tsx
Normal file
25
context/AccountsContext.tsx
Normal 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 };
|
5
index.js
5
index.js
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
5
types.ts
5
types.ts
@ -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 = {
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user