laconic-wallet/utils/utils.ts
IshaVenikar 783758be39
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
2024-02-22 11:32:25 +05:30

221 lines
5.8 KiB
TypeScript

/* Importing this library provides react native with a secure random source.
For more information, "visit https://docs.ethers.org/v5/cookbook/react-native/#cookbook-reactnative-security" */
import 'react-native-get-random-values';
import '@ethersproject/shims';
import { HDNode } from 'ethers/lib/utils';
import {
getInternetCredentials,
resetInternetCredentials,
setInternetCredentials,
} from 'react-native-keychain';
import { AccountData, Secp256k1HdWallet } from '@cosmjs/amino';
import { stringToPath } from '@cosmjs/crypto';
const getMnemonic = async (): Promise<string> => {
const mnemonicStore = await getInternetCredentials('mnemonicServer');
if (!mnemonicStore) {
throw new Error('Mnemonic not found!');
}
const mnemonic = mnemonicStore.password;
return mnemonic;
};
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,
path: string,
): Promise<string> => {
switch (network) {
case 'eth':
return HDNode.fromMnemonic(mnemonic).derivePath(`m/44'/60'/${path}`)
.address;
case 'cosmos':
return (await getCosmosAccounts(mnemonic, `${path}`)).data.address;
default:
throw new Error('Invalid wallet type');
}
};
const getCosmosAccounts = async (
mnemonic: string,
path: string,
): Promise<{ cosmosWallet: Secp256k1HdWallet; data: AccountData }> => {
const cosmosWallet = await Secp256k1HdWallet.fromMnemonic(mnemonic, {
hdPaths: [stringToPath(`m/44'/118'/${path}`)],
});
const accountsData = await cosmosWallet.getAccounts();
const data = accountsData[0];
return { cosmosWallet, data };
};
const accountInfoFromHDPath = async (
hdPath: string,
): Promise<
| { privKey: string; pubKey: string; address: string; network: string }
| undefined
> => {
const mnemonicStore = await getInternetCredentials('mnemonicServer');
if (!mnemonicStore) {
throw new Error('Mnemonic not found!');
}
const mnemonic = mnemonicStore.password;
const hdNode = HDNode.fromMnemonic(mnemonic);
const node = hdNode.derivePath(hdPath);
const privKey = node.privateKey;
const pubKey = node.publicKey;
const parts = hdPath.split('/');
const path = parts.slice(-3).join('/');
const coinType = parts[2];
let network: string;
let address: string;
switch (coinType) {
case "60'":
network = 'eth';
address = node.address;
break;
case "118'":
network = 'cosmos';
address = (await getCosmosAccounts(mnemonic, path)).data.address;
break;
default:
throw new Error('Invalid wallet type');
}
return { privKey, pubKey, address, network };
};
const getPathKey = async (
network: string,
accountId: number,
): Promise<{
path: string;
privKey: string;
pubKey: string;
address: string;
}> => {
const pathKeyStore = await getInternetCredentials(
`${network}:keyServer:${accountId}`,
);
if (!pathKeyStore) {
throw new Error('Error while fetching counter');
}
const pathKeyVal = pathKeyStore.password;
const pathkey = pathKeyVal.split(',');
const path = pathkey[0];
const privKey = pathkey[1];
const pubKey = pathkey[2];
const address = pathkey[3];
return { path, privKey, pubKey, address };
};
const getGlobalCounter = async (
network: string,
): Promise<{
accountCounter: string;
counterIds: number[];
counterId: number;
}> => {
const counterStore = await getInternetCredentials(`${network}:globalCounter`);
if (!counterStore) {
throw new Error('Error while fetching counter');
}
let accountCounter = counterStore.password;
const counterIds = accountCounter.split(',').map(Number);
const counterId = counterIds[counterIds.length - 1] + 1;
return { accountCounter, counterIds, counterId };
};
const updateGlobalCounter = async (
network: string,
): Promise<{ accountCounter: string; counterId: number }> => {
const globalCounterData = await getGlobalCounter(network);
const accountCounter = globalCounterData.accountCounter;
const counterId = globalCounterData.counterId;
const updatedAccountCounter = `${accountCounter},${counterId.toString()}`;
await resetInternetCredentials(`${network}:globalCounter`);
await setInternetCredentials(
`${network}:globalCounter`,
`${network}Global`,
updatedAccountCounter,
);
return { accountCounter: updatedAccountCounter, counterId };
};
const getNextAccountId = async (network: string): Promise<number> => {
const idStore = await getInternetCredentials(`${network}:accountIndices`);
if (!idStore) {
throw new Error('Account id not found');
}
const accountIds = idStore.password;
const ids = accountIds.split(',').map(Number);
return ids[ids.length - 1] + 1;
};
const updateAccountIndices = async (
network: string,
id: number,
): Promise<void> => {
const idStore = await getInternetCredentials(`${network}:accountIndices`);
if (!idStore) {
throw new Error('Account id not found');
}
const updatedIndices = `${idStore.password},${id.toString()}`;
await resetInternetCredentials(`${network}:accountIndices`);
await setInternetCredentials(
`${network}:accountIndices`,
`${network}Counter`,
updatedIndices,
);
};
const resetKeyServers = async (prefix: string) => {
const idStore = await getInternetCredentials(`${prefix}:accountIndices`);
if (!idStore) {
throw new Error('Account id not found.');
}
const accountIds = idStore.password;
const ids = accountIds.split(',').map(Number);
const id = ids[ids.length - 1];
for (let i = 0; i <= id; i++) {
await resetInternetCredentials(`${prefix}:keyServer:${i}`);
}
};
export {
accountInfoFromHDPath,
getCosmosAccounts,
getMnemonic,
getPathKey,
getNextAccountId,
updateGlobalCounter,
updateAccountIndices,
getHDPath,
getAddress,
resetKeyServers,
};