diff options
author | Kevin Serrano <kevgagser@gmail.com> | 2017-03-02 02:01:21 +0800 |
---|---|---|
committer | Kevin Serrano <kevgagser@gmail.com> | 2017-03-02 02:01:21 +0800 |
commit | 0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66 (patch) | |
tree | cb569b1419363928282cd9ae0b4862d436c8fa58 /app | |
parent | 930dafc4b0648353f847c529cdc19e2d762553ad (diff) | |
parent | f162a11585392df5e593018a02549f8b03018d22 (diff) | |
download | tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar.gz tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar.bz2 tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar.lz tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar.xz tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.tar.zst tangerine-wallet-browser-0a3849ec8477b4a61c50d715bd72b3e8f1ea8b66.zip |
Fix merge conflicts.
Diffstat (limited to 'app')
-rw-r--r-- | app/scripts/background.js | 4 | ||||
-rw-r--r-- | app/scripts/keyring-controller.js | 23 | ||||
-rw-r--r-- | app/scripts/keyrings/hd.js | 125 | ||||
-rw-r--r-- | app/scripts/keyrings/simple.js | 100 | ||||
-rw-r--r-- | app/scripts/lib/config-manager.js | 14 | ||||
-rw-r--r-- | app/scripts/lib/id-management.js | 9 | ||||
-rw-r--r-- | app/scripts/lib/idStore-migrator.js | 4 | ||||
-rw-r--r-- | app/scripts/lib/idStore.js | 1 | ||||
-rw-r--r-- | app/scripts/lib/message-manager.js | 3 | ||||
-rw-r--r-- | app/scripts/lib/personal-message-manager.js | 119 | ||||
-rw-r--r-- | app/scripts/lib/sig-util.js | 28 | ||||
-rw-r--r-- | app/scripts/lib/tx-utils.js | 6 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 143 | ||||
-rw-r--r-- | app/scripts/transaction-manager.js | 15 |
14 files changed, 267 insertions, 327 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 2e5a992b9..254737dec 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -15,6 +15,10 @@ const firstTimeState = require('./first-time-state') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const log = require('loglevel') +window.log = log +log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') + let popupIsOpen = false // state persistence diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index b30161003..e1b1c4335 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -5,10 +5,11 @@ const EventEmitter = require('events').EventEmitter const ObservableStore = require('obs-store') const filter = require('promise-filter') const encryptor = require('browser-passworder') -const normalizeAddress = require('./lib/sig-util').normalize +const sigUtil = require('eth-sig-util') +const normalizeAddress = sigUtil.normalize // Keyrings: -const SimpleKeyring = require('./keyrings/simple') -const HdKeyring = require('./keyrings/hd') +const SimpleKeyring = require('eth-simple-keyring') +const HdKeyring = require('eth-hd-keyring') const keyringTypes = [ SimpleKeyring, HdKeyring, @@ -262,6 +263,21 @@ class KeyringController extends EventEmitter { }) } + // Sign Personal Message + // @object msgParams + // + // returns Promise(@buffer rawSig) + // + // Attempts to sign the provided @object msgParams. + // Prefixes the hash before signing as per the new geth behavior. + signPersonalMessage (msgParams) { + const address = normalizeAddress(msgParams.from) + return this.getKeyringForAccount(address) + .then((keyring) => { + return keyring.signPersonalMessage(address, msgParams.data) + }) + } + // PRIVATE METHODS // // THESE METHODS ARE ONLY USED INTERNALLY TO THE KEYRING-CONTROLLER @@ -471,6 +487,7 @@ class KeyringController extends EventEmitter { // the specified `address` if one exists. getKeyringForAccount (address) { const hexed = normalizeAddress(address) + log.debug(`KeyringController - getKeyringForAccount: ${hexed}`) return Promise.all(this.keyrings.map((keyring) => { return Promise.all([ diff --git a/app/scripts/keyrings/hd.js b/app/scripts/keyrings/hd.js deleted file mode 100644 index 3a66f7868..000000000 --- a/app/scripts/keyrings/hd.js +++ /dev/null @@ -1,125 +0,0 @@ -const EventEmitter = require('events').EventEmitter -const hdkey = require('ethereumjs-wallet/hdkey') -const bip39 = require('bip39') -const ethUtil = require('ethereumjs-util') - -// *Internal Deps -const sigUtil = require('../lib/sig-util') - -// Options: -const hdPathString = `m/44'/60'/0'/0` -const type = 'HD Key Tree' - -class HdKeyring extends EventEmitter { - - /* PUBLIC METHODS */ - - constructor (opts = {}) { - super() - this.type = type - this.deserialize(opts) - } - - serialize () { - return Promise.resolve({ - mnemonic: this.mnemonic, - numberOfAccounts: this.wallets.length, - }) - } - - deserialize (opts = {}) { - this.opts = opts || {} - this.wallets = [] - this.mnemonic = null - this.root = null - - if (opts.mnemonic) { - this._initFromMnemonic(opts.mnemonic) - } - - if (opts.numberOfAccounts) { - return this.addAccounts(opts.numberOfAccounts) - } - - return Promise.resolve([]) - } - - addAccounts (numberOfAccounts = 1) { - if (!this.root) { - this._initFromMnemonic(bip39.generateMnemonic()) - } - - const oldLen = this.wallets.length - const newWallets = [] - for (let i = oldLen; i < numberOfAccounts + oldLen; i++) { - const child = this.root.deriveChild(i) - const wallet = child.getWallet() - newWallets.push(wallet) - this.wallets.push(wallet) - } - const hexWallets = newWallets.map(w => w.getAddress().toString('hex')) - return Promise.resolve(hexWallets) - } - - getAccounts () { - return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex'))) - } - - // tx is an instance of the ethereumjs-transaction class. - signTransaction (address, tx) { - const wallet = this._getWalletForAccount(address) - var privKey = wallet.getPrivateKey() - tx.sign(privKey) - return Promise.resolve(tx) - } - - // For eth_sign, we need to sign transactions: - // hd - signMessage (withAccount, data) { - const wallet = this._getWalletForAccount(withAccount) - const message = ethUtil.stripHexPrefix(data) - var privKey = wallet.getPrivateKey() - var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) - var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) - return Promise.resolve(rawMsgSig) - } - - // For eth_sign, we need to sign transactions: - newGethSignMessage (withAccount, msgHex) { - const wallet = this._getWalletForAccount(withAccount) - const privKey = wallet.getPrivateKey() - const msgBuffer = ethUtil.toBuffer(msgHex) - const msgHash = ethUtil.hashPersonalMessage(msgBuffer) - const msgSig = ethUtil.ecsign(msgHash, privKey) - const rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) - return Promise.resolve(rawMsgSig) - } - - exportAccount (address) { - const wallet = this._getWalletForAccount(address) - return Promise.resolve(wallet.getPrivateKey().toString('hex')) - } - - - /* PRIVATE METHODS */ - - _initFromMnemonic (mnemonic) { - this.mnemonic = mnemonic - const seed = bip39.mnemonicToSeed(mnemonic) - this.hdWallet = hdkey.fromMasterSeed(seed) - this.root = this.hdWallet.derivePath(hdPathString) - } - - - _getWalletForAccount (account) { - const targetAddress = sigUtil.normalize(account) - return this.wallets.find((w) => { - const address = w.getAddress().toString('hex') - return ((address === targetAddress) || - (sigUtil.normalize(address) === targetAddress)) - }) - } -} - -HdKeyring.type = type -module.exports = HdKeyring diff --git a/app/scripts/keyrings/simple.js b/app/scripts/keyrings/simple.js deleted file mode 100644 index 82881aa2d..000000000 --- a/app/scripts/keyrings/simple.js +++ /dev/null @@ -1,100 +0,0 @@ -const EventEmitter = require('events').EventEmitter -const Wallet = require('ethereumjs-wallet') -const ethUtil = require('ethereumjs-util') -const type = 'Simple Key Pair' -const sigUtil = require('../lib/sig-util') - -class SimpleKeyring extends EventEmitter { - - /* PUBLIC METHODS */ - - constructor (opts) { - super() - this.type = type - this.opts = opts || {} - this.wallets = [] - } - - serialize () { - return Promise.resolve(this.wallets.map(w => w.getPrivateKey().toString('hex'))) - } - - deserialize (privateKeys = []) { - return new Promise((resolve, reject) => { - try { - this.wallets = privateKeys.map((privateKey) => { - const stripped = ethUtil.stripHexPrefix(privateKey) - const buffer = new Buffer(stripped, 'hex') - const wallet = Wallet.fromPrivateKey(buffer) - return wallet - }) - } catch (e) { - reject(e) - } - resolve() - }) - } - - addAccounts (n = 1) { - var newWallets = [] - for (var i = 0; i < n; i++) { - newWallets.push(Wallet.generate()) - } - this.wallets = this.wallets.concat(newWallets) - const hexWallets = newWallets.map(w => ethUtil.bufferToHex(w.getAddress())) - return Promise.resolve(hexWallets) - } - - getAccounts () { - return Promise.resolve(this.wallets.map(w => ethUtil.bufferToHex(w.getAddress()))) - } - - // tx is an instance of the ethereumjs-transaction class. - signTransaction (address, tx) { - const wallet = this._getWalletForAccount(address) - var privKey = wallet.getPrivateKey() - tx.sign(privKey) - return Promise.resolve(tx) - } - - // For eth_sign, we need to sign transactions: - signMessage (withAccount, data) { - const wallet = this._getWalletForAccount(withAccount) - const message = ethUtil.stripHexPrefix(data) - var privKey = wallet.getPrivateKey() - var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) - var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) - return Promise.resolve(rawMsgSig) - } - - // For eth_sign, we need to sign transactions: - - newGethSignMessage (withAccount, msgHex) { - const wallet = this._getWalletForAccount(withAccount) - const privKey = wallet.getPrivateKey() - const msgBuffer = ethUtil.toBuffer(msgHex) - const msgHash = ethUtil.hashPersonalMessage(msgBuffer) - const msgSig = ethUtil.ecsign(msgHash, privKey) - const rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) - return Promise.resolve(rawMsgSig) - } - - exportAccount (address) { - const wallet = this._getWalletForAccount(address) - return Promise.resolve(wallet.getPrivateKey().toString('hex')) - } - - - /* PRIVATE METHODS */ - - _getWalletForAccount (account) { - const address = sigUtil.normalize(account) - let wallet = this.wallets.find(w => ethUtil.bufferToHex(w.getAddress()) === address) - if (!wallet) throw new Error('Simple Keyring - Unable to find matching address.') - return wallet - } - -} - -SimpleKeyring.type = type -module.exports = SimpleKeyring diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 6267eab68..6868637e5 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -1,6 +1,6 @@ const MetamaskConfig = require('../config.js') const ethUtil = require('ethereumjs-util') -const normalize = require('./sig-util').normalize +const normalize = require('eth-sig-util').normalize const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet @@ -228,18 +228,6 @@ ConfigManager.prototype._emitUpdates = function (state) { }) } -ConfigManager.prototype.getGasMultiplier = function () { - var data = this.getData() - return data.gasMultiplier -} - -ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) { - var data = this.getData() - - data.gasMultiplier = gasMultiplier - this.setData(data) -} - ConfigManager.prototype.setLostAccounts = function (lostAccounts) { var data = this.getData() data.lostAccounts = lostAccounts diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js index 421f2105f..90b3fdb13 100644 --- a/app/scripts/lib/id-management.js +++ b/app/scripts/lib/id-management.js @@ -7,7 +7,6 @@ */ const ethUtil = require('ethereumjs-util') -const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') module.exports = IdManagement @@ -25,13 +24,9 @@ function IdManagement (opts) { } this.signTx = function (txParams) { - // calculate gas with custom gas multiplier - var gasMultiplier = this.configManager.getGasMultiplier() || 1 - var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16) - gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10)) - txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) - // normalize values + // normalize values + txParams.gasPrice = ethUtil.intToHex(txParams.gasPrice) txParams.to = ethUtil.addHexPrefix(txParams.to) txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase()) txParams.value = ethUtil.addHexPrefix(txParams.value) diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js index 655aed0af..62d21eee7 100644 --- a/app/scripts/lib/idStore-migrator.js +++ b/app/scripts/lib/idStore-migrator.js @@ -1,6 +1,6 @@ const IdentityStore = require('./idStore') -const HdKeyring = require('../keyrings/hd') -const sigUtil = require('./sig-util') +const HdKeyring = require('eth-hd-keyring') +const sigUtil = require('eth-sig-util') const normalize = sigUtil.normalize const denodeify = require('denodeify') diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 7a6968c6c..01474035e 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -95,7 +95,6 @@ IdentityStore.prototype.getState = function () { isUnlocked: this._isUnlocked(), seedWords: seedWords, selectedAddress: configManager.getSelectedAccount(), - gasMultiplier: configManager.getGasMultiplier(), })) } diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index ceaf8ee2f..711d5f159 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -33,6 +33,7 @@ module.exports = class MessageManager extends EventEmitter{ msgParams: msgParams, time: time, status: 'unapproved', + type: 'eth_sign', } this.addMsg(msgData) @@ -115,4 +116,4 @@ function normalizeMsgData(data) { // data is unicode, convert to hex return ethUtil.bufferToHex(new Buffer(data, 'utf8')) } -}
\ No newline at end of file +} diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js new file mode 100644 index 000000000..3b8510767 --- /dev/null +++ b/app/scripts/lib/personal-message-manager.js @@ -0,0 +1,119 @@ +const EventEmitter = require('events') +const ObservableStore = require('obs-store') +const ethUtil = require('ethereumjs-util') +const createId = require('./random-id') + + +module.exports = class PersonalMessageManager extends EventEmitter{ + constructor (opts) { + super() + this.memStore = new ObservableStore({ + unapprovedPersonalMsgs: {}, + unapprovedPersonalMsgCount: 0, + }) + this.messages = [] + } + + get unapprovedPersonalMsgCount () { + return Object.keys(this.getUnapprovedMsgs()).length + } + + getUnapprovedMsgs () { + return this.messages.filter(msg => msg.status === 'unapproved') + .reduce((result, msg) => { result[msg.id] = msg; return result }, {}) + } + + addUnapprovedMessage (msgParams) { + msgParams.data = normalizeMsgData(msgParams.data) + // 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', + type: 'personal_sign', + } + this.addMsg(msgData) + + // signal update + this.emit('update') + return msgId + } + + addMsg (msg) { + this.messages.push(msg) + this._saveMsgList() + } + + getMsg (msgId) { + return this.messages.find(msg => msg.id === msgId) + } + + approveMessage (msgParams) { + this.setMsgStatusApproved(msgParams.metamaskId) + return this.prepMsgForSigning(msgParams) + } + + setMsgStatusApproved (msgId) { + this._setMsgStatus(msgId, 'approved') + } + + setMsgStatusSigned (msgId, rawSig) { + const msg = this.getMsg(msgId) + msg.rawSig = rawSig + this._updateMsg(msg) + this._setMsgStatus(msgId, 'signed') + } + + prepMsgForSigning (msgParams) { + delete msgParams.metamaskId + return Promise.resolve(msgParams) + } + + rejectMsg (msgId) { + this._setMsgStatus(msgId, 'rejected') + } + + // + // PRIVATE METHODS + // + + _setMsgStatus (msgId, status) { + const msg = this.getMsg(msgId) + if (!msg) throw new Error('PersonalMessageManager - Message not found for id: "${msgId}".') + msg.status = status + this._updateMsg(msg) + this.emit(`${msgId}:${status}`, msg) + if (status === 'rejected' || status === 'signed') { + this.emit(`${msgId}:finished`, msg) + } + } + + _updateMsg (msg) { + const index = this.messages.findIndex((message) => message.id === msg.id) + if (index !== -1) { + this.messages[index] = msg + } + this._saveMsgList() + } + + _saveMsgList () { + const unapprovedPersonalMsgs = this.getUnapprovedMsgs() + const unapprovedPersonalMsgCount = Object.keys(unapprovedPersonalMsgs).length + this.memStore.updateState({ unapprovedPersonalMsgs, unapprovedPersonalMsgCount }) + this.emit('updateBadge') + } + +} + +function normalizeMsgData(data) { + if (data.slice(0, 2) === '0x') { + // data is already hex + return data + } else { + // data is unicode, convert to hex + return ethUtil.bufferToHex(new Buffer(data, 'utf8')) + } +} diff --git a/app/scripts/lib/sig-util.js b/app/scripts/lib/sig-util.js deleted file mode 100644 index 193dda381..000000000 --- a/app/scripts/lib/sig-util.js +++ /dev/null @@ -1,28 +0,0 @@ -const ethUtil = require('ethereumjs-util') - -module.exports = { - - concatSig: function (v, r, s) { - const rSig = ethUtil.fromSigned(r) - const sSig = ethUtil.fromSigned(s) - const vSig = ethUtil.bufferToInt(v) - const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) - const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) - const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) - return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') - }, - - normalize: function (address) { - if (!address) return - return ethUtil.addHexPrefix(address.toLowerCase()) - }, - -} - -function padWithZeroes (number, length) { - var myString = '' + number - while (myString.length < length) { - myString = '0' + myString - } - return myString -} diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 5116cb93b..19a2d430e 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -2,7 +2,7 @@ const async = require('async') const EthQuery = require('eth-query') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') -const normalize = require('./sig-util').normalize +const normalize = require('eth-sig-util').normalize const BN = ethUtil.BN /* @@ -92,11 +92,10 @@ module.exports = class txProviderUtils { } // builds ethTx from txParams object - buildEthTxFromParams (txParams, gasMultiplier = 1) { + buildEthTxFromParams (txParams) { // apply gas multiplyer let gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice), 16) // multiply and divide by 100 so as to add percision to integer mul - gasPrice = gasPrice.mul(new BN(gasMultiplier * 100, 10)).div(new BN(100, 10)) txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) // normalize values txParams.to = normalize(txParams.to) @@ -106,6 +105,7 @@ module.exports = class txProviderUtils { txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas) txParams.nonce = normalize(txParams.nonce) // build ethTx + log.info(`Prepared tx for signing: ${JSON.stringify(txParams)}`) const ethTx = new Transaction(txParams) return ethTx } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ad67a5875..cbef8924a 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -16,6 +16,7 @@ const CurrencyController = require('./lib/controllers/currency') const NoticeController = require('./notice-controller') const ShapeShiftController = require('./lib/controllers/shapeshift') const MessageManager = require('./lib/message-manager') +const PersonalMessageManager = require('./lib/personal-message-manager') const TxManager = require('./transaction-manager') const ConfigManager = require('./lib/config-manager') const extension = require('./lib/extension') @@ -105,6 +106,7 @@ module.exports = class MetamaskController extends EventEmitter { this.lookupNetwork() this.messageManager = new MessageManager() + this.personalMessageManager = new PersonalMessageManager() this.publicConfigStore = this.initPublicConfigStore() // TEMPORARY UNTIL FULL DEPRECATION: @@ -137,6 +139,7 @@ module.exports = class MetamaskController extends EventEmitter { this.ethStore.subscribe(this.sendUpdate.bind(this)) this.txManager.memStore.subscribe(this.sendUpdate.bind(this)) this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) + this.personalMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) this.keyringController.memStore.subscribe(this.sendUpdate.bind(this)) this.preferencesController.store.subscribe(this.sendUpdate.bind(this)) this.currencyController.store.subscribe(this.sendUpdate.bind(this)) @@ -149,6 +152,7 @@ module.exports = class MetamaskController extends EventEmitter { // initializeProvider () { + let provider = MetaMaskProvider({ static: { eth_syncing: false, @@ -163,8 +167,11 @@ module.exports = class MetamaskController extends EventEmitter { }, // tx signing processTransaction: (txParams, cb) => this.newUnapprovedTransaction(txParams, cb), - // msg signing + // old style msg signing processMessage: this.newUnsignedMessage.bind(this), + + // new style msg signing + processPersonalMessage: this.newUnsignedPersonalMessage.bind(this), }) return provider } @@ -209,6 +216,7 @@ module.exports = class MetamaskController extends EventEmitter { this.ethStore.getState(), this.txManager.memStore.getState(), this.messageManager.memStore.getState(), + this.personalMessageManager.memStore.getState(), this.keyringController.memStore.getState(), this.preferencesController.store.getState(), this.currencyController.store.getState(), @@ -231,7 +239,6 @@ module.exports = class MetamaskController extends EventEmitter { const keyringController = this.keyringController const preferencesController = this.preferencesController const txManager = this.txManager - const messageManager = this.messageManager const noticeController = this.noticeController return { @@ -241,7 +248,6 @@ module.exports = class MetamaskController extends EventEmitter { setProviderType: this.setProviderType.bind(this), useEtherscanProvider: this.useEtherscanProvider.bind(this), setCurrentCurrency: this.setCurrentCurrency.bind(this), - setGasMultiplier: this.setGasMultiplier.bind(this), markAccountsFound: this.markAccountsFound.bind(this), // coinbase buyEth: this.buyEth.bind(this), @@ -270,12 +276,17 @@ module.exports = class MetamaskController extends EventEmitter { exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), // txManager - approveTransaction: txManager.approveTransaction.bind(txManager), - cancelTransaction: txManager.cancelTransaction.bind(txManager), + approveTransaction: txManager.approveTransaction.bind(txManager), + cancelTransaction: txManager.cancelTransaction.bind(txManager), + updateAndApproveTransaction: this.updateAndApproveTx.bind(this), // messageManager - signMessage: this.signMessage.bind(this), - cancelMessage: messageManager.rejectMsg.bind(messageManager), + signMessage: nodeify(this.signMessage).bind(this), + cancelMessage: this.cancelMessage.bind(this), + + // personalMessageManager + signPersonalMessage: nodeify(this.signPersonalMessage).bind(this), + cancelPersonalMessage: this.cancelPersonalMessage.bind(this), // notices checkNotices: noticeController.updateNoticesList.bind(noticeController), @@ -397,6 +408,7 @@ module.exports = class MetamaskController extends EventEmitter { // newUnapprovedTransaction (txParams, cb) { + log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const self = this self.txManager.addUnapprovedTransaction(txParams, (err, txMeta) => { if (err) return cb(err) @@ -425,31 +437,109 @@ module.exports = class MetamaskController extends EventEmitter { case 'signed': return cb(null, data.rawSig) case 'rejected': - return cb(new Error('MetaMask Message Signature: User denied transaction signature.')) + return cb(new Error('MetaMask Message Signature: User denied message signature.')) default: return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) } }) } + newUnsignedPersonalMessage (msgParams, cb) { + if (!msgParams.from) { + return cb(new Error('MetaMask Message Signature: from field is required.')) + } + + let msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) + this.sendUpdate() + this.opts.showUnconfirmedMessage() + this.personalMessageManager.once(`${msgId}:finished`, (data) => { + switch (data.status) { + case 'signed': + return cb(null, data.rawSig) + case 'rejected': + return cb(new Error('MetaMask Message Signature: User denied message signature.')) + default: + return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) + } + }) + } + + updateAndApproveTx(txMeta, cb) { + log.debug(`MetaMaskController - updateAndApproveTx: ${JSON.stringify(txMeta)}`) + const txManager = this.txManager + txManager.updateTx(txMeta) + txManager.approveTransaction(txMeta.id, cb) + } + signMessage (msgParams, cb) { + log.info('MetaMaskController - signMessage') const msgId = msgParams.metamaskId - promiseToCallback( - // sets the status op the message to 'approved' - // and removes the metamaskId for signing - this.messageManager.approveMessage(msgParams) - .then((cleanMsgParams) => { - // signs the message - return this.keyringController.signMessage(cleanMsgParams) - }) - .then((rawSig) => { - // tells the listener that the message has been signed - // and can be returned to the dapp - this.messageManager.setMsgStatusSigned(msgId, rawSig) - }) - )(cb) + + // sets the status op the message to 'approved' + // and removes the metamaskId for signing + return this.messageManager.approveMessage(msgParams) + .then((cleanMsgParams) => { + // signs the message + return this.keyringController.signMessage(cleanMsgParams) + }) + .then((rawSig) => { + // tells the listener that the message has been signed + // and can be returned to the dapp + this.messageManager.setMsgStatusSigned(msgId, rawSig) + return this.getState() + }) + } + + cancelMessage(msgId, cb) { + const messageManager = this.messageManager + messageManager.rejectMsg(msgId) + if (cb && typeof cb === 'function') { + cb(null, this.getState()) + } } + // Prefixed Style Message Signing Methods: + approvePersonalMessage (msgParams, cb) { + let msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) + this.sendUpdate() + this.opts.showUnconfirmedMessage() + this.personalMessageManager.once(`${msgId}:finished`, (data) => { + switch (data.status) { + case 'signed': + return cb(null, data.rawSig) + case 'rejected': + return cb(new Error('MetaMask Message Signature: User denied transaction signature.')) + default: + return cb(new Error(`MetaMask Message Signature: Unknown problem: ${JSON.stringify(msgParams)}`)) + } + }) + } + + signPersonalMessage (msgParams) { + log.info('MetaMaskController - signPersonalMessage') + const msgId = msgParams.metamaskId + // sets the status op the message to 'approved' + // and removes the metamaskId for signing + return this.personalMessageManager.approveMessage(msgParams) + .then((cleanMsgParams) => { + // signs the message + return this.keyringController.signPersonalMessage(cleanMsgParams) + }) + .then((rawSig) => { + // tells the listener that the message has been signed + // and can be returned to the dapp + this.personalMessageManager.setMsgStatusSigned(msgId, rawSig) + return this.getState() + }) + } + + cancelPersonalMessage(msgId, cb) { + const messageManager = this.personalMessageManager + messageManager.rejectMsg(msgId) + if (cb && typeof cb === 'function') { + cb(null, this.getState()) + } + } markAccountsFound (cb) { this.configManager.setLostAccounts([]) @@ -563,15 +653,6 @@ module.exports = class MetamaskController extends EventEmitter { this.shapeshiftController.createShapeShiftTx(depositAddress, depositType) } - setGasMultiplier (gasMultiplier, cb) { - try { - this.txManager.setGasMultiplier(gasMultiplier) - cb() - } catch (err) { - cb(err) - } - } - // // network // diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 6299091f2..07c90af7e 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -13,7 +13,6 @@ module.exports = class TransactionManager extends EventEmitter { super() this.store = new ObservableStore(extend({ transactions: [], - gasMultiplier: 1, }, opts.initState)) this.memStore = new ObservableStore({}) this.networkStore = opts.networkStore || new ObservableStore({}) @@ -52,14 +51,6 @@ module.exports = class TransactionManager extends EventEmitter { return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) } - getGasMultiplier () { - return this.store.getState().gasMultiplier - } - - setGasMultiplier (gasMultiplier) { - return this.store.updateState({ gasMultiplier }) - } - // Adds a tx to the txlist addTx (txMeta) { var txList = this.getTxList() @@ -129,7 +120,6 @@ module.exports = class TransactionManager extends EventEmitter { id: txId, time: time, status: 'unapproved', - gasMultiplier: this.getGasMultiplier(), metamaskNetworkId: this.getNetwork(), txParams: txParams, } @@ -147,16 +137,15 @@ module.exports = class TransactionManager extends EventEmitter { setMaxTxCostAndFee (txMeta) { var txParams = txMeta.txParams - var gasMultiplier = txMeta.gasMultiplier var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txMeta.estimatedGas), 16) var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16) - gasPrice = gasPrice.mul(new BN(gasMultiplier * 100), 10).div(new BN(100, 10)) var txFee = gasCost.mul(gasPrice) var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16) var maxCost = txValue.add(txFee) txMeta.txFee = txFee txMeta.txValue = txValue txMeta.maxCost = maxCost + txMeta.gasPrice = gasPrice this.updateTx(txMeta) } @@ -209,7 +198,7 @@ module.exports = class TransactionManager extends EventEmitter { let txMeta = this.getTx(txId) let txParams = txMeta.txParams let fromAddress = txParams.from - let ethTx = this.txProviderUtils.buildEthTxFromParams(txParams, txMeta.gasMultiplier) + let ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) this.signEthTx(ethTx, fromAddress).then(() => { this.setTxStatusSigned(txMeta.id) cb(null, ethUtil.bufferToHex(ethTx.serialize())) |