parent
a350e80fee
commit
d0447f9058
@ -0,0 +1,76 @@ |
|||||||
|
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 () { |
||||||
|
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 |
@ -0,0 +1,28 @@ |
|||||||
|
const assert = require('assert') |
||||||
|
const sinon = require('sinon') |
||||||
|
const TokenRatesController = require('../../app/scripts/controllers/token-rates') |
||||||
|
const ObservableStore = require('obs-store') |
||||||
|
|
||||||
|
describe('TokenRatesController', () => { |
||||||
|
it('should listen for preferences store updates', () => { |
||||||
|
const preferences = new ObservableStore({ tokens: [] }) |
||||||
|
const controller = new TokenRatesController({ preferences }) |
||||||
|
preferences.putState({ tokens: ['foo'] }) |
||||||
|
assert.deepEqual(controller._tokens, ['foo']) |
||||||
|
}) |
||||||
|
|
||||||
|
it('should poll on correct interval', async () => { |
||||||
|
const stub = sinon.stub(global, 'setInterval') |
||||||
|
new TokenRatesController({ interval: 1337 }) // eslint-disable-line no-new
|
||||||
|
assert.strictEqual(stub.getCall(0).args[1], 1337) |
||||||
|
stub.restore() |
||||||
|
}) |
||||||
|
|
||||||
|
it('should fetch each token rate based on address', async () => { |
||||||
|
const controller = new TokenRatesController() |
||||||
|
controller.fetchExchangeRate = address => address |
||||||
|
controller.tokens = [{ address: 'foo' }, { address: 'bar' }] |
||||||
|
await controller.updateExchangeRates() |
||||||
|
assert.deepEqual(controller.store.getState().contractExchangeRates, { foo: 'foo', bar: 'bar' }) |
||||||
|
}) |
||||||
|
}) |
Loading…
Reference in new issue