mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
feature: integrate gaba/CurrencyRateController (#6570)
This commit is contained in:
parent
44616befc7
commit
47024fd9a5
@ -1,205 +0,0 @@
|
||||
const ObservableStore = require('obs-store')
|
||||
const extend = require('xtend')
|
||||
const log = require('loglevel')
|
||||
|
||||
// every ten minutes
|
||||
const POLLING_INTERVAL = 600000
|
||||
|
||||
class CurrencyController {
|
||||
|
||||
/**
|
||||
* Controller responsible for managing data associated with the currently selected currency.
|
||||
*
|
||||
* @typedef {Object} CurrencyController
|
||||
* @param {object} opts Overrides the defaults for the initial state of this.store
|
||||
* @property {array} opts.initState initializes the the state of the CurrencyController. Can contain an
|
||||
* currentCurrency, conversionRate and conversionDate properties
|
||||
* @property {string} currentCurrency A 2-4 character shorthand that describes a specific currency, currently
|
||||
* selected by the user
|
||||
* @property {number} conversionRate The conversion rate from ETH to the selected currency.
|
||||
* @property {string} conversionDate The date at which the conversion rate was set. Expressed in in milliseconds
|
||||
* since midnight of January 1, 1970
|
||||
* @property {number} conversionInterval The id of the interval created by the scheduleConversionInterval method.
|
||||
* Used to clear an existing interval on subsequent calls of that method.
|
||||
* @property {string} nativeCurrency The ticker/symbol of the native chain currency
|
||||
*
|
||||
*/
|
||||
constructor (opts = {}) {
|
||||
const initState = extend({
|
||||
currentCurrency: 'usd',
|
||||
conversionRate: 0,
|
||||
conversionDate: 'N/A',
|
||||
nativeCurrency: 'ETH',
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
/**
|
||||
* A getter for the nativeCurrency property
|
||||
*
|
||||
* @returns {string} A 2-4 character shorthand that describes the specific currency
|
||||
*
|
||||
*/
|
||||
getNativeCurrency () {
|
||||
return this.store.getState().nativeCurrency
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the nativeCurrency property
|
||||
*
|
||||
* @param {string} nativeCurrency The new currency to set as the nativeCurrency in the store
|
||||
*
|
||||
*/
|
||||
setNativeCurrency (nativeCurrency) {
|
||||
this.store.updateState({
|
||||
nativeCurrency,
|
||||
ticker: nativeCurrency,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the currentCurrency property
|
||||
*
|
||||
* @returns {string} A 2-4 character shorthand that describes a specific currency, currently selected by the user
|
||||
*
|
||||
*/
|
||||
getCurrentCurrency () {
|
||||
return this.store.getState().currentCurrency
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the currentCurrency property
|
||||
*
|
||||
* @param {string} currentCurrency The new currency to set as the currentCurrency in the store
|
||||
*
|
||||
*/
|
||||
setCurrentCurrency (currentCurrency) {
|
||||
this.store.updateState({ currentCurrency })
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the conversionRate property
|
||||
*
|
||||
* @returns {string} The conversion rate from ETH to the selected currency.
|
||||
*
|
||||
*/
|
||||
getConversionRate () {
|
||||
return this.store.getState().conversionRate
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the conversionRate property
|
||||
*
|
||||
* @param {number} conversionRate The new rate to set as the conversionRate in the store
|
||||
*
|
||||
*/
|
||||
setConversionRate (conversionRate) {
|
||||
this.store.updateState({ conversionRate })
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the conversionDate property
|
||||
*
|
||||
* @returns {string} The date at which the conversion rate was set. Expressed in milliseconds since midnight of
|
||||
* January 1, 1970
|
||||
*
|
||||
*/
|
||||
getConversionDate () {
|
||||
return this.store.getState().conversionDate
|
||||
}
|
||||
|
||||
/**
|
||||
* A setter for the conversionDate property
|
||||
*
|
||||
* @param {number} conversionDate The date, expressed in milliseconds since midnight of January 1, 1970, that the
|
||||
* conversionRate was set
|
||||
*
|
||||
*/
|
||||
setConversionDate (conversionDate) {
|
||||
this.store.updateState({ conversionDate })
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the conversionRate and conversionDate properties associated with the currentCurrency. Updated info is
|
||||
* fetched from an external API
|
||||
*
|
||||
*/
|
||||
async updateConversionRate () {
|
||||
let currentCurrency, nativeCurrency
|
||||
try {
|
||||
currentCurrency = this.getCurrentCurrency()
|
||||
nativeCurrency = this.getNativeCurrency()
|
||||
// select api
|
||||
let apiUrl
|
||||
if (nativeCurrency === 'ETH') {
|
||||
// ETH
|
||||
apiUrl = `https://api.infura.io/v1/ticker/eth${currentCurrency.toLowerCase()}`
|
||||
} else {
|
||||
// ETC
|
||||
apiUrl = `https://min-api.cryptocompare.com/data/price?fsym=${nativeCurrency.toUpperCase()}&tsyms=${currentCurrency.toUpperCase()}`
|
||||
}
|
||||
// attempt request
|
||||
let response
|
||||
try {
|
||||
response = await fetch(apiUrl)
|
||||
} catch (err) {
|
||||
log.error(new Error(`CurrencyController - Failed to request currency from Infura:\n${err.stack}`))
|
||||
return
|
||||
}
|
||||
// parse response
|
||||
let rawResponse
|
||||
let parsedResponse
|
||||
try {
|
||||
rawResponse = await response.text()
|
||||
parsedResponse = JSON.parse(rawResponse)
|
||||
} catch (err) {
|
||||
log.error(new Error(`CurrencyController - Failed to parse response "${rawResponse}"`))
|
||||
return
|
||||
}
|
||||
// set conversion rate
|
||||
if (nativeCurrency === 'ETH') {
|
||||
// ETH
|
||||
this.setConversionRate(Number(parsedResponse.bid))
|
||||
this.setConversionDate(Number(parsedResponse.timestamp))
|
||||
} else {
|
||||
// ETC
|
||||
if (parsedResponse[currentCurrency.toUpperCase()]) {
|
||||
this.setConversionRate(Number(parsedResponse[currentCurrency.toUpperCase()]))
|
||||
this.setConversionDate(parseInt((new Date()).getTime() / 1000))
|
||||
} else {
|
||||
this.setConversionRate(0)
|
||||
this.setConversionDate('N/A')
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// reset current conversion rate
|
||||
log.warn(`MetaMask - Failed to query currency conversion:`, nativeCurrency, currentCurrency, err)
|
||||
this.setConversionRate(0)
|
||||
this.setConversionDate('N/A')
|
||||
// throw error
|
||||
log.error(new Error(`CurrencyController - Failed to query rate for currency "${currentCurrency}":\n${err.stack}`))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new poll, using setInterval, to periodically call updateConversionRate. The id of the interval is
|
||||
* stored at the controller's conversionInterval property. If it is called and such an id already exists, the
|
||||
* previous interval is clear and a new one is created.
|
||||
*
|
||||
*/
|
||||
scheduleConversionInterval () {
|
||||
if (this.conversionInterval) {
|
||||
clearInterval(this.conversionInterval)
|
||||
}
|
||||
this.conversionInterval = setInterval(() => {
|
||||
this.updateConversionRate()
|
||||
}, POLLING_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CurrencyController
|
@ -30,7 +30,7 @@ class TokenRatesController {
|
||||
async updateExchangeRates () {
|
||||
if (!this.isActive) { return }
|
||||
const contractExchangeRates = {}
|
||||
const nativeCurrency = this.currency ? this.currency.getState().nativeCurrency.toLowerCase() : 'eth'
|
||||
const nativeCurrency = this.currency ? this.currency.state.nativeCurrency.toLowerCase() : 'eth'
|
||||
const pairs = this._tokens.map(token => token.address).join(',')
|
||||
const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}`
|
||||
if (this._tokens.length > 0) {
|
||||
|
@ -26,7 +26,6 @@ const KeyringController = require('eth-keyring-controller')
|
||||
const NetworkController = require('./controllers/network')
|
||||
const PreferencesController = require('./controllers/preferences')
|
||||
const AppStateController = require('./controllers/app-state')
|
||||
const CurrencyController = require('./controllers/currency')
|
||||
const InfuraController = require('./controllers/infura')
|
||||
const CachedBalancesController = require('./controllers/cached-balances')
|
||||
const RecentBlocksController = require('./controllers/recent-blocks')
|
||||
@ -56,6 +55,7 @@ const ethUtil = require('ethereumjs-util')
|
||||
const sigUtil = require('eth-sig-util')
|
||||
const {
|
||||
AddressBookController,
|
||||
CurrencyRateController,
|
||||
ShapeShiftController,
|
||||
PhishingController,
|
||||
} = require('gaba')
|
||||
@ -109,11 +109,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
})
|
||||
|
||||
// currency controller
|
||||
this.currencyController = new CurrencyController({
|
||||
initState: initState.CurrencyController,
|
||||
})
|
||||
this.currencyController.updateConversionRate()
|
||||
this.currencyController.scheduleConversionInterval()
|
||||
this.currencyRateController = new CurrencyRateController(undefined, initState.CurrencyController)
|
||||
|
||||
// infura controller
|
||||
this.infuraController = new InfuraController({
|
||||
@ -130,7 +126,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
// token exchange rate tracker
|
||||
this.tokenRatesController = new TokenRatesController({
|
||||
currency: this.currencyController.store,
|
||||
currency: this.currencyRateController,
|
||||
preferences: this.preferencesController.store,
|
||||
})
|
||||
|
||||
@ -232,8 +228,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
})
|
||||
this.networkController.on('networkDidChange', () => {
|
||||
this.balancesController.updateAllBalances()
|
||||
const currentCurrency = this.currencyController.getCurrentCurrency()
|
||||
this.setCurrentCurrency(currentCurrency, function () {})
|
||||
this.setCurrentCurrency(this.currencyRateController.state.currentCurrency, function () {})
|
||||
})
|
||||
this.balancesController.updateAllBalances()
|
||||
|
||||
@ -262,7 +257,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
KeyringController: this.keyringController.store,
|
||||
PreferencesController: this.preferencesController.store,
|
||||
AddressBookController: this.addressBookController,
|
||||
CurrencyController: this.currencyController.store,
|
||||
CurrencyController: this.currencyRateController,
|
||||
ShapeShiftController: this.shapeshiftController,
|
||||
NetworkController: this.networkController.store,
|
||||
InfuraController: this.infuraController.store,
|
||||
@ -284,7 +279,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
PreferencesController: this.preferencesController.store,
|
||||
RecentBlocksController: this.recentBlocksController.store,
|
||||
AddressBookController: this.addressBookController,
|
||||
CurrencyController: this.currencyController.store,
|
||||
CurrencyController: this.currencyRateController,
|
||||
ShapeshiftController: this.shapeshiftController,
|
||||
InfuraController: this.infuraController.store,
|
||||
ProviderApprovalController: this.providerApprovalController.store,
|
||||
@ -1596,16 +1591,13 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
setCurrentCurrency (currencyCode, cb) {
|
||||
const { ticker } = this.networkController.getNetworkConfig()
|
||||
try {
|
||||
this.currencyController.setNativeCurrency(ticker)
|
||||
this.currencyController.setCurrentCurrency(currencyCode)
|
||||
this.currencyController.updateConversionRate()
|
||||
const data = {
|
||||
nativeCurrency: ticker || 'ETH',
|
||||
conversionRate: this.currencyController.getConversionRate(),
|
||||
currentCurrency: this.currencyController.getCurrentCurrency(),
|
||||
conversionDate: this.currencyController.getConversionDate(),
|
||||
const currencyState = {
|
||||
nativeCurrency: ticker,
|
||||
currentCurrency: currencyCode,
|
||||
}
|
||||
cb(null, data)
|
||||
this.currencyRateController.update(currencyState)
|
||||
this.currencyRateController.configure(currencyState)
|
||||
cb(null, this.currencyRateController.state)
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
}
|
||||
|
15599
package-lock.json
generated
15599
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -230,7 +230,7 @@
|
||||
"file-loader": "^1.1.11",
|
||||
"fs-extra": "^6.0.1",
|
||||
"fs-promise": "^2.0.3",
|
||||
"gaba": "^1.0.1",
|
||||
"gaba": "^1.3.0",
|
||||
"ganache-cli": "^6.1.0",
|
||||
"ganache-core": "^2.5.3",
|
||||
"geckodriver": "^1.14.1",
|
||||
|
@ -1,78 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const nock = require('nock')
|
||||
const CurrencyController = require('../../../../app/scripts/controllers/currency')
|
||||
|
||||
describe('currency-controller', function () {
|
||||
var currencyController
|
||||
|
||||
beforeEach(function () {
|
||||
currencyController = new CurrencyController()
|
||||
})
|
||||
|
||||
describe('currency conversions', function () {
|
||||
describe('#setCurrentCurrency', function () {
|
||||
it('should return USD as default', function () {
|
||||
assert.equal(currencyController.getCurrentCurrency(), 'usd')
|
||||
})
|
||||
|
||||
it('should be able to set to other currency', function () {
|
||||
assert.equal(currencyController.getCurrentCurrency(), 'usd')
|
||||
currencyController.setCurrentCurrency('JPY')
|
||||
var result = currencyController.getCurrentCurrency()
|
||||
assert.equal(result, 'JPY')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getConversionRate', function () {
|
||||
it('should return undefined if non-existent', function () {
|
||||
var result = currencyController.getConversionRate()
|
||||
assert.ok(!result)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#updateConversionRate', function () {
|
||||
it('should retrieve an update for ETH to USD and set it in memory', function (done) {
|
||||
this.timeout(15000)
|
||||
nock('https://api.infura.io')
|
||||
.get('/v1/ticker/ethusd')
|
||||
.reply(200, '{"base": "ETH", "quote": "USD", "bid": 288.45, "ask": 288.46, "volume": 112888.17569277, "exchange": "bitfinex", "total_volume": 272175.00106721005, "num_exchanges": 8, "timestamp": 1506444677}')
|
||||
|
||||
assert.equal(currencyController.getConversionRate(), 0)
|
||||
currencyController.setCurrentCurrency('usd')
|
||||
currencyController.updateConversionRate()
|
||||
.then(function () {
|
||||
var result = currencyController.getConversionRate()
|
||||
assert.equal(typeof result, 'number')
|
||||
done()
|
||||
}).catch(function (err) {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
|
||||
it('should work for JPY as well.', function () {
|
||||
this.timeout(15000)
|
||||
assert.equal(currencyController.getConversionRate(), 0)
|
||||
|
||||
nock('https://api.infura.io')
|
||||
.get('/v1/ticker/ethjpy')
|
||||
.reply(200, '{"base": "ETH", "quote": "JPY", "bid": 32300.0, "ask": 32400.0, "volume": 247.4616071, "exchange": "kraken", "total_volume": 247.4616071, "num_exchanges": 1, "timestamp": 1506444676}')
|
||||
|
||||
|
||||
var promise = new Promise(
|
||||
function (resolve) {
|
||||
currencyController.setCurrentCurrency('jpy')
|
||||
currencyController.updateConversionRate().then(function () {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
promise.then(function () {
|
||||
var result = currencyController.getConversionRate()
|
||||
assert.equal(typeof result, 'number')
|
||||
}).catch(function (done, err) {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -45,6 +45,11 @@ describe('MetaMaskController', function () {
|
||||
.get(/.*/)
|
||||
.reply(200)
|
||||
|
||||
nock('https://min-api.cryptocompare.com')
|
||||
.persist()
|
||||
.get(/.*/)
|
||||
.reply(200, '{"JPY":12415.9}')
|
||||
|
||||
metamaskController = new MetaMaskController({
|
||||
showUnapprovedTx: noop,
|
||||
showUnconfirmedMessage: noop,
|
||||
@ -441,7 +446,7 @@ describe('MetaMaskController', function () {
|
||||
let defaultMetaMaskCurrency
|
||||
|
||||
beforeEach(function () {
|
||||
defaultMetaMaskCurrency = metamaskController.currencyController.getCurrentCurrency()
|
||||
defaultMetaMaskCurrency = metamaskController.currencyRateController.state.currentCurrency
|
||||
})
|
||||
|
||||
it('defaults to usd', function () {
|
||||
@ -450,7 +455,7 @@ describe('MetaMaskController', function () {
|
||||
|
||||
it('sets currency to JPY', function () {
|
||||
metamaskController.setCurrentCurrency('JPY', noop)
|
||||
assert.equal(metamaskController.currencyController.getCurrentCurrency(), 'JPY')
|
||||
assert.equal(metamaskController.currencyRateController.state.currentCurrency, 'JPY')
|
||||
})
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user