From 19b3d9bb1560dbd15ac0b133c2436408d3c5fa33 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 27 Jan 2017 17:54:41 -0300 Subject: [PATCH] refactor bitpay card --- src/js/controllers/bitpayCard.js | 29 ++- src/js/controllers/bitpayCardIntro.js | 30 ++- src/js/controllers/preferencesBitpayCard.js | 13 +- src/js/controllers/tab-home.js | 20 +- src/js/controllers/tab-settings.js | 2 +- src/js/services/bitpayCardService.js | 167 +++++++-------- src/js/services/bitpayService.js | 7 +- src/js/services/fileStorage.js | 2 +- src/js/services/localStorage.js | 16 +- src/js/services/openURL.js | 1 + src/js/services/storageService.js | 220 +++++++++----------- 11 files changed, 244 insertions(+), 263 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index f50218d9f..4654a2e18 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -10,7 +10,11 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.network = bitpayService.getEnvironment().network; var updateHistoryFromCache = function(cb) { - bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { + // TODO no cache for now + $log.warn ('TODO: cache'); + return cb(); + + bitpayCardService.getHistory($scope.cardId, function(err, data) { if (err ||  lodash.isEmpty(data)) return cb(); $scope.historyCached = true; self.bitpayCardTransactionHistory = data.transactions; @@ -86,15 +90,18 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi self.bitpayCardCurrentBalance = history.currentCardBalance; if ($scope.dateRange.value == 'last30Days') { - $log.debug('BitPay Card: store cache history'); - var cacheHistory = { - balance: history.currentCardBalance, - transactions: history.txs - }; - bitpayCardService.setBitpayDebitCardsHistory($scope.cardId, cacheHistory, {}, function(err) { - if (err) $log.error(err); - $scope.historyCached = true; - }); + + // TODO CACHE + // + // $log.debug('BitPay Card: store cache history'); + // var cacheHistory = { + // balance: history.currentCardBalance, + // transactions: history.txs + // }; + // bitpayCardService.setHistory($scope.cardId, cacheHistory, {}, function(err) { + // if (err) $log.error(err); + // $scope.historyCached = true; + // }); } $timeout(function() { $scope.$apply(); @@ -147,7 +154,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi updateHistoryFromCache(function() { self.update(); }); - bitpayCardService.getBitpayDebitCards(function(err, cards) { + bitpayCardService.getCards(function(err, cards) { if (err) return; $scope.card = lodash.find(cards, function(card) { return card.eid == $scope.cardId; diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index d829b918f..9fea27978 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService, appIdentityService, bitpayService) { +angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService, appIdentityService, bitpayService, lodash) { $scope.$on("$ionicView.beforeEnter", function(event, data) { if (data.stateParams && data.stateParams.secret) { @@ -18,27 +18,23 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f return; } if (paired) { - bitpayCardService.fetchBitpayDebitCards(apiContext, function(err, data) { - + bitpayCardService.sync(apiContext, function(err, cards) { if (err) { - popupService.showAlert(gettextCatalog.getString('Error fetching Debit Cards'), err); + popupService.showAlert(gettextCatalog.getString('Error updating Debit Cards'), err); return; } // Set flag for nextStep storageService.setNextStep('BitpayCard', 'true', function(err) {}); - // Save data - bitpayCardService.setBitpayDebitCards(data, function(err) { - if (err) return; - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - $state.go('tabs.home').then(function() { - if (data.cards[0]) { - $state.transitionTo('tabs.bitpayCard', { - id: data.cards[0].id - }); - } - }); + + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.go('tabs.home').then(function() { + if (cards[0]) { + $state.transitionTo('tabs.bitpayCard', { + id: cards[0].id + }); + } }); }); } diff --git a/src/js/controllers/preferencesBitpayCard.js b/src/js/controllers/preferencesBitpayCard.js index 6b43b62b6..8ac6ba2d7 100644 --- a/src/js/controllers/preferencesBitpayCard.js +++ b/src/js/controllers/preferencesBitpayCard.js @@ -1,19 +1,21 @@ 'use strict'; angular.module('copayApp.controllers').controller('preferencesBitpayCardController', - function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService, gettextCatalog) { + function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService, gettextCatalog, $log) { $scope.remove = function(card) { var msg = gettextCatalog.getString('Are you sure you would like to remove your BitPay Card ({{lastFourDigits}}) from this device?', { lastFourDigits: card.lastFourDigits }); popupService.showConfirm(null, msg, null, null, function(res) { - if (res) remove(card); + $log.info('Removing bitpay card:' + card.eid) + if (res) + remove(card.eid); }); }; - var remove = function(card) { - bitpayCardService.remove(card, function(err) { + var remove = function(cardEid) { + bitpayCardService.remove(cardEid, function(err) { if (err) { return popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not remove card')); } @@ -25,8 +27,9 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll }; $scope.$on("$ionicView.beforeEnter", function(event, data) { - bitpayCardService.getBitpayDebitCards(function(err, data) { + bitpayCardService.getCards(function(err, data) { if (err) return; + $scope.bitpayCards = data; }); }); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 4ccd7685c..2564baea4 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -285,7 +285,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', }; var bitpayCardCache = function() { - bitpayCardService.getBitpayDebitCards(function(err, data) { + bitpayCardService.getCards(function(err, data) { if (err) return; if (lodash.isEmpty(data)) { $scope.bitpayCards = null; @@ -296,14 +296,16 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.$digest(); }, 100); }); - bitpayCardService.getBitpayDebitCardsHistory(null, function(err, data) { - if (err) return; - if (lodash.isEmpty(data)) { - $scope.cardsHistory = null; - return; - } - $scope.cardsHistory = data; - }); + + // TODO + // bitpayCardService.getCardsHistoryCache(function(err, data) { + // if (err) return; + // if (lodash.isEmpty(data)) { + // $scope.cardsHistory = null; + // return; + // } + // $scope.cardsHistory = data; + // }); }; $scope.onRefresh = function() { diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 4a3624c2f..7f34d7347 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -29,7 +29,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct $scope.coinbaseEnabled = config.coinbaseV2 && !isWindowsPhoneApp; if ($scope.bitpayCardEnabled) { - bitpayCardService.getBitpayDebitCards(function(err, cards) { + bitpayCardService.getCards(function(err, cards) { if (err) $log.error(err); $scope.bitpayCards = cards && cards.length > 0; }); diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index d26b35c9b..bf3bb0440 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -10,7 +10,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }; var _processTransactions = function(invoices, history) { - invoices = invoices || []; + invoices = invoices ||  []; for (var i = 0; i < invoices.length; i++) { var matched = false; for (var j = 0; j < history.length; j++) { @@ -22,8 +22,8 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, if (!matched && isInvoiceLessThanOneDayOld) { var isInvoiceUnderpaid = invoices[i].exceptionStatus === 'paidPartial'; - if(['paid', 'confirmed', 'complete'].indexOf(invoices[i].status) >= 0 - || (invoices[i].status === 'invalid' || isInvoiceUnderpaid)) { + if (['paid', 'confirmed', 'complete'].indexOf(invoices[i].status) >= 0 || + (invoices[i].status === 'invalid' || isInvoiceUnderpaid)) { history.unshift({ timestamp: new Date(invoices[i].invoiceTime), @@ -39,7 +39,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, return history; }; - root.fetchBitpayDebitCards = function(apiContext, cb) { + root.sync = function(apiContext, cb) { var json = { method: 'getDebitCards' }; @@ -47,65 +47,111 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, bitpayService.post('/api/v2/' + apiContext.token, json, function(data) { if (data && data.data.error) return cb(data.data.error); $log.info('BitPay Get Debit Cards: SUCCESS'); - return cb(data.data.error, {token: apiContext.token, cards: data.data.data, email: apiContext.pairData.email}); + + var cards = []; + + lodash.each(data.data.data, function(x) { + var n = {}; + + if (!x.eid || !x.id || !x.lastFourDigits || !x.token) { + $log.warn('BAD data from Bitpay card' + JSON.stringify(x)); + return; + } + + n.eid = x.eid; + n.id = x.id; + n.lastFourDigits = x.lastFourDigits; + n.token = x.token; + cards.push(n); + }); + + storageService.setBitpayDebitCards(bitpayService.getEnvironment().network, apiContext.pairData.email, cards, function(err) { + return cb(err, cards); + }); }, function(data) { return cb(_setError('BitPay Card Error: Get Debit Cards', data)); }); }; - root.getHistory = function(cardId, params, cb) { + // opts: range + root.getHistory = function(cardId, opts, cb) { var invoices, transactions; - params = params || {}; + opts = opts || {}; + var json = { method: 'getInvoiceHistory', - params: JSON.stringify(params) + params: JSON.stringify(opts) }; + appIdentityService.getIdentity(bitpayService.getEnvironment().network, function(err, appIdentity) { if (err) return cb(err); - root.getBitpayDebitCards(function(err, data) { + + root.getCards(function(err, data) { if (err) return cb(err); - var card = lodash.find(data, {id : cardId}); - if (!card) return cb(_setError('Card not found')); + var card = lodash.find(data, { + id: cardId + }); + + if (!card) + return cb(_setError('Card not found')); + // Get invoices bitpayService.post('/api/v2/' + card.token, json, function(data) { $log.info('BitPay Get Invoices: SUCCESS'); invoices = data.data.data || []; - if (lodash.isEmpty(invoices)) $log.info('No invoices'); + + if (lodash.isEmpty(invoices)) + $log.info('No invoices'); + json = { method: 'getTransactionHistory', - params: JSON.stringify(params) + params: JSON.stringify(opts) }; // Get transactions list bitpayService.post('/api/v2/' + card.token, json, function(data) { $log.info('BitPay Get Transactions: SUCCESS'); transactions = data.data.data || {}; transactions['txs'] = _processTransactions(invoices, transactions.transactionList); + + // TODO CACHE? + // update cache? + // if (lodash.isEmpty(opts)) { + // root.setHistoryCache(cardId, transactions, function() {}); + // } + return cb(data.data.error, transactions); }, function(data) { return cb(_setError('BitPay Card Error: Get Transactions', data)); }); }, function(data) { - return cb(_setError('BitPay Card Error: Get Invoices', data)); + return cb(_setError('BitPay Card Error: Get Invoices', data)); }); }); }); }; - root.topUp = function(cardId, params, cb) { - params = params || {}; + root.topUp = function(cardId, opts, cb) { + opts = opts || {}; var json = { method: 'generateTopUpInvoice', - params: JSON.stringify(params) + params: JSON.stringify(opts) }; appIdentityService.getIdentity(bitpayService.getEnvironment().network, function(err, appIdentity) { if (err) return cb(err); - root.getBitpayDebitCards(function(err, data) { + + root.getCards(function(err, data) { if (err) return cb(err); - var card = lodash.find(data, {id : cardId}); - if (!card) return cb(_setError('Card not found')); + + var card = lodash.find(data, { + id: cardId + }); + + if (!card) + return cb(_setError('Card not found')); + bitpayService.post('/api/v2/' + card.token, json, function(data) { $log.info('BitPay TopUp: SUCCESS'); - if(data.data.error) { + if (data.data.error) { return cb(data.data.error); } else { return cb(null, data.data.data.invoice); @@ -126,75 +172,32 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }); }; - root.getBitpayDebitCards = function(cb) { - storageService.getBitpayDebitCards(bitpayService.getEnvironment().network, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - return cb(null, data); - }); + // get all cards, for all accounts. + root.getCards = function(cb) { + storageService.getBitpayDebitCards(bitpayService.getEnvironment().network, cb); }; - root.setBitpayDebitCards = function(data, cb) { - data = JSON.stringify(data); - storageService.setBitpayDebitCards(bitpayService.getEnvironment().network, data, function(err) { - if (err) return cb(err); - return cb(); - }); - }; - - root.getBitpayDebitCardsHistory = function(cardId, cb) { - storageService.getBitpayDebitCardsHistory(bitpayService.getEnvironment().network, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - if (cardId) data = data[cardId]; - return cb(null, data); - }); - }; - - root.setBitpayDebitCardsHistory = function(cardId, data, opts, cb) { - storageService.getBitpayDebitCardsHistory(bitpayService.getEnvironment().network, function(err, oldData) { - if (lodash.isString(oldData)) { - oldData = JSON.parse(oldData); - } - if (lodash.isString(data)) { - data = JSON.parse(data); - } - var inv = oldData || {}; - inv[cardId] = data; - if (opts && opts.remove) { - delete(inv[cardId]); - } - inv = JSON.stringify(inv); - - storageService.setBitpayDebitCardsHistory(bitpayService.getEnvironment().network, inv, function(err) { - return cb(err); - }); - }); - }; - - root.remove = function(card, cb) { - storageService.removeBitpayDebitCard(bitpayService.getEnvironment().network, card, function(err) { + // TODO?? + // root.getHistoryCache = function(cardId, cb) { + // storageService.getBitpayDebitCardHistory(cardId, cb); + // }; + // + // root.setHistoryCache = function(cardId, data, cb) { + // storageService.setBitpayDebitCardHistory(cardId, data, cb); + // }; + // + + root.remove = function(cardId, cb) { + storageService.removeBitpayDebitCard(bitpayService.getEnvironment().network, cardId, function(err) { if (err) { $log.error('Error removing BitPay debit card: ' + err); - // Continue, try to remove/cleanup card history + return cb(err); } - storageService.removeBitpayDebitCardHistory(bitpayService.getEnvironment().network, card, function(err) { - if (err) { - $log.error('Error removing BitPay debit card transaction history: ' + err); - return cb(err); - } - $log.info('Successfully removed BitPay debit card'); - return cb(); - }); + storageService.removeBitpayDebitCardHistory(cardId, cb); }); }; + root.getRates = function(currency, cb) { bitpayService.get('/rates/' + currency, function(data) { $log.info('BitPay Get Rates: SUCCESS'); diff --git a/src/js/services/bitpayService.js b/src/js/services/bitpayService.js index 6cf7f1eab..743d58922 100644 --- a/src/js/services/bitpayService.js +++ b/src/js/services/bitpayService.js @@ -136,13 +136,10 @@ angular.module('copayApp.services').factory('bitpayService', function($log, $htt }; var setBitpayAccount = function(accountData, cb) { - var data = JSON.stringify(accountData); - storageService.setBitpayAccount(root.getEnvironment().network, data, function(err) { - if (err) return cb(err); - return cb(); - }); + storageService.setBitpayAccount(root.getEnvironment().network, accountData, cb); }; + var _get = function(endpoint) { return { method: 'GET', diff --git a/src/js/services/fileStorage.js b/src/js/services/fileStorage.js index b93bde832..643effe83 100644 --- a/src/js/services/fileStorage.js +++ b/src/js/services/fileStorage.js @@ -93,7 +93,7 @@ angular.module('copayApp.services') if (lodash.isObject(v)) v = JSON.stringify(v); - if (!lodash.isString(v)) { + if (v && !lodash.isString(v)) { v = v.toString(); } diff --git a/src/js/services/localStorage.js b/src/js/services/localStorage.js index e6327e300..c772b7eef 100644 --- a/src/js/services/localStorage.js +++ b/src/js/services/localStorage.js @@ -43,16 +43,17 @@ angular.module('copayApp.services') }; root.set = function(k, v, cb) { + + if (lodash.isObject(v)) { + v = JSON.stringify(v); + } + if (v && !lodash.isString(v)) { + v = v.toString(); + } + if (isChromeApp || isNW) { var obj = {}; - if (lodash.isObject(v)) { - v = JSON.stringify(v); - } - if (!lodash.isString(v)) { - v = v.toString(); - } - obj[k] = v; chrome.storage.local.set(obj, cb); @@ -60,7 +61,6 @@ angular.module('copayApp.services') ls.setItem(k, v); return cb(); } - }; root.remove = function(k, cb) { diff --git a/src/js/services/openURL.js b/src/js/services/openURL.js index adc4c6f72..ff01dc78c 100644 --- a/src/js/services/openURL.js +++ b/src/js/services/openURL.js @@ -84,6 +84,7 @@ angular.module('copayApp.services').factory('openURLService', function($rootScop $log.debug('Registering Browser handlers base:' + base); navigator.registerProtocolHandler('bitcoin', url, 'Copay Bitcoin Handler'); navigator.registerProtocolHandler('web+copay', url, 'Copay Wallet Handler'); + navigator.registerProtocolHandler('web+bitpay', url, 'Bitpay Wallet Handler'); } } }; diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index e999b058d..8823ca472 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -24,6 +24,9 @@ angular.module('copayApp.services') }, cb); }; + // This is only used in Copay, we used to encrypt profile + // using device's UUID. + var decryptOnMobile = function(text, cb) { var json; try { @@ -74,7 +77,6 @@ angular.module('copayApp.services') }); }; - // This is only use in Copay, for very old instalations // in which we use to use localStorage instead of fileStorage root.tryToMigrate = function(cb) { @@ -342,51 +344,35 @@ angular.module('copayApp.services') storage.remove('coinbaseTxs-' + network, cb); }; - root.setBitpayDebitCardsHistory = function(network, data, cb) { - storage.set('bitpayDebitCardsHistory-' + network, data, cb); + root.setBitpayDebitCardHistory = function(cardId, data, cb) { + storage.set('bitpayDebitCardHistory-' + cardId, data, cb); }; - root.getBitpayDebitCardsHistory = function(network, cb) { - storage.get('bitpayDebitCardsHistory-' + network, cb); + root.getBitpayDebitCardHistory = function(cardId, cb) { + storage.get('bitpayDebitCardHistory-' + cardId, cb); }; - root.removeBitpayDebitCardHistory = function(network, card, cb) { - root.getBitpayDebitCardsHistory(network, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - delete data[card.eid]; - root.setBitpayDebitCardsHistory(network, JSON.stringify(data), cb); - }); + root.removeBitpayDebitCardHistory = function(cardId, cb) { + storage.remove('bitpayDebitCardHistory-' + cardId, cb); }; - // data: { // cards: [ // eid: card id // id: card id // lastFourDigits: card number // token: card token // ] - // email: account email - // token: account token - // } - root.setBitpayDebitCards = function(network, data, cb) { - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - if (lodash.isEmpty(data) || !data.email) return cb('Cannot set cards: no account to set'); - storage.get('bitpayAccounts-v2-' + network, function(err, bitpayAccounts) { + root.setBitpayDebitCards = function(network, email, cards, cb) { + + root.getBitpayAccounts(network, function(err, allAccounts) { if (err) return cb(err); - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); + + if (!allAccounts[email]) { + return cb('Cannot set cards for unknown account ' + email); } - bitpayAccounts = bitpayAccounts || {}; - bitpayAccounts[data.email] = bitpayAccounts[data.email] || {}; - bitpayAccounts[data.email]['bitpayDebitCards-' + network] = data.cards; - storage.set('bitpayAccounts-v2-' + network, JSON.stringify(bitpayAccounts), cb); + + allAccounts[email].cards = cards; + storage.set('bitpayAccounts-v2-' + network, allAccounts, cb); }); }; @@ -399,24 +385,24 @@ angular.module('copayApp.services') // email: account email // ] root.getBitpayDebitCards = function(network, cb) { - storage.get('bitpayAccounts-v2-' + network, function(err, bitpayAccounts) { - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); - } - bitpayAccounts = bitpayAccounts || {}; - var cards = []; - _asyncEach(Object.keys(bitpayAccounts), function(email, callback) { - // For the UI, add the account email to the card object. - var acctCards = bitpayAccounts[email]['bitpayDebitCards-' + network] || []; - for (var i = 0; i < acctCards.length; i++) { - acctCards[i].email = email; - } - cards = cards.concat(acctCards); - callback(); - }, function() { - // done - cb(err, cards); + + root.getBitpayAccounts(network, function(err, allAccounts) { + if (err) return cb(err); + + var allCards = []; + + lodash.each(allAccounts, function(account) { + + var cards = lodash.clone(account.cards); + + lodash.each(allAccounts, function(x) { + x.email = account.email; + }); + + allCards = allCards.concat(cards); }); + + return cb(null, allCards); }); }; @@ -426,95 +412,84 @@ angular.module('copayApp.services') // lastFourDigits: card number // token: card token // } - root.removeBitpayDebitCard = function(network, card, cb) { - if (lodash.isString(card)) { - card = JSON.parse(card); - } - card = card || {}; - if (lodash.isEmpty(card) || !card.eid) return cb('No card to remove'); - storage.get('bitpayAccounts-v2-' + network, function(err, bitpayAccounts) { - if (err) cb(err); - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); - } - bitpayAccounts = bitpayAccounts || {}; - _asyncEach(Object.keys(bitpayAccounts), function(email, callback) { - var data = bitpayAccounts[email]['bitpayDebitCards-' + network]; - var newCards = lodash.reject(data, { - 'eid': card.eid - }); - data = {}; - data.cards = newCards; - data.email = email; - root.setBitpayDebitCards(network, data, function(err) { - if (err) cb(err); - // If there are no more cards in storage then re-enable the next step entry. - root.getBitpayDebitCards(network, function(err, cards) { - if (err) cb(err); - if (cards.length == 0) { - root.removeNextStep('BitpayCard', callback()); - } else { - callback() - } - }); - }); - }, function() { - // done - cb(); - }); - }); - }; + root.removeBitpayDebitCard = function(network, cardEid, cb) { - // data: { - // email: account email - // token: account token - // } - root.setBitpayAccount = function(network, data, cb) { - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - if (lodash.isEmpty(data) || !data.email) return cb('No account to set'); - storage.get('bitpayAccounts-v2-' + network, function(err, bitpayAccounts) { - if (err) return cb(err); - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); - } - bitpayAccounts = bitpayAccounts || {}; - bitpayAccounts[data.email] = bitpayAccounts[data.email] || {}; - bitpayAccounts[data.email]['bitpayApi-' + network] = bitpayAccounts[data.email]['bitpayApi-' + network] || {}; - bitpayAccounts[data.email]['bitpayApi-' + network].token = data.token; - storage.set('bitpayAccounts-v2-' + network, JSON.stringify(bitpayAccounts), cb); + root.getBitpayAccounts(network, function(err, allAccounts){ + + lodash.each(allAccounts, function(account){ + account.cards = lodash.reject(account.cards, { + 'eid': cardEid + }); + }); + + storage.set('bitpayAccounts-v2-' + network, allAccounts, cb); }); }; // cb(err, accounts) // accounts: { // email_1: { - // bitpayApi-: { - // token: account token - // } - // bitpayDebitCards-: { + // token: account token + // cards: { // // } // } // ... // email_n: { - // bitpayApi-: { - // token: account token - // } - // bitpayDebitCards-: { + // token: account token + // cards: { // // } // } // } + // root.getBitpayAccounts = function(network, cb) { - storage.get('bitpayAccounts-v2-' + network, function(err, bitpayAccounts) { + storage.get('bitpayAccounts-v2-' + network, function(err, allAccountsStr) { if (err) return cb(err); - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); - } - cb(err, bitpayAccounts); + + var allAccounts = {}; + try { + allAccounts = JSON.parse(allAccountsStr); + } catch (e) {}; + + lodash.each(allAccounts, function(account, email) { + + // Migrate old `'bitpayApi-' + network` key, if exists + if (!account.token && account['bitpayApi-' + network].token) { + $log.info('Migrating all bitpayApi-network branch'); + account = account['bitpayApi-' + network]; + delete account['bitpayApi-' + network]; + } + }); + + return cb(err, allAccounts); + }); + }; + + + // data: { + // email: account email + // token: account token + // } + root.setBitpayAccount = function(network, data, cb) { + + if (!lodash.isObject(data) || !data.email || !data.token) + return cb('No account to set'); + + var email = data.email; + var token = data.token; + + + root.getBitpayAccounts(network, function(err, allAccounts) { + if (err) return cb(err); + + var account = allAccounts[email] || {}; + account.token = token; + + allAccounts[email] = account; + + $log.info('Storing BitPay accounts with new account:' + email); + storage.set('bitpayAccounts-v2-' + network, allAccounts, cb); }); }; @@ -525,10 +500,7 @@ angular.module('copayApp.services') root.getAppIdentity = function(network, cb) { storage.get('appIdentity-' + network, function(err, data) { if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - cb(err, data); + cb(err, JSON.parse(data || '{}')); }); };