From 931ae5f64a233b472c3dada8aa6af77e0bffad5e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 20 Dec 2016 13:53:14 -0800 Subject: [PATCH] Make notices confirmation configurable - Confirm button will now dismiss the lost accounts array. --- app/scripts/keyring-controller.js | 1 - app/scripts/metamask-controller.js | 17 ++++++++++++++++- ui/app/actions.js | 12 ++++++++++++ ui/app/app.js | 16 +++++++++++++++- ui/app/notice.js | 18 ++++++------------ ui/lib/lost-accounts-notice.js | 23 +++++++++++++++++++++++ 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 ui/lib/lost-accounts-notice.js diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 2888e58a9..61ee56638 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -114,7 +114,6 @@ module.exports = class KeyringController extends EventEmitter { conversionDate: this.configManager.getConversionDate(), keyringTypes: this.keyringTypes.map(krt => krt.type), identities: this.identities, - lostAccounts: this.configManager.getLostAccounts(), } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4b8fa4323..edb25d300 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -52,7 +52,9 @@ module.exports = class MetamaskController { this.ethStore.getState(), this.configManager.getConfig(), this.keyringController.getState(), - this.noticeController.getState() + this.noticeController.getState(), { + lostAccounts: this.configManager.getLostAccounts(), + } ) } @@ -71,6 +73,7 @@ module.exports = class MetamaskController { setTOSHash: this.setTOSHash.bind(this), checkTOSChange: this.checkTOSChange.bind(this), setGasMultiplier: this.setGasMultiplier.bind(this), + markAccountsFound: this.markAccountsFound.bind(this), // forward directly to keyringController createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController), @@ -410,4 +413,16 @@ module.exports = class MetamaskController { getStateNetwork () { return this.state.network } + + markAccountsFound(cb) { + this.configManager.setLostAccounts([]) + this.keyringController.getAccounts() + .then((accounts) => { + return this.keyringController.setSelectedAccount(accounts[0]) + }) + .then(() => { + this.sendUpdate() + cb(null, this.getState()) + }) + } } diff --git a/ui/app/actions.js b/ui/app/actions.js index 1c32c9bb1..606460314 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -20,6 +20,7 @@ var actions = { showNotice: showNotice, CLEAR_NOTICES: 'CLEAR_NOTICES', clearNotices: clearNotices, + markAccountsFound, // intialize screen AGREE_TO_DISCLAIMER: 'AGREE_TO_DISCLAIMER', agreeToDisclaimer: agreeToDisclaimer, @@ -591,6 +592,17 @@ function clearNotices () { } } +function markAccountsFound() { + return (dispatch) => { + dispatch(this.showLoadingIndication()) + background.markAccountsFound((err, newState) => { + dispatch(this.hideLoadingIndication()) + if (err) return dispatch(this.showWarning(err.message)) + dispatch(actions.updateMetamaskState(newState)) + }) + } +} + // // config // diff --git a/ui/app/app.js b/ui/app/app.js index 2fa6415dd..886bc987a 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -17,6 +17,7 @@ const SendTransactionScreen = require('./send') const ConfirmTxScreen = require('./conf-tx') // notice const NoticeScreen = require('./notice') +const lostAccountsNotice = require('../lib/lost-accounts-notice') // other views const ConfigScreen = require('./config') const InfoScreen = require('./info') @@ -55,6 +56,8 @@ function mapStateToProps (state) { network: state.metamask.network, provider: state.metamask.provider, forgottenPassword: state.appState.forgottenPassword, + lastUnreadNotice: state.metamask.lastUnreadNotice, + lostAccounts: state.metamask.lostAccounts, } } @@ -366,8 +369,19 @@ App.prototype.renderPrimary = function () { } } + // notices if (!props.noActiveNotices) { - return h(NoticeScreen, {key: 'NoticeScreen'}) + return h(NoticeScreen, { + notice: props.lastUnreadNotice, + key: 'NoticeScreen', + onConfirm: () => props.dispatch(actions.markNoticeRead(notice)), + }) + } else if (props.lostAccounts && props.lostAccounts.length > 0) { + return h(NoticeScreen, { + notice: lostAccountsNotice(props.lostAccounts), + key: 'LostAccountsNotice', + onConfirm: () => props.dispatch(actions.markAccountsFound()), + }) } // show current view diff --git a/ui/app/notice.js b/ui/app/notice.js index 3c2c746f2..92c171c4d 100644 --- a/ui/app/notice.js +++ b/ui/app/notice.js @@ -7,13 +7,7 @@ const actions = require('./actions') const linker = require('extension-link-enabler') const findDOMNode = require('react-dom').findDOMNode -module.exports = connect(mapStateToProps)(Notice) - -function mapStateToProps (state) { - return { - lastUnreadNotice: state.metamask.lastUnreadNotice, - } -} +module.exports = Notice inherits(Notice, Component) function Notice () { @@ -21,9 +15,8 @@ function Notice () { } Notice.prototype.render = function () { - const props = this.props - const title = props.lastUnreadNotice.title - const date = props.lastUnreadNotice.date + const { notice, onConfirm } = this.props + const { title, date, body } = notice return ( h('.flex-column.flex-center.flex-grow', [ @@ -59,6 +52,7 @@ Notice.prototype.render = function () { .markdown { overflow-x: hidden; } + .markdown h1, .markdown h2, .markdown h3 { margin: 10px 0; font-weight: bold; @@ -92,13 +86,13 @@ Notice.prototype.render = function () { }, }, [ h(ReactMarkdown, { - source: props.lastUnreadNotice.body, + source: body, skipHtml: true, }), ]), h('button', { - onClick: () => props.dispatch(actions.markNoticeRead(props.lastUnreadNotice)), + onClick: onConfirm, style: { marginTop: '18px', }, diff --git a/ui/lib/lost-accounts-notice.js b/ui/lib/lost-accounts-notice.js new file mode 100644 index 000000000..49b055778 --- /dev/null +++ b/ui/lib/lost-accounts-notice.js @@ -0,0 +1,23 @@ +const summary = require('../app/util').addressSummary + +module.exports = function (lostAccounts) { + return { + date: new Date().toDateString(), + title: 'Account Problem Caught', + body: `MetaMask has fixed a bug where some accounts were previously mis-generated. This was a rare issue, but you were affected! + +We have successfully imported the accounts that were mis-generated, but they will no longer be recovered with your normal seed phrase. + +We have marked the affected accounts as "Loose", and recommend you transfer ether and tokens away from those accounts, or export & back them up elsewhere. + +Your affected accounts are: +${lostAccounts.map(acct => ` - ${summary(acct)}`).join('\n')} + +These accounts have been marked as "Loose" so they will be easy to recognize in the account list. + +For more information, please read [our blog post.][1] + +[1]: https://medium.com/metamask/metamask-3-migration-guide-914b79533cdd#.7d8ktj4h3 + ` + } +}