diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 2681b3d48..b93d4a156 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -9,6 +9,7 @@ const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') const createId = require('web3-provider-engine/util/random-id') const autoFaucet = require('./lib/auto-faucet') +const bip39 = require('bip39') // TEMPORARY UNTIL FULL DEPRECATION: const IdStoreMigrator = require('./lib/idStore-migrator') @@ -46,6 +47,8 @@ module.exports = class KeyringController extends EventEmitter { } getState() { + let address = this.configManager.getSelectedAccount() + return { seedWords: this.configManager.getSeedWords(), isInitialized: !!this.configManager.getVault(), @@ -55,7 +58,8 @@ module.exports = class KeyringController extends EventEmitter { transactions: this.configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), messages: messageManager.getMsgList(), - selectedAddress: this.configManager.getSelectedAccount(), + selectedAddress: address, + selectedAccount: address, shapeShiftTxList: this.configManager.getShapeShiftTxList(), currentFiat: this.configManager.getCurrentFiat(), conversionRate: this.configManager.getConversionRate(), @@ -78,12 +82,33 @@ module.exports = class KeyringController extends EventEmitter { } createNewVaultAndRestore(password, seed, cb) { + if (typeof password !== 'string') { + return cb('Password must be text.') + } + + if (!bip39.validateMnemonic(seed)) { + return cb('Seed phrase is invalid.') + } + + this.clearKeyrings() + this.createNewVault(password, '', (err) => { if (err) return cb(err) this.addNewKeyring('HD Key Tree', { mnemonic: seed, n: 1, - }, cb) + }, (err) => { + if (err) return cb(err) + const firstKeyring = this.keyrings[0] + const accounts = firstKeyring.getAccounts() + const firstAccount = accounts[0] + const hexAccount = ethUtil.addHexPrefix(firstAccount) + this.configManager.setSelectedAccount(hexAccount) + + this.setupAccounts(accounts) + this.emit('update') + cb(null, this.getState()) + }) }) } @@ -138,6 +163,7 @@ module.exports = class KeyringController extends EventEmitter { return this.unlockKeyrings(key) }) .then(() => { + this.emit('update') cb(null, this.getState()) }) .catch((err) => { @@ -175,6 +201,7 @@ module.exports = class KeyringController extends EventEmitter { const ring = this.keyrings[keyRingNum] const accounts = ring.addAccounts(1) this.setupAccounts(accounts) + this.persistAllKeyrings() cb(null, this.getState()) } @@ -468,10 +495,6 @@ module.exports = class KeyringController extends EventEmitter { cb(null, '0xPrivateKey') } - tryPassword(password, cb) { - cb() - } - getNetwork(err) { if (err) { this.network = 'loading' @@ -503,6 +526,22 @@ module.exports = class KeyringController extends EventEmitter { cb(null, this.configManager.getSelectedAccount()) } + clearKeyrings() { + let accounts + try { + accounts = Object.keys(this.ethStore._currentState.accounts) + } catch (e) { + accounts = [] + } + accounts.forEach((address) => { + this.ethStore.removeAccount(address) + }) + + this.keyrings = [] + this.identities = {} + this.configManager.setSelectedAccount() + } + } function noop () {} diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js index 69b8d25bc..90052d9e7 100644 --- a/app/scripts/keyrings/hd.js +++ b/app/scripts/keyrings/hd.js @@ -13,7 +13,7 @@ module.exports = class HdKeyring extends EventEmitter { return type } - constructor(opts) { + constructor(opts = {}) { super() this.type = type this.opts = opts || {} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 7ce22b642..6dffefe98 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -38,8 +38,8 @@ module.exports = class MetamaskController { return extend( this.state, this.ethStore.getState(), - this.keyringController.getState(), - this.configManager.getConfig() + this.configManager.getConfig(), + this.keyringController.getState() ) } @@ -73,7 +73,6 @@ module.exports = class MetamaskController { setLocked: keyringController.setLocked.bind(keyringController), exportAccount: keyringController.exportAccount.bind(keyringController), saveAccountLabel: keyringController.saveAccountLabel.bind(keyringController), - tryPassword: keyringController.tryPassword.bind(keyringController), // coinbase buyEth: this.buyEth.bind(this), // shapeshift diff --git a/ui/app/actions.js b/ui/app/actions.js index 0586e07a3..8218e05ef 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -161,7 +161,7 @@ function tryUnlockMetamask (password) { background.submitPassword(password, (err, newState) => { dispatch(actions.hideLoadingIndication()) if (err) { - dispatch(actions.unlockFailed()) + dispatch(actions.unlockFailed(err.message)) } else { dispatch(this.updateMetamaskState(newState)) let selectedAccount @@ -407,9 +407,10 @@ function unlockInProgress () { } } -function unlockFailed () { +function unlockFailed (message) { return { type: actions.UNLOCK_FAILED, + value: message, } } diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index d34cd1c2a..49507eb30 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -335,7 +335,7 @@ function reduceApp (state, action) { case actions.UNLOCK_FAILED: return extend(appState, { - warning: 'Incorrect password. Try again.', + warning: action.value || 'Incorrect password. Try again.', }) case actions.SHOW_LOADING: diff --git a/ui/app/unlock.js b/ui/app/unlock.js index 5c9a94f39..ec467f483 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -55,6 +55,8 @@ UnlockScreen.prototype.render = function () { h('.error', { style: { display: warning ? 'block' : 'none', + padding: '0 20px', + textAlign: 'center', }, }, warning),