From 8be68575bbef1dcc89b51355abaee90dbf018387 Mon Sep 17 00:00:00 2001 From: Frankie Date: Fri, 27 Jan 2017 16:11:59 -0800 Subject: Clean up message manger includes: Provider egine bump Remove presence of message manger in keyring controller Change the status wording fom conf to approved make Message manager a class fix messages not being apart of the badge re write message manger to better reflect controller pattern --- app/scripts/background.js | 9 ++-- app/scripts/keyring-controller.js | 105 +++++++------------------------------ app/scripts/lib/message-manager.js | 77 +++++++++++++++++++++++---- app/scripts/metamask-controller.js | 62 +++++++++++++--------- app/scripts/transaction-manager.js | 2 +- 5 files changed, 129 insertions(+), 126 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index da9c4f24b..2e5a992b9 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -8,7 +8,6 @@ const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') const notification = require('./lib/notifications.js') -const messageManager = require('./lib/message-manager') const MetamaskController = require('./metamask-controller') const extension = require('./lib/extension') const firstTimeState = require('./first-time-state') @@ -112,14 +111,14 @@ function setupController (initState) { updateBadge() controller.txManager.on('updateBadge', updateBadge) + controller.messageManager.on('updateBadge', updateBadge) // plugin badge text function updateBadge () { var label = '' var unapprovedTxCount = controller.txManager.unapprovedTxCount - var unconfMsgs = messageManager.unconfirmedMsgs() - var unconfMsgLen = Object.keys(unconfMsgs).length - var count = unapprovedTxCount + unconfMsgLen + var unapprovedMsgCount = controller.messageManager.unapprovedMsgCount + var count = unapprovedTxCount + unapprovedMsgCount if (count) { label = String(count) } @@ -145,4 +144,4 @@ extension.runtime.onInstalled.addListener(function (details) { if ((details.reason === 'install') && (!METAMASK_DEBUG)) { extension.tabs.create({url: 'https://metamask.io/#how-it-works'}) } -}) \ No newline at end of file +}) diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index a4bee8ae1..b6c9aa3a7 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -5,7 +5,6 @@ const filter = require('promise-filter') const encryptor = require('browser-passworder') const normalize = require('./lib/sig-util').normalize -const messageManager = require('./lib/message-manager') const BN = ethUtil.BN // Keyrings: @@ -16,8 +15,6 @@ const keyringTypes = [ HdKeyring, ] -const createId = require('./lib/random-id') - module.exports = class KeyringController extends EventEmitter { // PUBLIC METHODS @@ -35,9 +32,6 @@ module.exports = class KeyringController extends EventEmitter { this.keyringTypes = keyringTypes this.keyrings = [] this.identities = {} // Essentially a name hash - - this._unconfMsgCbs = {} - this.getNetwork = opts.getNetwork } @@ -84,8 +78,6 @@ module.exports = class KeyringController extends EventEmitter { isInitialized: (!!wallet || !!vault), isUnlocked: Boolean(this.password), isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), - unconfMsgs: messageManager.unconfirmedMsgs(), - messages: messageManager.getMsgList(), selectedAccount: address, shapeShiftTxList: this.configManager.getShapeShiftTxList(), currentFiat: this.configManager.getCurrentFiat(), @@ -154,6 +146,17 @@ module.exports = class KeyringController extends EventEmitter { .then(this.fullUpdate.bind(this)) } + // ClearSeedWordCache + // + // returns Promise( @string currentSelectedAccount ) + // + // Removes the current vault's seed words from the UI's state tree, + // ensuring they are only ever available in the background process. + clearSeedWordCache () { + this.configManager.setSeedWords(null) + return Promise.resolve(this.configManager.getSelectedAccount()) + } + // Set Locked // returns Promise( @object state ) // @@ -204,8 +207,8 @@ module.exports = class KeyringController extends EventEmitter { this.keyrings.push(keyring) return this.setupAccounts(accounts) }) - .then(() => this.persistAllKeyrings()) - .then(() => this.fullUpdate()) + .then(() => { return this.password }) + .then(this.persistAllKeyrings.bind(this)) .then(() => { return keyring }) @@ -287,86 +290,19 @@ module.exports = class KeyringController extends EventEmitter { return keyring.signTransaction(fromAddress, ethTx) }) } - // Add Unconfirmed Message - // @object msgParams - // @function cb - // - // Does not call back, only emits an `update` event. - // - // Adds the given `msgParams` and `cb` to a local cache, - // for displaying to a user for approval before signing or canceling. - addUnconfirmedMessage (msgParams, cb) { - // create txData obj with parameters and meta data - var time = (new Date()).getTime() - var msgId = createId() - var msgData = { - id: msgId, - msgParams: msgParams, - time: time, - status: 'unconfirmed', - } - messageManager.addMsg(msgData) - console.log('addUnconfirmedMessage:', msgData) - - // keep the cb around for after approval (requires user interaction) - // This cb fires completion to the Dapp's write operation. - this._unconfMsgCbs[msgId] = cb - - // signal update - this.emit('update') - return msgId - } - - // Cancel Message - // @string msgId - // @function cb (optional) - // - // Calls back to cached `unconfMsgCb`. - // Calls back to `cb` if provided. - // - // Forgets any messages matching `msgId`. - cancelMessage (msgId, cb) { - var approvalCb = this._unconfMsgCbs[msgId] || noop - - // reject tx - approvalCb(null, false) - // clean up - messageManager.rejectMsg(msgId) - delete this._unconfTxCbs[msgId] - - if (cb && typeof cb === 'function') { - cb() - } - } // Sign Message // @object msgParams - // @function cb // // returns Promise(@buffer rawSig) - // calls back @function cb with @buffer rawSig - // calls back cached Dapp's @function unconfMsgCb. // // Attempts to sign the provided @object msgParams. - signMessage (msgParams, cb) { - try { - const msgId = msgParams.metamaskId - delete msgParams.metamaskId - const approvalCb = this._unconfMsgCbs[msgId] || noop - - const address = normalize(msgParams.from) - return this.getKeyringForAccount(address) - .then((keyring) => { - return keyring.signMessage(address, msgParams.data) - }).then((rawSig) => { - cb(null, rawSig) - approvalCb(null, true) - messageManager.confirmMsg(msgId) - return rawSig - }) - } catch (e) { - cb(e) - } + signMessage (msgParams) { + const address = normalize(msgParams.from) + return this.getKeyringForAccount(address) + .then((keyring) => { + return keyring.signMessage(address, msgParams.data) + }) } // PRIVATE METHODS @@ -643,6 +579,3 @@ module.exports = class KeyringController extends EventEmitter { } } - - -function noop () {} diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 379f38917..bc9a9e6c8 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -1,23 +1,61 @@ const EventEmitter = require('events') +const ObservableStore = require('obs-store') +const createId = require('./random-id') + module.exports = class MessageManager extends EventEmitter{ constructor (opts) { super() - this.messages = [] + this.memStore = new ObservableStore({ messages: [] }) + } + + getState() { + return { + unapprovedMsgs: this.unapprovedMsgs(), + messages: this.getMsgList(), + } } getMsgList () { - return this.messages + return this.memStore.getState().messages } - unconfirmedMsgs () { + get unapprovedMsgCount () { + return Object.keys(this.unapprovedMsgs()).length + } + + unapprovedMsgs () { let messages = this.getMsgList() - return messages.filter(msg => msg.status === 'unconfirmed') + return messages.filter(msg => msg.status === 'unapproved') .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) } _saveMsgList (msgList) { - this.messages = msgList + this.emit('updateBadge') + let state = this.memStore.getState() + state.messages = msgList + this.memStore.putState(state) + } + + addUnapprovedMessage (msgParams) { + // create txData obj with parameters and meta data + var time = (new Date()).getTime() + var msgId = createId() + var msgData = { + id: msgId, + msgParams: msgParams, + time: time, + status: 'unapproved', + } + this.addMsg(msgData) + console.log('addUnapprovedMessage:', msgData) + + // keep the cb around for after approval (requires user interaction) + // This cb fires completion to the Dapp's write operation. + + // signal update + this.emit('update') + return msgId } addMsg (msg) { @@ -32,8 +70,28 @@ module.exports = class MessageManager extends EventEmitter{ return matching.length > 0 ? matching[0] : null } - confirmMsg (msgId) { - this._setMsgStatus(msgId, 'confirmed') + brodcastMessage (rawSig, msgId, status) { + this.emit(`${msgId}:finished`, {status, rawSig}) + } + + approveMessage (msgParams) { + this.setMessageApproved(msgParams.metamaskId) + return this.prepMsgForSigning(msgParams) + } + + setMessageApproved (msgId) { + this._setMsgStatus(msgId, 'approved') + } + prepMsgForSigning (msgParams) { + delete msgParams.metamaskId + return Promise.resolve(msgParams) + } + + cancelMessage (msgId) { + // reject tx + // clean up + this.brodcastMessage(null, msgId, 'rejected') + this.rejectMsg(msgId) } rejectMsg (msgId) { @@ -43,14 +101,13 @@ module.exports = class MessageManager extends EventEmitter{ _setMsgStatus (msgId, status) { let msg = this.getMsg(msgId) if (msg) msg.status = status - this.updateMsg(msg) + this._updateMsg(msg) } - updateMsg (msg) { + _updateMsg (msg) { let messages = this.getMsgList() let index = messages.findIndex((message) => message.id === msg.id) if (index !== -1) { - this.emit('update', msg.id) messages[index] = msg } this._saveMsgList(messages) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 3ce9c2373..571968b65 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -12,7 +12,7 @@ const MetaMaskProvider = require('web3-provider-engine/zero.js') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') const NoticeController = require('./notice-controller') -const messageManager = require('./lib/message-manager') +const MessageManager = require('./lib/message-manager') const TxManager = require('./transaction-manager') const ConfigManager = require('./lib/config-manager') const extension = require('./lib/extension') @@ -32,7 +32,7 @@ module.exports = class MetamaskController extends EventEmitter { // observable state store this.store = new ObservableStore(opts.initState) - + // config manager this.configManager = new ConfigManager({ store: this.store, @@ -47,7 +47,7 @@ module.exports = class MetamaskController extends EventEmitter { // eth data query tools this.ethQuery = new EthQuery(this.provider) this.ethStore = new EthStore(this.provider) - + // key mgmt this.keyringController = new KeyringController({ ethStore: this.ethStore, @@ -70,7 +70,7 @@ module.exports = class MetamaskController extends EventEmitter { provider: this.provider, blockTracker: this.provider, }) - + // notices this.noticeController = new NoticeController({ configManager: this.configManager, @@ -80,7 +80,7 @@ module.exports = class MetamaskController extends EventEmitter { // this.noticeController.startPolling() this.getNetwork() - this.messageManager = messageManager + this.messageManager = new MessageManager() this.publicConfigStore = this.initPublicConfigStore() this.checkTOSChange() @@ -96,6 +96,7 @@ module.exports = class MetamaskController extends EventEmitter { this.ethStore.on('update', this.sendUpdate.bind(this)) this.keyringController.on('update', this.sendUpdate.bind(this)) this.txManager.on('update', this.sendUpdate.bind(this)) + this.messageManager.on('update', this.sendUpdate.bind(this)) } // @@ -118,11 +119,7 @@ module.exports = class MetamaskController extends EventEmitter { // tx signing processTransaction: (txParams, cb) => this.newUnapprovedTransaction(txParams, cb), // msg signing - approveMessage: this.newUnsignedMessage.bind(this), - signMessage: (...args) => { - this.keyringController.signMessage(...args) - this.sendUpdate() - }, + processMessage: this.newUnsignedMessage.bind(this), }) return provider } @@ -163,6 +160,7 @@ module.exports = class MetamaskController extends EventEmitter { this.ethStore.getState(), this.configManager.getConfig(), this.txManager.getState(), + this.messageManager.getState(), keyringControllerState, this.noticeController.getState(), { lostAccounts: this.configManager.getLostAccounts(), @@ -178,6 +176,7 @@ module.exports = class MetamaskController extends EventEmitter { getApi () { const keyringController = this.keyringController const txManager = this.txManager + const messageManager = this.messageManager const noticeController = this.noticeController return { @@ -197,7 +196,7 @@ module.exports = class MetamaskController extends EventEmitter { buyEth: this.buyEth.bind(this), // shapeshift createShapeShiftTx: this.createShapeShiftTx.bind(this), - + // primary HD keyring management addNewAccount: this.addNewAccount.bind(this), placeSeedWords: this.placeSeedWords.bind(this), @@ -219,8 +218,8 @@ module.exports = class MetamaskController extends EventEmitter { // signing methods approveTransaction: txManager.approveTransaction.bind(txManager), cancelTransaction: txManager.cancelTransaction.bind(txManager), - signMessage: keyringController.signMessage.bind(keyringController), - cancelMessage: keyringController.cancelMessage.bind(keyringController), + signMessage: this.signMessage.bind(this), + cancelMessage: messageManager.cancelMessage.bind(messageManager), // notices checkNotices: noticeController.updateNoticesList.bind(noticeController), @@ -358,20 +357,35 @@ module.exports = class MetamaskController extends EventEmitter { } newUnsignedMessage (msgParams, cb) { - var state = this.keyringController.getState() - if (!state.isUnlocked) { - this.keyringController.addUnconfirmedMessage(msgParams, cb) - this.opts.unlockAccountMessage() - } else { - this.addUnconfirmedMessage(msgParams, cb) + this.keyringController.getState() + .then((state) => { + let msgId = this.messageManager.addUnapprovedMessage(msgParams) this.sendUpdate() - } + state.isUnlocked ? this.opts.unlockAccountMessage() : this.opts.showUnconfirmedMessage() + this.messageManager.once(`${msgId}:finished`, (data) => { + switch (data.status) { + case 'approved': + return cb(null, data.rawSig) + case 'rejected': + return cb(new Error('MetaMask Tx Signature: User denied transaction signature.')) + default: + return cb(new Error(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) + } + }) + }) } - addUnconfirmedMessage (msgParams, cb) { - const keyringController = this.keyringController - const msgId = keyringController.addUnconfirmedMessage(msgParams, cb) - this.opts.showUnconfirmedMessage(msgParams, msgId) + signMessage (msgParams, cb) { + const msgId = msgParams.metamaskId + return this.messageManager.approveMessage(msgParams) + .then((cleanMsgParams) => { + return this.keyringController.signMessage(cleanMsgParams) + }) + .then((rawSig) => { + this.messageManager.brodcastMessage(rawSig, msgId, 'approved') + }).then(() => { + cb() + }).catch((err) => cb(err)) } setupPublicConfig (outStream) { diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 6d0121afd..153b8bc28 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -28,7 +28,7 @@ module.exports = class TransactionManager extends EventEmitter { var selectedAccount = this.getSelectedAccount() return { transactions: this.getTxList(), - unconfTxs: this.getUnapprovedTxList(), + unapprovedTxs: this.getUnapprovedTxList(), selectedAccountTxList: this.getFilteredTxList({metamaskNetworkId: this.getNetwork(), from: selectedAccount}), } } -- cgit v1.2.3