diff --git a/config.js b/config.js
index 4e6e38d67..eea37cd1e 100644
--- a/config.js
+++ b/config.js
@@ -46,9 +46,8 @@ var defaultConfig = {
storageSalt: 'mjuBtGybi/4=',
},
- rate: {
- url: 'https://bitpay.com/api/rates',
- updateFrequencySeconds: 60 * 60
+ rates: {
+ url: 'https://insight.bitpay.com:443/api/rates',
},
verbose: 1,
diff --git a/js/controllers/history.js b/js/controllers/history.js
index 3f47fb95c..2328a1de9 100644
--- a/js/controllers/history.js
+++ b/js/controllers/history.js
@@ -140,11 +140,26 @@ angular.module('copayApp.controllers').controller('HistoryController',
}
var items = res.items;
-
- _.each(items, function(r) {
- r.ts = r.minedTs || r.sentTs;
+ var now = new Date();
+ _.each(items, function(tx) {
+ tx.ts = tx.minedTs || tx.sentTs;
+ tx.rateTs = Math.floor((tx.ts || now) / 1000);
});
+ var index = _.indexBy(items, 'rateTs');
+ rateService.getHistoricRates(w.settings.alternativeIsoCode, _.keys(index), function(err, res) {
+ if (!err && res) {
+ _.each(res, function(r) {
+ var tx = index[r.ts];
+ tx.alternativeAmount = r.rate != null ? tx.amountSat * rateService.SAT_TO_BTC * r.rate : null;
+ });
+ setTimeout(function() {
+ $scope.$digest();
+ }, 1);
+ }
+ });
+
+
$scope.blockchain_txs = w.cached_txs = items;
$scope.nbPages = res.nbPages;
diff --git a/js/controllers/settings.js b/js/controllers/settings.js
index 7beec08ff..2756f55d3 100644
--- a/js/controllers/settings.js
+++ b/js/controllers/settings.js
@@ -1,8 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('SettingsController', function($scope, $rootScope, $window, $route, $location, $anchorScroll, controllerUtils, notification) {
-
-
controllerUtils.redirIfLogged();
$scope.title = 'Settings';
@@ -93,6 +91,9 @@ angular.module('copayApp.controllers').controller('SettingsController', function
EncryptedInsightStorage: _.extend(config.EncryptedInsightStorage, {
url: insightSettings.livenet.url + '/api/email'
}),
+ rates: _.extend(config.rates, {
+ url: insightSettings.livenet.url + '/api/rates'
+ }),
}));
// Go home reloading the application
diff --git a/js/models/RateService.js b/js/models/RateService.js
index 55995a567..c0819f8c2 100644
--- a/js/models/RateService.js
+++ b/js/models/RateService.js
@@ -21,6 +21,8 @@ var RateService = function(opts) {
self.UNAVAILABLE_ERROR = 'Service is not available - check for service.isAvailable() or use service.whenAvailable()';
self.UNSUPPORTED_CURRENCY_ERROR = 'Currency not supported';
+ self._url = opts.url || 'https://insight.bitpay.com:443/api/rates';
+
self._isAvailable = false;
self._rates = {};
self._alternatives = [];
@@ -45,7 +47,7 @@ RateService.prototype._fetchCurrencies = function() {
var updateFrequencySeconds = 3600;
var rateServiceUrl = 'https://bitpay.com/api/rates';
- var retrieve = function () {
+ var retrieve = function() {
log.info('Fetching exchange rates');
self.request.get({
url: rateServiceUrl,
@@ -53,7 +55,7 @@ RateService.prototype._fetchCurrencies = function() {
}, function(err, res, body) {
if (err || !body) {
log.debug('Error fetching exchange rates', err);
- setTimeout(function () {
+ setTimeout(function() {
backoffSeconds *= 1.5;
retrieve();
}, backoffSeconds * 1000);
@@ -78,16 +80,39 @@ RateService.prototype._fetchCurrencies = function() {
retrieve();
};
-RateService.prototype._getRate = function(code) {
+RateService.prototype.getRate = function(code) {
return this._rates[code];
};
-RateService.prototype._getHistoricRate = function(code, date, cb) {
- // TODO (isocolsky): implement with a remote call
- return cb(new Error('Not implemented'));
+RateService.prototype.getHistoricRate = function(code, date, cb) {
+ var self = this;
+
+ self.request.get({
+ url: self._url + '/' + code + '?ts=' + date,
+ json: true
+ }, function(err, res, body) {
+ if (err || res.statusCode != 200 || !body) return cb(err || res);
+ return cb(null, body.rate);
+ });
};
-RateService.prototype._getAlternatives = function() {
+RateService.prototype.getHistoricRates = function(code, dates, cb) {
+ var self = this;
+
+ var tsList = dates.join(',');
+ self.request.get({
+ url: self._url + '/' + code + '?ts=' + tsList,
+ json: true
+ }, function(err, res, body) {
+ if (err || res.statusCode != 200 || !body) return cb(err || res);
+ if (!_.isArray(body)) {
+ body = [{ ts: dates[0], rate: body.rate }];
+ }
+ return cb(null, body);
+ });
+};
+
+RateService.prototype.getAlternatives = function() {
return this._alternatives;
};
@@ -107,13 +132,13 @@ RateService.prototype.toFiat = function(satoshis, code) {
if (!this.isAvailable()) {
throw new Error(this.UNAVAILABLE_ERROR);
}
- return satoshis * this.SAT_TO_BTC * this._getRate(code);
+ return satoshis * this.SAT_TO_BTC * this.getRate(code);
};
RateService.prototype.toFiatHistoric = function(satoshis, code, date, cb) {
var self = this;
- self._getHistoricRate(code, date, function(err, rate) {
+ self.getHistoricRate(code, date, function(err, rate) {
if (err) return cb(err);
return cb(null, satoshis * self.SAT_TO_BTC * rate);
});
@@ -123,7 +148,7 @@ RateService.prototype.fromFiat = function(amount, code) {
if (!this.isAvailable()) {
throw new Error(this.UNAVAILABLE_ERROR);
}
- return amount / this._getRate(code) * this.BTC_TO_SAT;
+ return amount / this.getRate(code) * this.BTC_TO_SAT;
};
RateService.prototype.listAlternatives = function() {
@@ -131,7 +156,7 @@ RateService.prototype.listAlternatives = function() {
throw new Error(this.UNAVAILABLE_ERROR);
}
- return _.map(this._getAlternatives(), function(item) {
+ return _.map(this.getAlternatives(), function(item) {
return {
name: item.name,
isoCode: item.isoCode
diff --git a/js/services/rate.js b/js/services/rate.js
index cbfeb2726..64dd100d4 100644
--- a/js/services/rate.js
+++ b/js/services/rate.js
@@ -1,7 +1,8 @@
'use strict';
angular.module('copayApp.services').factory('rateService', function(request) {
- return copay.RateService.singleton({
+ var cfg = _.extend(config.rates, {
request: request
});
+ return copay.RateService.singleton(cfg);
});
diff --git a/test/RateService.js b/test/RateService.js
index ad2b27e5c..db2445976 100644
--- a/test/RateService.js
+++ b/test/RateService.js
@@ -86,7 +86,7 @@ describe('RateService model', function() {
it('should return current valuation', function() {
var rs = new RateService();
rs.isAvailable = sinon.stub().returns(true);
- var getRateStub = sinon.stub(rs, '_getRate')
+ var getRateStub = sinon.stub(rs, 'getRate')
getRateStub.withArgs('USD').returns(300.00);
getRateStub.withArgs('EUR').returns(250.00);
var params = [{
@@ -119,7 +119,7 @@ describe('RateService model', function() {
rs.isAvailable = sinon.stub().returns(true);
var today = Date.now();
var yesterday = today - 24 * 3600;
- var getHistoricalRateStub = sinon.stub(rs, '_getHistoricRate');
+ var getHistoricalRateStub = sinon.stub(rs, 'getHistoricRate');
getHistoricalRateStub.withArgs('USD', today).yields(null, 300.00);
getHistoricalRateStub.withArgs('USD', yesterday).yields(null, 250.00);
getHistoricalRateStub.withArgs('EUR', today).yields(null, 250.00);
@@ -185,7 +185,7 @@ describe('RateService model', function() {
it('should return current valuation', function() {
var rs = new RateService();
rs.isAvailable = sinon.stub().returns(true);
- var getRateStub = sinon.stub(rs, '_getRate')
+ var getRateStub = sinon.stub(rs, 'getRate')
getRateStub.withArgs('USD').returns(300.00);
getRateStub.withArgs('EUR').returns(250.00);
var params = [{
@@ -223,7 +223,7 @@ describe('RateService model', function() {
it('should return list of available currencies', function() {
var rs = new RateService();
rs.isAvailable = sinon.stub().returns(true);
- sinon.stub(rs, '_getAlternatives').returns([{
+ sinon.stub(rs, 'getAlternatives').returns([{
name: 'United States Dollar',
isoCode: 'USD',
rate: 300.00,
diff --git a/views/history.html b/views/history.html
index 682bf6de6..6115b9b10 100644
--- a/views/history.html
+++ b/views/history.html
@@ -47,6 +47,7 @@
'text-warning': btx.action == 'sent',
'text-gray': btx.action == 'moved'}">
{{btx.amount| noFractionNumber}} {{$root.wallet.settings.unitName}}
+ {{btx.alternativeAmount| noFractionNumber}} {{$root.wallet.settings.alternativeIsoCode}}