From 67b392bdc338192f3fa6a68fbe598d40a6af6f68 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Mon, 3 Nov 2014 16:53:57 -0300 Subject: [PATCH 01/10] fixed alternative amount in TXP view --- js/controllers/send.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/js/controllers/send.js b/js/controllers/send.js index cba594c7b..3d6a0b00e 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -24,6 +24,7 @@ angular.module('copayApp.controllers').controller('SendController', $scope.isRateAvailable = false; $scope.rateService = rateService; + $scope.alternativeCurrency = []; rateService.whenAvailable(function() { @@ -88,6 +89,15 @@ angular.module('copayApp.controllers').controller('SendController', return w && _.keys(w.addressBook).length > 0; }; + $scope.amountAlternative = function(amount, txIndex, cb) { + var w = $rootScope.wallet; + rateService.whenAvailable(function() { + var valueSat = amount * w.settings.unitToSatoshi; + $scope.alternativeCurrency[txIndex] = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); + return cb ? cb() : null; + }); + }; + if ($rootScope.pendingPayment) { var pp = $rootScope.pendingPayment; $scope.address = pp.address + ''; From 9db19422e4d48e40934c74a7cf14d433cd88fb46 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Tue, 4 Nov 2014 10:56:13 -0300 Subject: [PATCH 02/10] compute alternative currency for pending txps --- js/services/controllerUtils.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index 52b37c4c9..ee5129272 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -324,6 +324,17 @@ angular.module('copayApp.services') }; root.updateTxs = function(opts) { + function computeAlternativeAmount(w, tx, cb) { + rateService.whenAvailable(function() { + _.each(tx.outs, function(out) { + var valueSat = out.value * w.settings.unitToSatoshi; + out.alternativeAmount = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); + out.alternativeIsoCode = w.settings.alternativeIsoCode; + }); + if (cb) return cb(); + }); + }; + var w = opts.wallet || $rootScope.wallet; if (!w) return; opts = opts || $rootScope.txsOpts || {}; @@ -364,6 +375,9 @@ angular.module('copayApp.services') i.fee = i.builder.feeSat * satToUnit; i.missingSignatures = tx.countInputMissingSignatures(0); i.actionList = getActionList(i.peerActions); + if (i.isPending) { + computeAlternativeAmount(w, i); + } txs.push(i); } }); From 377dc7a176813cf9b79edeae2532822da8d22fc4 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Tue, 4 Nov 2014 11:04:05 -0300 Subject: [PATCH 03/10] show alternative amount on txps --- js/controllers/send.js | 11 ----------- views/includes/transaction.html | 5 +++++ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/js/controllers/send.js b/js/controllers/send.js index 3d6a0b00e..46eb1d7cb 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -24,8 +24,6 @@ angular.module('copayApp.controllers').controller('SendController', $scope.isRateAvailable = false; $scope.rateService = rateService; - $scope.alternativeCurrency = []; - rateService.whenAvailable(function() { $scope.isRateAvailable = true; @@ -89,15 +87,6 @@ angular.module('copayApp.controllers').controller('SendController', return w && _.keys(w.addressBook).length > 0; }; - $scope.amountAlternative = function(amount, txIndex, cb) { - var w = $rootScope.wallet; - rateService.whenAvailable(function() { - var valueSat = amount * w.settings.unitToSatoshi; - $scope.alternativeCurrency[txIndex] = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); - return cb ? cb() : null; - }); - }; - if ($rootScope.pendingPayment) { var pp = $rootScope.pendingPayment; $scope.address = pp.address + ''; diff --git a/views/includes/transaction.html b/views/includes/transaction.html index aa52d45d1..0de242379 100644 --- a/views/includes/transaction.html +++ b/views/includes/transaction.html @@ -10,6 +10,11 @@
{{out.value |noFractionNumber}} {{$root.wallet.settings.unitName}} + {{out.alternativeAmount|noFractionNumber}} {{out.alternativeIsoCode}} +
+
+ {{out.value |noFractionNumber}} {{$root.wallet.settings.unitName}} + {{out.alternativeAmount|noFractionNumber}} {{out.alternativeIsoCode}}
From 8517dcd2d6148821f07430498cdadc96a1756ea5 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Tue, 4 Nov 2014 16:01:45 -0300 Subject: [PATCH 04/10] cleanup unused method for alt currency conversion --- js/controllers/history.js | 10 +--------- test/unit/controllers/controllersSpec.js | 23 ++++++----------------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/js/controllers/history.js b/js/controllers/history.js index b7331b7ad..01868c399 100644 --- a/js/controllers/history.js +++ b/js/controllers/history.js @@ -59,7 +59,7 @@ angular.module('copayApp.controllers').controller('HistoryController', return; } - _.each(res, function (r) { + _.each(res, function(r) { r.ts = r.minedTs || r.sentTs; if (r.action === 'sent' && r.peerActions) { r.actionList = controllerUtils.getActionList(r.peerActions); @@ -82,14 +82,6 @@ angular.module('copayApp.controllers').controller('HistoryController', var w = $rootScope.wallet; return w.getNetworkName().substring(0, 4); }; - $scope.amountAlternative = function(amount, txIndex, cb) { - var w = $rootScope.wallet; - rateService.whenAvailable(function() { - var valueSat = amount * w.settings.unitToSatoshi; - $scope.alternativeCurrency[txIndex] = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); - return cb ? cb() : null; - }); - }; // Autoload transactions $scope.getTransactions(); diff --git a/test/unit/controllers/controllersSpec.js b/test/unit/controllers/controllersSpec.js index dfc539e55..13a990411 100644 --- a/test/unit/controllers/controllersSpec.js +++ b/test/unit/controllers/controllersSpec.js @@ -26,11 +26,11 @@ describe("Unit: Controllers", function() { var server; beforeEach(module('copayApp')); - beforeEach(module('copayApp.controllers')); - beforeEach(module(function($provide) { - $provide.value('request', { - 'get': function(_, cb) { - cb(null, null, [{ + beforeEach(module('copayApp.controllers')); + beforeEach(module(function($provide) { + $provide.value('request', { + 'get': function(_, cb) { + cb(null, null, [{ name: 'USD Dollars', code: 'USD', rate: 2 @@ -71,7 +71,7 @@ describe("Unit: Controllers", function() { w.createTx = sinon.stub().yields(null); w.sendTx = sinon.stub().yields(null); w.requiresMultipleSignatures = sinon.stub().returns(true); - w.getTxProposals = sinon.stub().returns([1,2,3]); + w.getTxProposals = sinon.stub().returns([1, 2, 3]); $rootScope.wallet = w; @@ -172,17 +172,6 @@ describe("Unit: Controllers", function() { scope.getTransactions(); expect(scope.blockchain_txs).to.be.empty; }); - - it('should call amountAlternative and return a value', function() { - var cb = sinon.spy(); - var s1 = sinon.stub(scope, 'amountAlternative'); - s1.onCall(0).returns(1000); - s1.onCall(1).returns(2000); - expect(s1(100, 0, cb)).equal(1000); - expect(s1(200, 1, cb)).equal(2000); - sinon.assert.callCount(scope.amountAlternative, 2); - s1.restore(); - }); }); describe('Send Controller', function() { From 476f6395e5e391931aac96a857375cf284e24a74 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Wed, 5 Nov 2014 12:57:21 -0300 Subject: [PATCH 05/10] rate service + tests --- copay.js | 1 + js/models/RateService.js | 125 +++++++++++++++++++++++++++ test/RateService.js | 179 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 js/models/RateService.js create mode 100644 test/RateService.js diff --git a/copay.js b/copay.js index f3d332743..bdb5c759b 100644 --- a/copay.js +++ b/copay.js @@ -12,6 +12,7 @@ module.exports.logger = require('./js/log'); // components var Async = module.exports.Async = require('./js/models/Async'); var Insight = module.exports.Insight = require('./js/models/Insight'); +var RateService = module.exports.RateService = require('./js/models/RateService'); module.exports.Identity = require('./js/models/Identity'); module.exports.Wallet = require('./js/models/Wallet'); diff --git a/js/models/RateService.js b/js/models/RateService.js new file mode 100644 index 000000000..267631419 --- /dev/null +++ b/js/models/RateService.js @@ -0,0 +1,125 @@ +'use strict'; + +var util = require('util'); +var _ = require('lodash'); +var log = require('../log'); +var preconditions = require('preconditions').singleton(); +var request = require('request'); + +/* + This class lets interfaces with BitPay's exchange rate API. +*/ + +var RateService = function(opts) { + var self = this; + + self.SAT_TO_BTC = 1 / 1e8; + self.BTC_TO_SAT = 1e8; + self.UNAVAILABLE_ERROR = 'Service is not available - check for service.isAvailable() or use service.whenAvailable()'; + self.UNSUPPORTED_CURRENCY_ERROR = 'Currency not supported'; + + self._isAvailable = false; + self._rates = {}; + self._alternatives = {}; + self.queued = []; + + self._fetchCurrencies(); +} + +RateService.prototype._fetchCurrencies = function() { + var self = this; + + var backoffSeconds = 5; + var updateFrequencySeconds = 3600; + var rateServiceUrl = 'https://bitpay.com/api/rates'; + + request.get({ + url: rateServiceUrl, + json: true + }, function(err, res, body) { + if (err || !body) { + backoffSeconds *= 1.5; + setTimeout(retrieve, backoffSeconds * 1000); + return; + } + _.each(body, function(currency) { + self.rates[currency.code] = currency.rate; + self.alternatives.push({ + name: currency.name, + isoCode: currency.code, + rate: currency.rate + }); + }); + self._isAvailable = true; + _.each(self.queued, function(callback) { + setTimeout(callback, 1); + }); + setTimeout(function() { + self._fetchCurrencies() + }, updateFrequencySeconds * 1000); + }); +}; + +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._getAlternatives = function() { + return this._alternatives; +}; + +RateService.prototype.isAvailable = function() { + return this._isAvailable; +}; + +RateService.prototype.whenAvailable = function(callback) { + if (!this.isAvailable()) { + setTimeout(callback, 1); + } else { + this.queued.push(callback); + } +}; + +RateService.prototype.toFiat = function(satoshis, code) { + if (!this.isAvailable()) { + throw new Error(this.UNAVAILABLE_ERROR); + } + 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) { + if (err) return cb(err); + return cb(null, satoshis * self.SAT_TO_BTC * rate); + }); +}; + +RateService.prototype.fromFiat = function(amount, code) { + if (!this.isAvailable()) { + throw new Error(this.UNAVAILABLE_ERROR); + } + return amount / this._getRate(code) * this.BTC_TO_SAT; +}; + +RateService.prototype.listAlternatives = function() { + if (!this.isAvailable()) { + throw new Error(this.UNAVAILABLE_ERROR); + } + + return _.map(this._getAlternatives(), function(item) { + return { + name: item.name, + isoCode: item.isoCode + } + }); +}; + + +module.exports = RateService; diff --git a/test/RateService.js b/test/RateService.js new file mode 100644 index 000000000..3ebb9a5dc --- /dev/null +++ b/test/RateService.js @@ -0,0 +1,179 @@ +'use strict'; + +var RateService = copay.RateService; + +describe('RateService model', function() { + before(function() { + sinon.stub(RateService.prototype, '_fetchCurrencies').returns(); + }); + after(function() {}); + + it('should create an instance', function() { + var rs = new RateService(); + should.exist(rs); + }); + + describe('#toFiat', function() { + it('should throw error when unavailable', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(false); + (function() { + rs.toFiat(10000, 'USD'); + }).should.throw; + }); + it('should return current valuation', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(true); + var getRateStub = sinon.stub(rs, '_getRate') + getRateStub.withArgs('USD').returns(300.00); + getRateStub.withArgs('EUR').returns(250.00); + var params = [{ + satoshis: 0, + code: 'USD', + expected: '0.00' + }, { + satoshis: 1e8, + code: 'USD', + expected: '300.00' + }, { + satoshis: 10000, + code: 'USD', + expected: '0.03' + }, { + satoshis: 20000, + code: 'EUR', + expected: '0.05' + }, ]; + + _.each(params, function(p) { + rs.toFiat(p.satoshis, p.code).toFixed(2).should.equal(p.expected); + }); + }); + }); + + describe('#toFiatHistoric', function() { + it('should return historic valuation', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(true); + var today = Date.now(); + var yesterday = today - 24 * 3600; + 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); + getHistoricalRateStub.withArgs('EUR', yesterday).yields(null, 200.00); + var params = [{ + satoshis: 0, + code: 'USD', + date: today, + expected: '0.00' + }, { + satoshis: 1e8, + code: 'USD', + date: today, + expected: '300.00' + }, { + satoshis: 10000, + code: 'USD', + date: today, + expected: '0.03' + }, { + satoshis: 0, + code: 'USD', + date: today, + expected: '0.00' + }, { + satoshis: 1e8, + code: 'USD', + date: today, + expected: '300.00' + }, { + satoshis: 10000, + code: 'USD', + date: today, + expected: '0.03' + }, { + satoshis: 20000, + code: 'EUR', + date: today, + expected: '0.05' + }, { + satoshis: 20000, + code: 'EUR', + date: yesterday, + expected: '0.04' + }, ]; + + _.each(params, function(p) { + rs.toFiatHistoric(p.satoshis, p.code, p.date, function(err, rate) { + rate.toFixed(2).should.equal(p.expected); + }); + }); + }); + }); + + describe('#fromFiat', function() { + it('should throw error when unavailable', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(false); + (function() { + rs.fromFiat(300, 'USD'); + }).should.throw; + }); + it('should return current valuation', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(true); + var getRateStub = sinon.stub(rs, '_getRate') + getRateStub.withArgs('USD').returns(300.00); + getRateStub.withArgs('EUR').returns(250.00); + var params = [{ + amount: 0, + code: 'USD', + expected: 0 + }, { + amount: 300.00, + code: 'USD', + expected: 1e8 + }, { + amount: 600.00, + code: 'USD', + expected: 2e8 + }, { + amount: 250.00, + code: 'EUR', + expected: 1e8 + }, ]; + + _.each(params, function(p) { + rs.fromFiat(p.amount, p.code).should.equal(p.expected); + }); + }); + }); + describe('#listAlternatives', function() { + it('should throw error when unavailable', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(false); + (function() { + rs.listAlternatives(); + }).should.throw; + }); + + it('should return list of available currencies', function() { + var rs = new RateService(); + rs.isAvailable = sinon.stub().returns(true); + sinon.stub(rs, '_getAlternatives').returns([{ + name: 'United States Dollar', + isoCode: 'USD', + rate: 300.00, + }, { + name: 'European Union Euro', + isoCode: 'EUR', + rate: 250.00, + }, ]) + + var list = rs.listAlternatives(); + list.should.exist; + list.length.should.equal(2); + }); + }); +}); From 015af226385929a4fc04ef95db3adce726c8b86d Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Wed, 5 Nov 2014 22:05:09 -0300 Subject: [PATCH 06/10] added rate services to wallet --- js/models/Identity.js | 4 +++- js/models/RateService.js | 25 ++++++++++++++++++------- test/PayPro.js | 1 + test/Wallet.js | 6 +++--- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/js/models/Identity.js b/js/models/Identity.js index 4e6effb71..bf1985258 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -86,7 +86,9 @@ Identity.create = function(opts, cb) { opts = _.extend({}, opts); var iden = new Identity(opts); - iden.store(_.extend(opts, {failIfExists: true}), function(err) { + iden.store(_.extend(opts, { + failIfExists: true + }), function(err) { if (err) return cb(err); return cb(null, iden); }); diff --git a/js/models/RateService.js b/js/models/RateService.js index 267631419..29fd21971 100644 --- a/js/models/RateService.js +++ b/js/models/RateService.js @@ -20,15 +20,26 @@ var RateService = function(opts) { self._isAvailable = false; self._rates = {}; - self._alternatives = {}; - self.queued = []; + self._alternatives = []; + self._queued = []; self._fetchCurrencies(); -} +}; + +var _instance; +RateService.singleton = function(opts) { + if (!_instance) { + _instance = new RateService(opts); + } + return _instance; +}; + RateService.prototype._fetchCurrencies = function() { var self = this; + log.info('Fetching exchange rates'); + var backoffSeconds = 5; var updateFrequencySeconds = 3600; var rateServiceUrl = 'https://bitpay.com/api/rates'; @@ -43,15 +54,15 @@ RateService.prototype._fetchCurrencies = function() { return; } _.each(body, function(currency) { - self.rates[currency.code] = currency.rate; - self.alternatives.push({ + self._rates[currency.code] = currency.rate; + self._alternatives.push({ name: currency.name, isoCode: currency.code, rate: currency.rate }); }); self._isAvailable = true; - _.each(self.queued, function(callback) { + _.each(self._queued, function(callback) { setTimeout(callback, 1); }); setTimeout(function() { @@ -81,7 +92,7 @@ RateService.prototype.whenAvailable = function(callback) { if (!this.isAvailable()) { setTimeout(callback, 1); } else { - this.queued.push(callback); + this._queued.push(callback); } }; diff --git a/test/PayPro.js b/test/PayPro.js index 969c64dcf..8a2cd58ea 100644 --- a/test/PayPro.js +++ b/test/PayPro.js @@ -83,6 +83,7 @@ describe('PayPro (in Wallet) model', function() { c.network.getHexNonces = sinon.stub(); c.network.send = sinon.stub(); + Wallet._newRateService = sinon.stub().returns(null); return new Wallet(c); } diff --git a/test/Wallet.js b/test/Wallet.js index 4c760977e..4412cae69 100644 --- a/test/Wallet.js +++ b/test/Wallet.js @@ -56,8 +56,8 @@ var addCopayers = function(w) { } }; -describe('Wallet model', function() { +describe('Wallet model', function() { it('should fail to create an instance', function() { (function() { new Wallet(walletConfig) @@ -102,8 +102,6 @@ describe('Wallet model', function() { c.network.peerFromCopayer = sinon.stub().returns('xxxx'); c.network.send = sinon.stub(); - - c.addressBook = { '2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ': { label: 'John', @@ -122,6 +120,8 @@ describe('Wallet model', function() { c.networkName = walletConfig.networkName; c.version = '0.0.1'; + Wallet._newRateService = sinon.stub().returns(null); + return new Wallet(c); } From b8a708c8631f2f5e37189d24d77653f2d7817046 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Wed, 5 Nov 2014 22:21:32 -0300 Subject: [PATCH 07/10] fixed whenAvailable() --- js/models/RateService.js | 2 +- js/models/TxProposal.js | 1 + js/models/Wallet.js | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/js/models/RateService.js b/js/models/RateService.js index 29fd21971..048acb7dd 100644 --- a/js/models/RateService.js +++ b/js/models/RateService.js @@ -89,7 +89,7 @@ RateService.prototype.isAvailable = function() { }; RateService.prototype.whenAvailable = function(callback) { - if (!this.isAvailable()) { + if (this.isAvailable()) { setTimeout(callback, 1); } else { this._queued.push(callback); diff --git a/js/models/TxProposal.js b/js/models/TxProposal.js index ae9de2dd9..5f806f8bb 100644 --- a/js/models/TxProposal.js +++ b/js/models/TxProposal.js @@ -37,6 +37,7 @@ function TxProposal(opts) { this.comment = opts.comment || null; this.readonly = opts.readonly || null; this.merchant = opts.merchant || null; + this.altCurrency = opts.altCurrency || null; this._sync(); } diff --git a/js/models/Wallet.js b/js/models/Wallet.js index c1d4b876e..6f66162f6 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -2866,19 +2866,23 @@ Wallet.prototype.getTransactionHistory = function(cb) { type: 'out' }); - var proposal = _.findWhere(proposals, { - sentTxid: tx.txid - }); - tx.comment = proposal ? proposal.comment : undefined; tx.labelTo = firstOut ? firstOut.label : undefined; tx.addressTo = firstOut ? firstOut.address : undefined; tx.amountSat = Math.abs(amount); tx.amount = tx.amountSat * satToUnit; - tx.sentTs = proposal ? proposal.sentTs : undefined; tx.minedTs = !_.isNaN(tx.time) ? tx.time * 1000 : undefined; - tx.merchant = proposal ? proposal.merchant : undefined; - tx.peerActions = proposal ? proposal.peerActions : undefined; - tx.finallyRejected = proposal ? proposal.finallyRejected : undefined; + + var proposal = _.findWhere(proposals, { + sentTxid: tx.txid + }); + + if (proposal) { + tx.comment = proposal.comment; + tx.sentTs = proposal.sentTs; + tx.merchant = proposal.merchant; + tx.peerActions = proposal.peerActions; + tx.finallyRejected = proposal.finallyRejected; + } }; if (addresses.length > 0) { From e1eef196a3fad0ec4dd31520fd318795a3bcc17a Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Wed, 5 Nov 2014 22:31:55 -0300 Subject: [PATCH 08/10] removed layout for small devices --- views/includes/transaction.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/views/includes/transaction.html b/views/includes/transaction.html index 0de242379..f4847c54b 100644 --- a/views/includes/transaction.html +++ b/views/includes/transaction.html @@ -12,10 +12,6 @@ {{out.value |noFractionNumber}} {{$root.wallet.settings.unitName}} {{out.alternativeAmount|noFractionNumber}} {{out.alternativeIsoCode}} -
- {{out.value |noFractionNumber}} {{$root.wallet.settings.unitName}} - {{out.alternativeAmount|noFractionNumber}} {{out.alternativeIsoCode}} -
From 505951a0b11c7f647f8ab225801a6ef95883e6e5 Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Thu, 6 Nov 2014 11:34:52 -0300 Subject: [PATCH 09/10] replaced old rate service as angular controller --- js/models/RateService.js | 5 ++- js/services/rate.js | 86 ++-------------------------------------- 2 files changed, 8 insertions(+), 83 deletions(-) diff --git a/js/models/RateService.js b/js/models/RateService.js index 048acb7dd..7c952f3b3 100644 --- a/js/models/RateService.js +++ b/js/models/RateService.js @@ -13,6 +13,9 @@ var request = require('request'); var RateService = function(opts) { var self = this; + opts = opts || {}; + self.request = opts.request || request; + self.SAT_TO_BTC = 1 / 1e8; self.BTC_TO_SAT = 1e8; self.UNAVAILABLE_ERROR = 'Service is not available - check for service.isAvailable() or use service.whenAvailable()'; @@ -44,7 +47,7 @@ RateService.prototype._fetchCurrencies = function() { var updateFrequencySeconds = 3600; var rateServiceUrl = 'https://bitpay.com/api/rates'; - request.get({ + self.request.get({ url: rateServiceUrl, json: true }, function(err, res, body) { diff --git a/js/services/rate.js b/js/services/rate.js index 6599905c1..cbfeb2726 100644 --- a/js/services/rate.js +++ b/js/services/rate.js @@ -1,85 +1,7 @@ 'use strict'; -var MINS_IN_HOUR = 60; -var MILLIS_IN_SECOND = 1000; - -var RateService = function(request) { - this.isAvailable = false; - this.UNAVAILABLE_ERROR = 'Service is not available - check for service.isAvailable or use service.whenAvailable'; - this.SAT_TO_BTC = 1 / 1e8; - this.BTC_TO_SAT = 1e8; - var rateServiceConfig = config.rate; - var updateFrequencySeconds = rateServiceConfig.updateFrequencySeconds || 60 * MINS_IN_HOUR; - var rateServiceUrl = rateServiceConfig.url || 'https://bitpay.com/api/rates'; - this.queued = []; - this.alternatives = []; - var self = this; - var backoffSeconds = 5; - var retrieve = function() { - request.get({ - url: rateServiceUrl, - json: true - }, function(err, response, listOfCurrencies) { - if (err) { - backoffSeconds *= 1.5; - setTimeout(retrieve, backoffSeconds * MILLIS_IN_SECOND); - return; - } - var rates = {}; - listOfCurrencies.forEach(function(element) { - rates[element.code] = element.rate; - self.alternatives.push({ - name: element.name, - isoCode: element.code, - rate: element.rate - }); - }); - self.isAvailable = true; - self.rates = rates; - self.queued.forEach(function(callback) { - setTimeout(callback, 1); - }); - setTimeout(retrieve, updateFrequencySeconds * MILLIS_IN_SECOND); - }); - }; - retrieve(); -}; - -RateService.prototype.whenAvailable = function(callback) { - if (this.isAvailable) { - setTimeout(callback, 1); - } else { - this.queued.push(callback); - } -}; - -RateService.prototype.toFiat = function(satoshis, code) { - if (!this.isAvailable) { - throw new Error(this.UNAVAILABLE_ERROR); - } - return satoshis * this.SAT_TO_BTC * this.rates[code]; -}; - -RateService.prototype.fromFiat = function(amount, code) { - if (!this.isAvailable) { - throw new Error(this.UNAVAILABLE_ERROR); - } - return amount / this.rates[code] * this.BTC_TO_SAT; -}; - -RateService.prototype.listAlternatives = function() { - if (!this.isAvailable) { - throw new Error(this.UNAVAILABLE_ERROR); - } - - var alts = []; - this.alternatives.forEach(function(element) { - alts.push({ - name: element.name, - isoCode: element.isoCode - }); +angular.module('copayApp.services').factory('rateService', function(request) { + return copay.RateService.singleton({ + request: request }); - return alts; -}; - -angular.module('copayApp.services').service('rateService', RateService); +}); From 49ea9d8c3d304c9621d2f4e456432cd5c813e7dd Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Thu, 6 Nov 2014 12:37:00 -0300 Subject: [PATCH 10/10] removed from wallet model --- js/models/TxProposal.js | 1 - test/PayPro.js | 2 -- test/Wallet.js | 2 -- 3 files changed, 5 deletions(-) diff --git a/js/models/TxProposal.js b/js/models/TxProposal.js index 5f806f8bb..ae9de2dd9 100644 --- a/js/models/TxProposal.js +++ b/js/models/TxProposal.js @@ -37,7 +37,6 @@ function TxProposal(opts) { this.comment = opts.comment || null; this.readonly = opts.readonly || null; this.merchant = opts.merchant || null; - this.altCurrency = opts.altCurrency || null; this._sync(); } diff --git a/test/PayPro.js b/test/PayPro.js index 8a2cd58ea..c8a19bb7d 100644 --- a/test/PayPro.js +++ b/test/PayPro.js @@ -83,8 +83,6 @@ describe('PayPro (in Wallet) model', function() { c.network.getHexNonces = sinon.stub(); c.network.send = sinon.stub(); - Wallet._newRateService = sinon.stub().returns(null); - return new Wallet(c); } diff --git a/test/Wallet.js b/test/Wallet.js index 4412cae69..0a4f25890 100644 --- a/test/Wallet.js +++ b/test/Wallet.js @@ -120,8 +120,6 @@ describe('Wallet model', function() { c.networkName = walletConfig.networkName; c.version = '0.0.1'; - Wallet._newRateService = sinon.stub().returns(null); - return new Wallet(c); }