diff options
author | Dan Finlay <542863+danfinlay@users.noreply.github.com> | 2018-04-17 07:49:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-17 07:49:53 +0800 |
commit | e4eb69dcc290a7e7eb27cab7ec57a8097345d81e (patch) | |
tree | c3c3b50de25ba7aafe6c58a426f0ba6212d63b71 /app | |
parent | 6a7fd3c774f50954050d651f7e6b8ff325ce2940 (diff) | |
parent | 06689765146c3ca88fc206d93387b05e1db3b81c (diff) | |
download | tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar.gz tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar.bz2 tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar.lz tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar.xz tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.tar.zst tangerine-wallet-browser-e4eb69dcc290a7e7eb27cab7ec57a8097345d81e.zip |
Merge pull request #3982 from MetaMask/i3981-contract-rates
Fetch token prices based on contract address
Diffstat (limited to 'app')
-rw-r--r-- | app/scripts/background.js | 3 | ||||
-rw-r--r-- | app/scripts/controllers/token-rates.js | 77 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 16 |
3 files changed, 96 insertions, 0 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 451b0d609..35c484ec5 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -199,6 +199,7 @@ function setupController (initState, initLangCode) { if (isMetaMaskInternalProcess) { // communication with popup popupIsOpen = popupIsOpen || (remotePort.name === 'popup') + controller.isClientOpen = true controller.setupTrustedCommunication(portStream, 'MetaMask') // record popup as closed if (remotePort.sender.url.match(/home.html$/)) { @@ -210,6 +211,8 @@ function setupController (initState, initLangCode) { if (remotePort.sender.url.match(/home.html$/)) { openMetamaskTabsIDs[remotePort.sender.tab.id] = false } + controller.isClientOpen = popupIsOpen || + Object.keys(openMetamaskTabsIDs).some(key => openMetamaskTabsIDs[key]) }) } if (remotePort.name === 'notification') { diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js new file mode 100644 index 000000000..22e3e8154 --- /dev/null +++ b/app/scripts/controllers/token-rates.js @@ -0,0 +1,77 @@ +const ObservableStore = require('obs-store') + +// By default, poll every 3 minutes +const DEFAULT_INTERVAL = 180 * 1000 + +/** + * A controller that polls for token exchange + * rates based on a user's current token list + */ +class TokenRatesController { + /** + * Creates a TokenRatesController + * + * @param {Object} [config] - Options to configure controller + */ + constructor ({ interval = DEFAULT_INTERVAL, preferences } = {}) { + this.store = new ObservableStore() + this.preferences = preferences + this.interval = interval + } + + /** + * Updates exchange rates for all tokens + */ + async updateExchangeRates () { + if (!this.isActive) { return } + const contractExchangeRates = {} + for (const i in this._tokens) { + const address = this._tokens[i].address + contractExchangeRates[address] = await this.fetchExchangeRate(address) + } + 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://exchanges.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) { } + } + + /** + * @type {Number} - Interval used to poll for exchange rates + */ + set interval (interval) { + this._handle && clearInterval(this._handle) + if (!interval) { return } + this._handle = setInterval(() => { this.updateExchangeRates() }, interval) + } + + /** + * @type {Object} - Preferences controller instance + */ + set preferences (preferences) { + this._preferences && this._preferences.unsubscribe() + if (!preferences) { return } + this._preferences = preferences + this.tokens = preferences.getState().tokens + preferences.subscribe(({ tokens = [] }) => { this.tokens = tokens }) + } + + /** + * @type {Array} - Array of token objects with contract addresses + */ + set tokens (tokens) { + this._tokens = tokens + this.updateExchangeRates() + } +} + +module.exports = TokenRatesController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index dbb8efc6e..a12b6776e 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -34,6 +34,7 @@ const PersonalMessageManager = require('./lib/personal-message-manager') const TypedMessageManager = require('./lib/typed-message-manager') const TransactionController = require('./controllers/transactions') const BalancesController = require('./controllers/computed-balances') +const TokenRatesController = require('./controllers/token-rates') const ConfigManager = require('./lib/config-manager') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') @@ -105,6 +106,11 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker + // token exchange rate tracker + this.tokenRatesController = new TokenRatesController({ + preferences: this.preferencesController.store, + }) + this.recentBlocksController = new RecentBlocksController({ blockTracker: this.blockTracker, provider: this.provider, @@ -202,6 +208,7 @@ module.exports = class MetamaskController extends EventEmitter { AccountTracker: this.accountTracker.store, TxController: this.txController.memStore, BalancesController: this.balancesController.store, + TokenRatesController: this.tokenRatesController.store, MessageManager: this.messageManager.memStore, PersonalMessageManager: this.personalMessageManager.memStore, TypesMessageManager: this.typedMessageManager.memStore, @@ -263,6 +270,7 @@ module.exports = class MetamaskController extends EventEmitter { // memStore -> transform -> publicConfigStore this.on('update', (memState) => { + this.isClientOpenAndUnlocked = memState.isUnlocked && this._isClientOpen const publicState = selectPublicState(memState) publicConfigStore.putState(publicState) }) @@ -1024,4 +1032,12 @@ module.exports = class MetamaskController extends EventEmitter { } } + set isClientOpen (open) { + this._isClientOpen = open + this.isClientOpenAndUnlocked = this.getState().isUnlocked && open + } + + set isClientOpenAndUnlocked (active) { + this.tokenRatesController.isActive = active + } } |