forked from cerc-io/laconic-wallet
* Send networks data to dapp * Reflect switching tabs in dapp dropdown * Fix current network name not showing in Dapp * Modify variable names * Modify method and variable names * Modify networks type * Use selectedNetwork state and networkId * Fix networks context states * Add separate file for network methods
225 lines
7.1 KiB
TypeScript
225 lines
7.1 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { ScrollView, TouchableOpacity, View } from 'react-native';
|
|
import { Button, List, Text, useTheme } from 'react-native-paper';
|
|
import mergeWith from 'lodash/mergeWith';
|
|
|
|
import { useNavigation } from '@react-navigation/native';
|
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
|
|
import { AccountsProps, StackParamsList, Account } from '../types';
|
|
import { addAccount } from '../utils/accounts';
|
|
import styles from '../styles/stylesheet';
|
|
import HDPathDialog from './HDPathDialog';
|
|
import AccountDetails from './AccountDetails';
|
|
import { useAccounts } from '../context/AccountsContext';
|
|
import { web3wallet } from '../utils/wallet-connect/WalletConnectUtils';
|
|
import { EIP155_SIGNING_METHODS } from '../utils/wallet-connect/EIP155Data';
|
|
import { COSMOS_METHODS } from '../utils/wallet-connect/COSMOSData';
|
|
import { useNetworks } from '../context/NetworksContext';
|
|
import { COSMOS, EIP155 } from '../utils/constants';
|
|
import { NETWORK_METHODS } from '../utils/wallet-connect/common-data';
|
|
|
|
const Accounts = ({ currentIndex, updateIndex }: AccountsProps) => {
|
|
const navigation =
|
|
useNavigation<NativeStackNavigationProp<StackParamsList>>();
|
|
|
|
const { accounts, setAccounts } = useAccounts();
|
|
const { selectedNetwork } = useNetworks();
|
|
const [expanded, setExpanded] = useState(false);
|
|
const [isAccountCreating, setIsAccountCreating] = useState(false);
|
|
const [hdDialog, setHdDialog] = useState(false);
|
|
const [pathCode, setPathCode] = useState('');
|
|
const theme = useTheme();
|
|
|
|
const handlePress = () => setExpanded(!expanded);
|
|
|
|
const updateAccounts = (account: Account) => {
|
|
setAccounts([...accounts, account]);
|
|
};
|
|
|
|
useEffect(() => {
|
|
const updateSessions = async () => {
|
|
const sessions = (web3wallet && web3wallet.getActiveSessions()) || {};
|
|
// Iterate through each session
|
|
|
|
for (const topic in sessions) {
|
|
const session = sessions[topic];
|
|
const combinedNamespaces = mergeWith(
|
|
session.requiredNamespaces,
|
|
session.optionalNamespaces,
|
|
(obj, src) =>
|
|
Array.isArray(obj) && Array.isArray(src)
|
|
? [...src, ...obj]
|
|
: undefined,
|
|
);
|
|
|
|
const namespaceChainId = `${selectedNetwork?.namespace}:${selectedNetwork?.chainId}`;
|
|
|
|
let updatedNamespaces;
|
|
switch (selectedNetwork?.namespace) {
|
|
case EIP155:
|
|
updatedNamespaces = {
|
|
eip155: {
|
|
chains: [namespaceChainId],
|
|
// TODO: Debug optional namespace methods and events being required for approval
|
|
methods: [
|
|
...Object.values(EIP155_SIGNING_METHODS),
|
|
...Object.values(NETWORK_METHODS),
|
|
...(combinedNamespaces.eip155?.methods ?? []),
|
|
],
|
|
events: [...(combinedNamespaces.eip155?.events ?? [])],
|
|
accounts: accounts.map(ethAccount => {
|
|
return `${namespaceChainId}:${ethAccount.address}`;
|
|
}),
|
|
},
|
|
cosmos: {
|
|
chains: [],
|
|
methods: [],
|
|
events: [],
|
|
accounts: [],
|
|
},
|
|
};
|
|
break;
|
|
case COSMOS:
|
|
updatedNamespaces = {
|
|
cosmos: {
|
|
chains: [namespaceChainId],
|
|
methods: [
|
|
...Object.values(COSMOS_METHODS),
|
|
...Object.values(NETWORK_METHODS),
|
|
...(combinedNamespaces.cosmos?.methods ?? []),
|
|
],
|
|
events: [...(combinedNamespaces.cosmos?.events ?? [])],
|
|
accounts: accounts.map(cosmosAccount => {
|
|
return `${namespaceChainId}:${cosmosAccount.address}`;
|
|
}),
|
|
},
|
|
eip155: {
|
|
chains: [],
|
|
methods: [],
|
|
events: [],
|
|
accounts: [],
|
|
},
|
|
};
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!updatedNamespaces) {
|
|
return;
|
|
}
|
|
|
|
await web3wallet!.updateSession({
|
|
topic,
|
|
namespaces: updatedNamespaces,
|
|
});
|
|
}
|
|
};
|
|
// Call the updateSessions function when the 'accounts' dependency changes
|
|
updateSessions();
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [accounts]);
|
|
|
|
const addAccountHandler = async () => {
|
|
setIsAccountCreating(true);
|
|
const newAccount = await addAccount(selectedNetwork!);
|
|
setIsAccountCreating(false);
|
|
if (newAccount) {
|
|
updateAccounts(newAccount);
|
|
updateIndex(newAccount.index);
|
|
}
|
|
};
|
|
|
|
const renderAccountItems = () =>
|
|
accounts.map(account => (
|
|
<List.Item
|
|
key={account.index}
|
|
title={`Account ${account.index + 1}`}
|
|
onPress={() => {
|
|
updateIndex(account.index);
|
|
setExpanded(false);
|
|
}}
|
|
/>
|
|
));
|
|
|
|
return (
|
|
<ScrollView>
|
|
<View>
|
|
<HDPathDialog
|
|
visible={hdDialog}
|
|
hideDialog={() => setHdDialog(false)}
|
|
updateAccounts={updateAccounts}
|
|
updateIndex={updateIndex}
|
|
pathCode={pathCode}
|
|
/>
|
|
<List.Accordion
|
|
title={`Account ${currentIndex + 1}`}
|
|
expanded={expanded}
|
|
onPress={handlePress}>
|
|
{renderAccountItems()}
|
|
</List.Accordion>
|
|
|
|
<View style={styles.addAccountButton}>
|
|
<Button
|
|
mode="contained"
|
|
onPress={addAccountHandler}
|
|
loading={isAccountCreating}>
|
|
{isAccountCreating ? 'Adding' : 'Add Account'}
|
|
</Button>
|
|
</View>
|
|
|
|
<View style={styles.addAccountButton}>
|
|
<Button
|
|
mode="contained"
|
|
onPress={() => {
|
|
setHdDialog(true);
|
|
// TODO: Use coin type while adding from HD path
|
|
setPathCode(
|
|
selectedNetwork!.namespace === EIP155
|
|
? "m/44'/60'/"
|
|
: "m/44'/118'/",
|
|
);
|
|
}}>
|
|
Add Account from HD path
|
|
</Button>
|
|
</View>
|
|
|
|
<AccountDetails account={accounts[currentIndex]} />
|
|
|
|
<View style={styles.signLink}>
|
|
<TouchableOpacity
|
|
onPress={() => {
|
|
navigation.navigate('SignMessage', {
|
|
selectedNamespace: selectedNetwork!.namespace,
|
|
selectedChainId: selectedNetwork!.chainId,
|
|
accountInfo: accounts[currentIndex],
|
|
});
|
|
}}>
|
|
<Text
|
|
variant="titleSmall"
|
|
style={[styles.hyperlink, { color: theme.colors.primary }]}>
|
|
Sign Message
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<View style={styles.signLink}>
|
|
<TouchableOpacity
|
|
onPress={() => {
|
|
navigation.navigate('AddNetwork');
|
|
}}>
|
|
<Text
|
|
variant="titleSmall"
|
|
style={[styles.hyperlink, { color: theme.colors.primary }]}>
|
|
Add Network
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
</ScrollView>
|
|
);
|
|
};
|
|
|
|
export default Accounts;
|