From 5b1cbe0ab964cfcfd7c7f34306425bb955e606f0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 27 Jan 2017 10:51:51 -0300 Subject: [PATCH 01/18] rm upgraders --- src/js/routes.js | 64 +++---- src/js/services/storageService.js | 307 +----------------------------- 2 files changed, 29 insertions(+), 342 deletions(-) diff --git a/src/js/routes.js b/src/js/routes.js index cc8037381..315a26415 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -1153,50 +1153,40 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }); } - $log.info('Verifying storage...'); - storageService.verify(function(err) { + $log.info('Init profile...'); + // Try to open local profile + profileService.loadAndBindProfile(function(err) { + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); if (err) { - $log.error('Storage failed to verify: ' + err); - // TODO - what next? - } else { - $log.info('Storage OK'); - } - - $log.info('Init profile...'); - // Try to open local profile - profileService.loadAndBindProfile(function(err) { - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - if (err) { - if (err.message && err.message.match('NOPROFILE')) { - $log.debug('No profile... redirecting'); + if (err.message && err.message.match('NOPROFILE')) { + $log.debug('No profile... redirecting'); + $state.go('onboarding.welcome'); + } else if (err.message && err.message.match('NONAGREEDDISCLAIMER')) { + if (lodash.isEmpty(profileService.getWallets())) { + $log.debug('No wallets and no disclaimer... redirecting'); $state.go('onboarding.welcome'); - } else if (err.message && err.message.match('NONAGREEDDISCLAIMER')) { - if (lodash.isEmpty(profileService.getWallets())) { - $log.debug('No wallets and no disclaimer... redirecting'); - $state.go('onboarding.welcome'); - } else { - $log.debug('Display disclaimer... redirecting'); - $state.go('onboarding.disclaimer', { - resume: true - }); - } } else { - throw new Error(err); // TODO + $log.debug('Display disclaimer... redirecting'); + $state.go('onboarding.disclaimer', { + resume: true + }); } } else { - profileService.storeProfileIfDirty(); - $log.debug('Profile loaded ... Starting UX.'); - scannerService.gentleInitialize(); - $state.go('tabs.home'); + throw new Error(err); // TODO } + } else { + profileService.storeProfileIfDirty(); + $log.debug('Profile loaded ... Starting UX.'); + scannerService.gentleInitialize(); + $state.go('tabs.home'); + } - // After everything have been loaded, initialize handler URL - $timeout(function() { - openURLService.init(); - }, 1000); - }); + // After everything have been loaded, initialize handler URL + $timeout(function() { + openURLService.init(); + }, 1000); }); }); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 526c65a87..e999b058d 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -74,312 +74,9 @@ angular.module('copayApp.services') }); }; - //////////////////////////////////////////////////////////////////////////// - // - // UPGRADING STORAGE - // - // Upgraders are executed in numerical order per the '##_' object key prefix. Each upgrader will run. - // Each upgrader should detect storage configuraton and fail-safe; no upgrader should damage the ability - // of another to function properly (in order). Each upgrader should upgrade storage incrementally; storage - // upgrade is not complete until all upgraders have run. - // - // 1. Write a function to upgrade the desired storage key(s). The function should have the protocol: - // - // _upgrade_x(key, network, cb), where: - // - // `x` is the name of the storage key - // `key` is the name of the storage key being upgraded - // `network` is one of 'livenet', 'testnet' - // - // 2. Add the storage key to `_upgraders` object using the name of the key as the `_upgrader` object key - // with the value being the name of the upgrade function (e.g., _upgrade_x). In order to avoid conflicts - // when a storage key is involved in multiple upgraders as well as predicte the order in which upgrades - // occur the `_upgrader` object key should be prefixed with '##_' (e.g., '01_') to create a unique and - // sortable name. This format is interpreted by the _upgrade() function. - // - // 3. Any dependency functions called by upgraders should be copied/factored out and remain unchanged as - // long as the upgrader remains in effect. By convention the dependency function is prefixed by '##_' to - // match the upgrader key. - // - var _upgraders = { - '00_bitpayDebitCards' : _upgrade_bitpayDebitCards, // 2016-11: Upgrade bitpayDebitCards-x to bitpayAccounts-x - '01_bitpayCardCredentials' : _upgrade_bitpayCardCredentials, // 2016-11: Upgrade bitpayCardCredentials-x to appIdentity-x - '02_bitpayAccounts' : _upgrade_bitpayAccounts, // 2016-12: Upgrade bitpayAccounts-x to bitpayAccounts-v2-x - '03_bitpayAccounts-v2' : _validate_bitpayAccounts_v2 // 2017-01: Validate keys on bitpayAccounts-v2-x, remove if not valid - }; - - function _upgrade_bitpayDebitCards(key, network, cb) { - key += '-' + network; - storage.get(key, function(err, data) { - if (err) return cb(err); - if (data != null) { - // Needs upgrade - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - _00_setBitpayDebitCards(network, data, function(err) { - if (err) return cb(err); - storage.remove(key, function() { - cb(null, 'replaced with \'bitpayAccounts\''); - }); - }); - } else { - cb(); - } - }); - }; - - function _upgrade_bitpayCardCredentials(key, network, cb) { - key += '-' + network; - storage.get(key, function(err, data) { - if (err) return cb(err); - if (data != null) { - // Needs upgrade - _01_setAppIdentity(network, data, function(err) { - if (err) return cb(err); - storage.remove(key, function() { - cb(null, 'replaced with \'appIdentity\''); - }); - }); - } else { - cb(); - } - }); - }; - - function _upgrade_bitpayAccounts(key, network, cb) { - key += '-' + network; - storage.get(key, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - var upgraded = ''; - _asyncEach(Object.keys(data), function(key, callback) { - // Keys are account emails - if (!data[key]['bitpayApi-' + network]) { - // Needs upgrade - upgraded += ' ' + key; - var acctData = { - acct: data[key], - token: data[key]['bitpayDebitCards-' + network].token, - email: key - }; - _02_setBitpayAccount(network, acctData, function(err) { - if (err) return cb(err); - - _02_setBitpayDebitCards(network, data[key]['bitpayDebitCards-' + network], function(err) { - if (err) return cb(err); - callback(); - }); - }); - } - callback(); - }, function() { - // done - // Remove obsolete key. - storage.remove('bitpayAccounts-' + network, function() { - if (upgraded.length > 0) { - cb(null, 'upgraded to \'bitpayAccounts-v2-' + network + '\':' + upgraded); - } else { - cb(); - } - }); - }); - }); - }; - - function _validate_bitpayAccounts_v2(key, network, cb) { - key += '-' + network; - storage.get(key, function(err, data) { - if (err) return cb(err); - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - var verified = ''; - var toRemove = []; - _asyncEach(Object.keys(data), function(key, callback) { - // Verify account API data - if (!data[key]['bitpayApi-' + network] || - !data[key]['bitpayApi-' + network].token) { - // Invalid entry - one or more keys are missing - toRemove.push(key); - return callback(); - } - // Verify debit cards - if (Array.isArray(data[key]['bitpayDebitCards-' + network])) { - for (var i = 0; i < data[key]['bitpayDebitCards-' + network].length; i++) { - if (!data[key]['bitpayDebitCards-' + network][i].token || - !data[key]['bitpayDebitCards-' + network][i].eid || - !data[key]['bitpayDebitCards-' + network][i].id || - !data[key]['bitpayDebitCards-' + network][i].lastFourDigits) { - // Invalid entry - one or more keys are missing - toRemove.push(key); - return callback(); - } - } - } - verified += ' ' + key; - return callback(); - }, function() { - // done, remove invalid account entrys - if (toRemove.length > 0) { - var removed = ''; - for (var i = 0; i < toRemove.length; i++) { - removed += ' ' + toRemove[i]; - delete data[toRemove[i]]; - } - storage.set('bitpayAccounts-v2-' + network, JSON.stringify(data), function(err) { - if (err) return cb(err); - // Ensure next step for cards is visible - storage.get('bitpayAccounts-v2-' + network, function(err, data) { - if (err) return cb(err); - if (lodash.isEmpty(data)) { - root.removeNextStep('BitpayCard', function(err) {}); - } - }); - cb(null, 'removed invalid account records, please re-pair cards for these accounts:' + removed + '; ' + - 'the following accounts validated OK: ' + (verified.length > 0 ? verified : 'none')); - }); - } else { - cb(null, (verified.length > 0 ? 'accounts OK: ' + verified : 'no accounts found')); - } - }); - }); - }; - // - //////////////////////////////////////////////////////////////////////////// - // - // UPGRADER DEPENDENCIES - // These functions remain as long as the upgrader remains in effect. - // - var _00_setBitpayDebitCards = function(network, data, cb) { - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - if (lodash.isEmpty(data) || !data.email) return cb('No card(s) to set'); - storage.get('bitpayAccounts-' + 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]['bitpayDebitCards-' + network] = data; - storage.set('bitpayAccounts-' + network, JSON.stringify(bitpayAccounts), cb); - }); - }; - - var _01_setAppIdentity = function(network, data, cb) { - storage.set('appIdentity-' + network, data, cb); - }; - - var _02_setBitpayAccount = function(network, data, cb) { - if (lodash.isString(data)) { - data = JSON.parse(data); - } - data = data || {}; - if (lodash.isEmpty(data) || !data.email || !data.acct) 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] = data.acct; - bitpayAccounts[data.email]['bitpayApi-' + network] = {}; - bitpayAccounts[data.email]['bitpayApi-' + network].token = data.token; - storage.set('bitpayAccounts-v2-' + network, JSON.stringify(bitpayAccounts), cb); - }); - }; - - var _02_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) { - if (err) return cb(err); - if (lodash.isString(bitpayAccounts)) { - bitpayAccounts = JSON.parse(bitpayAccounts); - } - bitpayAccounts = bitpayAccounts || {}; - bitpayAccounts[data.email] = bitpayAccounts[data.email] || {}; - bitpayAccounts[data.email]['bitpayDebitCards-' + network] = data.cards; - storage.set('bitpayAccounts-v2-' + network, JSON.stringify(bitpayAccounts), cb); - }); - }; - // - //////////////////////////////////////////////////////////////////////////// - - // IMPORTANT: This function is designed to block execution until it completes. - // Ideally storage should not be used until it has been verified. - root.verify = function(cb) { - _upgrade(function(err) { - cb(err); - }); - }; - - function _handleUpgradeError(key, err) { - $log.error('Failed to upgrade storage for \'' + key + '\': ' + err); - }; - - function _handleUpgradeSuccess(key, msg) { - $log.info('Storage upgraded for \'' + key + '\': ' + msg); - }; - - // IMPORTANT: This function is designed to block execution until it completes. - // Ideally storage should not be used until it has been verified. - function _upgrade(cb) { - var errorCount = 0; - var errorMessage = undefined; - var keys = Object.keys(_upgraders).sort(); - var networks = ['livenet', 'testnet']; - _asyncEach(keys, function(key, callback_keys) { - _asyncEach(networks, function(network, callback_networks) { - var storagekey = key.split('_')[1]; - _upgraders[key](storagekey, network, function(err, msg) { - if (err) { - _handleUpgradeError(storagekey + '-' + network, err); - errorCount++; - errorMessage = errorCount + ' storage upgrade failures'; - } - if (msg) _handleUpgradeSuccess(storagekey + '-' + network, msg); - callback_networks(); - }); - }, function() { - // done - networks - callback_keys(); - }); - }, function() { - //done - keys - cb(errorMessage); - }); - }; - - function _asyncEach(iterableList, callback, done) { - var i = -1; - var length = iterableList.length; - - function loop() { - i++; - if (i === length) { - done(); - return; - } else if (i < length) { - callback(iterableList[i], loop); - } else { - return; - } - } - loop(); - }; + // This is only use in Copay, for very old instalations + // in which we use to use localStorage instead of fileStorage root.tryToMigrate = function(cb) { if (!shouldUseFileStorage) return cb(); From 19b3d9bb1560dbd15ac0b133c2436408d3c5fa33 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 27 Jan 2017 17:54:41 -0300 Subject: [PATCH 02/18] 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 || '{}')); }); }; From d85da2cc45c343b4d51943675ec9660dbd03c4cd Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 30 Jan 2017 18:04:17 -0300 Subject: [PATCH 03/18] buyAndSell services + nextSteps --- .../controllers/buyAndSellCardController.js | 14 ++ src/js/controllers/buyandsellController.js | 11 +- src/js/controllers/coinbase.js | 1 - src/js/controllers/nextStepsController.js | 16 ++ src/js/controllers/tab-home.js | 65 ++----- src/js/routes.js | 2 +- src/js/services/amazonService.js | 17 +- src/js/services/buyAndSellService.js | 60 ++++++ src/js/services/coinbaseService.js | 172 +++++++++++------- src/js/services/glideraService.js | 35 ++-- src/js/services/nextStepsService.js | 38 ++++ www/views/buyandsell.html | 12 +- www/views/includes/buyAndSellCard.html | 13 ++ www/views/includes/nextSteps.html | 28 +++ www/views/tab-home.html | 52 +----- 15 files changed, 342 insertions(+), 194 deletions(-) create mode 100644 src/js/controllers/buyAndSellCardController.js create mode 100644 src/js/controllers/nextStepsController.js create mode 100644 src/js/services/buyAndSellService.js create mode 100644 src/js/services/nextStepsService.js create mode 100644 www/views/includes/buyAndSellCard.html create mode 100644 www/views/includes/nextSteps.html diff --git a/src/js/controllers/buyAndSellCardController.js b/src/js/controllers/buyAndSellCardController.js new file mode 100644 index 000000000..1c33c8112 --- /dev/null +++ b/src/js/controllers/buyAndSellCardController.js @@ -0,0 +1,14 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('buyAndSellCardController', function($scope, nextStepsService, $ionicScrollDelegate, buyAndSellService) { + + $scope.services = buyAndSellService.getLinked(); + + $scope.toggle = function() { + $scope.hide = !$scope.hide; + $timeout(function() { + $ionicScrollDelegate.resize(); + $scope.$apply(); + }, 10); + }; +}); diff --git a/src/js/controllers/buyandsellController.js b/src/js/controllers/buyandsellController.js index 93df71069..643ba401a 100644 --- a/src/js/controllers/buyandsellController.js +++ b/src/js/controllers/buyandsellController.js @@ -1,14 +1,11 @@ 'use strict'; -angular.module('copayApp.controllers').controller('buyandsellController', function($scope, $ionicHistory, configService) { +angular.module('copayApp.controllers').controller('buyandsellController', function($scope, $ionicHistory, buyAndSellService, lodash) { $scope.$on("$ionicView.beforeEnter", function(event, data) { - configService.whenAvailable(function(config) { - $scope.isCoinbaseEnabled = config.coinbaseV2; - $scope.isGlideraEnabled = config.glidera.enabled; + $scope.services = buyAndSellService.get(); - if (!$scope.isCoinbaseEnabled && !$scope.isGlideraEnabled) - $ionicHistory.goBack(); - }); + if (lodash.isEmpty($scope.services)) + $ionicHistory.goBack(); }); }); diff --git a/src/js/controllers/coinbase.js b/src/js/controllers/coinbase.js index a038e6546..161b7e380 100644 --- a/src/js/controllers/coinbase.js +++ b/src/js/controllers/coinbase.js @@ -112,7 +112,6 @@ angular.module('copayApp.controllers').controller('coinbaseController', function var self = this; $scope.$on("$ionicView.beforeEnter", function(event, data) { - coinbaseService.setCredentials(); if (data.stateParams && data.stateParams.code) { coinbaseService.getStoredToken(function(at) { if (!at) self.submitOauthCode(data.stateParams.code); diff --git a/src/js/controllers/nextStepsController.js b/src/js/controllers/nextStepsController.js new file mode 100644 index 000000000..b745825ec --- /dev/null +++ b/src/js/controllers/nextStepsController.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('nextStepsController', function($scope, nextStepsService, $ionicScrollDelegate, $timeout) { + + $scope.hide = false; + $scope.services = nextStepsService.get(); + + $scope.toggle = function() { + $scope.hide = !$scope.hide; + $timeout(function() { + $ionicScrollDelegate.resize(); + $scope.$apply(); + }, 10); + }; + +}); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 2564baea4..8653e9252 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('tabHomeController', - function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService, bwcError, coinbaseService) { + function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService) { var wallet; var listeners = []; var notifications = []; @@ -83,10 +83,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', var wallet = profileService.getWallet(walletId); updateWallet(wallet); if ($scope.recentTransactionsEnabled) getNotifications(); - if ($scope.coinbaseEnabled && type == 'NewBlock' && n && n.data && n.data.network == 'livenet') { - // Update Coinbase - coinbaseService.updatePendingTransactions(); - } + }), $rootScope.$on('Local/TxAction', function(e, walletId) { $log.debug('Got action for wallet ' + walletId); @@ -96,31 +93,22 @@ angular.module('copayApp.controllers').controller('tabHomeController', }) ]; + + $scope.nextStepsItems = nextStepsService.get(); + $scope.buyAndSellItems = buyAndSellService.getLinked(); + +console.log('[tab-home.js.99]', $scope.buyAndSellItems); //TODO + configService.whenAvailable(function() { - nextStep(function() { - var config = configService.getSync(); - var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; + var config = configService.getSync(); + $scope.recentTransactionsEnabled = config.recentTransactions.enabled; + if ($scope.recentTransactionsEnabled) getNotifications(); - $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; - $scope.coinbaseEnabled = config.coinbaseV2 && !isWindowsPhoneApp; - $scope.amazonEnabled = config.amazon.enabled; - $scope.bitpayCardEnabled = config.bitpayCard.enabled; - - var buyAndSellEnabled = !$scope.externalServices.BuyAndSell && ($scope.glideraEnabled || $scope.coinbaseEnabled); - var amazonEnabled = !$scope.externalServices.AmazonGiftCards && $scope.amazonEnabled; - var bitpayCardEnabled = !$scope.externalServices.BitpayCard && $scope.bitpayCardEnabled; - - $scope.nextStepEnabled = buyAndSellEnabled || amazonEnabled || bitpayCardEnabled; - $scope.recentTransactionsEnabled = config.recentTransactions.enabled; - - if ($scope.recentTransactionsEnabled) getNotifications(); - - if ($scope.bitpayCardEnabled) bitpayCardCache(); - $timeout(function() { - $ionicScrollDelegate.resize(); - $scope.$apply(); - }, 10); - }); + if ($scope.bitpayCardEnabled) bitpayCardCache(); + $timeout(function() { + $ionicScrollDelegate.resize(); + $scope.$apply(); + }, 10); }); }); @@ -213,7 +201,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', walletService.getStatus(wallet, {}, function(err, status) { if (err) { - wallet.error = (err === 'WALLET_NOT_REGISTERED') ? gettextCatalog.getString('Wallet not registered') : bwcError.msg(err); + wallet.error = (err === 'WALLET_NOT_REGISTERED') ? gettextCatalog.getString('Wallet not registered') : bwcError.msg(err); $log.error(err); } else { @@ -265,25 +253,6 @@ angular.module('copayApp.controllers').controller('tabHomeController', }); }; - var nextStep = function(cb) { - var i = 0; - var services = ['AmazonGiftCards', 'BitpayCard', 'BuyAndSell']; - lodash.each(services, function(service) { - storageService.getNextStep(service, function(err, value) { - $scope.externalServices[service] = value == 'true' ? true : false; - if (++i == services.length) return cb(); - }); - }); - }; - - $scope.shouldHideNextSteps = function() { - $scope.hideNextSteps = !$scope.hideNextSteps; - $timeout(function() { - $ionicScrollDelegate.resize(); - $scope.$apply(); - }, 10); - }; - var bitpayCardCache = function() { bitpayCardService.getCards(function(err, data) { if (err) return; diff --git a/src/js/routes.js b/src/js/routes.js index 315a26415..e3ddbab3f 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -1088,7 +1088,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }); }) - .run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService) { + .run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService) { uxLanguage.init(); diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js index e44166172..ff8b5e707 100644 --- a/src/js/services/amazonService.js +++ b/src/js/services/amazonService.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.services').factory('amazonService', function($http, $log, lodash, moment, storageService, configService, platformInfo) { +angular.module('copayApp.services').factory('amazonService', function($http, $log, lodash, moment, storageService, configService, platformInfo, nextStepsService) { var root = {}; var credentials = {}; @@ -69,8 +69,9 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }); }); + // TODO // Show pending task from the UI - storageService.setNextStep('AmazonGiftCards', 'true', function(err) {}); + // storageService.setNextStep('AmazonGiftCards', 'true', function(err) {}); }; root.getPendingGiftCards = function(cb) { @@ -144,6 +145,16 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }); }; - return root; + var register = function () { + nextStepsService.register({ + name: 'amazon', + title: 'Buy a gift card', + icon: 'icon-amazon', + sref: 'tabs.giftcards.amazon', + }); + }; + register(); + + return root; }); diff --git a/src/js/services/buyAndSellService.js b/src/js/services/buyAndSellService.js new file mode 100644 index 000000000..326241a18 --- /dev/null +++ b/src/js/services/buyAndSellService.js @@ -0,0 +1,60 @@ +'use strict'; + +angular.module('copayApp.services').factory('buyAndSellService', function($log, nextStepsService, lodash, $ionicScrollDelegate, $timeout) { + var root = {}; + var services = []; + var linkedServices = []; + + root.updateNextSteps = function() { + + var newLinked = lodash.filter(services, function(x) { + return x.linked; + }); + + + // This is to preserve linkedServices pointer + while(linkedServices.length) + linkedServices.pop(); + + while(newLinked.length) + linkedServices.push(newLinked.pop()); + // + +console.log('[buyAndSellService.js.10:linkedServices:]',linkedServices); //TODO + + $log.debug('buyAndSell Service, updating nextSteps. linked/total: ' + linkedServices.length + '/'+ services.length); + + if (linkedServices.length == 0) { + nextStepsService.register({ + name: 'Buy and Sell', + icon: 'icon-buy-bitcoin', + sref: 'tabs.buyandsell', + }); + }; + + + $timeout(function() { + $ionicScrollDelegate.resize(); + }, 10); + }; + + var updateNextStepsDebunced = lodash.debounce(root.updateNextSteps, 1000); + + root.register = function(serviceInfo) { + services.push(serviceInfo); + $log.info('Adding Buy and Sell service:' + serviceInfo.name + ' linked:' + serviceInfo.linked); + updateNextStepsDebunced(); + }; + + root.get = function() { + return services; + }; + + + root.getLinked = function() { + return linkedServices; + }; + + + return root; +}); diff --git a/src/js/services/coinbaseService.js b/src/js/services/coinbaseService.js index 9057ae729..54139eafc 100644 --- a/src/js/services/coinbaseService.js +++ b/src/js/services/coinbaseService.js @@ -1,37 +1,32 @@ 'use strict'; -angular.module('copayApp.services').factory('coinbaseService', function($http, $log, $window, $filter, platformInfo, lodash, storageService, configService, appConfigService, txFormatService) { +angular.module('copayApp.services').factory('coinbaseService', function($http, $log, $window, $filter, platformInfo, lodash, storageService, configService, appConfigService, txFormatService, buyAndSellService, $rootScope) { var root = {}; var credentials = {}; var isCordova = platformInfo.isCordova; var isNW = platformInfo.isNW; + var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; + + root.priceSensitivity = [{ + value: 0.5, + name: '0.5%' + }, { + value: 1, + name: '1%' + }, { + value: 2, + name: '2%' + }, { + value: 5, + name: '5%' + }, { + value: 10, + name: '10%' + }]; - root.priceSensitivity = [ - { - value: 0.5, - name: '0.5%' - }, - { - value: 1, - name: '1%' - }, - { - value: 2, - name: '2%' - }, - { - value: 5, - name: '5%' - }, - { - value: 10, - name: '10%' - } - ]; - root.selectedPriceSensitivity = root.priceSensitivity[1]; - root.setCredentials = function() { + var setCredentials = function() { if (!$window.externalServices || !$window.externalServices.coinbase) { return; @@ -46,19 +41,19 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ credentials.NETWORK = 'livenet'; // Coinbase permissions - credentials.SCOPE = '' - + 'wallet:accounts:read,' - + 'wallet:addresses:read,' - + 'wallet:addresses:create,' - + 'wallet:user:read,' - + 'wallet:user:email,' - + 'wallet:buys:read,' - + 'wallet:buys:create,' - + 'wallet:sells:read,' - + 'wallet:sells:create,' - + 'wallet:transactions:read,' - + 'wallet:transactions:send,' - + 'wallet:payment-methods:read'; + credentials.SCOPE = '' + + 'wallet:accounts:read,' + + 'wallet:addresses:read,' + + 'wallet:addresses:create,' + + 'wallet:user:read,' + + 'wallet:user:email,' + + 'wallet:buys:read,' + + 'wallet:buys:create,' + + 'wallet:sells:read,' + + 'wallet:sells:create,' + + 'wallet:transactions:read,' + + 'wallet:transactions:send,' + + 'wallet:payment-methods:read'; // NW has a bug with Window Object if (isCordova) { @@ -72,8 +67,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ credentials.API = coinbase.sandbox.api; credentials.CLIENT_ID = coinbase.sandbox.client_id; credentials.CLIENT_SECRET = coinbase.sandbox.client_secret; - } - else { + } else { credentials.HOST = coinbase.production.host; credentials.API = coinbase.production.api; credentials.CLIENT_ID = coinbase.production.client_id; @@ -107,8 +101,8 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ root.getAvailableCurrency = function() { var config = configService.getSync().wallet.settings; // ONLY "USD" - switch(config.alternativeIsoCode) { - default : return 'USD' + switch (config.alternativeIsoCode) { + default: return 'USD' }; }; @@ -117,7 +111,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ var satToBtc = 1 / 100000000; var unitToSatoshi = config.unitToSatoshi; var amountUnitStr; - + // IF 'USD' if (currency) { amountUnitStr = $filter('formatFiatAmount')(amount) + ' ' + currency; @@ -128,19 +122,19 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ amount = (amountSat * satToBtc).toFixed(8); currency = 'BTC'; } - + return [amount, currency, amountUnitStr]; }; root.getOauthCodeUrl = function() { - return credentials.HOST - + '/oauth/authorize?response_type=code&client_id=' - + credentials.CLIENT_ID - + '&redirect_uri=' - + credentials.REDIRECT_URI - + '&state=SECURE_RANDOM&scope=' - + credentials.SCOPE - + '&meta[send_limit_amount]=1000&meta[send_limit_currency]=USD&meta[send_limit_period]=day'; + return credentials.HOST + + '/oauth/authorize?response_type=code&client_id=' + + credentials.CLIENT_ID + + '&redirect_uri=' + + credentials.REDIRECT_URI + + '&state=SECURE_RANDOM&scope=' + + credentials.SCOPE + + '&meta[send_limit_amount]=1000&meta[send_limit_currency]=USD&meta[send_limit_period]=day'; }; root.getToken = function(code, cb) { @@ -152,9 +146,9 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ 'Accept': 'application/json' }, data: { - grant_type : 'authorization_code', + grant_type: 'authorization_code', code: code, - client_id : credentials.CLIENT_ID, + client_id: credentials.CLIENT_ID, client_secret: credentials.CLIENT_SECRET, redirect_uri: credentials.REDIRECT_URI } @@ -163,7 +157,6 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ $http(req).then(function(data) { $log.info('Coinbase Authorization Access Token: SUCCESS'); // Show pending task from the UI - storageService.setNextStep('BuyAndSell', 'true', function(err) {}); _afterTokenReceived(data.data, cb); }, function(data) { $log.error('Coinbase Authorization Access Token: ERROR ' + data.statusText); @@ -180,8 +173,8 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ 'Accept': 'application/json' }, data: { - grant_type : 'refresh_token', - client_id : credentials.CLIENT_ID, + grant_type: 'refresh_token', + client_id: credentials.CLIENT_ID, client_secret: credentials.CLIENT_SECRET, redirect_uri: credentials.REDIRECT_URI, refresh_token: refreshToken @@ -211,6 +204,19 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ }); }; + root.isActive = function(cb) { + + if (isWindowsPhoneApp) + return cb(); + + if (lodash.isEmpty(credentials.CLIENT_ID)) + return cb(); + + storageService.getCoinbaseToken(credentials.NETWORK, function(err, accessToken) { + return cb(err, !!accessToken); + }); + } + root.init = lodash.throttle(function(cb) { if (lodash.isEmpty(credentials.CLIENT_ID)) { return cb('Coinbase is Disabled'); @@ -230,7 +236,10 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ if (err) return cb(err); _getMainAccountId(newToken, function(err, accountId) { if (err) return cb(err); - return cb(null, {accessToken: newToken, accountId: accountId}); + return cb(null, { + accessToken: newToken, + accountId: accountId + }); }); }); }); @@ -238,7 +247,10 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ return cb(err); } } else { - return cb(null, {accessToken: accessToken, accountId: accountId}); + return cb(null, { + accessToken: accessToken, + accountId: accountId + }); } }); } @@ -402,7 +414,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ var data = { amount: data.amount, currency: data.currency, - payment_method: data.payment_method || null, + payment_method: data.payment_method ||  null, commit: data.commit || false, quote: data.quote || false }; @@ -483,7 +495,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ }; // Pending transactions - + root.savePendingTransaction = function(ctx, opts, cb) { _savePendingTransaction(ctx, opts, cb); }; @@ -516,7 +528,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ storageService.getCoinbaseTxs(credentials.NETWORK, function(err, txs) { txs = txs ? JSON.parse(txs) : {}; coinbasePendingTransactions.data = lodash.isEmpty(txs) ? null : txs; - + root.init(function(err, data) { if (err || lodash.isEmpty(data)) { if (err) $log.error(err); @@ -529,7 +541,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ if ((dataFromStorage.type == 'sell' && dataFromStorage.status == 'completed') || (dataFromStorage.type == 'buy' && dataFromStorage.status == 'completed') || dataFromStorage.status == 'error' || - (dataFromStorage.type == 'send' && dataFromStorage.status == 'completed')) + (dataFromStorage.type == 'send' && dataFromStorage.status == 'completed')) return; root.getTransaction(accessToken, accountId, txId, function(err, tx) { if (err || lodash.isEmpty(tx) || (tx.data && tx.data.error)) { @@ -591,9 +603,10 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ root.updatePendingTransactions = lodash.throttle(function() { $log.debug('Updating pending transactions...'); - root.setCredentials(); - var pendingTransactions = { data: {} }; - root.getPendingTransactions(pendingTransactions); + var pendingTransactions = { + data: {} + }; + root.getPendingTransactions(pendingTransactions); }, 20000); var _updateTxs = function(coinbasePendingTransactions) { @@ -707,6 +720,31 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ }); }; - return root; + var register = function() { + root.isActive(function(err, isActive){ + if (err) return; + + buyAndSellService.register({ + name: 'Coinbase', + logo: 'img/coinbase-logo.png', + sref: 'tabs.buyandsell.coinbase', + linked: isActive, + }); + }); + }; + + setCredentials(); + register(); + + $rootScope.$on('bwsEvent', function(e, walletId, type, n) { + if (type == 'NewBlock' && n && n.data && n.data.network == 'livenet') { + root.isActive(function(err,isActive){ + // Update Coinbase + if (isActive) + root.updatePendingTransactions(); + }); + } + }); + return root; }); diff --git a/src/js/services/glideraService.js b/src/js/services/glideraService.js index 06e30cf14..01edc677a 100644 --- a/src/js/services/glideraService.js +++ b/src/js/services/glideraService.js @@ -1,11 +1,12 @@ 'use strict'; -angular.module('copayApp.services').factory('glideraService', function($http, $log, $window, platformInfo, storageService) { +angular.module('copayApp.services').factory('glideraService', function($http, $log, $window, platformInfo, storageService, buyAndSellService) { var root = {}; var credentials = {}; var isCordova = platformInfo.isCordova; + var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; - var _setCredentials = function() { + var setCredentials = function() { if (!$window.externalServices || !$window.externalServices.glidera) { return; } @@ -16,7 +17,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l * Development: 'testnet' * Production: 'livenet' */ - credentials.NETWORK = 'livenet'; +// credentials.NETWORK = 'livenet'; + credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { credentials.HOST = glidera.sandbox.host; @@ -44,24 +46,20 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }; root.getEnvironment = function() { - _setCredentials(); return credentials.NETWORK; }; root.getOauthCodeUrl = function() { - _setCredentials(); return credentials.HOST + '/oauth2/auth?response_type=code&client_id=' + credentials.CLIENT_ID + '&redirect_uri=' + credentials.REDIRECT_URI; }; root.removeToken = function(cb) { - _setCredentials(); storageService.removeGlideraToken(credentials.NETWORK, function() { return cb(); }); }; root.getToken = function(code, cb) { - _setCredentials(); var req = { method: 'POST', url: credentials.HOST + '/api/v1/oauth/token', @@ -90,7 +88,6 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }; var _get = function(endpoint, token) { - _setCredentials(); return { method: 'GET', url: credentials.HOST + '/api/v1' + endpoint, @@ -208,7 +205,6 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }; var _post = function(endpoint, token, twoFaCode, data) { - _setCredentials(); return { method: 'POST', url: credentials.HOST + '/api/v1' + endpoint, @@ -285,7 +281,6 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }; root.init = function(accessToken, cb) { - _setCredentials(); $log.debug('Init Glidera...'); var glidera = { @@ -317,6 +312,24 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l }); }; - return root; + var register = function() { + if (isWindowsPhoneApp) return; + + storageService.getGlideraToken(credentials.NETWORK, function(err, token) { + if (err) return cb(err); + +console.log('[glideraService.js.326:token:]',token); //TODO + buyAndSellService.register({ + name: 'Glidera', + logo: 'img/glidera-logo.png', + sref: 'tabs.buyandsell.glidera', + linked: !!token, + }); + }); + }; + + setCredentials(); + register(); + return root; }); diff --git a/src/js/services/nextStepsService.js b/src/js/services/nextStepsService.js new file mode 100644 index 000000000..3ca781dfa --- /dev/null +++ b/src/js/services/nextStepsService.js @@ -0,0 +1,38 @@ + 'use strict'; + angular.module('copayApp.services').factory('nextStepsService', function(configService, $log) { + var root = {}; + + // + // configService.whenAvailable(function() { + // nextStep(function() { + // var config = configService.getSync(); + // var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; + // + // $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; + // $scope.coinbaseEnabled = config.coinbaseV2 && !isWindowsPhoneApp; + // $scope.amazonEnabled = config.amazon.enabled; + // $scope.bitpayCardEnabled = config.bitpayCard.enabled; + + + var services = []; + + root.register = function(serviceInfo) { + $log.info('Adding NextSteps entry:' + serviceInfo.name); + services.push(serviceInfo); + }; + + + root.unregister = function(serviceName) { + services = lodash.filter(services, function(x) { + return x.name != serviceName + }); + }; + + + root.get = function() { + return services; + }; + + return root; + + }); diff --git a/www/views/buyandsell.html b/www/views/buyandsell.html index b48b777f2..18d063a17 100644 --- a/www/views/buyandsell.html +++ b/www/views/buyandsell.html @@ -7,14 +7,10 @@
- -
- - -
-
- - +
+
+ +
diff --git a/www/views/includes/buyAndSellCard.html b/www/views/includes/buyAndSellCard.html new file mode 100644 index 000000000..a736b77fa --- /dev/null +++ b/www/views/includes/buyAndSellCard.html @@ -0,0 +1,13 @@ + +
+
+ Buy & Sell Bitcoin + +
+ +
diff --git a/www/views/includes/nextSteps.html b/www/views/includes/nextSteps.html new file mode 100644 index 000000000..8f19f31d2 --- /dev/null +++ b/www/views/includes/nextSteps.html @@ -0,0 +1,28 @@ +
+
+ Next steps + + +
+ +
+ + + + + + + + + + diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 89a1a7fdc..a532a2a75 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -115,24 +115,10 @@
-
-
- Buy & Sell Bitcoin - -
- -
-
+
+ + - +
From 5357ba7fcd53a2b391abb516e84c4b5bd99b11ae Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 30 Jan 2017 19:38:52 -0300 Subject: [PATCH 04/18] fix refresh in home / settings --- src/js/controllers/homeIntegrations.js | 16 +++++++++ src/js/controllers/preferencesCoinbase.js | 1 - src/js/controllers/tab-home.js | 5 ++- src/js/controllers/tab-settings.js | 19 ++--------- src/js/services/amazonService.js | 36 +++++++++++--------- src/js/services/buyAndSellService.js | 33 ++++++++++++------ src/js/services/coinbaseService.js | 5 ++- src/js/services/glideraService.js | 13 +++++--- src/js/services/homeIntegrations.js | 23 +++++++++++++ src/js/services/homeIntegrationsService.js | 23 +++++++++++++ src/js/services/nextStepsService.js | 39 +++++++++++----------- www/views/includes/nextSteps.html | 1 + www/views/tab-home.html | 12 +------ www/views/tab-settings.html | 20 ++++------- 14 files changed, 150 insertions(+), 96 deletions(-) create mode 100644 src/js/controllers/homeIntegrations.js create mode 100644 src/js/services/homeIntegrations.js create mode 100644 src/js/services/homeIntegrationsService.js diff --git a/src/js/controllers/homeIntegrations.js b/src/js/controllers/homeIntegrations.js new file mode 100644 index 000000000..fe01d816b --- /dev/null +++ b/src/js/controllers/homeIntegrations.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('homeIntegrationsController', function($scope, homeIntegrationsService, $ionicScrollDelegate, $timeout) { + + $scope.hide = false; + $scope.services = homeIntegrationsService.get(); + + $scope.toggle = function() { + $scope.hide = !$scope.hide; + $timeout(function() { + $ionicScrollDelegate.resize(); + $scope.$apply(); + }, 10); + }; + +}); diff --git a/src/js/controllers/preferencesCoinbase.js b/src/js/controllers/preferencesCoinbase.js index eea526bad..5537fb37b 100644 --- a/src/js/controllers/preferencesCoinbase.js +++ b/src/js/controllers/preferencesCoinbase.js @@ -16,7 +16,6 @@ angular.module('copayApp.controllers').controller('preferencesCoinbaseController }; $scope.$on("$ionicView.enter", function(event, data){ - coinbaseService.setCredentials(); ongoingProcess.set('connectingCoinbase', true); coinbaseService.init(function(err, data) { if (err || lodash.isEmpty(data)) { diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 8653e9252..329d1c7fd 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('tabHomeController', - function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService) { + function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService) { var wallet; var listeners = []; var notifications = []; @@ -96,8 +96,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.nextStepsItems = nextStepsService.get(); $scope.buyAndSellItems = buyAndSellService.getLinked(); - -console.log('[tab-home.js.99]', $scope.buyAndSellItems); //TODO + $scope.homeIntegrations = homeIntegrationsService.get(); configService.whenAvailable(function() { var config = configService.getSync(); diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 7f34d7347..87fd027c4 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, appConfigService, $log, lodash, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService, bitpayCardService, storageService, glideraService, coinbaseService, gettextCatalog) { +angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, appConfigService, $log, lodash, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService, bitpayCardService, storageService, glideraService, coinbaseService, gettextCatalog, buyAndSellService) { var updateConfig = function() { var isCordova = platformInfo.isCordova; @@ -16,6 +16,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct $scope.currentFeeLevel = feeService.getCurrentFeeLevel(); $scope.wallets = profileService.getWallets(); + $scope.buyAndSellServices = buyAndSellService.getLinked(); configService.whenAvailable(function(config) { $scope.unitName = config.wallet.settings.unitName; @@ -25,8 +26,6 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct }; $scope.bitpayCardEnabled = config.bitpayCard.enabled; - $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; - $scope.coinbaseEnabled = config.coinbaseV2 && !isWindowsPhoneApp; if ($scope.bitpayCardEnabled) { bitpayCardService.getCards(function(err, cards) { @@ -35,20 +34,6 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct }); } - if ($scope.glideraEnabled) { - storageService.getGlideraToken(glideraService.getEnvironment(), function(err, token) { - if (err) $log.error(err); - $scope.glideraToken = token; - }); - } - - if ($scope.coinbaseEnabled) { - coinbaseService.setCredentials(); - coinbaseService.getStoredToken(function(at) { - $scope.coinbaseToken = at; - }); - } - }); }; diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js index ff8b5e707..1bc0a153f 100644 --- a/src/js/services/amazonService.js +++ b/src/js/services/amazonService.js @@ -1,14 +1,15 @@ 'use strict'; -angular.module('copayApp.services').factory('amazonService', function($http, $log, lodash, moment, storageService, configService, platformInfo, nextStepsService) { +angular.module('copayApp.services').factory('amazonService', function($http, $log, lodash, moment, storageService, configService, platformInfo, nextStepsService, homeIntegrationsService) { var root = {}; var credentials = {}; - var _setCredentials = function() { + var setCredentials = function() { /* * Development: 'testnet' * Production: 'livenet' */ - credentials.NETWORK = 'livenet'; + //credentials.NETWORK = 'livenet'; + credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { credentials.BITPAY_API_URL = "https://test.bitpay.com"; @@ -18,7 +19,6 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }; var _getBitPay = function(endpoint) { - _setCredentials(); return { method: 'GET', url: credentials.BITPAY_API_URL + endpoint, @@ -29,7 +29,6 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }; var _postBitPay = function(endpoint, data) { - _setCredentials(); return { method: 'POST', url: credentials.BITPAY_API_URL + endpoint, @@ -41,7 +40,6 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }; root.getNetwork = function() { - _setCredentials(); return credentials.NETWORK; }; @@ -68,10 +66,6 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo return cb(err); }); }); - - // TODO - // Show pending task from the UI - // storageService.setNextStep('AmazonGiftCards', 'true', function(err) {}); }; root.getPendingGiftCards = function(cb) { @@ -146,14 +140,26 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }; var register = function () { - nextStepsService.register({ - name: 'amazon', - title: 'Buy a gift card', - icon: 'icon-amazon', - sref: 'tabs.giftcards.amazon', + storageService.getAmazonGiftCards(root.getNetwork(), function(err, giftCards) { + if (giftCards) { + homeIntegrationsService.register({ + name: 'amazon', + title: 'Amazon Gift Cards', + icon: 'icon-amazon', + sref: 'tabs.giftcards.amazon', + }); + } else { + nextStepsService.register({ + name: 'amazon', + title: 'Buy a gift card', + icon: 'icon-amazon', + sref: 'tabs.giftcards.amazon', + }); + } }); }; + setCredentials(); register(); return root; diff --git a/src/js/services/buyAndSellService.js b/src/js/services/buyAndSellService.js index 326241a18..bbfbe6632 100644 --- a/src/js/services/buyAndSellService.js +++ b/src/js/services/buyAndSellService.js @@ -5,40 +5,41 @@ angular.module('copayApp.services').factory('buyAndSellService', function($log, var services = []; var linkedServices = []; - root.updateNextSteps = function() { + root.update = function() { var newLinked = lodash.filter(services, function(x) { return x.linked; }); - // This is to preserve linkedServices pointer - while(linkedServices.length) + while (linkedServices.length) linkedServices.pop(); - while(newLinked.length) + while (newLinked.length) linkedServices.push(newLinked.pop()); // -console.log('[buyAndSellService.js.10:linkedServices:]',linkedServices); //TODO - - $log.debug('buyAndSell Service, updating nextSteps. linked/total: ' + linkedServices.length + '/'+ services.length); + $log.debug('buyAndSell Service, updating nextSteps. linked/total: ' + linkedServices.length + '/' + services.length); if (linkedServices.length == 0) { nextStepsService.register({ - name: 'Buy and Sell', + title: 'Buy and Sell', + name: 'buyandsell', icon: 'icon-buy-bitcoin', sref: 'tabs.buyandsell', }); + } else { + nextStepsService.unregister({ + name: 'buyandsell', + }); }; - $timeout(function() { $ionicScrollDelegate.resize(); }, 10); }; - var updateNextStepsDebunced = lodash.debounce(root.updateNextSteps, 1000); + var updateNextStepsDebunced = lodash.debounce(root.update, 1000); root.register = function(serviceInfo) { services.push(serviceInfo); @@ -46,6 +47,18 @@ console.log('[buyAndSellService.js.10:linkedServices:]',linkedServices); //TODO updateNextStepsDebunced(); }; + + root.updateLink = function(name, linked) { + var service = lodash.find(services, function(x) { + return x.name == name; + }); + $log.info('Updating Buy and Sell service:' + name + ' linked:' + linked); + service.linked = linked + + root.update(); + }; + + root.get = function() { return services; }; diff --git a/src/js/services/coinbaseService.js b/src/js/services/coinbaseService.js index 54139eafc..12b3bb46d 100644 --- a/src/js/services/coinbaseService.js +++ b/src/js/services/coinbaseService.js @@ -79,6 +79,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ if (data && data.access_token && data.refresh_token) { storageService.setCoinbaseToken(credentials.NETWORK, data.access_token, function() { storageService.setCoinbaseRefreshToken(credentials.NETWORK, data.refresh_token, function() { + buyAndSellService.updateLink('coinbase', true); return cb(null, data.access_token); }); }); @@ -712,6 +713,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ root.logout = function(cb) { storageService.removeCoinbaseToken(credentials.NETWORK, function() { + buyAndSellService.updateLink('coinbase', false); storageService.removeCoinbaseRefreshToken(credentials.NETWORK, function() { storageService.removeCoinbaseTxs(credentials.NETWORK, function() { return cb(); @@ -726,9 +728,10 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ if (err) return; buyAndSellService.register({ - name: 'Coinbase', + name: 'coinbase', logo: 'img/coinbase-logo.png', sref: 'tabs.buyandsell.coinbase', + configSref: 'tabs.preferences.coinbase', linked: isActive, }); }); diff --git a/src/js/services/glideraService.js b/src/js/services/glideraService.js index 01edc677a..aa7da0fba 100644 --- a/src/js/services/glideraService.js +++ b/src/js/services/glideraService.js @@ -17,7 +17,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l * Development: 'testnet' * Production: 'livenet' */ -// credentials.NETWORK = 'livenet'; + // credentials.NETWORK = 'livenet'; credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { @@ -55,6 +55,7 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l root.removeToken = function(cb) { storageService.removeGlideraToken(credentials.NETWORK, function() { + buyAndSellService.updateLink('glidera', false); return cb(); }); }; @@ -299,6 +300,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l getToken(function(err, accessToken) { if (err || !accessToken) return cb(); else { + buyAndSellService.updateLink('glidera', true); + root.getAccessTokenPermissions(accessToken, function(err, p) { if (err) { return cb(err); @@ -319,13 +322,13 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l storageService.getGlideraToken(credentials.NETWORK, function(err, token) { if (err) return cb(err); -console.log('[glideraService.js.326:token:]',token); //TODO - buyAndSellService.register({ - name: 'Glidera', + buyAndSellService.register({ + name: 'glidera', logo: 'img/glidera-logo.png', sref: 'tabs.buyandsell.glidera', + configSref: 'tabs.preferences.glidera', linked: !!token, - }); + }); }); }; diff --git a/src/js/services/homeIntegrations.js b/src/js/services/homeIntegrations.js new file mode 100644 index 000000000..d99588a80 --- /dev/null +++ b/src/js/services/homeIntegrations.js @@ -0,0 +1,23 @@ + 'use strict'; + angular.module('copayApp.services').factory('', function(configService, $log) { + var root = {}; + var services = []; + + root.register = function(serviceInfo) { + $log.info('Adding homeIntegration entry:' + serviceInfo.name); + services.push(serviceInfo); + }; + + root.unregister = function(serviceName) { + services = lodash.filter(services, function(x) { + return x.name != serviceName + }); + }; + + root.get = function() { + return services; + }; + + return root; + + }); diff --git a/src/js/services/homeIntegrationsService.js b/src/js/services/homeIntegrationsService.js new file mode 100644 index 000000000..5f3b067ff --- /dev/null +++ b/src/js/services/homeIntegrationsService.js @@ -0,0 +1,23 @@ + 'use strict'; + angular.module('copayApp.services').factory('homeIntegrationsService', function(configService, $log) { + var root = {}; + var services = []; + + root.register = function(serviceInfo) { + $log.info('Adding home Integrations entry:' + serviceInfo.name); + services.push(serviceInfo); + }; + + root.unregister = function(serviceName) { + services = lodash.filter(services, function(x) { + return x.name != serviceName + }); + }; + + root.get = function() { + return services; + }; + + return root; + + }); diff --git a/src/js/services/nextStepsService.js b/src/js/services/nextStepsService.js index 3ca781dfa..8172a1948 100644 --- a/src/js/services/nextStepsService.js +++ b/src/js/services/nextStepsService.js @@ -1,33 +1,32 @@ 'use strict'; - angular.module('copayApp.services').factory('nextStepsService', function(configService, $log) { + angular.module('copayApp.services').factory('nextStepsService', function(configService, $log, lodash) { var root = {}; - - // - // configService.whenAvailable(function() { - // nextStep(function() { - // var config = configService.getSync(); - // var isWindowsPhoneApp = platformInfo.isWP && platformInfo.isCordova; - // - // $scope.glideraEnabled = config.glidera.enabled && !isWindowsPhoneApp; - // $scope.coinbaseEnabled = config.coinbaseV2 && !isWindowsPhoneApp; - // $scope.amazonEnabled = config.amazon.enabled; - // $scope.bitpayCardEnabled = config.bitpayCard.enabled; - - var services = []; root.register = function(serviceInfo) { $log.info('Adding NextSteps entry:' + serviceInfo.name); - services.push(serviceInfo); - }; + if (!lodash.find(services, function(x) { + return x.name == serviceInfo.name; + })) { + services.push(serviceInfo); + } + }; root.unregister = function(serviceName) { - services = lodash.filter(services, function(x) { - return x.name != serviceName - }); - }; +console.log('[nextStepsService.js.16:serviceName:] UNR',serviceName); //TODO + var newS = lodash.filter(services, function(x) { + return x.name!=serviceName; + }); + // This is to preserve services pointer + while(services.length) + services.pop(); + + while(newS.length) + services.push(newS.pop()); +console.log('[nextStepsService.js.26:services:]',services); //TODO + }; root.get = function() { return services; diff --git a/www/views/includes/nextSteps.html b/www/views/includes/nextSteps.html index 8f19f31d2..6283cc818 100644 --- a/www/views/includes/nextSteps.html +++ b/www/views/includes/nextSteps.html @@ -25,4 +25,5 @@ + diff --git a/www/views/tab-home.html b/www/views/tab-home.html index a532a2a75..82fdb4d6a 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -117,17 +117,7 @@
- - - +
diff --git a/www/views/tab-settings.html b/www/views/tab-settings.html index 868388c56..f6ec0ddbb 100644 --- a/www/views/tab-settings.html +++ b/www/views/tab-settings.html @@ -126,19 +126,13 @@ - - - - - - - - - +
From 54c8c643512b5ba2ca420aea57e6bda5d87a1d67 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 08:21:18 -0300 Subject: [PATCH 05/18] fix amazon"s next steps --- src/js/services/amazonService.js | 57 +++++++++++++++-------------- src/js/services/coinbaseService.js | 2 +- src/js/services/nextStepsService.js | 3 +- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js index 1bc0a153f..25f25282d 100644 --- a/src/js/services/amazonService.js +++ b/src/js/services/amazonService.js @@ -3,19 +3,31 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo var root = {}; var credentials = {}; - var setCredentials = function() { - /* - * Development: 'testnet' - * Production: 'livenet' - */ - //credentials.NETWORK = 'livenet'; - credentials.NETWORK = 'testnet'; + /* + * Development: 'testnet' + * Production: 'livenet' + */ + //credentials.NETWORK = 'livenet'; + credentials.NETWORK = 'testnet'; - if (credentials.NETWORK == 'testnet') { - credentials.BITPAY_API_URL = "https://test.bitpay.com"; - } else { - credentials.BITPAY_API_URL = "https://bitpay.com"; - }; + if (credentials.NETWORK == 'testnet') { + credentials.BITPAY_API_URL = "https://test.bitpay.com"; + } else { + credentials.BITPAY_API_URL = "https://bitpay.com"; + }; + + var homeItem = { + name: 'amazon', + title: 'Amazon Gift Cards', + icon: 'icon-amazon', + sref: 'tabs.giftcards.amazon', + }; + + var nextStepItem = { + name: 'amazon', + title: 'Buy a gift card', + icon: 'icon-amazon', + sref: 'tabs.giftcards.amazon', }; var _getBitPay = function(endpoint) { @@ -63,6 +75,9 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo inv = JSON.stringify(inv); storageService.setAmazonGiftCards(network, inv, function(err) { + + homeIntegrationsService.register(homeItem); + nextStepsService.unregister(nextStepItem.name); return cb(err); }); }); @@ -139,28 +154,16 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo }); }; - var register = function () { + var register = function() { storageService.getAmazonGiftCards(root.getNetwork(), function(err, giftCards) { if (giftCards) { - homeIntegrationsService.register({ - name: 'amazon', - title: 'Amazon Gift Cards', - icon: 'icon-amazon', - sref: 'tabs.giftcards.amazon', - }); + homeIntegrationsService.register(homeItem); } else { - nextStepsService.register({ - name: 'amazon', - title: 'Buy a gift card', - icon: 'icon-amazon', - sref: 'tabs.giftcards.amazon', - }); + nextStepsService.register(nextStepItem); } }); }; - setCredentials(); register(); - return root; }); diff --git a/src/js/services/coinbaseService.js b/src/js/services/coinbaseService.js index 12b3bb46d..b01bed695 100644 --- a/src/js/services/coinbaseService.js +++ b/src/js/services/coinbaseService.js @@ -603,7 +603,7 @@ angular.module('copayApp.services').factory('coinbaseService', function($http, $ }; root.updatePendingTransactions = lodash.throttle(function() { - $log.debug('Updating pending transactions...'); + $log.debug('Updating coinbase pending transactions...'); var pendingTransactions = { data: {} }; diff --git a/src/js/services/nextStepsService.js b/src/js/services/nextStepsService.js index 8172a1948..641a910ec 100644 --- a/src/js/services/nextStepsService.js +++ b/src/js/services/nextStepsService.js @@ -14,7 +14,7 @@ }; root.unregister = function(serviceName) { -console.log('[nextStepsService.js.16:serviceName:] UNR',serviceName); //TODO + $log.info('Removing NextSteps entry:' + serviceName); var newS = lodash.filter(services, function(x) { return x.name!=serviceName; }); @@ -25,7 +25,6 @@ console.log('[nextStepsService.js.16:serviceName:] UNR',serviceName); //TODO while(newS.length) services.push(newS.pop()); -console.log('[nextStepsService.js.26:services:]',services); //TODO }; root.get = function() { From 8e5d42edc5702a8e88ba05712853360a2dc78f9e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 09:12:21 -0300 Subject: [PATCH 06/18] add debit card to nextsteps --- src/js/routes.js | 2 +- src/js/services/bitpayCardService.js | 25 +++++++++++++++++++++++- src/js/services/nextStepsService.js | 22 ++++++++++++--------- www/views/includes/homeIntegrations.html | 20 +++++++++++++++++++ 4 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 www/views/includes/homeIntegrations.html diff --git a/src/js/routes.js b/src/js/routes.js index e3ddbab3f..59202bea4 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -1088,7 +1088,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }); }) - .run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService) { + .run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService, /* plugins START HERE => */ coinbaseService, glideraService, amazonService, bitpayCardService) { uxLanguage.init(); diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index bf3bb0440..08fbe8a77 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('bitpayCardService', function($log, $rootScope, lodash, storageService, bitauthService, platformInfo, moment, appIdentityService, bitpayService) { +angular.module('copayApp.services').factory('bitpayCardService', function($log, $rootScope, lodash, storageService, bitauthService, platformInfo, moment, appIdentityService, bitpayService, nextStepsService) { var root = {}; var _setError = function(msg, e) { @@ -66,6 +66,8 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }); storageService.setBitpayDebitCards(bitpayService.getEnvironment().network, apiContext.pairData.email, cards, function(err) { + register(); + return cb(err, cards); }); }, function(data) { @@ -193,6 +195,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, $log.error('Error removing BitPay debit card: ' + err); return cb(err); } + register(); storageService.removeBitpayDebitCardHistory(cardId, cb); }); }; @@ -1244,6 +1247,26 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, 'bp002': 'default' }; + var nextStepItem = { + name: 'bitpaycard', + title: 'Add Bitpay VISA Card', + icon: 'icon-bitpay-card', + sref: 'tabs.bitpayCardIntro', + }; + + + var register = function() { + root.getCards(function(err, cards) { + if (lodash.isEmpty(cards)) { + nextStepsService.register(nextStepItem); + } else { + nextStepsService.unregister(nextStepItem); + // homeIntegrationsService.register(homeItem); + } + }); + }; + + register(); return root; }); diff --git a/src/js/services/nextStepsService.js b/src/js/services/nextStepsService.js index 641a910ec..566efd7be 100644 --- a/src/js/services/nextStepsService.js +++ b/src/js/services/nextStepsService.js @@ -14,17 +14,21 @@ }; root.unregister = function(serviceName) { + + var newS = lodash.filter(services, function(x) { + return x.name != serviceName; + }); + + // Found? + if (newS.length == services.length) return; + $log.info('Removing NextSteps entry:' + serviceName); - var newS = lodash.filter(services, function(x) { - return x.name!=serviceName; - }); + // This is to preserve services pointer + while (services.length) + services.pop(); - // This is to preserve services pointer - while(services.length) - services.pop(); - - while(newS.length) - services.push(newS.pop()); + while (newS.length) + services.push(newS.pop()); }; root.get = function() { diff --git a/www/views/includes/homeIntegrations.html b/www/views/includes/homeIntegrations.html new file mode 100644 index 000000000..06dae8ae7 --- /dev/null +++ b/www/views/includes/homeIntegrations.html @@ -0,0 +1,20 @@ + + + From 24c2d735cc2f91ac351b9437012b0ba8a6a68a90 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 09:30:27 -0300 Subject: [PATCH 07/18] bitpay card integration in home. Cache TODO --- src/js/controllers/tab-home.js | 29 +++++-------------------- src/js/services/bitpayCardService.js | 28 +++++++++++++++++++++--- www/views/includes/bitpayCardsCard.html | 21 ++++++++++++++++++ www/views/tab-home.html | 22 +------------------ 4 files changed, 52 insertions(+), 48 deletions(-) create mode 100644 www/views/includes/bitpayCardsCard.html diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 329d1c7fd..40a3ba6fc 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('tabHomeController', - function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService) { + function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService) { var wallet; var listeners = []; var notifications = []; @@ -98,6 +98,10 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.buyAndSellItems = buyAndSellService.getLinked(); $scope.homeIntegrations = homeIntegrationsService.get(); + bitpayCardService.get(function(err, cards) { + $scope.bitpayCardItems = cards; + }); + configService.whenAvailable(function() { var config = configService.getSync(); $scope.recentTransactionsEnabled = config.recentTransactions.enabled; @@ -252,29 +256,6 @@ angular.module('copayApp.controllers').controller('tabHomeController', }); }; - var bitpayCardCache = function() { - bitpayCardService.getCards(function(err, data) { - if (err) return; - if (lodash.isEmpty(data)) { - $scope.bitpayCards = null; - return; - } - $scope.bitpayCards = data; - $timeout(function() { - $scope.$digest(); - }, 100); - }); - - // TODO - // bitpayCardService.getCardsHistoryCache(function(err, data) { - // if (err) return; - // if (lodash.isEmpty(data)) { - // $scope.cardsHistory = null; - // return; - // } - // $scope.cardsHistory = data; - // }); - }; $scope.onRefresh = function() { $timeout(function() { diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 08fbe8a77..b63eb7bac 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -60,8 +60,8 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, n.eid = x.eid; n.id = x.id; - n.lastFourDigits = x.lastFourDigits; - n.token = x.token; + n.lastFourDigits = x.lastFourDigits; + n.token = x.token; cards.push(n); }); @@ -188,7 +188,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, // storageService.setBitpayDebitCardHistory(cardId, data, cb); // }; // - + root.remove = function(cardId, cb) { storageService.removeBitpayDebitCard(bitpayService.getEnvironment().network, cardId, function(err) { if (err) { @@ -210,6 +210,28 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }); }; + + root.get = function(cb) { + root.getCards(function(err, cards) { + if (err) return; + if (lodash.isEmpty(cards)) { + return cb(); + } + // TODO + // bitpayCardService.getCardsHistoryCache(function(err, data) { + // if (err) return; + // if (lodash.isEmpty(data)) { + // $scope.cardsHistory = null; + // return; + // } + // $scope.cardsHistory = data; + // }); + + return cb(null, cards); + }); + + }; + /* * CONSTANTS */ diff --git a/www/views/includes/bitpayCardsCard.html b/www/views/includes/bitpayCardsCard.html new file mode 100644 index 000000000..89787d080 --- /dev/null +++ b/www/views/includes/bitpayCardsCard.html @@ -0,0 +1,21 @@ + + + + diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 82fdb4d6a..c84614a10 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -95,27 +95,7 @@
- - - - +
From 1501d74558975c910ce349a5a9d2a72fe00918b2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 14:24:13 -0300 Subject: [PATCH 08/18] fix bitpay card --- src/js/controllers/bitpayCard.js | 75 +++++++++++-------------- src/js/controllers/tab-home.js | 5 +- src/js/controllers/tab-settings.js | 1 + src/js/services/bitpayCardService.js | 74 +++++++++++++++--------- src/js/services/bwcError.js | 2 +- src/js/services/profileService.js | 33 ++++++++++- src/js/services/storageService.js | 8 +-- www/views/bitpayCard.html | 13 +++-- www/views/includes/bitpayCardsCard.html | 2 +- www/views/tab-home.html | 3 +- 10 files changed, 135 insertions(+), 81 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 4654a2e18..0123d47ab 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -9,20 +9,6 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi }; $scope.network = bitpayService.getEnvironment().network; - var updateHistoryFromCache = function(cb) { - // 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; - self.bitpayCardCurrentBalance = data.balance; - return cb(); - }); - }; - var setDateRange = function(preset) { var startDate, endDate; preset = preset ||  'last30Days'; @@ -49,13 +35,19 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi }; var setGetStarted = function(history, cb) { - if (lodash.isEmpty(history.transactionList)) { - var dateRange = setDateRange('all'); - bitpayCardService.getHistory($scope.cardId, dateRange, function(err, history) { - if (lodash.isEmpty(history.transactionList)) return cb(true); - return cb(false); - }); - } else return cb(false); + + // Is the card new? + if (!lodash.isEmpty(history.transactionList)) + return cb(); + + var dateRange = setDateRange('all'); + bitpayCardService.getHistory($scope.cardId, dateRange, function(err, history) { + + if (!err && lodash.isEmpty(history.transactionList)) + self.getStated=true; + + return cb(); + }); }; this.update = function() { @@ -63,18 +55,18 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.loadingHistory = true; bitpayCardService.getHistory($scope.cardId, dateRange, function(err, history) { + $scope.loadingHistory = false; if (err) { $log.error(err); self.bitpayCardTransactionHistory = null; - self.bitpayCardCurrentBalance = null; + self.balance = null; popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not get transactions')); return; } - setGetStarted(history, function(getStarted) { - self.getStarted = getStarted; + setGetStarted(history, function() { var txs = lodash.clone(history.txs); runningBalance = parseFloat(history.endingBalance); @@ -87,13 +79,13 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi _runningBalance(txs[i]); } self.bitpayCardTransactionHistory = txs; - self.bitpayCardCurrentBalance = history.currentCardBalance; + self.balance = history.currentCardBalance; + self.updatedOn = null; if ($scope.dateRange.value == 'last30Days') { - // TODO CACHE - // - // $log.debug('BitPay Card: store cache history'); + // TODO? + // $log.debug('BitPay Card: storing cache history'); // var cacheHistory = { // balance: history.currentCardBalance, // transactions: history.txs @@ -143,24 +135,25 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.cardId = data.stateParams.id; + if (!$scope.cardId) { - var msg = gettextCatalog.getString('Bad param'); $ionicHistory.nextViewOptions({ disableAnimate: true }); $state.go('tabs.home'); - popupService.showAlert(gettextCatalog.getString('Error'), msg); - } else { - updateHistoryFromCache(function() { - self.update(); - }); - bitpayCardService.getCards(function(err, cards) { - if (err) return; - $scope.card = lodash.find(cards, function(card) { - return card.eid == $scope.cardId; - }); - }); } - }); + bitpayCardService.get({ + cardId: $scope.cardId, + noRefresh: true, + }, function(err, cards) { + + if (cards && cards[0]) { + self.lastFourDigits = cards[0].lastFourDigits; + self.balance = cards[0].balance; + self.updatedOn = cards[0].updatedOn; + } + self.update(); + }); + }); }); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 40a3ba6fc..8690f169c 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -98,7 +98,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.buyAndSellItems = buyAndSellService.getLinked(); $scope.homeIntegrations = homeIntegrationsService.get(); - bitpayCardService.get(function(err, cards) { + bitpayCardService.get({}, function(err, cards) { $scope.bitpayCardItems = cards; }); @@ -210,6 +210,9 @@ angular.module('copayApp.controllers').controller('tabHomeController', } else { wallet.error = null; wallet.status = status; + + // TODO service refactor? not in profile service + profileService.setLastKnownBalance(wallet.id, wallet.status.totalBalanceStr, function() {}); } if (++j == i) { updateTxps(); diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 87fd027c4..d43b4cc6d 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -25,6 +25,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct isoCode: config.wallet.settings.alternativeIsoCode }; + // TODO Move this to a generic service, like buyAndSell. $scope.bitpayCardEnabled = config.bitpayCard.enabled; if ($scope.bitpayCardEnabled) { diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index b63eb7bac..36696dd5e 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -115,11 +115,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, transactions = data.data.data || {}; transactions['txs'] = _processTransactions(invoices, transactions.transactionList); - // TODO CACHE? - // update cache? - // if (lodash.isEmpty(opts)) { - // root.setHistoryCache(cardId, transactions, function() {}); - // } + root.setLastKnownBalance(cardId, transactions.currentCardBalance, function() {}); return cb(data.data.error, transactions); }, function(data) { @@ -179,15 +175,32 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, storageService.getBitpayDebitCards(bitpayService.getEnvironment().network, cb); }; - // TODO?? - // root.getHistoryCache = function(cardId, cb) { - // storageService.getBitpayDebitCardHistory(cardId, cb); - // }; - // - // root.setHistoryCache = function(cardId, data, cb) { - // storageService.setBitpayDebitCardHistory(cardId, data, cb); - // }; - // + root.getLastKnownBalance = function(cardId, cb) { + storageService.getBalanceCache(cardId, cb); + }; + + root.addLastKnownBalance = function(card, cb) { + var now = Math.floor(Date.now()/1000); + var showRange = 600 ; // 10min; + + root.getLastKnownBalance(card.eid, function(err, data){ + if (data) { + data = JSON.parse(data); + card.balance = data.balance; + card.updatedOn = ( data.updatedOn < now - showRange) ? data.updatedOn : null; + } + return cb(); + }); + }; + + root.setLastKnownBalance = function(cardId, balance, cb) { + + storageService.setBalanceCache(cardId, { + balance: balance, + updatedOn: Math.floor(Date.now()/1000), + }, cb); + }; + root.remove = function(cardId, cb) { storageService.removeBitpayDebitCard(bitpayService.getEnvironment().network, cardId, function(err) { @@ -211,25 +224,33 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }; - root.get = function(cb) { + root.get = function(opts, cb) { root.getCards(function(err, cards) { if (err) return; + if (lodash.isEmpty(cards)) { return cb(); } - // TODO - // bitpayCardService.getCardsHistoryCache(function(err, data) { - // if (err) return; - // if (lodash.isEmpty(data)) { - // $scope.cardsHistory = null; - // return; - // } - // $scope.cardsHistory = data; - // }); + + // Async, no problem + lodash.each(cards, function(x){ + + if (opts.cardId) { + if (opts.cardId != x.eid) return; + } + + root.addLastKnownBalance(x, function() {}); + + if (!opts.noRefresh) { + root.getHistory(x.id, {}, function(err, data) { + if (err) return; + root.addLastKnownBalance(x, function() {}); + }); + } + }); return cb(null, cards); }); - }; /* @@ -1282,8 +1303,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, if (lodash.isEmpty(cards)) { nextStepsService.register(nextStepItem); } else { - nextStepsService.unregister(nextStepItem); - // homeIntegrationsService.register(homeItem); + nextStepsService.unregister(nextStepItem.name); } }); }; diff --git a/src/js/services/bwcError.js b/src/js/services/bwcError.js index 6ea0b91d5..9740af88e 100644 --- a/src/js/services/bwcError.js +++ b/src/js/services/bwcError.js @@ -44,7 +44,7 @@ angular.module('copayApp.services') body = gettextCatalog.getString('Insufficient funds'); break; case 'CONNECTION_ERROR': - body = gettextCatalog.getString('Network connection error'); + body = gettextCatalog.getString('Network error'); break; case 'NOT_FOUND': body = gettextCatalog.getString('Wallet service not found'); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index a9416fcf3..964b48eac 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -747,6 +747,31 @@ angular.module('copayApp.services') storageService.storeProfile(root.profile, cb); }; + root.getLastKnownBalance = function(wid, cb) { + storageService.getBalanceCache(wid, cb); + }; + + root.addLastKnownBalance = function(wallet, cb) { + var now = Math.floor(Date.now() / 1000); + var showRange = 600; // 10min; + + root.getLastKnownBalance(wallet.id, function(err, data) { + if (data) { + data = JSON.parse(data); + wallet.cachedBalance = data.balance; + wallet.cachedBalanceUpdatedOn = (data.updatedOn < now - showRange) ? data.updatedOn : null; + } + return cb(); + }); + }; + + root.setLastKnownBalance = function(wid, balance, cb) { + storageService.setBalanceCache(wid, { + balance: balance, + updatedOn: Math.floor(Date.now() / 1000), + }, cb); + }; + root.getWallets = function(opts) { if (opts && !lodash.isObject(opts)) @@ -780,6 +805,12 @@ angular.module('copayApp.services') }); } else {} + // Add cached balance async + lodash.each(ret, function(x) { + root.addLastKnownBalance(x, function() {}); + }); + + return lodash.sortBy(ret, [ function(x) { @@ -796,7 +827,7 @@ angular.module('copayApp.services') root.getNotifications = function(opts, cb) { opts = opts || {}; - var TIME_STAMP = 60 * 60 * 6; + var TIME_STAMP = 60 * 60 * 6; var MAX = 30; var typeFilter = { diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 8823ca472..5faf7afb6 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -344,12 +344,12 @@ angular.module('copayApp.services') storage.remove('coinbaseTxs-' + network, cb); }; - root.setBitpayDebitCardHistory = function(cardId, data, cb) { - storage.set('bitpayDebitCardHistory-' + cardId, data, cb); + root.setBalanceCache = function(cardId, data, cb) { + storage.set('bitpayDebitCardBalance-' + cardId, data, cb); }; - root.getBitpayDebitCardHistory = function(cardId, cb) { - storage.get('bitpayDebitCardHistory-' + cardId, cb); + root.getBalanceCache = function(cardId, cb) { + storage.get('bitpayDebitCardBalance-' + cardId, cb); }; root.removeBitpayDebitCardHistory = function(cardId, cb) { diff --git a/www/views/bitpayCard.html b/www/views/bitpayCard.html index 46371ff19..8ea540d74 100644 --- a/www/views/bitpayCard.html +++ b/www/views/bitpayCard.html @@ -2,7 +2,7 @@ - BitPay Visa® Card ({{card.lastFourDigits}}) + BitPay Visa® Card ({{bitpayCard.lastFourDigits}}) @@ -14,8 +14,13 @@
-
-
${{bitpayCard.bitpayCardCurrentBalance}}
+
+
${{bitpayCard.balance}}
+ +
+ {{bitpayCard.updatedOn * 1000 | amTimeAgo}} +
+ @@ -23,7 +28,7 @@ {{'Add Funds'|translate}}
-
+
...
diff --git a/www/views/includes/bitpayCardsCard.html b/www/views/includes/bitpayCardsCard.html index 89787d080..4f97fdc84 100644 --- a/www/views/includes/bitpayCardsCard.html +++ b/www/views/includes/bitpayCardsCard.html @@ -12,7 +12,7 @@
BitPay Visa® Card ({{card.lastFourDigits}}) -

{{card.balance ? '$' + card.balance : 'Add funds to get started'|translate}}

+

{{card.balance ? '$' + card.balance : 'Add funds to get started'|translate}} {{card.updatedOn ? (' | ' + (card.updatedOn * 1000 | amTimeAgo)) : ''}}

diff --git a/www/views/tab-home.html b/www/views/tab-home.html index c84614a10..85eaf7964 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -81,7 +81,8 @@ Incomplete - {{wallet.status.totalBalanceStr}} + {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + ' | ' + (wallet.cachedBalanceUpdatedOn ? ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} + [Balance Hidden] {{wallet.m}}-of-{{wallet.n}} From 44cf9dc971aae11a3fb36c458ff52c4437733105 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 14:52:52 -0300 Subject: [PATCH 09/18] credentials --- src/js/controllers/buyCoinbase.js | 2 -- src/js/controllers/sellCoinbase.js | 2 -- src/js/services/amazonService.js | 4 ++-- src/js/services/glideraService.js | 4 ++-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/js/controllers/buyCoinbase.js b/src/js/controllers/buyCoinbase.js index 587ef778e..babc2a2fd 100644 --- a/src/js/controllers/buyCoinbase.js +++ b/src/js/controllers/buyCoinbase.js @@ -34,8 +34,6 @@ angular.module('copayApp.controllers').controller('buyCoinbaseController', funct }; $scope.$on("$ionicView.beforeEnter", function(event, data) { - coinbaseService.setCredentials(); - $scope.isFiat = data.stateParams.currency ? true : false; [amount, currency, $scope.amountUnitStr] = coinbaseService.parseAmount( data.stateParams.amount, diff --git a/src/js/controllers/sellCoinbase.js b/src/js/controllers/sellCoinbase.js index d7b385e72..bd86bd0d1 100644 --- a/src/js/controllers/sellCoinbase.js +++ b/src/js/controllers/sellCoinbase.js @@ -117,8 +117,6 @@ angular.module('copayApp.controllers').controller('sellCoinbaseController', func }; $scope.$on("$ionicView.beforeEnter", function(event, data) { - coinbaseService.setCredentials(); - $scope.isFiat = data.stateParams.currency ? true : false; [amount, currency, $scope.amountUnitStr] = coinbaseService.parseAmount( data.stateParams.amount, diff --git a/src/js/services/amazonService.js b/src/js/services/amazonService.js index 25f25282d..d0c715220 100644 --- a/src/js/services/amazonService.js +++ b/src/js/services/amazonService.js @@ -7,8 +7,8 @@ angular.module('copayApp.services').factory('amazonService', function($http, $lo * Development: 'testnet' * Production: 'livenet' */ - //credentials.NETWORK = 'livenet'; - credentials.NETWORK = 'testnet'; + credentials.NETWORK = 'livenet'; + //credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { credentials.BITPAY_API_URL = "https://test.bitpay.com"; diff --git a/src/js/services/glideraService.js b/src/js/services/glideraService.js index aa7da0fba..13401ed1c 100644 --- a/src/js/services/glideraService.js +++ b/src/js/services/glideraService.js @@ -17,8 +17,8 @@ angular.module('copayApp.services').factory('glideraService', function($http, $l * Development: 'testnet' * Production: 'livenet' */ - // credentials.NETWORK = 'livenet'; - credentials.NETWORK = 'testnet'; + credentials.NETWORK = 'livenet'; + //credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { credentials.HOST = glidera.sandbox.host; From 34bc2ba209b2b57a5d28bf7edbc0f1a23437dac1 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 16:32:45 -0300 Subject: [PATCH 10/18] hide next steps --- src/js/controllers/advancedSettings.js | 56 ++++---------------------- src/js/controllers/tab-home.js | 6 ++- src/js/services/configService.js | 20 ++------- www/views/advancedSettings.html | 25 ++++-------- www/views/tab-home.html | 2 +- 5 files changed, 24 insertions(+), 85 deletions(-) diff --git a/src/js/controllers/advancedSettings.js b/src/js/controllers/advancedSettings.js index 9bfd90a58..0664a0804 100644 --- a/src/js/controllers/advancedSettings.js +++ b/src/js/controllers/advancedSettings.js @@ -3,27 +3,18 @@ angular.module('copayApp.controllers').controller('advancedSettingsController', function($scope, $rootScope, $log, $window, lodash, configService, uxLanguage, platformInfo, pushNotificationsService, profileService, feeService, storageService, $ionicHistory, $timeout, $ionicScrollDelegate) { var updateConfig = function() { - var config = configService.getSync(); $scope.spendUnconfirmed = { value: config.wallet.spendUnconfirmed }; - $scope.bitpayCardEnabled = { - value: config.bitpayCard.enabled - }; - $scope.amazonEnabled = { - value: config.amazon.enabled - }; - $scope.glideraEnabled = { - value: config.glidera.enabled - }; - $scope.coinbaseEnabled = { - value: config.coinbaseV2 - }; $scope.recentTransactionsEnabled = { value: config.recentTransactions.enabled }; + + $scope.hideNextSteps = { + value: config.hideNextSteps.enabled + }; }; $scope.spendUnconfirmedChange = function() { @@ -37,42 +28,11 @@ angular.module('copayApp.controllers').controller('advancedSettingsController', }); }; - $scope.bitpayCardChange = function() { + $scope.nextStepsChange = function() { var opts = { - bitpayCard: { - enabled: $scope.bitpayCardEnabled.value - } - }; - configService.set(opts, function(err) { - if (err) $log.debug(err); - }); - }; - - $scope.amazonChange = function() { - var opts = { - amazon: { - enabled: $scope.amazonEnabled.value - } - }; - configService.set(opts, function(err) { - if (err) $log.debug(err); - }); - }; - - $scope.glideraChange = function() { - var opts = { - glidera: { - enabled: $scope.glideraEnabled.value - } - }; - configService.set(opts, function(err) { - if (err) $log.debug(err); - }); - }; - - $scope.coinbaseChange = function() { - var opts = { - coinbaseV2: $scope.coinbaseEnabled.value + hideNextSteps: { + enabled: $scope.hideNextSteps.value + }, }; configService.set(opts, function(err) { if (err) $log.debug(err); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 8690f169c..ded89466e 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -94,7 +94,6 @@ angular.module('copayApp.controllers').controller('tabHomeController', ]; - $scope.nextStepsItems = nextStepsService.get(); $scope.buyAndSellItems = buyAndSellService.getLinked(); $scope.homeIntegrations = homeIntegrationsService.get(); @@ -107,7 +106,10 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.recentTransactionsEnabled = config.recentTransactions.enabled; if ($scope.recentTransactionsEnabled) getNotifications(); - if ($scope.bitpayCardEnabled) bitpayCardCache(); + if (!config.hideNextSteps.enabled) { + $scope.nextStepsItems = nextStepsService.get(); + } + $timeout(function() { $ionicScrollDelegate.resize(); $scope.$apply(); diff --git a/src/js/services/configService.js b/src/js/services/configService.js index fd6b3206a..09dfe268f 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -43,26 +43,14 @@ angular.module('copayApp.services').factory('configService', function(storageSer }, // External services - glidera: { - enabled: true, - testnet: false - }, - - coinbaseV2: true, - - bitpayCard: { - enabled: true - }, - - amazon: { - enabled: true - }, - - recentTransactions: { enabled: true, }, + hideNextSteps: { + enabled: false, + }, + rates: { url: 'https://insight.bitpay.com:443/api/rates', }, diff --git a/www/views/advancedSettings.html b/www/views/advancedSettings.html index afbbf764b..03632f52c 100644 --- a/www/views/advancedSettings.html +++ b/www/views/advancedSettings.html @@ -7,24 +7,6 @@
-
Enabled Integrations
- - - Enable BitPay Card Integration - - - - Enable Amazon Integration - - - - Enable Glidera Service - - - - Enable Coinbase Service - -
Wallet Operation
@@ -41,6 +23,13 @@ If enabled, the Recent Transactions card - a list of transactions occuring across all wallets - will appear in the Home tab.
+ + + Hide Next Steps Card + + + +
diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 85eaf7964..788422bb3 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -81,7 +81,7 @@ Incomplete - {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + ' | ' + (wallet.cachedBalanceUpdatedOn ? ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} + {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' | ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} [Balance Hidden] From 776154ffbf82687a4dc586357067b9b02024db02 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 16:59:27 -0300 Subject: [PATCH 11/18] fix old format migration --- src/js/services/bitpayCardService.js | 2 +- src/js/services/storageService.js | 29 ++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 36696dd5e..0e12e7fb8 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -209,7 +209,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, return cb(err); } register(); - storageService.removeBitpayDebitCardHistory(cardId, cb); + storageService.removeBalanceCache(cardId, cb); }); }; diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 5faf7afb6..9a9e6d31e 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -345,15 +345,15 @@ angular.module('copayApp.services') }; root.setBalanceCache = function(cardId, data, cb) { - storage.set('bitpayDebitCardBalance-' + cardId, data, cb); + storage.set('balanceCache-' + cardId, data, cb); }; root.getBalanceCache = function(cardId, cb) { - storage.get('bitpayDebitCardBalance-' + cardId, cb); + storage.get('balanceCache-' + cardId, cb); }; - root.removeBitpayDebitCardHistory = function(cardId, cb) { - storage.remove('bitpayDebitCardHistory-' + cardId, cb); + root.removeBalanceCache = function(cardId, cb) { + storage.remove('balanceCache-' + cardId, cb); }; // cards: [ @@ -452,17 +452,34 @@ angular.module('copayApp.services') allAccounts = JSON.parse(allAccountsStr); } catch (e) {}; + var anyMigration; + 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]; + account.token = account['bitpayApi-' + network].token; + account.cards = lodash.clone(account['bitpayApi-' + network].cards); + if (!account.cards) { + account.cards = lodash.clone(account['bitpayDebitCards-' + network]); + } + + delete account['bitpayDebitCards-' + network]; delete account['bitpayApi-' + network]; + anyMigration = true; + } }); - return cb(err, allAccounts); + if (anyMigration) { + storage.set('bitpayAccounts-v2-' + network, allAccounts, function(){ + return cb(err, allAccounts); + }); + } else + return cb(err, allAccounts); + }); }; From 2235cb60bbb3b4b8fd875c2e3cc29838925126de Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 17:32:11 -0300 Subject: [PATCH 12/18] config Service --- src/js/services/configService.js | 15 ++++----------- www/views/includes/bitpayCardsCard.html | 2 +- www/views/includes/homeIntegrations.html | 2 +- www/views/includes/nextSteps.html | 12 +----------- 4 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/js/services/configService.js b/src/js/services/configService.js index 09dfe268f..3b2ef3826 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -179,18 +179,11 @@ angular.module('copayApp.services').factory('configService', function(storageSer if (!configCache.wallet.settings.unitCode) { configCache.wallet.settings.unitCode = defaultConfig.wallet.settings.unitCode; } - if (!configCache.glidera) { - configCache.glidera = defaultConfig.glidera; - } - if (!configCache.coinbaseV2) { - configCache.coinbaseV2 = defaultConfig.coinbaseV2; - } - if (!configCache.amazon) { - configCache.amazon = defaultConfig.amazon; - } - if (!configCache.bitpayCard) { - configCache.bitpayCard = defaultConfig.bitpayCard; + + if (!configCache.hideNextSteps) { + configCache.hideNextSteps = defaultConfig.hideNextSteps; } + if (!configCache.recentTransactions) { configCache.recentTransactions = defaultConfig.recentTransactions; } diff --git a/www/views/includes/bitpayCardsCard.html b/www/views/includes/bitpayCardsCard.html index 4f97fdc84..08cc56889 100644 --- a/www/views/includes/bitpayCardsCard.html +++ b/www/views/includes/bitpayCardsCard.html @@ -5,7 +5,7 @@
-
+
- - - - - - - - - - - From 210ebf9514dc10ee2c01b8af921cd775e3248240 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 31 Jan 2017 17:45:19 -0300 Subject: [PATCH 13/18] fix refresh --- src/js/controllers/tab-home.js | 4 +++- src/js/controllers/tab-settings.js | 14 +++++--------- www/views/tab-settings.html | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index ded89466e..35efbf203 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -106,7 +106,9 @@ angular.module('copayApp.controllers').controller('tabHomeController', $scope.recentTransactionsEnabled = config.recentTransactions.enabled; if ($scope.recentTransactionsEnabled) getNotifications(); - if (!config.hideNextSteps.enabled) { + if (config.hideNextSteps.enabled) { + $scope.nextStepsItems = null; + } else { $scope.nextStepsItems = nextStepsService.get(); } diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index d43b4cc6d..98d2b1bf5 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -25,15 +25,11 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct isoCode: config.wallet.settings.alternativeIsoCode }; - // TODO Move this to a generic service, like buyAndSell. - $scope.bitpayCardEnabled = config.bitpayCard.enabled; - - if ($scope.bitpayCardEnabled) { - bitpayCardService.getCards(function(err, cards) { - if (err) $log.error(err); - $scope.bitpayCards = cards && cards.length > 0; - }); - } + // TODO move this to a generic service + bitpayCardService.getCards(function(err, cards) { + if (err) $log.error(err); + $scope.bitpayCards = cards && cards.length > 0; + }); }); }; diff --git a/www/views/tab-settings.html b/www/views/tab-settings.html index f6ec0ddbb..3474e80fd 100644 --- a/www/views/tab-settings.html +++ b/www/views/tab-settings.html @@ -117,7 +117,7 @@
From f6a7a42a545309851c1a7343aa4b28333cd65c5b Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 31 Jan 2017 20:23:25 -0300 Subject: [PATCH 14/18] BitPay RC v1.3.3 --- app-template/bitpay/appConfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app-template/bitpay/appConfig.json b/app-template/bitpay/appConfig.json index 664fe156f..56b9bd721 100644 --- a/app-template/bitpay/appConfig.json +++ b/app-template/bitpay/appConfig.json @@ -21,8 +21,8 @@ "windowsAppId": "2d1002d7-ee34-4f60-bd29-0c871ba0c195", "pushSenderId": "1036948132229", "description": "Secure Bitcoin Wallet", - "version": "1.3.2", - "androidVersion": "132000", + "version": "1.3.3", + "androidVersion": "133000", "_extraCSS": null, "_enabledExtensions": { "coinbase": true, From d51c4f5c0f2683beff6d795d31c7da6325359e5c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 1 Feb 2017 11:35:50 -0300 Subject: [PATCH 15/18] middot as separator --- www/views/includes/bitpayCardsCard.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/views/includes/bitpayCardsCard.html b/www/views/includes/bitpayCardsCard.html index 08cc56889..b3b909c6e 100644 --- a/www/views/includes/bitpayCardsCard.html +++ b/www/views/includes/bitpayCardsCard.html @@ -12,7 +12,7 @@
BitPay Visa® Card ({{card.lastFourDigits}}) -

{{card.balance ? '$' + card.balance : 'Add funds to get started'|translate}} {{card.updatedOn ? (' | ' + (card.updatedOn * 1000 | amTimeAgo)) : ''}}

+

{{card.balance ? '$' + card.balance : 'Add funds to get started'|translate}} {{card.updatedOn ? (' · ' + (card.updatedOn * 1000 | amTimeAgo)) : ''}}

From 4911d50b0d854e0831fb9e8283119991d08a4dfb Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 1 Feb 2017 11:36:05 -0300 Subject: [PATCH 16/18] add email to account deletion --- src/js/services/storageService.js | 8 ++++---- www/views/tab-home.html | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 9a9e6d31e..5f78725a3 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -391,12 +391,12 @@ angular.module('copayApp.services') var allCards = []; - lodash.each(allAccounts, function(account) { + lodash.each(allAccounts, function(account, email) { + // Add account's email to card list, for convenience var cards = lodash.clone(account.cards); - - lodash.each(allAccounts, function(x) { - x.email = account.email; + lodash.each(cards, function(x) { + x.email = email; }); allCards = allCards.concat(cards); diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 8ec616673..c750802b1 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -90,7 +90,7 @@ Incomplete - {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' | ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} + {{wallet.status.totalBalanceStr ? wallet.status.totalBalanceStr : ( wallet.cachedBalance ? wallet.cachedBalance + (wallet.cachedBalanceUpdatedOn ? ' · ' + ( wallet.cachedBalanceUpdatedOn * 1000 | amTimeAgo) : '') : '' ) }} [Balance Hidden] From 96764917c722968b9c3f34ba96c593c6bc4b576d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 1 Feb 2017 11:42:18 -0300 Subject: [PATCH 17/18] fix selection of cards at .get --- src/js/controllers/bitpayCard.js | 1 + src/js/services/bitpayCardService.js | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 0123d47ab..05a823a3e 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -143,6 +143,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $state.go('tabs.home'); } + bitpayCardService.get({ cardId: $scope.cardId, noRefresh: true, diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 0e12e7fb8..a2ce4aa52 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -176,18 +176,18 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, }; root.getLastKnownBalance = function(cardId, cb) { - storageService.getBalanceCache(cardId, cb); + storageService.getBalanceCache(cardId, cb); }; root.addLastKnownBalance = function(card, cb) { - var now = Math.floor(Date.now()/1000); - var showRange = 600 ; // 10min; - - root.getLastKnownBalance(card.eid, function(err, data){ + var now = Math.floor(Date.now() / 1000); + var showRange = 600; // 10min; + + root.getLastKnownBalance(card.eid, function(err, data) { if (data) { data = JSON.parse(data); card.balance = data.balance; - card.updatedOn = ( data.updatedOn < now - showRange) ? data.updatedOn : null; + card.updatedOn = (data.updatedOn < now - showRange) ? data.updatedOn : null; } return cb(); }); @@ -197,7 +197,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, storageService.setBalanceCache(cardId, { balance: balance, - updatedOn: Math.floor(Date.now()/1000), + updatedOn: Math.floor(Date.now() / 1000), }, cb); }; @@ -232,15 +232,18 @@ angular.module('copayApp.services').factory('bitpayCardService', function($log, return cb(); } - // Async, no problem - lodash.each(cards, function(x){ + if (opts.cardId) { + cards = lodash.filter(cards, function(x) { + return opts.cardId == x.eid; + }); + } - if (opts.cardId) { - if (opts.cardId != x.eid) return; - } + // Async, no problem + lodash.each(cards, function(x) { root.addLastKnownBalance(x, function() {}); + // async refresh if (!opts.noRefresh) { root.getHistory(x.id, {}, function(err, data) { if (err) return; From 04f8ecfaf8670c37b32c806e3ac15f4cb0e16e2e Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 1 Feb 2017 12:43:06 -0300 Subject: [PATCH 18/18] New release v1.3.4 --- app-template/bitpay/appConfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app-template/bitpay/appConfig.json b/app-template/bitpay/appConfig.json index 56b9bd721..3282d4feb 100644 --- a/app-template/bitpay/appConfig.json +++ b/app-template/bitpay/appConfig.json @@ -21,8 +21,8 @@ "windowsAppId": "2d1002d7-ee34-4f60-bd29-0c871ba0c195", "pushSenderId": "1036948132229", "description": "Secure Bitcoin Wallet", - "version": "1.3.3", - "androidVersion": "133000", + "version": "1.3.4", + "androidVersion": "134000", "_extraCSS": null, "_enabledExtensions": { "coinbase": true,