/* 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 { utils } from 'ethers'; import { HDNode } from 'ethers/lib/utils'; import { setInternetCredentials, resetInternetCredentials, } from 'react-native-keychain'; import { Account, WalletDetails } from '../types'; import { accountInfoFromHDPath, getAddress, getCosmosAccounts, getHDPath, getMnemonic, getNextAccountId, resetKeyServers, updateAccountIndices, updateGlobalCounter, } from './utils'; const createWallet = async (): Promise => { try { const mnemonic = utils.entropyToMnemonic(utils.randomBytes(16)); await setInternetCredentials('mnemonicServer', 'mnemonic', mnemonic); const hdNode = HDNode.fromMnemonic(mnemonic); const ethNode = hdNode.derivePath("m/44'/60'/0'/0/0"); const cosmosNode = hdNode.derivePath("m/44'/118'/0'/0/0"); const ethAddress = ethNode.address; const cosmosAddress = (await getCosmosAccounts(mnemonic, `0'/0/0`)).data .address; const ethAccountInfo = `${`0'/0/0`},${ethNode.privateKey}`; const cosmosAccountInfo = `${`0'/0/0`},${cosmosNode.privateKey}`; await Promise.all([ setInternetCredentials( 'eth:keyServer:0', 'eth:pathKey:0', ethAccountInfo, ), setInternetCredentials( 'cosmos:keyServer:0', 'cosmos:pathKey:0', cosmosAccountInfo, ), setInternetCredentials('eth:accountIndices', 'ethCounter', '0'), setInternetCredentials('cosmos:accountIndices', 'cosmosCounter', '0'), setInternetCredentials('eth:globalCounter', 'ethGlobal', '0'), setInternetCredentials('cosmos:globalCounter', 'cosmosGlobal', '0'), ]); const ethAccounts = { counterId: 0, pubKey: ethNode.publicKey, address: ethAddress, hdPath: "m/44'/60'/0'/0/0", }; const cosmosAccounts = { counterId: 0, pubKey: cosmosNode.publicKey, address: cosmosAddress, hdPath: "m/44'/118'/0'/0/0", }; return { mnemonic, ethAccounts, cosmosAccounts }; } catch (error) { console.error('Error creating HD wallet:', error); return { mnemonic: '', ethAccounts: undefined, cosmosAccounts: undefined }; } }; const addAccount = async (network: string): Promise => { try { const mnemonic = await getMnemonic(); const hdNode = HDNode.fromMnemonic(mnemonic); const id = await getNextAccountId(network); const hdPath = getHDPath(network, id); const node = hdNode.derivePath(hdPath); const pubKey = node.publicKey; const address = await getAddress(network, mnemonic, id); await updateAccountIndices(network, id); const { accountCounter, 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}`, ), ]); return { counterId, pubKey, address, hdPath }; } catch (error) { console.error('Error creating account:', error); } }; const addAccountFromHDPath = async ( hdPath: string, ): Promise => { try { const account = await accountInfoFromHDPath(hdPath); if (!account) { throw new Error('Error while creating account'); } const parts = hdPath.split('/'); const path = parts.slice(-3).join('/'); const { privKey, pubKey, address, network } = account; const { accountCounter, counterId } = await updateGlobalCounter(network); const updatedAccountCounter = `${accountCounter},${counterId.toString()}`; await Promise.all([ resetInternetCredentials(`${network}:globalCounter`), setInternetCredentials( `${network}:globalCounter`, `${network}Global`, updatedAccountCounter, ), setInternetCredentials( `${network}:keyServer:${counterId}`, `${network}:pathKey:${counterId}`, `${path},${privKey}`, ), ]); return { counterId, pubKey, address, hdPath }; } catch (error) { console.error(error); } }; const resetWallet = async () => { try { await Promise.all([ resetInternetCredentials('mnemonicServer'), resetKeyServers('eth'), resetKeyServers('cosmos'), resetInternetCredentials('eth:accountIndices'), resetInternetCredentials('cosmos:accountIndices'), resetInternetCredentials('eth:globalCounter'), resetInternetCredentials('cosmos:globalCounter'), ]); } catch (error) { console.error('Error resetting wallet:', error); throw error; } }; export { createWallet, addAccount, addAccountFromHDPath, resetWallet };