Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug/persists old account names #2469

Merged
merged 12 commits into from
Apr 15, 2021
Merged
3 changes: 2 additions & 1 deletion app/components/Views/Login/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ class Login extends PureComponent {
// Restore vault with user entered password
await KeyringController.submitPassword(this.state.password);
const encryptionLib = await AsyncStorage.getItem(ENCRYPTION_LIB);
if (encryptionLib !== ORIGINAL) {
const existingUser = await AsyncStorage.getItem(EXISTING_USER);
if (encryptionLib !== ORIGINAL && existingUser) {
await recreateVaultWithSamePassword(this.state.password, this.props.selectedAddress);
await AsyncStorage.setItem(ENCRYPTION_LIB, ORIGINAL);
}
Expand Down
10 changes: 6 additions & 4 deletions app/components/Views/ResetPassword/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { ONBOARDING, PREVIOUS_SCREEN } from '../../../constants/navigation';
import { EXISTING_USER, TRUE, BIOMETRY_CHOICE_DISABLED } from '../../../constants/storage';
import { getPasswordStrengthWord, passwordRequirementsMet } from '../../../util/password';
import NotificationManager from '../../../core/NotificationManager';
import { syncPrefs } from '../../../util/sync';

const styles = StyleSheet.create({
mainWrapper: {
Expand Down Expand Up @@ -401,6 +402,7 @@ class ResetPassword extends PureComponent {
const { originalPassword, password: newPassword } = this.state;
const { KeyringController, PreferencesController } = Engine.context;
const seedPhrase = await this.getSeedPhrase();
const oldPrefs = PreferencesController.state;

let importedAccounts = [];
try {
Expand All @@ -427,7 +429,6 @@ class ResetPassword extends PureComponent {
const hdKeyring = KeyringController.state.keyrings[0];
const existingAccountCount = hdKeyring.accounts.length;
const selectedAddress = this.props.selectedAddress;
let preferencesControllerState = PreferencesController.state;

// Create previous accounts again
for (let i = 0; i < existingAccountCount - 1; i++) {
Expand All @@ -443,11 +444,12 @@ class ResetPassword extends PureComponent {
Logger.error(e, 'error while trying to import accounts on recreate vault');
}

// Reset preferencesControllerState
preferencesControllerState = PreferencesController.state;
//Persist old account/identities names
const preferencesControllerState = PreferencesController.state;
const prefUpdates = syncPrefs(oldPrefs, preferencesControllerState);

// Set preferencesControllerState again
await PreferencesController.update(preferencesControllerState);
await PreferencesController.update(prefUpdates);
// Reselect previous selected account if still available
if (hdKeyring.accounts.includes(selectedAddress)) {
PreferencesController.setSelectedAddress(selectedAddress);
Expand Down
19 changes: 14 additions & 5 deletions app/core/Vault.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Engine from './Engine';
import Logger from '../util/Logger';
import { syncPrefs, syncAccounts } from '../util/sync';

/**
* Returns current vault seed phrase
Expand All @@ -18,8 +19,10 @@ export const getSeedPhrase = async (password = '') => {
* @param password - Password to recreate and set the vault with
*/
export const recreateVaultWithSamePassword = async (password = '', selectedAddress) => {
const { KeyringController, PreferencesController } = Engine.context;
const { KeyringController, PreferencesController, AccountTrackerController } = Engine.context;
const seedPhrase = await getSeedPhrase(password);
const oldPrefs = PreferencesController.state;
const oldAccounts = AccountTrackerController.accounts;

let importedAccounts = [];
try {
Expand All @@ -42,7 +45,6 @@ export const recreateVaultWithSamePassword = async (password = '', selectedAddre
// Get props to restore vault
const hdKeyring = KeyringController.state.keyrings[0];
const existingAccountCount = hdKeyring.accounts.length;
let preferencesControllerState = PreferencesController.state;

// Create previous accounts again
for (let i = 0; i < existingAccountCount - 1; i++) {
Expand All @@ -58,11 +60,18 @@ export const recreateVaultWithSamePassword = async (password = '', selectedAddre
Logger.error(e, 'error while trying to import accounts on recreate vault');
}

// Reset preferencesControllerState
preferencesControllerState = PreferencesController.state;
//Persist old account/identities names
const preferencesControllerState = PreferencesController.state;
const prefUpdates = syncPrefs(oldPrefs, preferencesControllerState);

//Persist old account data
const accounts = AccountTrackerController.accounts;
const updateAccounts = syncAccounts(oldAccounts, accounts);

// Set preferencesControllerState again
await PreferencesController.update(preferencesControllerState);
await PreferencesController.update(prefUpdates);
await AccountTrackerController.update(updateAccounts);

// Reselect previous selected account if still available
if (hdKeyring.accounts.includes(selectedAddress)) {
PreferencesController.setSelectedAddress(selectedAddress);
Expand Down
37 changes: 37 additions & 0 deletions app/util/sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Function to persist the old account name during an new preferences update
* @param {Object} oldPrefs - old preferences object containing the account names
* @param {Object} updatedPref - preferences object that will be updated with oldPrefs
*/
export async function syncPrefs(oldPrefs, updatedPref) {
try {
Object.keys(oldPrefs.identities).forEach(ids => {
if (updatedPref.identities[ids]) {
updatedPref.identities[ids] = oldPrefs.identities[ids];
}
});

return updatedPref;
} catch (err) {
return updatedPref;
}
}

/**
* Function to persist the old account balance during an vault update
* @param {Object} oldAccounts - old account object containing the account names
* @param {Object} updatedAccounts - accounts object that will be updated with old accout balance
*/
export async function syncAccounts(oldAccounts, updatedAccounts) {
try {
Object.keys(oldAccounts).forEach(account => {
if (updatedAccounts[account]) {
updatedAccounts[account] = oldAccounts[account];
}
});

return updatedAccounts;
} catch (err) {
return updatedAccounts;
}
}
106 changes: 106 additions & 0 deletions app/util/sync.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { syncPrefs, syncAccounts } from '../util/sync';

const OLD_PREFS = {
accountTokens: {
'0x0942890c603273059a11a298F81cb137Be9CF704': { '0x1': [Array], '0x3': [Array] },
'0x120bfFfa4138fD00A8025a223C350b9ffaDAD8F5': { '0x3': [Array] },
'0x16C6C3079edE914e83B388a52fFD9255E1c3165': { '0x3': [Array] },
'0x223367C61c38FAcbdd0b92De5aA7B742e1e5a196': { '0x1': [Array], '0x3': [Array] },
'0x7b8C6B8363B9E7A77d279dDad49BEF2994a3bf28': { '0x3': [Array] },
'0x9236413AfD369B2aeb5e52C048f6B30e7308f2e3': { '0x1': [Array], '0x3': [Array] },
'0x9b07Ba86631bdb74eE2DDb5750440986DECB9e11': { '0x1': [Array], '0x3': [Array] },
'0xE4D7f194b07B85511973f1FAAB31b8C2F1f9F344': { '0x3': [Array] }
},
currentLocale: 'en',
featureFlags: {},
frequentRpcList: [],
identities: {
'0x7f9f9A0e248Ef58298e911219e5B45D610C4B539': {
address: '0x7f9f9A0e248Ef58298e911219e5B45D610C4B539',
name: 'Testy Account'
}
},
ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/',
lostIdentities: {},
selectedAddress: '0x7f9f9A0e248Ef58298e911219e5B45D610C4B539',
tokens: []
};
const OLD_ACCOUNTS = {
'0x0942890c603273059a11a298F81cb137Be9CF704': { balance: '0x365369025dd23000' },
'0x120bfFfa4138fD00A8025a223C350b9ffaDAD8F5': { balance: '0x0' },
'0x16C6C3079edE914e83B388a52fFD9255E1c3165': { balance: '0x0' },
'0x223367C61c38FAcbdd0b92De5aA7B742e1e5a196': { balance: '0x1bf5ef59d293408b' },
'0x7b8C6B8363B9E7A77d279dDad49BEF2994a3bf28': { balance: '0x0' },
'0x9236413AfD369B2aeb5e52C048f6B30e7308f2e3': { balance: '0x0' },
'0x9b07Ba86631bdb74eE2DDb5750440986DECB9e11': { balance: '0xe8d4a51000' },
'0xE4D7f194b07B85511973f1FAAB31b8C2F1f9F344': { balance: '0x0' }
};
const NEW_PREFS = {
accountTokens: {
'0x0942890c603273059a11a298F81cb137Be9CF704': { '0x1': [Array], '0x3': [Array] },
'0x120bfFfa4138fD00A8025a223C350b9ffaDAD8F5': { '0x3': [Array] },
'0x16C6C3079edE914e83B388a52fFD9255E1c3165': { '0x3': [Array] },
'0x223367C61c38FAcbdd0b92De5aA7B742e1e5a196': { '0x1': [Array], '0x3': [Array] },
'0x7b8C6B8363B9E7A77d279dDad49BEF2994a3bf28': { '0x3': [Array] },
'0x9236413AfD369B2aeb5e52C048f6B30e7308f2e3': { '0x1': [Array], '0x3': [Array] },
'0x9b07Ba86631bdb74eE2DDb5750440986DECB9e11': { '0x1': [Array], '0x3': [Array] },
'0xE4D7f194b07B85511973f1FAAB31b8C2F1f9F344': { '0x3': [Array] }
},
currentLocale: 'en',
featureFlags: {},
frequentRpcList: [],
identities: {
'0x7f9f9A0e248Ef58298e911219e5B45D610C4B539': {
address: '0x7f9f9A0e248Ef58298e911219e5B45D610C4B539',
name: 'Account 1'
},
'0x7f9f9A0e248Ef58298e911219e5B45D610C4B589': {
address: '0x7f9f9A0e248Ef58298e911219e5B45D610C4B589',
name: 'Account 2'
}
},
ipfsGateway: 'https://cloudflare-ipfs.com/ipfs/',
lostIdentities: {},
selectedAddress: '0x7f9f9A0e248Ef58298e911219e5B45D610C4B539',
tokens: []
};
const NEW_ACCOUNTS = {
'0x0942890c603273059a11a298F81cb137Be9CF704': { balance: '0x0' },
'0x120bfFfa4138fD00A8025a223C350b9ffaDAD8F5': { balance: '0x0' },
'0x16C6C3079edE914e83B388a52fFD9255E1c3165': { balance: '0x0' },
'0x223367C61c38FAcbdd0b92De5aA7B742e1e5a196': { balance: '0x0' },
'0x7b8C6B8363B9E7A77d279dDad49BEF2994a3bf28': { balance: '0x0' },
'0x9236413AfD369B2aeb5e52C048f6B30e7308f2e3': { balance: '0x0' },
'0x9b07Ba86631bdb74eE2DDb5750440986DECB9e11': { balance: '0x0' },
'0xE4D7f194b07B85511973f1FAAB31b8C2F1f9F344': { balance: '0x0' }
};

describe('Success Sync', () => {
it('should succeed sync prefs of varying lengths', async () => {
const syncedPrefs = await syncPrefs(OLD_PREFS, NEW_PREFS);
expect(Object.values(syncedPrefs.identities)[0]).toEqual(Object.values(syncedPrefs.identities)[0]);
expect(Object.values(syncedPrefs.identities)[1]).not.toBeUndefined();
expect(Object.values(syncedPrefs.identities).length).not.toEqual(Object.values(OLD_PREFS.identities).length);
});
it('should succeed sync accounts balances', async () => {
const syncedAccounts = await syncAccounts(OLD_ACCOUNTS, NEW_ACCOUNTS);
expect(Object.values(syncedAccounts)[0].balance).toEqual(Object.values(OLD_ACCOUNTS)[0].balance);
expect(Object.values(syncedAccounts)[3].balance).toEqual(Object.values(OLD_ACCOUNTS)[3].balance);
expect(Object.values(syncedAccounts)[6].balance).toEqual(Object.values(OLD_ACCOUNTS)[6].balance);
});
});

describe('Error Syncs', () => {
it('should return undefined sync prefs', async () => {
expect(await syncPrefs(OLD_PREFS, undefined)).toEqual(undefined);
});
it('should return new sync prefs', async () => {
expect(await syncPrefs(undefined, NEW_PREFS)).toEqual(NEW_PREFS);
});
it('should return new sync accounts', async () => {
expect(await syncAccounts(undefined, NEW_ACCOUNTS)).toEqual(NEW_ACCOUNTS);
});
it('should return undefined sync accounts', async () => {
expect(await syncAccounts(OLD_ACCOUNTS, undefined)).toEqual(undefined);
});
});