From 899cb90d407e22c09aacd50882c8e41045103c88 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 9 Aug 2024 14:25:58 +0530 Subject: [PATCH] Implement functionality to import wallet from mnemonic --- src/components/CreateWallet.tsx | 2 +- src/components/ImportWalletDialog.tsx | 60 +++++++++++++++++++ .../{Dialog.tsx => MnemonicDialog.tsx} | 4 +- src/screens/HomeScreen.tsx | 48 +++++++++++---- src/styles/stylesheet.js | 6 ++ src/utils/accounts.ts | 17 +++++- 6 files changed, 120 insertions(+), 17 deletions(-) create mode 100644 src/components/ImportWalletDialog.tsx rename src/components/{Dialog.tsx => MnemonicDialog.tsx} (96%) diff --git a/src/components/CreateWallet.tsx b/src/components/CreateWallet.tsx index 5ba0708..584377c 100644 --- a/src/components/CreateWallet.tsx +++ b/src/components/CreateWallet.tsx @@ -1,5 +1,5 @@ -import { View } from 'react-native'; import React from 'react'; +import { View } from 'react-native'; import { Button } from 'react-native-paper'; import { CreateWalletProps } from '../types'; diff --git a/src/components/ImportWalletDialog.tsx b/src/components/ImportWalletDialog.tsx new file mode 100644 index 0000000..9ecc053 --- /dev/null +++ b/src/components/ImportWalletDialog.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import { View, TextInput } from 'react-native'; +import { Dialog, Portal, Paragraph, Button } from 'react-native-paper'; + +import styles from '../styles/stylesheet'; + +const ImportWalletDialog = ({ + visible, + hideDialog, + importWalletHandler, +}: { + visible: boolean; + hideDialog: () => void; + importWalletHandler: (recoveryPhrase: string) => Promise; +}) => { + const [words, setWords] = useState(Array(12).fill('')); + + const handleWordChange = (index: number, value: string) => { + const newWords = [...words]; + newWords[index] = value; + setWords(newWords); + }; + + return ( + + + Import your wallet from your mnemonic + + + (You can paste your entire mnemonic into the first textbox) + + + {words.map((word, index) => ( + + handleWordChange(index, text)} + placeholder={`Word ${index + 1}`} + style={styles.textInput} + /> + + ))} + + + + + + + + + ); +}; + +export default ImportWalletDialog; diff --git a/src/components/Dialog.tsx b/src/components/MnemonicDialog.tsx similarity index 96% rename from src/components/Dialog.tsx rename to src/components/MnemonicDialog.tsx index 91f55b9..4c3e4f7 100644 --- a/src/components/Dialog.tsx +++ b/src/components/MnemonicDialog.tsx @@ -8,7 +8,7 @@ import styles from '../styles/stylesheet'; import GridView from './Grid'; import { CustomDialogProps } from '../types'; -const DialogComponent = ({ +const MnemonicDialog = ({ visible, hideDialog, contentText, @@ -55,4 +55,4 @@ const DialogComponent = ({ ); }; -export { DialogComponent }; +export { MnemonicDialog }; diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 98710cc..ed6c0b1 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -7,7 +7,8 @@ import { useNavigation } from '@react-navigation/native'; import { getSdkError } from '@walletconnect/utils'; import { createWallet, resetWallet, retrieveAccounts } from '../utils/accounts'; -import { DialogComponent } from '../components/Dialog'; +import { MnemonicDialog } from '../components/MnemonicDialog'; +import ImportWalletDialog from '../components/ImportWalletDialog'; import { NetworkDropdown } from '../components/NetworkDropdown'; import Accounts from '../components/Accounts'; import CreateWallet from '../components/CreateWallet'; @@ -55,12 +56,13 @@ const HomeScreen = () => { const [isWalletCreated, setIsWalletCreated] = useState(false); const [isWalletCreating, setIsWalletCreating] = useState(false); - const [walletDialog, setWalletDialog] = useState(false); + const [importWalletDialog, setImportWalletDialog] = useState(false); + const [mnemonicDialog, setMnemonicDialog] = useState(false); const [resetWalletDialog, setResetWalletDialog] = useState(false); const [isAccountsFetched, setIsAccountsFetched] = useState(false); const [phrase, setPhrase] = useState(''); - const hideWalletDialog = () => setWalletDialog(false); + const hideMnemonicDialog = () => setMnemonicDialog(false); const hideResetDialog = () => setResetWalletDialog(false); const fetchAccounts = useCallback(async () => { @@ -83,12 +85,22 @@ const HomeScreen = () => { const mnemonic = await createWallet(networksData); if (mnemonic) { fetchAccounts(); - setWalletDialog(true); + setMnemonicDialog(true); setPhrase(mnemonic); setSelectedNetwork(networksData[0]); } }; + const importWalletHandler = async (recoveryPhrase: string) => { + const mnemonic = await createWallet(networksData, recoveryPhrase); + if (mnemonic) { + fetchAccounts(); + setPhrase(mnemonic); + setSelectedNetwork(networksData[0]); + setImportWalletDialog(false); + } + }; + const confirmResetWallet = useCallback(async () => { setIsWalletCreated(false); setIsWalletCreating(false); @@ -152,14 +164,28 @@ const HomeScreen = () => { ) : ( - + <> + + + + + )} - setImportWalletDialog(false)} + importWalletHandler={importWalletHandler} + /> + => { - const mnemonic = utils.entropyToMnemonic(utils.randomBytes(16)); + const mnemonic = recoveryPhrase + ? recoveryPhrase + : utils.entropyToMnemonic(utils.randomBytes(16)); await setInternetCredentials('mnemonicServer', 'mnemonic', mnemonic); const hdNode = HDNode.fromMnemonic(mnemonic); + await createWalletFromMnemonic(networksData, hdNode, mnemonic); + + return mnemonic; +}; + +const createWalletFromMnemonic = async ( + networksData: NetworksDataState[], + hdNode: HDNode, + mnemonic: string, +): Promise => { for (const network of networksData) { const hdPath = `m/44'/${network.coinType}'/0'/0/0`; const node = hdNode.derivePath(hdPath); @@ -73,8 +86,6 @@ const createWallet = async ( ), ]); } - - return mnemonic; }; const addAccount = async (