diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cd7b90ff..d7e1dc4fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added an address book functionality that remembers the last 15 unique addresses sent to. - Can now change network to custom RPC URL from lock screen. - Removed support for old, lightwallet based vault. Users who have not opened app in over a month will need to recover with their seed phrase. This will allow Firefox support sooner. +- Polish the private key UI. ## 3.4.0 2017-3-8 diff --git a/development/states/private-key-export-success.json b/development/states/private-key-export-success.json new file mode 100644 index 000000000..2ff3c4d17 --- /dev/null +++ b/development/states/private-key-export-success.json @@ -0,0 +1,70 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0x07284e146926a4facd0ea60598dc4f001ad620f1": { + "address": "0x07284e146926a4facd0ea60598dc4f001ad620f1", + "name": "Account 1" + } + }, + "unapprovedTxs": {}, + "noActiveNotices": true, + "frequentRpcList": [], + "addressBook": [], + "network": "3", + "accounts": { + "0x07284e146926a4facd0ea60598dc4f001ad620f1": { + "code": "0x", + "nonce": "0x0", + "balance": "0x0", + "address": "0x07284e146926a4facd0ea60598dc4f001ad620f1" + } + }, + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "07284e146926a4facd0ea60598dc4f001ad620f1" + ] + } + ], + "selectedAddress": "0x07284e146926a4facd0ea60598dc4f001ad620f1", + "currentCurrency": "USD", + "conversionRate": 43.35903476, + "conversionDate": 1490105102, + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "seedWords": null + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "accountDetail", + "context": "0x07284e146926a4facd0ea60598dc4f001ad620f1" + }, + "accountDetail": { + "subview": "export", + "accountExport": "completed", + "privateKey": "549c9638ad06432568969accacad4a02f8548cc358085938071745138ec134b7" + }, + "transForward": true, + "isLoading": false, + "warning": null + }, + "identities": {} +} diff --git a/development/states/private-key-export.json b/development/states/private-key-export.json new file mode 100644 index 000000000..db7a53e22 --- /dev/null +++ b/development/states/private-key-export.json @@ -0,0 +1,69 @@ +{ + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "rpcTarget": "https://rawtestrpc.metamask.io/", + "identities": { + "0x07284e146926a4facd0ea60598dc4f001ad620f1": { + "address": "0x07284e146926a4facd0ea60598dc4f001ad620f1", + "name": "Account 1" + } + }, + "unapprovedTxs": {}, + "noActiveNotices": true, + "frequentRpcList": [], + "addressBook": [], + "network": "3", + "accounts": { + "0x07284e146926a4facd0ea60598dc4f001ad620f1": { + "code": "0x", + "nonce": "0x0", + "balance": "0x0", + "address": "0x07284e146926a4facd0ea60598dc4f001ad620f1" + } + }, + "transactions": {}, + "selectedAddressTxList": [], + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree" + ], + "keyrings": [ + { + "type": "HD Key Tree", + "accounts": [ + "07284e146926a4facd0ea60598dc4f001ad620f1" + ] + } + ], + "selectedAddress": "0x07284e146926a4facd0ea60598dc4f001ad620f1", + "currentCurrency": "USD", + "conversionRate": 43.35903476, + "conversionDate": 1490105102, + "provider": { + "type": "testnet" + }, + "shapeShiftTxList": [], + "lostAccounts": [], + "seedWords": null + }, + "appState": { + "menuOpen": false, + "currentView": { + "name": "accountDetail", + "context": "0x07284e146926a4facd0ea60598dc4f001ad620f1" + }, + "accountDetail": { + "subview": "export", + "accountExport": "requested" + }, + "transForward": true, + "isLoading": false, + "warning": null + }, + "identities": {} +} diff --git a/ui/app/actions.js b/ui/app/actions.js index b09021577..9d6676d01 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -698,7 +698,7 @@ function setRpcTarget (newRpc) { } } -// Calls the addressBookController to add a new address. +// Calls the addressBookController to add a new address. function addToAddressBook (recipient, nickname) { log.debug(`background.addToAddressBook`) return (dispatch) => { @@ -772,22 +772,30 @@ function requestExportAccount () { } } -function exportAccount (address) { +function exportAccount (password, address) { var self = this return function (dispatch) { dispatch(self.showLoadingIndication()) - log.debug(`background.exportAccount`) - background.exportAccount(address, function (err, result) { - dispatch(self.hideLoadingIndication()) - + log.debug(`background.submitPassword`) + background.submitPassword(password, function (err) { if (err) { - log.error(err) - return dispatch(self.displayWarning('Had a problem exporting the account.')) + log.error('Error in submiting password.') + dispatch(self.hideLoadingIndication()) + return dispatch(self.displayWarning('Incorrect Password.')) } + log.debug(`background.exportAccount`) + background.exportAccount(address, function (err, result) { + dispatch(self.hideLoadingIndication()) - dispatch(self.showPrivateKey(result)) + if (err) { + log.error(err) + return dispatch(self.displayWarning('Had a problem exporting the account.')) + } + + dispatch(self.showPrivateKey(result)) + }) }) } } diff --git a/ui/app/components/account-export.js b/ui/app/components/account-export.js index 6d8b099a5..38a1d28ef 100644 --- a/ui/app/components/account-export.js +++ b/ui/app/components/account-export.js @@ -4,14 +4,21 @@ const inherits = require('util').inherits const copyToClipboard = require('copy-to-clipboard') const actions = require('../actions') const ethUtil = require('ethereumjs-util') +const connect = require('react-redux').connect -module.exports = ExportAccountView +module.exports = connect(mapStateToProps)(ExportAccountView) inherits(ExportAccountView, Component) function ExportAccountView () { Component.call(this) } +function mapStateToProps (state) { + return { + warning: state.appState.warning, + } +} + ExportAccountView.prototype.render = function () { console.log('EXPORT VIEW') console.dir(this.props) @@ -28,35 +35,57 @@ ExportAccountView.prototype.render = function () { if (notExporting) return h('div') if (exportRequested) { - var warning = `Exporting your private key is very dangerous, - and you should only do it if you know what you're doing.` - var confirmation = `If you're absolutely sure, type "I understand" below and - submit.` + var warning = `Export private keys at your own risk.` return ( - h('div', { - key: 'exporting', style: { - margin: '0 20px', + display: 'inline-block', + textAlign: 'center', }, - }, [ - h('p.error', warning), - h('p', confirmation), - h('input#exportAccount.sizing-input', { - onKeyPress: this.onExportKeyPress.bind(this), - style: { - position: 'relative', - top: '1.5px', + }, + [ + h('div', { + key: 'exporting', + style: { + margin: '0 20px', + }, + }, [ + h('p.error', warning), + h('input#exportAccount.sizing-input', { + placeholder: 'confirm password', + onKeyPress: this.onExportKeyPress.bind(this), + style: { + position: 'relative', + top: '1.5px', + marginBottom: '7px', + }, + }), + ]), + h('div', { + key: 'buttons', + style: { + margin: '0 20px', + }, }, - }), - h('button', { - onClick: () => this.onExportKeyPress({ key: 'Enter', preventDefault: () => {} }), - }, 'Submit'), - h('button', { - onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)), - }, 'Cancel'), - ]) - + [ + h('button', { + onClick: () => this.onExportKeyPress({ key: 'Enter', preventDefault: () => {} }), + style: { + marginRight: '10px', + }, + }, 'Submit'), + h('button', { + onClick: () => this.props.dispatch(actions.backToAccountDetail(this.props.address)), + }, 'Cancel'), + ]), + (this.props.warning) && ( + h('span.error', { + style: { + margin: '20px', + }, + }, this.props.warning.split('-')) + ), + ]) ) } @@ -89,15 +118,6 @@ ExportAccountView.prototype.onExportKeyPress = function (event) { if (event.key !== 'Enter') return event.preventDefault() - var input = document.getElementById('exportAccount') - if (input.value === 'I understand') { - this.props.dispatch(actions.exportAccount(this.props.address)) - } else { - input.value = '' - input.placeholder = 'Please retype "I understand" exactly.' - } -} - -ExportAccountView.prototype.exportAccount = function (address) { - this.props.dispatch(actions.exportAccount(address)) + var input = document.getElementById('exportAccount').value + this.props.dispatch(actions.exportAccount(input, this.props.address)) } diff --git a/ui/app/css/index.css b/ui/app/css/index.css index 8c6ff29d3..3ec0ac5c5 100644 --- a/ui/app/css/index.css +++ b/ui/app/css/index.css @@ -266,8 +266,9 @@ app sections } .sizing-input{ - font-size: 1em; + font-size: 14px; height: 30px; + padding-left: 5px; } .editable-label{ display: flex;