forked from cerc-io/laconic-wallet
Retrieve accounts on reload (#29)
* Display HD path on sign message page * Create component for displaying account details * Add retrieve accounts function * Load accounts after closing app * Fix the retrieve accounts function * Use hdpath instead of id * Check if keystore is empty while retrieving accounts * Add spinner when accounts are being fetched * Display complete hd paths after reloading the app * Remove any return type * Store public key and address * Modify sign message function to use path * Fix the add accounts functionality
This commit is contained in:
@@ -8,6 +8,7 @@ import { HDNode } from 'ethers/lib/utils';
|
||||
import {
|
||||
setInternetCredentials,
|
||||
resetInternetCredentials,
|
||||
getInternetCredentials,
|
||||
} from 'react-native-keychain';
|
||||
|
||||
import { Account, WalletDetails } from '../types';
|
||||
@@ -18,6 +19,7 @@ import {
|
||||
getHDPath,
|
||||
getMnemonic,
|
||||
getNextAccountId,
|
||||
getPathKey,
|
||||
resetKeyServers,
|
||||
updateAccountIndices,
|
||||
updateGlobalCounter,
|
||||
@@ -33,11 +35,13 @@ const createWallet = async (): Promise<WalletDetails> => {
|
||||
const cosmosNode = hdNode.derivePath("m/44'/118'/0'/0/0");
|
||||
|
||||
const ethAddress = ethNode.address;
|
||||
const cosmosAddress = (await getCosmosAccounts(mnemonic, `0'/0/0`)).data
|
||||
const cosmosAddress = (await getCosmosAccounts(mnemonic, "0'/0/0")).data
|
||||
.address;
|
||||
|
||||
const ethAccountInfo = `${`0'/0/0`},${ethNode.privateKey}`;
|
||||
const cosmosAccountInfo = `${`0'/0/0`},${cosmosNode.privateKey}`;
|
||||
const ethAccountInfo = `${"0'/0/0"},${ethNode.privateKey},${ethNode.publicKey
|
||||
},${ethAddress}`;
|
||||
const cosmosAccountInfo = `${"0'/0/0"},${cosmosNode.privateKey},${cosmosNode.publicKey
|
||||
},${cosmosAddress}`;
|
||||
|
||||
await Promise.all([
|
||||
setInternetCredentials(
|
||||
@@ -82,26 +86,20 @@ const addAccount = async (network: string): Promise<Account | undefined> => {
|
||||
const mnemonic = await getMnemonic();
|
||||
const hdNode = HDNode.fromMnemonic(mnemonic);
|
||||
const id = await getNextAccountId(network);
|
||||
const hdPath = getHDPath(network, id);
|
||||
const hdPath = getHDPath(network, `0'/0/${id}`);
|
||||
|
||||
const node = hdNode.derivePath(hdPath);
|
||||
const pubKey = node.publicKey;
|
||||
const address = await getAddress(network, mnemonic, id);
|
||||
const address = await getAddress(network, mnemonic, `0'/0/${id}`);
|
||||
|
||||
await updateAccountIndices(network, id);
|
||||
const { accountCounter, counterId } = await updateGlobalCounter(network);
|
||||
const { counterId } = await updateGlobalCounter(network);
|
||||
|
||||
await Promise.all([
|
||||
resetInternetCredentials(`${network}:globalCounter`),
|
||||
setInternetCredentials(
|
||||
`${network}:globalCounter`,
|
||||
`${network}Global`,
|
||||
accountCounter,
|
||||
),
|
||||
setInternetCredentials(
|
||||
`${network}:keyServer:${counterId}`,
|
||||
`${network}:pathKey:${counterId}`,
|
||||
`0'/0/${id},${node.privateKey}`,
|
||||
`0'/0/${id},${node.privateKey},${node.publicKey},${address}`,
|
||||
),
|
||||
]);
|
||||
|
||||
@@ -125,20 +123,13 @@ const addAccountFromHDPath = async (
|
||||
|
||||
const { privKey, pubKey, address, network } = account;
|
||||
|
||||
const { accountCounter, counterId } = await updateGlobalCounter(network);
|
||||
const updatedAccountCounter = `${accountCounter},${counterId.toString()}`;
|
||||
const counterId = (await updateGlobalCounter(network)).counterId;
|
||||
|
||||
await Promise.all([
|
||||
resetInternetCredentials(`${network}:globalCounter`),
|
||||
setInternetCredentials(
|
||||
`${network}:globalCounter`,
|
||||
`${network}Global`,
|
||||
updatedAccountCounter,
|
||||
),
|
||||
setInternetCredentials(
|
||||
`${network}:keyServer:${counterId}`,
|
||||
`${network}:pathKey:${counterId}`,
|
||||
`${path},${privKey}`,
|
||||
`${path},${privKey},${pubKey},${address}`,
|
||||
),
|
||||
]);
|
||||
|
||||
@@ -148,6 +139,51 @@ const addAccountFromHDPath = async (
|
||||
}
|
||||
};
|
||||
|
||||
const retrieveAccountsForNetwork = async (
|
||||
network: string,
|
||||
count: string,
|
||||
): Promise<Account[]> => {
|
||||
const elementsArray = count.split(',');
|
||||
|
||||
const loadedAccounts = await Promise.all(
|
||||
elementsArray.map(async i => {
|
||||
const pubKey = (await getPathKey(network, Number(i))).pubKey;
|
||||
const address = (await getPathKey(network, Number(i))).address;
|
||||
const path = (await getPathKey(network, Number(i))).path;
|
||||
const hdPath = getHDPath(network, path);
|
||||
|
||||
const account: Account = {
|
||||
counterId: Number(i),
|
||||
pubKey: pubKey,
|
||||
address: address,
|
||||
hdPath: hdPath,
|
||||
};
|
||||
return account;
|
||||
}),
|
||||
);
|
||||
|
||||
return loadedAccounts;
|
||||
};
|
||||
|
||||
const retrieveAccounts = async (): Promise<{
|
||||
ethLoadedAccounts?: Account[];
|
||||
cosmosLoadedAccounts?: Account[];
|
||||
}> => {
|
||||
const ethServer = await getInternetCredentials('eth:globalCounter');
|
||||
const ethCounter = ethServer && ethServer.password;
|
||||
const cosmosServer = await getInternetCredentials('cosmos:globalCounter');
|
||||
const cosmosCounter = cosmosServer && cosmosServer.password;
|
||||
|
||||
const ethLoadedAccounts = ethCounter
|
||||
? await retrieveAccountsForNetwork('eth', ethCounter)
|
||||
: undefined;
|
||||
const cosmosLoadedAccounts = cosmosCounter
|
||||
? await retrieveAccountsForNetwork('cosmos', cosmosCounter)
|
||||
: undefined;
|
||||
|
||||
return { ethLoadedAccounts, cosmosLoadedAccounts };
|
||||
};
|
||||
|
||||
const resetWallet = async () => {
|
||||
try {
|
||||
await Promise.all([
|
||||
@@ -165,4 +201,10 @@ const resetWallet = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
export { createWallet, addAccount, addAccountFromHDPath, resetWallet };
|
||||
export {
|
||||
createWallet,
|
||||
addAccount,
|
||||
addAccountFromHDPath,
|
||||
retrieveAccounts,
|
||||
resetWallet,
|
||||
};
|
||||
@@ -13,13 +13,13 @@ const signMessage = async ({
|
||||
network,
|
||||
accountId,
|
||||
}: SignMessageParams): Promise<string | undefined> => {
|
||||
const hdPath = (await getPathKey(network, accountId)).hdPath;
|
||||
const path = (await getPathKey(network, accountId)).path;
|
||||
|
||||
switch (network) {
|
||||
case 'eth':
|
||||
return await signEthMessage(message, accountId);
|
||||
case 'cosmos':
|
||||
return await signCosmosMessage(message, hdPath);
|
||||
return await signCosmosMessage(message, path);
|
||||
default:
|
||||
throw new Error('Invalid wallet type');
|
||||
}
|
||||
@@ -43,11 +43,11 @@ const signEthMessage = async (
|
||||
|
||||
const signCosmosMessage = async (
|
||||
message: string,
|
||||
hdPath: string,
|
||||
path: string,
|
||||
): Promise<string | undefined> => {
|
||||
try {
|
||||
const mnemonic = await getMnemonic();
|
||||
const cosmosAccount = await getCosmosAccounts(mnemonic, hdPath);
|
||||
const cosmosAccount = await getCosmosAccounts(mnemonic, path);
|
||||
const address = cosmosAccount.data.address;
|
||||
const cosmosSignature = await cosmosAccount.cosmosWallet.signAmino(
|
||||
address,
|
||||
+17
-10
@@ -23,21 +23,21 @@ const getMnemonic = async (): Promise<string> => {
|
||||
return mnemonic;
|
||||
};
|
||||
|
||||
const getHDPath = (network: string, id: number): string => {
|
||||
return network === 'eth' ? `m/44'/60'/0'/0/${id}` : `m/44'/118'/0'/0/${id}`;
|
||||
const getHDPath = (network: string, path: string): string => {
|
||||
return network === 'eth' ? `m/44'/60'/${path}` : `m/44'/118'/${path}`;
|
||||
};
|
||||
|
||||
const getAddress = async (
|
||||
network: string,
|
||||
mnemonic: string,
|
||||
id: number,
|
||||
path: string,
|
||||
): Promise<string> => {
|
||||
switch (network) {
|
||||
case 'eth':
|
||||
return HDNode.fromMnemonic(mnemonic).derivePath(`m/44'/60'/0'/0/${id}`)
|
||||
return HDNode.fromMnemonic(mnemonic).derivePath(`m/44'/60'/${path}`)
|
||||
.address;
|
||||
case 'cosmos':
|
||||
return (await getCosmosAccounts(mnemonic, `0'/0/${id}`)).data.address;
|
||||
return (await getCosmosAccounts(mnemonic, `${path}`)).data.address;
|
||||
default:
|
||||
throw new Error('Invalid wallet type');
|
||||
}
|
||||
@@ -45,10 +45,10 @@ const getAddress = async (
|
||||
|
||||
const getCosmosAccounts = async (
|
||||
mnemonic: string,
|
||||
hdPath: string,
|
||||
path: string,
|
||||
): Promise<{ cosmosWallet: Secp256k1HdWallet; data: AccountData }> => {
|
||||
const cosmosWallet = await Secp256k1HdWallet.fromMnemonic(mnemonic, {
|
||||
hdPaths: [stringToPath(`m/44'/118'/${hdPath}`)],
|
||||
hdPaths: [stringToPath(`m/44'/118'/${path}`)],
|
||||
});
|
||||
|
||||
const accountsData = await cosmosWallet.getAccounts();
|
||||
@@ -100,7 +100,12 @@ const accountInfoFromHDPath = async (
|
||||
const getPathKey = async (
|
||||
network: string,
|
||||
accountId: number,
|
||||
): Promise<{ hdPath: string; privKey: string }> => {
|
||||
): Promise<{
|
||||
path: string;
|
||||
privKey: string;
|
||||
pubKey: string;
|
||||
address: string;
|
||||
}> => {
|
||||
const pathKeyStore = await getInternetCredentials(
|
||||
`${network}:keyServer:${accountId}`,
|
||||
);
|
||||
@@ -111,10 +116,12 @@ const getPathKey = async (
|
||||
|
||||
const pathKeyVal = pathKeyStore.password;
|
||||
const pathkey = pathKeyVal.split(',');
|
||||
const hdPath = pathkey[0];
|
||||
const path = pathkey[0];
|
||||
const privKey = pathkey[1];
|
||||
const pubKey = pathkey[2];
|
||||
const address = pathkey[3];
|
||||
|
||||
return { hdPath, privKey };
|
||||
return { path, privKey, pubKey, address };
|
||||
};
|
||||
|
||||
const getGlobalCounter = async (
|
||||
|
||||
Reference in New Issue
Block a user