/* 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 { Wallet, utils } from 'ethers'; import { HDNode } from 'ethers/lib/utils'; import { setInternetCredentials, getInternetCredentials, resetInternetCredentials, } from 'react-native-keychain'; import { AccountData, Secp256k1HdWallet } from '@cosmjs/amino'; import { stringToPath } from '@cosmjs/crypto'; const createWallet = async (): Promise<{ ethWalletInfo: { pubKey: string; address: string } | undefined; cosmosWalletInfo: { pubKey: string; address: string } | undefined; }> => { try { const mnemonic = utils.entropyToMnemonic(utils.randomBytes(32)); 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)).data.address; await setInternetCredentials( 'eth:keyServer:0', 'eth:key:0', ethNode.privateKey, ); await setInternetCredentials( 'cosmos:keyServer:0', 'cosmos:key:0', cosmosNode.privateKey, ); const ethWalletInfo = { pubKey: ethNode.publicKey, address: ethAddress }; const cosmosWalletInfo = { pubKey: cosmosNode.publicKey, address: cosmosAddress, }; return { ethWalletInfo, cosmosWalletInfo }; } catch (error) { console.error('Error creating HD wallet:', error); return { ethWalletInfo: undefined, cosmosWalletInfo: undefined }; } }; async function getCosmosAccounts( mnemonic: string, index: number, ): Promise<{ cosmosWallet: Secp256k1HdWallet; data: AccountData }> { const cosmosWallet = await Secp256k1HdWallet.fromMnemonic(mnemonic, { hdPaths: [stringToPath(`m/44'/118'/0'/0/${index}`)], }); const accountsData = await cosmosWallet.getAccounts(); const data = accountsData[index]; return { cosmosWallet, data }; } const signMessage = async ( message: string, walletType: string, index: number, ): Promise => { try { console.log(walletType); switch (walletType) { case 'eth': return await signEthMessage(message, index); case 'cosmos': return await signCosmosMessage(message, index); default: throw new Error('Invalid wallet type'); } } catch (error) { console.error('Error signing message:', error); } }; const signEthMessage = async ( message: string, index: number, ): Promise => { try { const keyCred = await getInternetCredentials(`eth:keyServer:${index}`); if (!keyCred) { throw new Error('Failed to retrieve internet credentials'); } const wallet = new Wallet(keyCred.password); const signature = await wallet.signMessage(message); return signature; } catch (error) { console.error('Error signing Ethereum message:', error); } }; const signCosmosMessage = async ( message: string, index: number, ): Promise => { try { const mnemonicStore = await getInternetCredentials('mnemonicServer'); if (mnemonicStore) { const mnemonic = mnemonicStore.password; const cosmosAddress = (await getCosmosAccounts(mnemonic, index)).data .address; const cosmosSignature = await ( await getCosmosAccounts(mnemonic, index) ).cosmosWallet.signAmino(cosmosAddress, { chain_id: '', account_number: '0', sequence: '0', fee: { gas: '0', amount: [], }, msgs: [ { type: 'sign/MsgSignData', value: { signer: cosmosAddress, data: btoa(message), }, }, ], memo: '', }); return cosmosSignature.signature.signature; } } catch (error) { console.error('Error signing message:', error); } }; // const createAccount const resetWallet = async () => { // TODO: Add method to reset all the accounts await resetInternetCredentials('mnemonicServer'); await resetInternetCredentials('eth:keyServer:0'); await resetInternetCredentials('cosmos:keyServer:0'); }; export { createWallet, signMessage, resetWallet };