diff options
author | Dan <danjm.com@gmail.com> | 2017-12-06 00:41:59 +0800 |
---|---|---|
committer | Chi Kei Chan <chikeichan@gmail.com> | 2017-12-07 13:11:52 +0800 |
commit | ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7 (patch) | |
tree | 4a89f70ed4481c78628f139676f92225f60e15fe /app | |
parent | 2b1f2557c7dbd589724fd690ec72f789f9650e3c (diff) | |
download | tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar.gz tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar.bz2 tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar.lz tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar.xz tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.tar.zst tangerine-wallet-browser-ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7.zip |
Merge branch 'master' into NewUI-flat-merge-with-master
Diffstat (limited to 'app')
-rw-r--r-- | app/scripts/background.js | 9 | ||||
-rw-r--r-- | app/scripts/controllers/network.js | 2 | ||||
-rw-r--r-- | app/scripts/inpage.js | 7 | ||||
-rw-r--r-- | app/scripts/lib/inpage-provider.js | 4 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 47 | ||||
-rw-r--r-- | app/scripts/migrations/020.js | 41 | ||||
-rw-r--r-- | app/scripts/migrations/index.js | 1 | ||||
-rw-r--r-- | app/scripts/notice-controller.js | 44 |
8 files changed, 129 insertions, 26 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 3e560d302..da022c490 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,10 +1,11 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') -const pipe = require('pump') +const pump = require('pump') const log = require('loglevel') const extension = require('extensionizer') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') +const asStream = require('obs-store/lib/asStream') const ExtensionPlatform = require('./platforms/extension') const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') @@ -72,10 +73,10 @@ function setupController (initState) { global.metamaskController = controller // setup state persistence - pipe( - controller.store, + pump( + asStream(controller.store), storeTransform(versionifyData), - diskStore + asStream(diskStore) ) function versionifyData (state) { diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 23afdc12b..045bfcc5d 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -53,7 +53,7 @@ module.exports = class NetworkController extends EventEmitter { lookupNetwork () { // Prevent firing when provider is not defined. if (!this.ethQuery || !this.ethQuery.sendAsync) { - return + return log.warn('NetworkController - lookupNetwork aborted due to missing ethQuery') } this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index b6889b00f..9261e7d64 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -31,6 +31,13 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream) // setup web3 // +if (typeof window.web3 !== 'undefined') { + throw new Error(`MetaMask detected another web3. + MetaMask will not work reliably with another web3 extension. + This usually happens if you have two MetaMasks installed, + or MetaMask and another web3 extension. Please remove one + and try again.`) +} var web3 = new Web3(inpageProvider) web3.setProvider = function () { log.debug('MetaMask - overrode web3.setProvider') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index da75c4be2..99cc5d2cf 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -3,6 +3,7 @@ const RpcEngine = require('json-rpc-engine') const createIdRemapMiddleware = require('json-rpc-engine/src/idRemapMiddleware') const createStreamMiddleware = require('json-rpc-middleware-stream') const LocalStorageStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const ObjectMultiplex = require('obj-multiplex') module.exports = MetamaskInpageProvider @@ -21,9 +22,10 @@ function MetamaskInpageProvider (connectionStream) { // subscribe to metamask public config (one-way) self.publicConfigStore = new LocalStorageStore({ storageKey: 'MetaMask-Config' }) + pump( mux.createStream('publicConfig'), - self.publicConfigStore, + asStream(self.publicConfigStore), (err) => logStreamDisconnectWarning('MetaMask PublicConfigStore', err) ) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 4dce89e3a..a96d20d3b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3,6 +3,7 @@ const extend = require('xtend') const pump = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') +const asStream = require('obs-store/lib/asStream') const AccountTracker = require('./lib/account-tracker') const EthQuery = require('eth-query') const RpcEngine = require('json-rpc-engine') @@ -31,6 +32,7 @@ const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') const getBuyEthUrl = require('./lib/buy-eth-url') +const Mutex = require('await-semaphore').Mutex const version = require('../manifest.json').version module.exports = class MetamaskController extends EventEmitter { @@ -38,10 +40,12 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() + this.sendUpdate = debounce(this.privateSendUpdate.bind(this), 200) this.opts = opts const initState = opts.initState || {} + this.recordFirstTimeInfo(initState) // platform-specific api this.platform = opts.platform @@ -49,6 +53,9 @@ module.exports = class MetamaskController extends EventEmitter { // observable state store this.store = new ObservableStore(initState) + // lock to ensure only one vault created at once + this.createVaultMutex = new Mutex() + // network store this.networkController = new NetworkController(initState.NetworkController) @@ -144,6 +151,8 @@ module.exports = class MetamaskController extends EventEmitter { // notices this.noticeController = new NoticeController({ initState: initState.NoticeController, + version, + firstVersion: initState.firstTimeInfo.version, }) this.noticeController.updateNoticesList() // to be uncommented when retrieving notices from a remote server. @@ -453,7 +462,7 @@ module.exports = class MetamaskController extends EventEmitter { setupPublicConfig (outStream) { pump( - this.publicConfigStore, + asStream(this.publicConfigStore), outStream, (err) => { if (err) log.error(err) @@ -469,15 +478,34 @@ module.exports = class MetamaskController extends EventEmitter { // Vault Management // - async createNewVaultAndKeychain (password, cb) { - const vault = await this.keyringController.createNewVaultAndKeychain(password) - this.selectFirstIdentity(vault) + async createNewVaultAndKeychain (password) { + const release = await this.createVaultMutex.acquire() + let vault + + try { + const accounts = await this.keyringController.getAccounts() + + if (accounts.length > 0) { + vault = await this.keyringController.fullUpdate() + + } else { + vault = await this.keyringController.createNewVaultAndKeychain(password) + this.selectFirstIdentity(vault) + } + release() + } catch (err) { + release() + throw err + } + return vault } - async createNewVaultAndRestore (password, seed, cb) { + async createNewVaultAndRestore (password, seed) { + const release = await this.createVaultMutex.acquire() const vault = await this.keyringController.createNewVaultAndRestore(password, seed) this.selectFirstIdentity(vault) + release() return vault } @@ -784,4 +812,13 @@ module.exports = class MetamaskController extends EventEmitter { } } + recordFirstTimeInfo (initState) { + if (!('firstTimeInfo' in initState)) { + initState.firstTimeInfo = { + version, + date: Date.now(), + } + } + } + } diff --git a/app/scripts/migrations/020.js b/app/scripts/migrations/020.js new file mode 100644 index 000000000..8159b3e70 --- /dev/null +++ b/app/scripts/migrations/020.js @@ -0,0 +1,41 @@ +const version = 20 + +/* + +This migration ensures previous installations +get a `firstTimeInfo` key on the metamask state, +so that we can version notices in the future. + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + if ('metamask' in newState && + !('firstTimeInfo' in newState.metamask)) { + newState.metamask.firstTimeInfo = { + version: '3.12.0', + date: Date.now(), + } + } + return newState +} + diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index e9cbd7b98..9d0631042 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -30,4 +30,5 @@ module.exports = [ require('./017'), require('./018'), require('./019'), + require('./020'), ] diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 57aad40c5..db2b8c4f4 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -1,13 +1,17 @@ const EventEmitter = require('events').EventEmitter +const semver = require('semver') const extend = require('xtend') const ObservableStore = require('obs-store') const hardCodedNotices = require('../../notices/notices.json') +const uniqBy = require('lodash.uniqby') module.exports = class NoticeController extends EventEmitter { constructor (opts) { super() this.noticePoller = null + this.firstVersion = opts.firstVersion + this.version = opts.version const initState = extend({ noticesList: [], }, opts.initState) @@ -30,9 +34,9 @@ module.exports = class NoticeController extends EventEmitter { return unreadNotices[unreadNotices.length - 1] } - setNoticesList (noticesList) { + async setNoticesList (noticesList) { this.store.updateState({ noticesList }) - return Promise.resolve(true) + return true } markNoticeRead (noticeToMark, cb) { @@ -50,12 +54,14 @@ module.exports = class NoticeController extends EventEmitter { } } - updateNoticesList () { - return this._retrieveNoticeData().then((newNotices) => { - var oldNotices = this.getNoticesList() - var combinedNotices = this._mergeNotices(oldNotices, newNotices) - return Promise.resolve(this.setNoticesList(combinedNotices)) - }) + async updateNoticesList () { + const newNotices = await this._retrieveNoticeData() + const oldNotices = this.getNoticesList() + const combinedNotices = this._mergeNotices(oldNotices, newNotices) + const filteredNotices = this._filterNotices(combinedNotices) + const result = this.setNoticesList(filteredNotices) + this._updateMemstore() + return result } startPolling () { @@ -68,22 +74,30 @@ module.exports = class NoticeController extends EventEmitter { } _mergeNotices (oldNotices, newNotices) { - var noticeMap = this._mapNoticeIds(oldNotices) - newNotices.forEach((notice) => { - if (noticeMap.indexOf(notice.id) === -1) { - oldNotices.push(notice) + return uniqBy(oldNotices.concat(newNotices), 'id') + } + + _filterNotices(notices) { + return notices.filter((newNotice) => { + if ('version' in newNotice) { + const satisfied = semver.satisfies(this.version, newNotice.version) + return satisfied + } + if ('firstVersion' in newNotice) { + const satisfied = semver.satisfies(this.firstVersion, newNotice.firstVersion) + return satisfied } + return true }) - return oldNotices } _mapNoticeIds (notices) { return notices.map((notice) => notice.id) } - _retrieveNoticeData () { + async _retrieveNoticeData () { // Placeholder for the API. - return Promise.resolve(hardCodedNotices) + return hardCodedNotices } _updateMemstore () { |