mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Added seed word recovery to config screen
This commit is contained in:
parent
01e63d41ed
commit
9cc04be5e4
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- Added seed word recovery to config screen.
|
||||||
|
|
||||||
## 2.2.0 2016-06-02
|
## 2.2.0 2016-06-02
|
||||||
|
|
||||||
- Redesigned init, vault create, vault restore and seed confirmation screens.
|
- Redesigned init, vault create, vault restore and seed confirmation screens.
|
||||||
|
@ -145,7 +145,7 @@ function setupPublicConfig(stream){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupProviderConnection(stream, originDomain){
|
function setupProviderConnection(stream, originDomain){
|
||||||
|
|
||||||
stream.on('data', function onRpcRequest(payload){
|
stream.on('data', function onRpcRequest(payload){
|
||||||
// Append origin to rpc payload
|
// Append origin to rpc payload
|
||||||
payload.origin = originDomain
|
payload.origin = originDomain
|
||||||
@ -195,6 +195,8 @@ function setupControllerConnection(stream){
|
|||||||
exportAccount: idStore.exportAccount.bind(idStore),
|
exportAccount: idStore.exportAccount.bind(idStore),
|
||||||
revealAccount: idStore.revealAccount.bind(idStore),
|
revealAccount: idStore.revealAccount.bind(idStore),
|
||||||
saveAccountLabel: idStore.saveAccountLabel.bind(idStore),
|
saveAccountLabel: idStore.saveAccountLabel.bind(idStore),
|
||||||
|
tryPassword: idStore.tryPassword.bind(idStore),
|
||||||
|
recoverSeed: idStore.recoverSeed.bind(idStore),
|
||||||
})
|
})
|
||||||
stream.pipe(dnode).pipe(stream)
|
stream.pipe(dnode).pipe(stream)
|
||||||
dnode.on('remote', function(remote){
|
dnode.on('remote', function(remote){
|
||||||
@ -246,7 +248,7 @@ function newUnsignedTransaction(txParams, cb){
|
|||||||
})
|
})
|
||||||
var txId = idStore.addUnconfirmedTransaction(txParams, cb)
|
var txId = idStore.addUnconfirmedTransaction(txParams, cb)
|
||||||
} else {
|
} else {
|
||||||
addUnconfirmedTx(txParams, cb)
|
addUnconfirmedTx(txParams, cb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ function newUnsignedMessage(msgParams, cb){
|
|||||||
})
|
})
|
||||||
var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
|
var msgId = idStore.addUnconfirmedMessage(msgParams, cb)
|
||||||
} else {
|
} else {
|
||||||
addUnconfirmedMsg(msgParams, cb)
|
addUnconfirmedMsg(msgParams, cb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,13 @@ IdentityStore.prototype.createNewVault = function(password, entropy, cb){
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentityStore.prototype.recoverSeed = function(cb){
|
||||||
|
configManager.setShowSeedWords(true)
|
||||||
|
if (!this_idmgmt) return cb(new Error('Unauthenticated. Please sign in.'))
|
||||||
|
var seedWords = this._idmgmt.getSeed()
|
||||||
|
cb(null, seedWords)
|
||||||
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
IdentityStore.prototype.recoverFromSeed = function(password, seed, cb){
|
||||||
this._createIdmgmt(password, seed, null, (err) => {
|
this._createIdmgmt(password, seed, null, (err) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
@ -150,7 +157,7 @@ IdentityStore.prototype.setLocked = function(cb){
|
|||||||
}
|
}
|
||||||
|
|
||||||
IdentityStore.prototype.submitPassword = function(password, cb){
|
IdentityStore.prototype.submitPassword = function(password, cb){
|
||||||
this._tryPassword(password, (err) => {
|
this.tryPassword(password, (err) => {
|
||||||
if (err) return cb(err)
|
if (err) return cb(err)
|
||||||
// load identities before returning...
|
// load identities before returning...
|
||||||
this._loadIdentities()
|
this._loadIdentities()
|
||||||
@ -366,7 +373,7 @@ IdentityStore.prototype._mayBeFauceting = function(i) {
|
|||||||
// keyStore managment - unlocking + deserialization
|
// keyStore managment - unlocking + deserialization
|
||||||
//
|
//
|
||||||
|
|
||||||
IdentityStore.prototype._tryPassword = function(password, cb){
|
IdentityStore.prototype.tryPassword = function(password, cb){
|
||||||
this._createIdmgmt(password, null, null, cb)
|
this._createIdmgmt(password, null, null, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ var actions = {
|
|||||||
createNewVaultInProgress: createNewVaultInProgress,
|
createNewVaultInProgress: createNewVaultInProgress,
|
||||||
showNewVaultSeed: showNewVaultSeed,
|
showNewVaultSeed: showNewVaultSeed,
|
||||||
showInfoPage: showInfoPage,
|
showInfoPage: showInfoPage,
|
||||||
|
// seed recovery actions
|
||||||
|
REVEAL_SEED_CONFIRMATION: 'REVEAL_SEED_CONFIRMATION',
|
||||||
|
revealSeedConfirmation: revealSeedConfirmation,
|
||||||
|
requestRevealSeed: requestRevealSeed,
|
||||||
// unlock screen
|
// unlock screen
|
||||||
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
UNLOCK_IN_PROGRESS: 'UNLOCK_IN_PROGRESS',
|
||||||
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
UNLOCK_FAILED: 'UNLOCK_FAILED',
|
||||||
@ -155,6 +159,26 @@ function createNewVault(password, entropy) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function revealSeedConfirmation() {
|
||||||
|
return {
|
||||||
|
type: this.REVEAL_SEED_CONFIRMATION,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestRevealSeed(password) {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch(actions.showLoadingIndication())
|
||||||
|
_accountManager.tryPassword(password, (err, seed) => {
|
||||||
|
dispatch(actions.hideLoadingIndication())
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
_accountManager.recoverSeed((err, seed) => {
|
||||||
|
if (err) return dispatch(actions.displayWarning(err.message))
|
||||||
|
dispatch(actions.showNewVaultSeed(seed))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function recoverFromSeed(password, seed) {
|
function recoverFromSeed(password, seed) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
// dispatch(actions.createNewVaultInProgress())
|
// dispatch(actions.createNewVaultInProgress())
|
||||||
@ -402,9 +426,10 @@ function previousTx() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showConfigPage() {
|
function showConfigPage(transitionForward = true) {
|
||||||
return {
|
return {
|
||||||
type: actions.SHOW_CONFIG_PAGE,
|
type: actions.SHOW_CONFIG_PAGE,
|
||||||
|
value: transitionForward,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ const SendTransactionScreen = require('./send')
|
|||||||
const ConfirmTxScreen = require('./conf-tx')
|
const ConfirmTxScreen = require('./conf-tx')
|
||||||
// other views
|
// other views
|
||||||
const ConfigScreen = require('./config')
|
const ConfigScreen = require('./config')
|
||||||
|
const RevealSeedConfirmation = require('./recover-seed/confirmation')
|
||||||
const InfoScreen = require('./info')
|
const InfoScreen = require('./info')
|
||||||
const LoadingIndicator = require('./loading')
|
const LoadingIndicator = require('./loading')
|
||||||
const txHelper = require('../lib/tx-helper')
|
const txHelper = require('../lib/tx-helper')
|
||||||
@ -232,6 +233,9 @@ App.prototype.renderPrimary = function(){
|
|||||||
case 'config':
|
case 'config':
|
||||||
return h(ConfigScreen, {key: 'config'})
|
return h(ConfigScreen, {key: 'config'})
|
||||||
|
|
||||||
|
case 'reveal-seed-conf':
|
||||||
|
return h(RevealSeedConfirmation, {key: 'reveal-seed-conf'})
|
||||||
|
|
||||||
case 'info':
|
case 'info':
|
||||||
return h(InfoScreen, {key: 'info'})
|
return h(InfoScreen, {key: 'info'})
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ ConfigScreen.prototype.render = function() {
|
|||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -86,11 +86,11 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setProviderType('mainnet'))
|
state.dispatch(actions.setProviderType('mainnet'))
|
||||||
}
|
}
|
||||||
}, 'Use Main Network')
|
}, 'Use Main Network'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -98,11 +98,11 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setProviderType('testnet'))
|
state.dispatch(actions.setProviderType('testnet'))
|
||||||
}
|
}
|
||||||
}, 'Use Morden Test Network')
|
}, 'Use Morden Test Network'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
h('div', [
|
h('div', [
|
||||||
h('button', {
|
h('button.spaced', {
|
||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
@ -110,7 +110,25 @@ ConfigScreen.prototype.render = function() {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
state.dispatch(actions.setRpcTarget('http://localhost:8545/'))
|
state.dispatch(actions.setRpcTarget('http://localhost:8545/'))
|
||||||
}
|
}
|
||||||
}, 'Use http://localhost:8545')
|
}, 'Use http://localhost:8545'),
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('hr.horizontal-line'),
|
||||||
|
|
||||||
|
h('div', {
|
||||||
|
style: {
|
||||||
|
marginTop: '20px',
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
h('button', {
|
||||||
|
style: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
},
|
||||||
|
onClick(event) {
|
||||||
|
event.preventDefault()
|
||||||
|
state.dispatch(actions.revealSeedConfirmation())
|
||||||
|
}
|
||||||
|
}, 'Reveal Seed Words')
|
||||||
]),
|
]),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
@ -45,6 +45,10 @@ button {
|
|||||||
transition: transform 50ms ease-in;
|
transition: transform 50ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.spaced {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
150
ui/app/recover-seed/confirmation.js
Normal file
150
ui/app/recover-seed/confirmation.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
const inherits = require('util').inherits
|
||||||
|
|
||||||
|
const Component = require('react').Component
|
||||||
|
const connect = require('react-redux').connect
|
||||||
|
const h = require('react-hyperscript')
|
||||||
|
const actions = require('../actions')
|
||||||
|
|
||||||
|
module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin)
|
||||||
|
|
||||||
|
|
||||||
|
inherits(RevealSeedConfirmatoin, Component)
|
||||||
|
function RevealSeedConfirmatoin() {
|
||||||
|
Component.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
warning: state.appState.warning,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand'
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.render = function() {
|
||||||
|
const props = this.props
|
||||||
|
const state = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
h('.initialize-screen.flex-column.flex-center.flex-grow', [
|
||||||
|
|
||||||
|
h('h3.flex-center.text-transform-uppercase', {
|
||||||
|
style: {
|
||||||
|
background: '#EBEBEB',
|
||||||
|
color: '#AEAEAE',
|
||||||
|
marginBottom: 24,
|
||||||
|
width: '100%',
|
||||||
|
fontSize: '20px',
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
'Reveal Seed Words',
|
||||||
|
]),
|
||||||
|
|
||||||
|
h('.div', {
|
||||||
|
style: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
padding: '20px',
|
||||||
|
justifyContent: 'center',
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
|
||||||
|
h('h4', 'Do not recover your seed words in a public place! These words can be used to steal all your accounts.'),
|
||||||
|
|
||||||
|
// confirmation
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'password',
|
||||||
|
id: 'password-box',
|
||||||
|
placeholder: 'Enter your password to confirm',
|
||||||
|
onKeyPress: this.checkConfirmation.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: '12px',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('h4', {
|
||||||
|
style: {
|
||||||
|
marginTop: '12px',
|
||||||
|
color: state && state.confirmationWrong ? 'red' : 'black',
|
||||||
|
}
|
||||||
|
}, `Enter the phrase "I understand" to proceed.`),
|
||||||
|
|
||||||
|
// confirm confirmation
|
||||||
|
h('input.large-input.letter-spacey', {
|
||||||
|
type: 'text',
|
||||||
|
id: 'confirm-box',
|
||||||
|
placeholder: this.confirmationPhrase,
|
||||||
|
onKeyPress: this.checkConfirmation.bind(this),
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
marginTop: 16,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
h('.flex-row.flex-space-between', {
|
||||||
|
style: {
|
||||||
|
marginTop: 30,
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
}, [
|
||||||
|
// cancel
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: this.goHome.bind(this),
|
||||||
|
}, 'CANCEL'),
|
||||||
|
|
||||||
|
// submit
|
||||||
|
h('button.primary', {
|
||||||
|
onClick: this.revealSeedWords.bind(this),
|
||||||
|
}, 'OK'),
|
||||||
|
|
||||||
|
]),
|
||||||
|
|
||||||
|
(props.warning) && (
|
||||||
|
h('span.error', {
|
||||||
|
style: {
|
||||||
|
margin: '20px',
|
||||||
|
}
|
||||||
|
}, props.warning.split('-'))
|
||||||
|
),
|
||||||
|
|
||||||
|
props.inProgress && (
|
||||||
|
h('span.in-progress-notification', 'Generating Seed...')
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.componentDidMount = function(){
|
||||||
|
document.getElementById('password-box').focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.goHome = function() {
|
||||||
|
this.props.dispatch(actions.showConfigPage(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// create vault
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.checkConfirmation = function(event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault()
|
||||||
|
this.revealSeedWords()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RevealSeedConfirmatoin.prototype.revealSeedWords = function(){
|
||||||
|
this.setState({ confirmationWrong: false })
|
||||||
|
|
||||||
|
const confirmBox = document.getElementById('confirm-box')
|
||||||
|
const confirmation = confirmBox.value
|
||||||
|
if (confirmation !== this.confirmationPhrase) {
|
||||||
|
confirmBox.value = ''
|
||||||
|
return this.setState({ confirmationWrong: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
var password = document.getElementById('password-box').value
|
||||||
|
this.props.dispatch(actions.requestRevealSeed(password))
|
||||||
|
}
|
@ -85,7 +85,7 @@ function reduceApp(state, action) {
|
|||||||
name: 'config',
|
name: 'config',
|
||||||
context: appState.currentView.context,
|
context: appState.currentView.context,
|
||||||
},
|
},
|
||||||
transForward: true,
|
transForward: action.value,
|
||||||
})
|
})
|
||||||
|
|
||||||
case actions.SHOW_INFO_PAGE:
|
case actions.SHOW_INFO_PAGE:
|
||||||
@ -144,6 +144,18 @@ function reduceApp(state, action) {
|
|||||||
warning: null,
|
warning: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// reveal seed words
|
||||||
|
|
||||||
|
case actions.REVEAL_SEED_CONFIRMATION:
|
||||||
|
return extend(appState, {
|
||||||
|
currentView: {
|
||||||
|
name: 'reveal-seed-conf',
|
||||||
|
},
|
||||||
|
transForward: true,
|
||||||
|
warning: null,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// accounts
|
// accounts
|
||||||
|
|
||||||
case actions.SET_SELECTED_ACCOUNT:
|
case actions.SET_SELECTED_ACCOUNT:
|
||||||
|
Loading…
Reference in New Issue
Block a user