aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts')
-rw-r--r--app/scripts/background.js1
-rw-r--r--app/scripts/contentscript.js16
-rw-r--r--app/scripts/controllers/provider-approval.js10
-rw-r--r--app/scripts/controllers/token-rates.js38
-rw-r--r--app/scripts/inpage.js101
-rw-r--r--app/scripts/metamask-controller.js1
6 files changed, 80 insertions, 87 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 2dcb79bef..d577ead41 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -448,6 +448,7 @@ function triggerUi () {
const currentlyActiveMetamaskTab = Boolean(tabs.find(tab => openMetamaskTabsIDs[tab.id]))
if (!popupIsOpen && !currentlyActiveMetamaskTab && !notificationIsOpen) {
notificationManager.showPopup()
+ notificationIsOpen = true
}
})
}
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index 1a10cdb34..ee38ee3ab 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -147,24 +147,28 @@ function listenForProviderRequest () {
}
})
- extension.runtime.onMessage.addListener(({ action = '', isApproved, caching, isUnlocked }) => {
+ extension.runtime.onMessage.addListener(({ action = '', isApproved, caching, isUnlocked, selectedAddress }) => {
switch (action) {
case 'approve-provider-request':
isEnabled = true
- injectScript(`window.dispatchEvent(new CustomEvent('ethereumprovider', { detail: {}}))`)
+ window.postMessage({ type: 'ethereumprovider', selectedAddress }, '*')
+ break
+ case 'approve-legacy-provider-request':
+ isEnabled = true
+ window.postMessage({ type: 'ethereumproviderlegacy', selectedAddress }, '*')
break
case 'reject-provider-request':
- injectScript(`window.dispatchEvent(new CustomEvent('ethereumprovider', { detail: { error: 'User rejected provider access' }}))`)
+ window.postMessage({ type: 'ethereumprovider', error: 'User rejected provider access' }, '*')
break
case 'answer-is-approved':
- injectScript(`window.dispatchEvent(new CustomEvent('ethereumisapproved', { detail: { isApproved: ${isApproved}, caching: ${caching}}}))`)
+ window.postMessage({ type: 'ethereumisapproved', isApproved, caching }, '*')
break
case 'answer-is-unlocked':
- injectScript(`window.dispatchEvent(new CustomEvent('metamaskisunlocked', { detail: { isUnlocked: ${isUnlocked}}}))`)
+ window.postMessage({ type: 'metamaskisunlocked', isUnlocked }, '*')
break
case 'metamask-set-locked':
isEnabled = false
- injectScript(`window.dispatchEvent(new CustomEvent('metamasksetlocked', { detail: {}}))`)
+ window.postMessage({ type: 'metamasksetlocked' }, '*')
break
}
})
diff --git a/app/scripts/controllers/provider-approval.js b/app/scripts/controllers/provider-approval.js
index d3b7f6dff..21d7fd22e 100644
--- a/app/scripts/controllers/provider-approval.js
+++ b/app/scripts/controllers/provider-approval.js
@@ -88,7 +88,10 @@ class ProviderApprovalController {
_handlePrivacyRequest () {
const privacyMode = this.preferencesController.getFeatureFlags().privacyMode
if (!privacyMode) {
- this.platform && this.platform.sendMessage({ action: 'approve-provider-request' }, { active: true })
+ this.platform && this.platform.sendMessage({
+ action: 'approve-legacy-provider-request',
+ selectedAddress: this.publicConfigStore.getState().selectedAddress,
+ }, { active: true })
this.publicConfigStore.emit('update', this.publicConfigStore.getState())
}
}
@@ -101,7 +104,10 @@ class ProviderApprovalController {
approveProviderRequest (origin) {
this.closePopup && this.closePopup()
const requests = this.store.getState().providerRequests || []
- this.platform && this.platform.sendMessage({ action: 'approve-provider-request' }, { active: true })
+ this.platform && this.platform.sendMessage({
+ action: 'approve-provider-request',
+ selectedAddress: this.publicConfigStore.getState().selectedAddress,
+ }, { active: true })
this.publicConfigStore.emit('update', this.publicConfigStore.getState())
const providerRequests = requests.filter(request => request.origin !== origin)
this.store.updateState({ providerRequests })
diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js
index b6f084841..a8936f13b 100644
--- a/app/scripts/controllers/token-rates.js
+++ b/app/scripts/controllers/token-rates.js
@@ -14,8 +14,9 @@ class TokenRatesController {
*
* @param {Object} [config] - Options to configure controller
*/
- constructor ({ interval = DEFAULT_INTERVAL, preferences } = {}) {
+ constructor ({ interval = DEFAULT_INTERVAL, currency, preferences } = {}) {
this.store = new ObservableStore()
+ this.currency = currency
this.preferences = preferences
this.interval = interval
}
@@ -26,33 +27,24 @@ class TokenRatesController {
async updateExchangeRates () {
if (!this.isActive) { return }
const contractExchangeRates = {}
- // copy array to ensure its not modified during iteration
- const tokens = this._tokens.slice()
- for (const token of tokens) {
- if (!token) return log.error(`TokenRatesController - invalid tokens state:\n${JSON.stringify(tokens, null, 2)}`)
- const address = token.address
- contractExchangeRates[address] = await this.fetchExchangeRate(address)
+ const nativeCurrency = this.currency ? this.currency.getState().nativeCurrency.toUpperCase() : 'ETH'
+ const pairs = this._tokens.map(token => `pairs[]=${token.address}/${nativeCurrency}`)
+ const query = pairs.join('&')
+ if (this._tokens.length > 0) {
+ try {
+ const response = await fetch(`https://exchanges.balanc3.net/pie?${query}&autoConversion=true`)
+ const { prices = [] } = await response.json()
+ prices.forEach(({ pair, price }) => {
+ contractExchangeRates[pair.split('/')[0]] = typeof price === 'number' ? price : 0
+ })
+ } catch (error) {
+ log.warn(`MetaMask - TokenRatesController exchange rate fetch failed.`, error)
+ }
}
this.store.putState({ contractExchangeRates })
}
/**
- * Fetches a token exchange rate by address
- *
- * @param {String} address - Token contract address
- */
- async fetchExchangeRate (address) {
- try {
- const response = await fetch(`https://metamask.balanc3.net/prices?from=${address}&to=ETH&autoConversion=false&summaryOnly=true`)
- const json = await response.json()
- return json && json.length ? json[0].averagePrice : 0
- } catch (error) {
- log.warn(`MetaMask - TokenRatesController exchange rate fetch failed for ${address}.`, error)
- return 0
- }
- }
-
- /**
* @type {Number}
*/
set interval (interval) {
diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js
index 327e25042..83392761e 100644
--- a/app/scripts/inpage.js
+++ b/app/scripts/inpage.js
@@ -22,6 +22,21 @@ console.warn('ATTENTION: In an effort to improve user privacy, MetaMask ' +
'accounts. Please see https://bit.ly/2QQHXvF for complete information and up-to-date ' +
'example code.')
+/**
+ * Adds a postMessage listener for a specific message type
+ *
+ * @param {string} messageType - postMessage type to listen for
+ * @param {Function} handler - event handler
+ * @param {boolean} remove - removes this handler after being triggered
+ */
+function onMessage(messageType, handler, remove) {
+ window.addEventListener('message', function ({ data }) {
+ if (!data || data.type !== messageType) { return }
+ remove && window.removeEventListener('message', handler)
+ handler.apply(window, arguments)
+ })
+}
+
//
// setup plugin communication
//
@@ -39,52 +54,36 @@ var inpageProvider = new MetamaskInpageProvider(metamaskStream)
inpageProvider.setMaxListeners(100)
// set up a listener for when MetaMask is locked
-window.addEventListener('metamasksetlocked', () => {
- isEnabled = false
-})
+onMessage('metamasksetlocked', () => { isEnabled = false })
+
+// set up a listener for privacy mode responses
+onMessage('ethereumproviderlegacy', ({ data: { selectedAddress } }) => {
+ isEnabled = true
+ inpageProvider.publicConfigStore.updateState({ selectedAddress })
+}, true)
// augment the provider with its enable method
inpageProvider.enable = function ({ force } = {}) {
return new Promise((resolve, reject) => {
- window.removeEventListener('ethereumprovider', providerHandle)
- providerHandle = ({ detail }) => {
- if (typeof detail.error !== 'undefined') {
- reject(detail.error)
+ providerHandle = ({ data: { error, selectedAddress } }) => {
+ if (typeof error !== 'undefined') {
+ reject(error)
} else {
- // wait for the publicConfig store to populate with an account
- const publicConfig = new Promise((resolve) => {
- const { selectedAddress } = inpageProvider.publicConfigStore.getState()
- inpageProvider._metamask.isUnlocked().then(unlocked => {
- if (!unlocked || selectedAddress) {
- resolve()
- } else {
- inpageProvider.publicConfigStore.on('update', ({ selectedAddress }) => {
- selectedAddress && resolve()
- })
- }
- })
- })
+ window.removeEventListener('message', providerHandle)
+ inpageProvider.publicConfigStore.updateState({ selectedAddress })
// wait for the background to update with an account
- const ethAccounts = new Promise((resolveAccounts, rejectAccounts) => {
- inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => {
- if (error) {
- rejectAccounts(error)
- } else {
- resolveAccounts(response.result)
- }
- })
- })
-
- Promise.all([ethAccounts, publicConfig])
- .then(([selectedAddress]) => {
+ inpageProvider.sendAsync({ method: 'eth_accounts', params: [] }, (error, response) => {
+ if (error) {
+ reject(error)
+ } else {
isEnabled = true
- resolve(selectedAddress)
- })
- .catch(reject)
+ resolve(response.result)
+ }
+ })
}
}
- window.addEventListener('ethereumprovider', providerHandle)
+ onMessage('ethereumprovider', providerHandle, true)
window.postMessage({ type: 'ETHEREUM_ENABLE_PROVIDER', force }, '*')
})
}
@@ -106,20 +105,15 @@ inpageProvider._metamask = new Proxy({
* @returns {Promise<boolean>} - Promise resolving to true if this domain has been previously approved
*/
isApproved: function() {
- return new Promise((resolve, reject) => {
- window.removeEventListener('ethereumisapproved', isApprovedHandle)
- isApprovedHandle = ({ detail }) => {
- if (typeof detail.error !== 'undefined') {
- reject(detail.error)
+ return new Promise((resolve) => {
+ isApprovedHandle = ({ data: { caching, isApproved } }) => {
+ if (caching) {
+ resolve(!!isApproved)
} else {
- if (detail.caching) {
- resolve(!!detail.isApproved)
- } else {
- resolve(false)
- }
+ resolve(false)
}
}
- window.addEventListener('ethereumisapproved', isApprovedHandle)
+ onMessage('ethereumisapproved', isApprovedHandle, true)
window.postMessage({ type: 'ETHEREUM_IS_APPROVED' }, '*')
})
},
@@ -130,16 +124,11 @@ inpageProvider._metamask = new Proxy({
* @returns {Promise<boolean>} - Promise resolving to true if MetaMask is currently unlocked
*/
isUnlocked: function () {
- return new Promise((resolve, reject) => {
- window.removeEventListener('metamaskisunlocked', isUnlockedHandle)
- isUnlockedHandle = ({ detail }) => {
- if (typeof detail.error !== 'undefined') {
- reject(detail.error)
- } else {
- resolve(!!detail.isUnlocked)
- }
+ return new Promise((resolve) => {
+ isUnlockedHandle = ({ data: { isUnlocked } }) => {
+ resolve(!!isUnlocked)
}
- window.addEventListener('metamaskisunlocked', isUnlockedHandle)
+ onMessage('metamaskisunlocked', isUnlockedHandle, true)
window.postMessage({ type: 'METAMASK_IS_UNLOCKED' }, '*')
})
},
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 5ae0f608d..641a7ef3f 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -117,6 +117,7 @@ module.exports = class MetamaskController extends EventEmitter {
// token exchange rate tracker
this.tokenRatesController = new TokenRatesController({
+ currency: this.currencyController.store,
preferences: this.preferencesController.store,
})