aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrankie <frankie.diamond@gmail.com>2017-04-03 14:04:21 +0800
committerGitHub <noreply@github.com>2017-04-03 14:04:21 +0800
commit235a70b9392d8b87eae4fc141e7f0be1d7788ee2 (patch)
treee7db8e909888506a21fa6c2fbfa04a3fa2cbcfc1
parent0a5c634081656c9450d4341b96bab6b4134a0b7a (diff)
parent86e882c51afca3a44bf20bcd1025161e214e6998 (diff)
downloadtangerine-wallet-browser-235a70b9392d8b87eae4fc141e7f0be1d7788ee2.tar.gz
tangerine-wallet-browser-235a70b9392d8b87eae4fc141e7f0be1d7788ee2.tar.zst
tangerine-wallet-browser-235a70b9392d8b87eae4fc141e7f0be1d7788ee2.zip
Merge pull request #1300 from MetaMask/platform
Introduce Platform API
-rw-r--r--app/scripts/background.js13
-rw-r--r--app/scripts/contentscript.js2
-rw-r--r--app/scripts/lib/extension-instance.js68
-rw-r--r--app/scripts/lib/extension.js17
-rw-r--r--app/scripts/lib/notification-manager.js74
-rw-r--r--app/scripts/lib/notifications.js67
-rw-r--r--app/scripts/metamask-controller.js14
-rw-r--r--app/scripts/platforms/extension.js23
-rw-r--r--app/scripts/popup-core.js27
-rw-r--r--app/scripts/popup.js48
-rw-r--r--development/mockExtension.js2
-rw-r--r--test/unit/extension-test.js77
-rw-r--r--ui/app/components/account-info-link.js3
-rw-r--r--ui/app/components/buy-button-subview.js3
-rw-r--r--ui/app/components/shift-list-item.js5
-rw-r--r--ui/app/components/transaction-list-item.js2
-rw-r--r--ui/app/info.js24
-rw-r--r--ui/app/reducers/app.js55
-rw-r--r--ui/index.js23
19 files changed, 213 insertions, 334 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 254737dec..7211f1e0c 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -4,12 +4,13 @@ const asyncQ = require('async-q')
const pipe = require('pump')
const LocalStorageStore = require('obs-store/lib/localStorage')
const storeTransform = require('obs-store/lib/transform')
+const ExtensionPlatform = require('./platforms/extension')
const Migrator = require('./lib/migrator/')
const migrations = require('./migrations/')
const PortStream = require('./lib/port-stream.js')
-const notification = require('./lib/notifications.js')
+const NotificationManager = require('./lib/notification-manager.js')
const MetamaskController = require('./metamask-controller')
-const extension = require('./lib/extension')
+const extension = require('extensionizer')
const firstTimeState = require('./first-time-state')
const STORAGE_KEY = 'metamask-config'
@@ -19,6 +20,10 @@ const log = require('loglevel')
window.log = log
log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn')
+const platform = new ExtensionPlatform()
+const notificationManager = new NotificationManager()
+global.METAMASK_NOTIFIER = notificationManager
+
let popupIsOpen = false
// state persistence
@@ -68,6 +73,8 @@ function setupController (initState) {
showUnapprovedTx: triggerUi,
// initial state
initState,
+ // platform specific api
+ platform,
})
global.metamaskController = controller
@@ -140,7 +147,7 @@ function setupController (initState) {
// popup trigger
function triggerUi () {
- if (!popupIsOpen) notification.show()
+ if (!popupIsOpen) notificationManager.showPopup()
}
// On first install, open a window to MetaMask website to how-it-works.
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index 9a390e580..4d7e682d3 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -2,7 +2,7 @@ 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')
+const extension = require('extensionizer')
const fs = require('fs')
const path = require('path')
diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js
deleted file mode 100644
index 628b62e3f..000000000
--- a/app/scripts/lib/extension-instance.js
+++ /dev/null
@@ -1,68 +0,0 @@
-const apis = [
- 'alarms',
- 'bookmarks',
- 'browserAction',
- 'commands',
- 'contextMenus',
- 'cookies',
- 'downloads',
- 'events',
- 'extension',
- 'extensionTypes',
- 'history',
- 'i18n',
- 'idle',
- 'notifications',
- 'pageAction',
- 'runtime',
- 'storage',
- 'tabs',
- 'webNavigation',
- 'webRequest',
- 'windows',
-]
-
-function Extension () {
- const _this = this
-
- apis.forEach(function (api) {
-
- _this[api] = null
-
- try {
- if (chrome[api]) {
- _this[api] = chrome[api]
- }
- } catch (e) {}
-
- try {
- if (window[api]) {
- _this[api] = window[api]
- }
- } catch (e) {}
-
- try {
- if (browser[api]) {
- _this[api] = browser[api]
- }
- } catch (e) {}
- try {
- _this.api = browser.extension[api]
- } catch (e) {}
- })
-
- try {
- if (browser && browser.runtime) {
- this.runtime = browser.runtime
- }
- } catch (e) {}
-
- try {
- if (browser && browser.browserAction) {
- this.browserAction = browser.browserAction
- }
- } catch (e) {}
-
-}
-
-module.exports = Extension
diff --git a/app/scripts/lib/extension.js b/app/scripts/lib/extension.js
deleted file mode 100644
index 6f8b5d800..000000000
--- a/app/scripts/lib/extension.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Extension.js
- *
- * A module for unifying browser differences in the WebExtension API.
- *
- * Initially implemented because Chrome hides all of their WebExtension API
- * behind a global `chrome` variable, but we'd like to start grooming
- * the code-base for cross-browser extension support.
- *
- * You can read more about the WebExtension API here:
- * https://developer.mozilla.org/en-US/Add-ons/WebExtensions
- */
-
-const Extension = require('./extension-instance')
-const instance = new Extension()
-window.METAMASK_EXTENSION = instance
-module.exports = instance
-
diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js
new file mode 100644
index 000000000..55e5b8dd2
--- /dev/null
+++ b/app/scripts/lib/notification-manager.js
@@ -0,0 +1,74 @@
+const extension = require('extensionizer')
+const height = 520
+const width = 360
+
+
+class NotificationManager {
+
+ //
+ // Public
+ //
+
+ showPopup () {
+ this._getPopup((err, popup) => {
+ if (err) throw err
+
+ if (popup) {
+ // bring focus to existing popup
+ extension.windows.update(popup.id, { focused: true })
+ } else {
+ // create new popup
+ extension.windows.create({
+ url: 'notification.html',
+ type: 'popup',
+ width,
+ height,
+ })
+ .catch((reason) => {
+ log.error('failed to create poupup', reason)
+ })
+ }
+ })
+ }
+
+ closePopup () {
+ this._getPopup((err, popup) => {
+ if (err) throw err
+ if (!popup) return
+ extension.windows.remove(popup.id, console.error)
+ })
+ }
+
+ //
+ // Private
+ //
+
+ _getPopup (cb) {
+ this._getWindows((err, windows) => {
+ if (err) throw err
+ cb(null, this._getPopupIn(windows))
+ })
+ }
+
+ _getWindows (cb) {
+ // Ignore in test environment
+ if (!extension.windows) {
+ return cb()
+ }
+
+ extension.windows.getAll({}, (windows) => {
+ cb(null, windows)
+ })
+ }
+
+ _getPopupIn (windows) {
+ return windows ? windows.find((win) => {
+ return (win && win.type === 'popup' &&
+ win.height === height &&
+ win.width === width)
+ }) : null
+ }
+
+}
+
+module.exports = NotificationManager \ No newline at end of file
diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js
deleted file mode 100644
index 0ec01f3a7..000000000
--- a/app/scripts/lib/notifications.js
+++ /dev/null
@@ -1,67 +0,0 @@
-const extension = require('./extension')
-const height = 520
-const width = 360
-
-const notifications = {
- show,
- getPopup,
- closePopup,
-}
-module.exports = notifications
-window.METAMASK_NOTIFIER = notifications
-
-function show () {
- getPopup((err, popup) => {
- if (err) throw err
-
- if (popup) {
- // bring focus to existing popup
- extension.windows.update(popup.id, { focused: true })
- } else {
- // create new popup
- extension.windows.create({
- url: 'notification.html',
- type: 'popup',
- width,
- height,
- })
- .catch((reason) => {
- log.error('failed to create poupup', reason)
- })
- }
- })
-}
-
-function getWindows (cb) {
- // Ignore in test environment
- if (!extension.windows) {
- return cb()
- }
-
- extension.windows.getAll({}, (windows) => {
- cb(null, windows)
- })
-}
-
-function getPopup (cb) {
- getWindows((err, windows) => {
- if (err) throw err
- cb(null, getPopupIn(windows))
- })
-}
-
-function getPopupIn (windows) {
- return windows ? windows.find((win) => {
- return (win && win.type === 'popup' &&
- win.height === height &&
- win.width === width)
- }) : null
-}
-
-function closePopup () {
- getPopup((err, popup) => {
- if (err) throw err
- if (!popup) return
- extension.windows.remove(popup.id, console.error)
- })
-}
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 03ea104e0..af8b4688d 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -20,7 +20,6 @@ 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')
const autoFaucet = require('./lib/auto-faucet')
const nodeify = require('./lib/nodeify')
const accountImporter = require('./account-import-strategies')
@@ -34,6 +33,9 @@ module.exports = class MetamaskController extends EventEmitter {
this.opts = opts
let initState = opts.initState || {}
+ // platform-specific api
+ this.platform = opts.platform
+
// observable state store
this.store = new ObservableStore(initState)
@@ -629,7 +631,7 @@ module.exports = class MetamaskController extends EventEmitter {
break
}
- if (url) extension.tabs.create({ url })
+ if (url) this.platform.openWindow({ url })
}
createShapeShiftTx (depositAddress, depositType) {
@@ -647,7 +649,7 @@ module.exports = class MetamaskController extends EventEmitter {
setDefaultRpc () {
this.configManager.setRpcTarget('http://localhost:8545')
- extension.runtime.reload()
+ this.platform.reload()
this.lookupNetwork()
return Promise.resolve('http://localhost:8545')
}
@@ -656,7 +658,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.configManager.setRpcTarget(rpcTarget)
return this.preferencesController.updateFrequentRpcList(rpcTarget)
.then(() => {
- extension.runtime.reload()
+ this.platform.reload()
this.lookupNetwork()
return Promise.resolve(rpcTarget)
})
@@ -664,13 +666,13 @@ module.exports = class MetamaskController extends EventEmitter {
setProviderType (type) {
this.configManager.setProviderType(type)
- extension.runtime.reload()
+ this.platform.reload()
this.lookupNetwork()
}
useEtherscanProvider () {
this.configManager.useEtherscanProvider()
- extension.runtime.reload()
+ this.platform.reload()
}
getNetworkState () {
diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js
new file mode 100644
index 000000000..00c2aa275
--- /dev/null
+++ b/app/scripts/platforms/extension.js
@@ -0,0 +1,23 @@
+const extension = require('extensionizer')
+
+class ExtensionPlatform {
+
+ //
+ // Public
+ //
+
+ reload () {
+ extension.runtime.reload()
+ }
+
+ openWindow ({ url }) {
+ extension.tabs.create({ url })
+ }
+
+ getVersion () {
+ return extension.runtime.getManifest().version
+ }
+
+}
+
+module.exports = ExtensionPlatform
diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js
index b1e521a7a..1e5d70e8b 100644
--- a/app/scripts/popup-core.js
+++ b/app/scripts/popup-core.js
@@ -1,7 +1,8 @@
const EventEmitter = require('events').EventEmitter
+const async = require('async')
const Dnode = require('dnode')
const Web3 = require('web3')
-const MetaMaskUi = require('../../ui')
+const launchMetamaskUi = require('../../ui')
const StreamProvider = require('web3-stream-provider')
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
@@ -9,9 +10,13 @@ const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
module.exports = initializePopup
-function initializePopup (connectionStream) {
+function initializePopup ({ container, connectionStream }, cb) {
// setup app
- connectToAccountManager(connectionStream, setupApp)
+ async.waterfall([
+ (cb) => connectToAccountManager(connectionStream, cb),
+ (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb),
+ ], cb)
+
}
function connectToAccountManager (connectionStream, cb) {
@@ -47,19 +52,3 @@ function setupControllerConnection (connectionStream, cb) {
cb(null, accountManager)
})
}
-
-function setupApp (err, accountManager) {
- var container = document.getElementById('app-content')
- if (err) {
- container.innerHTML = '<div class="critical-error">The MetaMask app failed to load: please open and close MetaMask again to restart.</div>'
- container.style.height = '80px'
- log.error(err.stack)
- throw err
- }
-
-
- MetaMaskUi({
- container: container,
- accountManager: accountManager,
- })
-}
diff --git a/app/scripts/popup.js b/app/scripts/popup.js
index 62db68c10..0fbde54b3 100644
--- a/app/scripts/popup.js
+++ b/app/scripts/popup.js
@@ -3,23 +3,47 @@ const MetaMaskUiCss = require('../../ui/css')
const startPopup = require('./popup-core')
const PortStream = require('./lib/port-stream.js')
const isPopupOrNotification = require('./lib/is-popup-or-notification')
-const extension = require('./lib/extension')
-const notification = require('./lib/notifications')
+const extension = require('extensionizer')
+const ExtensionPlatform = require('./platforms/extension')
+const NotificationManager = require('./lib/notification-manager')
+const notificationManager = new NotificationManager()
-var css = MetaMaskUiCss()
+// create platform global
+global.platform = new ExtensionPlatform()
+
+// inject css
+const css = MetaMaskUiCss()
injectCss(css)
-var name = isPopupOrNotification()
-closePopupIfOpen(name)
-window.METAMASK_UI_TYPE = name
+// identify window type (popup, notification)
+const windowType = isPopupOrNotification()
+global.METAMASK_UI_TYPE = windowType
+closePopupIfOpen(windowType)
+
+// setup stream to background
+const extensionPort = extension.runtime.connect({ name: windowType })
+const connectionStream = new PortStream(extensionPort)
-var pluginPort = extension.runtime.connect({ name })
-var portStream = new PortStream(pluginPort)
+// start ui
+const container = document.getElementById('app-content')
+startPopup({ container, connectionStream }, (err, store) => {
+ if (err) return displayCriticalError(err)
+ store.subscribe(() => {
+ const state = store.getState()
+ if (state.appState.shouldClose) notificationManager.closePopup()
+ })
+})
-startPopup(portStream)
-function closePopupIfOpen (name) {
- if (name !== 'notification') {
- notification.closePopup()
+function closePopupIfOpen (windowType) {
+ if (windowType !== 'notification') {
+ notificationManager.closePopup()
}
}
+
+function displayCriticalError(err) {
+ container.innerHTML = '<div class="critical-error">The MetaMask app failed to load: please open and close MetaMask again to restart.</div>'
+ container.style.height = '80px'
+ log.error(err.stack)
+ throw err
+}
diff --git a/development/mockExtension.js b/development/mockExtension.js
index 509487cce..55799b2bf 100644
--- a/development/mockExtension.js
+++ b/development/mockExtension.js
@@ -4,7 +4,7 @@
* and stubbing out all the extension methods with appropriate mocks.
*/
-const extension = require('../app/scripts/lib/extension')
+const extension = require('extensionizer')
const noop = function () {}
const apis = [
diff --git a/test/unit/extension-test.js b/test/unit/extension-test.js
deleted file mode 100644
index 8f259f05c..000000000
--- a/test/unit/extension-test.js
+++ /dev/null
@@ -1,77 +0,0 @@
-var assert = require('assert')
-var sinon = require('sinon')
-const ethUtil = require('ethereumjs-util')
-global.chrome = {}
-global.browser = {}
-
-var path = require('path')
-var Extension = require(path.join(__dirname, '..', '..', 'app', 'scripts', 'lib', 'extension-instance.js'))
-
-describe('extension', function() {
-
- describe('extension.getURL', function() {
- const desiredResult = 'http://the-desired-result.io'
-
- describe('in Chrome or Firefox', function() {
- global.chrome.extension = {
- getURL: () => desiredResult
- }
-
- it('returns the desired result', function() {
- const extension = new Extension()
- const result = extension.extension.getURL()
- assert.equal(result, desiredResult)
- })
- })
-
- describe('in Microsoft Edge', function() {
- global.browser.extension = {
- getURL: () => desiredResult
- }
-
- it('returns the desired result', function() {
- const extension = new Extension()
- const result = extension.extension.getURL()
- assert.equal(result, desiredResult)
- })
- })
- })
-
- describe('with chrome global', function() {
- let extension
-
- beforeEach(function() {
- global.chrome = {
- alarms: 'foo'
- }
- extension = new Extension()
- })
-
- it('should use the chrome global apis', function() {
- assert.equal(extension.alarms, 'foo')
- })
- })
-
- describe('without chrome global', function() {
- let extension
- let realWindow
-
- beforeEach(function() {
- realWindow = window
- window = global
- global.chrome = undefined
- global.alarms = 'foo'
- extension = new Extension()
- })
-
- after(function() {
- window = realWindow
- })
-
- it('should use the global apis', function() {
- assert.equal(extension.alarms, 'foo')
- })
- })
-
-
-})
diff --git a/ui/app/components/account-info-link.js b/ui/app/components/account-info-link.js
index 49c42e9ec..6526ab502 100644
--- a/ui/app/components/account-info-link.js
+++ b/ui/app/components/account-info-link.js
@@ -3,7 +3,6 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const Tooltip = require('./tooltip')
const genAccountLink = require('../../lib/account-link')
-const extension = require('../../../app/scripts/lib/extension')
module.exports = AccountInfoLink
@@ -35,7 +34,7 @@ AccountInfoLink.prototype.render = function () {
style: {
margin: '5px',
},
- onClick () { extension.tabs.create({ url }) },
+ onClick () { global.platform.openWindow({ url }) },
}),
]),
])
diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js
index 7b993110d..2b1675b6d 100644
--- a/ui/app/components/buy-button-subview.js
+++ b/ui/app/components/buy-button-subview.js
@@ -5,7 +5,6 @@ const connect = require('react-redux').connect
const actions = require('../actions')
const CoinbaseForm = require('./coinbase-form')
const ShapeshiftForm = require('./shapeshift-form')
-const extension = require('../../../app/scripts/lib/extension')
const Loading = require('./loading')
const TabBar = require('./tab-bar')
@@ -142,7 +141,7 @@ BuyButtonSubview.prototype.formVersionSubview = function () {
}
BuyButtonSubview.prototype.navigateTo = function (url) {
- extension.tabs.create({ url })
+ global.platform.openWindow({ url })
}
BuyButtonSubview.prototype.backButtonContext = function () {
diff --git a/ui/app/components/shift-list-item.js b/ui/app/components/shift-list-item.js
index e0243e247..96a7cba6e 100644
--- a/ui/app/components/shift-list-item.js
+++ b/ui/app/components/shift-list-item.js
@@ -4,7 +4,6 @@ const h = require('react-hyperscript')
const connect = require('react-redux').connect
const vreme = new (require('vreme'))
const explorerLink = require('../../lib/explorer-link')
-const extension = require('../../../app/scripts/lib/extension')
const actions = require('../actions')
const addressSummary = require('../util').addressSummary
@@ -172,9 +171,7 @@ ShiftListItem.prototype.renderInfo = function () {
width: '200px',
overflow: 'hidden',
},
- onClick: () => extension.tabs.create({
- url,
- }),
+ onClick: () => global.platform.openWindow({ url }),
}, [
h('div', {
style: {
diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js
index ee32be7d3..0052d9c70 100644
--- a/ui/app/components/transaction-list-item.js
+++ b/ui/app/components/transaction-list-item.js
@@ -7,7 +7,7 @@ const addressSummary = require('../util').addressSummary
const explorerLink = require('../../lib/explorer-link')
const CopyButton = require('./copyButton')
const vreme = new (require('vreme'))
-const extension = require('../../../app/scripts/lib/extension')
+const extension = require('extensionizer')
const Tooltip = require('./tooltip')
const TransactionIcon = require('./transaction-list-item-icon')
diff --git a/ui/app/info.js b/ui/app/info.js
index e79580be4..a6fdeb315 100644
--- a/ui/app/info.js
+++ b/ui/app/info.js
@@ -3,7 +3,6 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const actions = require('./actions')
-const extension = require('../../app/scripts/lib/extension')
module.exports = connect(mapStateToProps)(InfoScreen)
@@ -17,13 +16,8 @@ function InfoScreen () {
}
InfoScreen.prototype.render = function () {
- var state = this.props
- var manifest
- try {
- manifest = extension.runtime.getManifest()
- } catch (e) {
- manifest = { version: '2.0.0' }
- }
+ const state = this.props
+ const version = global.platform.getVersion()
return (
h('.flex-column.flex-grow', [
@@ -53,7 +47,7 @@ InfoScreen.prototype.render = function () {
style: {
marginBottom: '10px',
},
- }, `Version: ${manifest.version}`),
+ }, `Version: ${version}`),
]),
h('div', {
@@ -110,10 +104,12 @@ InfoScreen.prototype.render = function () {
onClick (event) { this.navigateTo(event.target.href) },
}, [
h('img.icon-size', {
- src: manifest.icons['128'],
+ src: 'images/icon-128.png',
style: {
- filter: 'grayscale(100%)', /* IE6-9 */
- WebkitFilter: 'grayscale(100%)', /* Microsoft Edge and Firefox 35+ */
+ // IE6-9
+ filter: 'grayscale(100%)',
+ // Microsoft Edge and Firefox 35+
+ WebkitFilter: 'grayscale(100%)',
},
}),
h('div.info', 'Visit our web site'),
@@ -139,7 +135,7 @@ InfoScreen.prototype.render = function () {
h('a.info', {
target: '_blank',
style: { width: '85vw' },
- onClick () { extension.tabs.create({url: 'mailto:help@metamask.io?subject=Feedback'}) },
+ onClick () { this.navigateTo('mailto:help@metamask.io?subject=Feedback') },
}, 'Email us!'),
]),
@@ -158,5 +154,5 @@ InfoScreen.prototype.render = function () {
}
InfoScreen.prototype.navigateTo = function (url) {
- extension.tabs.create({ url })
+ global.platform.openWindow({ url })
}
diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js
index 3a6baca91..7ad1229e5 100644
--- a/ui/app/reducers/app.js
+++ b/ui/app/reducers/app.js
@@ -1,20 +1,20 @@
const extend = require('xtend')
const actions = require('../actions')
const txHelper = require('../../lib/tx-helper')
-const notification = require('../../../app/scripts/lib/notifications')
module.exports = reduceApp
+
function reduceApp (state, action) {
log.debug('App Reducer got ' + action.type)
// clone and defaults
const selectedAddress = state.metamask.selectedAddress
- let pendingTxs = hasPendingTxs(state)
+ const hasUnconfActions = checkUnconfActions(state)
let name = 'accounts'
if (selectedAddress) {
name = 'accountDetail'
}
- if (pendingTxs) {
+ if (hasUnconfActions) {
log.debug('pending txs detected, defaulting to conf-tx view.')
name = 'confTx'
}
@@ -32,7 +32,9 @@ function reduceApp (state, action) {
seedWords,
}
+ // default state
var appState = extend({
+ shouldClose: false,
menuOpen: false,
currentView: seedWords ? seedConfView : defaultView,
accountDetail: {
@@ -302,7 +304,7 @@ function reduceApp (state, action) {
case actions.SHOW_CONF_MSG_PAGE:
return extend(appState, {
currentView: {
- name: pendingTxs ? 'confTx' : 'account-detail',
+ name: hasUnconfActions ? 'confTx' : 'account-detail',
context: 0,
},
transForward: true,
@@ -312,15 +314,11 @@ function reduceApp (state, action) {
case actions.COMPLETED_TX:
log.debug('reducing COMPLETED_TX for tx ' + action.value)
- var { unapprovedTxs, unapprovedMsgs,
- unapprovedPersonalMsgs, network } = state.metamask
-
- var unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, network)
+ const otherUnconfActions = getUnconfActionList(state)
.filter(tx => tx.id !== action.value )
+ const hasOtherUnconfActions = otherUnconfActions.length > 0
- pendingTxs = unconfTxList.length > 0
-
- if (pendingTxs) {
+ if (hasOtherUnconfActions) {
log.debug('reducer detected txs - rendering confTx view')
return extend(appState, {
transForward: false,
@@ -332,9 +330,9 @@ function reduceApp (state, action) {
})
} else {
log.debug('attempting to close popup')
- notification.closePopup()
-
return extend(appState, {
+ // indicate notification should close
+ shouldClose: true,
transForward: false,
warning: null,
currentView: {
@@ -580,26 +578,23 @@ function reduceApp (state, action) {
}
}
-function hasPendingTxs (state) {
- var { unapprovedTxs, unapprovedMsgs,
+function checkUnconfActions (state) {
+ const unconfActionList = getUnconfActionList(state)
+ const hasUnconfActions = unconfActionList.length > 0
+ return hasUnconfActions
+}
+
+function getUnconfActionList (state) {
+ const { unapprovedTxs, unapprovedMsgs,
unapprovedPersonalMsgs, network } = state.metamask
- var unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, network)
- var has = unconfTxList.length > 0
- return has
+ const unconfActionList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, network)
+ return unconfActionList
}
function indexForPending (state, txId) {
- var unapprovedTxs = state.metamask.unapprovedTxs
- var unapprovedMsgs = state.metamask.unapprovedMsgs
- var unapprovedPersonalMsgs = state.metamask.unapprovedPersonalMsgs
- var network = state.metamask.network
- var unconfTxList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, network)
- let idx
- unconfTxList.forEach((tx, i) => {
- if (tx.id === txId) {
- idx = i
- }
- })
- return idx
+ const unconfTxList = getUnconfActionList(state)
+ const match = unconfTxList.find((tx) => tx.id === txId)
+ const index = unconfTxList.indexOf(match)
+ return index
}
diff --git a/ui/index.js b/ui/index.js
index 1a65f813c..e3648c374 100644
--- a/ui/index.js
+++ b/ui/index.js
@@ -4,27 +4,28 @@ const Root = require('./app/root')
const actions = require('./app/actions')
const configureStore = require('./app/store')
const txHelper = require('./lib/tx-helper')
-module.exports = launchApp
+global.log = require('loglevel')
-let debugMode = window.METAMASK_DEBUG
-const log = require('loglevel')
-window.log = log
-log.setLevel(debugMode ? 'debug' : 'warn')
+module.exports = launchMetamaskUi
-function launchApp (opts) {
+
+log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn')
+
+function launchMetamaskUi (opts, cb) {
var accountManager = opts.accountManager
actions._setBackgroundConnection(accountManager)
// check if we are unlocked first
accountManager.getState(function (err, metamaskState) {
- if (err) throw err
- startApp(metamaskState, accountManager, opts)
+ if (err) return cb(err)
+ const store = startApp(metamaskState, accountManager, opts)
+ cb(null, store)
})
}
function startApp (metamaskState, accountManager, opts) {
// parse opts
- var store = configureStore({
+ const store = configureStore({
// metamaskState represents the cross-tab state
metamask: metamaskState,
@@ -37,7 +38,7 @@ function startApp (metamaskState, accountManager, opts) {
})
// if unconfirmed txs, start on txConf page
- var unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.network)
+ const unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.network)
if (unapprovedTxsAll.length > 0) {
store.dispatch(actions.showConfTxPage())
}
@@ -53,4 +54,6 @@ function startApp (metamaskState, accountManager, opts) {
store: store,
}
), opts.container)
+
+ return store
}