diff --git a/app/components/Views/ImportFromSeed/index.js b/app/components/Views/ImportFromSeed/index.js index b41830f048e..2636b125df9 100644 --- a/app/components/Views/ImportFromSeed/index.js +++ b/app/components/Views/ImportFromSeed/index.js @@ -29,7 +29,12 @@ import TermsAndConditions from '../TermsAndConditions'; import zxcvbn from 'zxcvbn'; import Icon from 'react-native-vector-icons/FontAwesome'; import Device from '../../../util/device'; -import { failedSeedPhraseRequirements, isValidMnemonic, parseSeedPhrase } from '../../../util/validators'; +import { + failedSeedPhraseRequirements, + isValidMnemonic, + parseSeedPhrase, + parseVaultValue, +} from '../../../util/validators'; import { OutlinedTextField } from 'react-native-material-textfield'; import { SEED_PHRASE_HINTS, @@ -243,7 +248,11 @@ class ImportFromSeed extends PureComponent { onPressImport = async () => { const { loading, seed, password, confirmPassword } = this.state; - const parsedSeed = parseSeedPhrase(seed); + + const vaultSeed = await parseVaultValue(password, seed); + const parsedSeed = parseSeedPhrase(vaultSeed || seed); + //Set the seed state with a valid parsed seed phrase (handle vault scenario) + this.setState({ seed: parsedSeed }); if (loading) return; InteractionManager.runAfterInteractions(() => { diff --git a/app/util/validators/index.js b/app/util/validators/index.js index 5b95237c11b..e2f187a1d4a 100644 --- a/app/util/validators/index.js +++ b/app/util/validators/index.js @@ -1,11 +1,36 @@ import { ethers } from 'ethers'; import { confusables } from 'unicode-confusables'; +import Encryptor from '../../core/Encryptor'; export const failedSeedPhraseRequirements = (seed) => { const wordCount = seed.split(/\s/u).length; return wordCount % 3 !== 0 || wordCount > 24 || wordCount < 12; }; +/** + * This method validates and decyrpts a raw vault. Only works with iOS/Android vaults! + * The extension uses different cryptography for the vault. + * @param {string} password - users password related to vault + * @param {string} vault - exported from ios/android filesytem + * @returns seed phrase from vault + */ +export const parseVaultValue = async (password, vault) => { + let vaultSeed; + + if (vault[0] === '{' && vault[vault.length - 1] === '}') + try { + const seedObject = JSON.parse(vault); + if (seedObject?.cipher && seedObject?.salt && seedObject?.iv && seedObject?.lib) { + const encryptor = new Encryptor(); + const result = await encryptor.decrypt(password, vault); + vaultSeed = result[0]?.data?.mnemonic; + } + } catch (error) { + //No-op + } + return vaultSeed; +}; + export const parseSeedPhrase = (seedPhrase) => (seedPhrase || '').trim().toLowerCase().match(/\w+/gu)?.join(' ') || ''; export const { isValidMnemonic } = ethers.utils;