diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/manifest.json | 2 | ||||
-rw-r--r-- | app/scripts/contentscript.js | 36 | ||||
-rw-r--r-- | app/scripts/inpage.js | 21 | ||||
-rw-r--r-- | app/scripts/keyring-controller.js | 44 | ||||
-rw-r--r-- | app/scripts/lib/auto-reload.js | 22 | ||||
-rw-r--r-- | app/scripts/lib/config-manager.js | 44 | ||||
-rw-r--r-- | app/scripts/lib/id-management.js | 7 | ||||
-rw-r--r-- | app/scripts/lib/idStore.js | 14 | ||||
-rw-r--r-- | app/scripts/lib/inpage-provider.js | 17 | ||||
-rw-r--r-- | app/scripts/lib/obj-multiplex.js | 8 | ||||
-rw-r--r-- | app/scripts/lib/port-stream.js | 3 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 13 |
12 files changed, 184 insertions, 47 deletions
diff --git a/app/manifest.json b/app/manifest.json index badeb7cb2..8f5a34ea6 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "2.13.3", + "version": "2.13.5", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index b3a560c88..e2a968ac9 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,4 +1,5 @@ const LocalMessageDuplexStream = require('post-message-stream') +const PongStream = require('ping-pong-stream/pong') const PortStream = require('./lib/port-stream.js') const ObjectMultiplex = require('./lib/obj-multiplex') const extension = require('./lib/extension') @@ -51,20 +52,35 @@ function setupStreams(){ // forward communication plugin->inpage pageStream.pipe(pluginStream).pipe(pageStream) - // connect contentscript->inpage reload stream + // setup local multistream channels var mx = ObjectMultiplex() mx.on('error', console.error) - mx.pipe(pageStream) - var reloadStream = mx.createStream('reload') - reloadStream.on('error', console.error) + mx.pipe(pageStream).pipe(mx) + + // connect ping stream + var pongStream = new PongStream({ objectMode: true }) + pongStream.pipe(mx.createStream('pingpong')).pipe(pongStream) + + // ignore unused channels (handled by background) + mx.ignoreStream('provider') + mx.ignoreStream('publicConfig') + mx.ignoreStream('reload') - // if we lose connection with the plugin, trigger tab refresh - pluginStream.on('close', function () { - reloadStream.write({ method: 'reset' }) - }) } function shouldInjectWeb3(){ - var shouldInject = (window.location.href.indexOf('.pdf') === -1) - return shouldInject + return isAllowedSuffix(window.location.href) +} + +function isAllowedSuffix(testCase) { + var prohibitedTypes = ['xml', 'pdf'] + var currentUrl = window.location.href + var currentRegex + for (let i = 0; i < prohibitedTypes.length; i++) { + currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`) + if (currentRegex.test(currentUrl)) { + return false + } + } + return true } diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 28a1223ac..85dd70b4d 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -2,6 +2,8 @@ cleanContextForImports() require('web3/dist/web3.min.js') const LocalMessageDuplexStream = require('post-message-stream') +const PingStream = require('ping-pong-stream/ping') +const endOfStream = require('end-of-stream') const setupDappAutoReload = require('./lib/auto-reload.js') const MetamaskInpageProvider = require('./lib/inpage-provider.js') restoreContextAfterImports() @@ -29,13 +31,22 @@ web3.setProvider = function () { console.log('MetaMask - overrode web3.setProvider') } console.log('MetaMask - injected web3') +// export global web3, with usage-detection reload fn +var triggerReload = setupDappAutoReload(web3) -// -// export global web3 with auto dapp reload -// - +// listen for reset requests from metamask var reloadStream = inpageProvider.multiStream.createStream('reload') -setupDappAutoReload(web3, reloadStream) +reloadStream.once('data', triggerReload) + +// setup ping timeout autoreload +// LocalMessageDuplexStream does not self-close, so reload if pingStream fails +var pingChannel = inpageProvider.multiStream.createStream('pingpong') +var pingStream = new PingStream({ objectMode: true }) +// wait for first successful reponse +metamaskStream.once('_data', function(){ + pingStream.pipe(pingChannel).pipe(pingStream) +}) +endOfStream(pingStream, triggerReload) // set web3 defaultAcount inpageProvider.publicConfigStore.subscribe(function (state) { diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index d96b9c101..db7e5e61e 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -1,7 +1,7 @@ -const scrypt = require('scrypt-async') -const bitcore = require('bitcore-lib') -const configManager = require('./lib/config-manager') const EventEmitter = require('events').EventEmitter +const encryptor = require('./lib/encryptor') +const messageManager = require('./lib/message-manager') + module.exports = class KeyringController extends EventEmitter { @@ -12,12 +12,17 @@ module.exports = class KeyringController extends EventEmitter { this.keyChains = [] } + keyFromPassword(password, callback) { + deriveKeyFromPassword(password, callback); + } + + // Takes a pw and callback, returns a password-dervied key getKeyForPassword(password, callback) { let salt = this.configManager.getSalt() if (!salt) { salt = generateSalt(32) - configManager.setSalt(salt) + this.configManager.setSalt(salt) } var logN = 14 @@ -39,7 +44,21 @@ module.exports = class KeyringController extends EventEmitter { } getState() { - return {} + return { + isInitialized: !!this.key, + isUnlocked: !!this.key, + isConfirmed: true, // this.configManager.getConfirmed(), + isEthConfirmed: this.configManager.getShouldntShowWarning(), + unconfTxs: this.configManager.unconfirmedTxs(), + transactions: this.configManager.getTxList(), + unconfMsgs: messageManager.unconfirmedMsgs(), + messages: messageManager.getMsgList(), + selectedAddress: this.configManager.getSelectedAccount(), + shapeShiftTxList: this.configManager.getShapeShiftTxList(), + currentFiat: this.configManager.getCurrentFiat(), + conversionRate: this.configManager.getConversionRate(), + conversionDate: this.configManager.getConversionDate(), + } } setStore(ethStore) { @@ -47,9 +66,22 @@ module.exports = class KeyringController extends EventEmitter { } createNewVault(password, entropy, cb) { - cb() + encryptor.keyFromPassword(password) + .then((key) => { + this.key = key + return encryptor.encryptWithKey(key, {}) + }) + .then((encryptedString) => { + this.configManager.setVault(encryptedString) + cb(null, []) + }) + .catch((err) => { + cb(err) + }) } + + submitPassword(password, cb) { cb() } diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index c4c8053f0..3c90905db 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -3,7 +3,7 @@ const ensnare = require('ensnare') module.exports = setupDappAutoReload -function setupDappAutoReload (web3, controlStream) { +function setupDappAutoReload (web3) { // export web3 as a global, checking for usage var pageIsUsingWeb3 = false var resetWasRequested = false @@ -16,19 +16,19 @@ function setupDappAutoReload (web3, controlStream) { global.web3 = web3 })) - // listen for reset requests from metamask - controlStream.once('data', function () { + return handleResetRequest + + function handleResetRequest() { resetWasRequested = true // ignore if web3 was not used if (!pageIsUsingWeb3) return // reload after short timeout - triggerReset() - }) - - // reload the page - function triggerReset () { - setTimeout(function () { - global.location.reload() - }, 500) + setTimeout(triggerReset, 500) } + } + +// reload the page +function triggerReset () { + global.location.reload() +}
\ No newline at end of file diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index ecc9bc5f7..d12304c46 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -110,6 +110,27 @@ ConfigManager.prototype.setWallet = function (wallet) { this.setData(data) } +ConfigManager.prototype.setVault = function (encryptedString) { + var data = this.getData() + data.vault = encryptedString + this.setData(data) +} + +ConfigManager.prototype.getVault = function () { + var data = this.getData() + return ('vault' in data) && data.vault +} + +ConfigManager.prototype.getKeychains = function () { + return this.migrator.getData().keychains || [] +} + +ConfigManager.prototype.setKeychains = function (keychains) { + var data = this.migrator.getData() + data.keychains = keychains + this.setData(data) +} + ConfigManager.prototype.getSelectedAccount = function () { var config = this.getConfig() return config.selectedAccount @@ -249,6 +270,17 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { // observable +ConfigManager.prototype.getSalt = function () { + var data = this.getData() + return ('salt' in data) && data.salt +} + +ConfigManager.prototype.setSalt = function(salt) { + var data = this.getData() + data.salt = salt + this.setData(data) +} + ConfigManager.prototype.subscribe = function (fn) { this._subs.push(fn) var unsubscribe = this.unsubscribe.bind(this, fn) @@ -384,3 +416,15 @@ ConfigManager.prototype.createShapeShiftTx = function (depositAddress, depositTy } this.setData(data) } + +ConfigManager.prototype.getGasMultiplier = function () { + var data = this.getData() + return ('gasMultiplier' in data) && data.gasMultiplier +} + +ConfigManager.prototype.setGasMultiplier = function (gasMultiplier) { + var data = this.getData() + + data.gasMultiplier = gasMultiplier + this.setData(data) +} diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js index 2d42e1e30..421f2105f 100644 --- a/app/scripts/lib/id-management.js +++ b/app/scripts/lib/id-management.js @@ -7,6 +7,7 @@ */ const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN const Transaction = require('ethereumjs-tx') module.exports = IdManagement @@ -24,7 +25,13 @@ 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 + 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.js b/app/scripts/lib/idStore.js index 6837a1e8d..9d0ca7f19 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -2,6 +2,7 @@ const EventEmitter = require('events').EventEmitter const inherits = require('util').inherits const async = require('async') const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN const EthQuery = require('eth-query') const KeyStore = require('eth-lightwallet').keystore const clone = require('clone') @@ -112,6 +113,8 @@ IdentityStore.prototype.getState = function () { currentFiat: configManager.getCurrentFiat(), conversionRate: configManager.getConversionRate(), conversionDate: configManager.getConversionDate(), + gasMultiplier: configManager.getGasMultiplier(), + })) } @@ -211,6 +214,7 @@ IdentityStore.prototype.exportAccount = function (address, cb) { // comes from dapp via zero-client hooked-wallet provider IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDoneCb, cb) { const configManager = this.configManager + var self = this // create txData obj with parameters and meta data var time = (new Date()).getTime() @@ -222,6 +226,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone txParams: txParams, time: time, status: 'unconfirmed', + gasMultiplier: configManager.getGasMultiplier() || 1, } console.log('addUnconfirmedTransaction:', txData) @@ -262,7 +267,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone function estimateGas(cb){ query.estimateGas(txParams, function(err, result){ if (err) return cb(err) - txData.estimatedGas = result + txData.estimatedGas = self.addGasBuffer(result) cb() }) } @@ -277,6 +282,13 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone } } +IdentityStore.prototype.addGasBuffer = function (gasHex) { + var gas = new BN(gasHex, 16) + var buffer = new BN('100000', 10) + var result = gas.add(buffer) + return ethUtil.addHexPrefix(result.toString(16)) +} + // comes from metamask ui IdentityStore.prototype.approveTransaction = function (txId, cb) { const configManager = this.configManager diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index bcde333d0..c6bfdb4da 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,6 +1,6 @@ const Streams = require('mississippi') -const ObjectMultiplex = require('./obj-multiplex') const StreamProvider = require('web3-stream-provider') +const ObjectMultiplex = require('./obj-multiplex') const RemoteStore = require('./remote-store.js').RemoteStore module.exports = MetamaskInpageProvider @@ -11,8 +11,9 @@ function MetamaskInpageProvider (connectionStream) { // setup connectionStream multiplexing var multiStream = ObjectMultiplex() Streams.pipe(connectionStream, multiStream, connectionStream, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask') - if (err) throw err + let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask' + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) }) self.multiStream = multiStream @@ -20,16 +21,18 @@ function MetamaskInpageProvider (connectionStream) { var publicConfigStore = remoteStoreWithLocalStorageCache('MetaMask-Config') var storeStream = publicConfigStore.createStream() Streams.pipe(storeStream, multiStream.createStream('publicConfig'), storeStream, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask publicConfig') - if (err) throw err + let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask publicConfig' + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) }) self.publicConfigStore = publicConfigStore // connect to async provider var asyncProvider = new StreamProvider() Streams.pipe(asyncProvider, multiStream.createStream('provider'), asyncProvider, function (err) { - console.warn('MetamaskInpageProvider - lost connection to MetaMask provider') - if (err) throw err + let warningMsg = 'MetamaskInpageProvider - lost connection to MetaMask provider' + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) }) asyncProvider.on('error', console.error.bind(console)) self.asyncProvider = asyncProvider diff --git a/app/scripts/lib/obj-multiplex.js b/app/scripts/lib/obj-multiplex.js index f54ff7653..bd114c394 100644 --- a/app/scripts/lib/obj-multiplex.js +++ b/app/scripts/lib/obj-multiplex.js @@ -10,9 +10,9 @@ function ObjectMultiplex (opts) { var data = chunk.data var substream = mx.streams[name] if (!substream) { - console.warn('orphaned data for stream ' + name) + console.warn(`orphaned data for stream "${name}"`) } else { - substream.push(data) + if (substream.push) substream.push(data) } return cb() }) @@ -36,5 +36,9 @@ function ObjectMultiplex (opts) { } return substream } + // ignore streams (dont display orphaned data warning) + mx.ignoreStream = function (name) { + mx.streams[name] = true + } return mx } diff --git a/app/scripts/lib/port-stream.js b/app/scripts/lib/port-stream.js index 6f59d4485..6f4ccc6ab 100644 --- a/app/scripts/lib/port-stream.js +++ b/app/scripts/lib/port-stream.js @@ -53,8 +53,7 @@ PortDuplexStream.prototype._write = function (msg, encoding, cb) { } cb() } catch (err) { - console.error(err) - // this.emit('error', err) + // console.error(err) cb(new Error('PortDuplexStream - disconnected')) } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 462c132e6..92551d633 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -57,6 +57,7 @@ module.exports = class MetamaskController { agreeToEthWarning: this.agreeToEthWarning.bind(this), setTOSHash: this.setTOSHash.bind(this), checkTOSChange: this.checkTOSChange.bind(this), + setGasMultiplier: this.setGasMultiplier.bind(this), // forward directly to idStore createNewVault: idStore.createNewVault.bind(idStore), @@ -278,9 +279,9 @@ module.exports = class MetamaskController { checkTOSChange () { try { const storedHash = this.configManager.getTOSHash() || 0 - if (storedHash !== global.newTOSHash) { + if (storedHash !== global.TOS_HASH) { this.resetDisclaimer() - this.setTOSHash(global.newTOSHash) + this.setTOSHash(global.TOS_HASH) } } catch (e) { console.error('Error in checking TOS change.') @@ -395,4 +396,12 @@ module.exports = class MetamaskController { }) } + setGasMultiplier (gasMultiplier, cb) { + try { + this.configManager.setGasMultiplier(gasMultiplier) + cb() + } catch (e) { + cb(e) + } + } } |