From 6d97ef57d57bcfcbed1f888fcc83d59fcbdf4588 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 4 Oct 2016 12:06:06 -0300 Subject: [PATCH 01/22] BitPay Card Intro (slides) --- public/views/bitpayCardIntro.html | 74 +++++++++++++++++++++++++ src/js/controllers/bitpayCardIntro.js | 57 ++++++++++++++++++++ src/js/controllers/tabsController.js | 1 + src/js/routes.js | 11 +++- src/sass/views/bitpayCardIntro.scss | 78 +++++++++++++++++++++++++++ src/sass/views/views.scss | 1 + www/views/tab-home.html | 2 +- 7 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 public/views/bitpayCardIntro.html create mode 100644 src/js/controllers/bitpayCardIntro.js create mode 100644 src/sass/views/bitpayCardIntro.scss diff --git a/public/views/bitpayCardIntro.html b/public/views/bitpayCardIntro.html new file mode 100644 index 000000000..d272f3639 --- /dev/null +++ b/public/views/bitpayCardIntro.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + +
+ +
+

+ Turn bitcoin into dollars, swipe anywhere Visa® is accepted. +

+
+ + +
+
+
+ + +
+ +
+

+ Get local cash anywhere you go, from any Visa®-compatible ATM. +

+ *ATM bank fees may apply +
+

+
+ + +
+
+
+ + +
+ +
+

+ Pay 0% fees to turn bitcoin into dollars. +

+
+ + +
+
+
+
+
diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js new file mode 100644 index 000000000..943a1c0fd --- /dev/null +++ b/src/js/controllers/bitpayCardIntro.js @@ -0,0 +1,57 @@ +'use strict'; +angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $state, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService) { + + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.data = { + index: 0 + }; + + $scope.options = { + loop: false, + effect: 'flip', + speed: 500, + spaceBetween: 100 + }; + + storageService.getNextStep('BitpayCard', function(err, value) { + if (value) { + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $state.go('tabs.home'); + $timeout(function() { + $state.transitionTo('tabs.bitpayCard'); + }, 100); + } + }); + }); + + $scope.orderBitPayCard = function() { + var url = 'https://bitpay.com/visa/'; + var target = '_system'; + externalLinkService.open(url, target); + }; + + $scope.connectBitPayCard = function() {}; + + $scope.goBack = function() { + if ($scope.data.index != 0) $scope.slider.slidePrev(); + else $state.go('tabs.home'); + }; + + $scope.slideNext = function() { + if ($scope.data.index != 2) $scope.slider.slideNext(); + else $state.go('tabs.home'); + }; + + $scope.$on("$ionicSlides.sliderInitialized", function(event, data) { + $scope.slider = data.slider; + }); + + $scope.$on("$ionicSlides.slideChangeStart", function(event, data) { + $scope.data.index = data.slider.activeIndex; + }); + + $scope.$on("$ionicSlides.slideChangeEnd", function(event, data) {}); +}); + diff --git a/src/js/controllers/tabsController.js b/src/js/controllers/tabsController.js index 3e93df45d..642948ab6 100644 --- a/src/js/controllers/tabsController.js +++ b/src/js/controllers/tabsController.js @@ -35,6 +35,7 @@ angular.module('copayApp.controllers').controller('tabsController', function($ro 'tabs.receive.backup', 'tabs.bitpayCard.amount', 'tabs.bitpayCard.confirm', + 'tabs.bitpayCardIntro' ]; $rootScope.$on('$ionicView.beforeEnter', function() { diff --git a/src/js/routes.js b/src/js/routes.js index 8e9a6729c..0782c14f2 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -846,7 +846,16 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr * */ - .state('tabs.bitpayCard', { + .state('tabs.bitpayCardIntro', { + url: '/bitpay-card-intro', + views: { + 'tab-home@tabs': { + controller: 'bitpayCardIntroController', + templateUrl: 'views/bitpayCardIntro.html' + } + } + }) + .state('tabs.bitpayCard', { url: '/bitpay-card', views: { 'tab-home@tabs': { diff --git a/src/sass/views/bitpayCardIntro.scss b/src/sass/views/bitpayCardIntro.scss new file mode 100644 index 000000000..1405a2f7d --- /dev/null +++ b/src/sass/views/bitpayCardIntro.scss @@ -0,0 +1,78 @@ +#bitpayCard-intro { + .swiper-container-horizontal > .swiper-pagination { + bottom: 150px; + } + .cta-button{ + text-align: center; + position: absolute; + bottom: 45px; + padding: 0 1.5rem; + width: 100%; + } + background: rgba(30, 49, 134, 1); + background: -moz-linear-gradient(top, rgba(30, 49, 134, 1) 0%, rgba(17, 27, 73, 1) 100%); + background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(30, 49, 134, 1)), color-stop(100%, rgba(17, 27, 73, 1))); + background: -webkit-linear-gradient(top, rgba(30, 49, 134, 1) 0%, rgba(17, 27, 73, 1) 100%); + background: -o-linear-gradient(top, rgba(30, 49, 134, 1) 0%, rgba(17, 27, 73, 1) 100%); + background: -ms-linear-gradient(top, rgba(30, 49, 134, 1) 0%, rgba(17, 27, 73, 1) 100%); + background: linear-gradient(to bottom, rgba(30, 49, 134, 1) 0%, rgba(17, 27, 73, 1) 100%); + color: #fff; + height: 100%; + .bar.bar-header { + background: rgb(30, 49, 134); + color: #fff; + button { + color: #fff; + } + .secondary-buttons { + button { + color: rgba(255, 255, 255, .5); + } + } + } + .bar.bar-stable{ + border-color: transparent; + border:none; + } + .swiper-pagination { + &-bullet { + background: rgb(100, 124, 232); + &-active { + background: rgb(100, 124, 232); + } + } + } + .button-transparent{ + background: none !important; + } + .button-translucent{ + background: rgba(215, 215, 215, 0.1) + } + .button-primary{ + background: rgb(100, 124, 232) !important; + color:#fff; + } + .light-blue{ + color:rgb(100, 124, 232); + } + .text-white{ + color: #ffffff; + } + ion-content { + background: url(../img/onboarding-welcome-bg.png); + background-position: top center; + background-size: contain; + background-repeat: repeat-x; + height: 100%; + .scroll{ + height: 100%; + } + color: #fff; + p { + text-align: center; + margin: 40px 20px; + font-size: 1.2rem; + color: rgba(255, 255, 255, .5); + } + } +} diff --git a/src/sass/views/views.scss b/src/sass/views/views.scss index 0112476f3..de6ee8d30 100644 --- a/src/sass/views/views.scss +++ b/src/sass/views/views.scss @@ -12,6 +12,7 @@ @import "walletDetails"; @import "advancedSettings"; @import "bitpayCard"; +@import "bitpayCardIntro"; @import "address-book"; @import "wallet-backup-phrase"; @import "zero-state"; diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 9b9cbdb14..531cc72eb 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -138,7 +138,7 @@
- +
From 4f5c814c508db93da407f53bf55ab40c69c219fb Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 5 Oct 2016 11:42:40 -0300 Subject: [PATCH 02/22] Fix first view --- src/js/controllers/bitpayCard.js | 1 + src/js/controllers/preferencesBitpayCard.js | 4 ++-- src/sass/views/bitpayCard.scss | 5 ++++- www/views/bitpayCard.html | 12 +++++++----- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 54a9c09a5..03d1d123f 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -94,6 +94,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi transactions: self.bitpayCardTransactionHistory }; bitpayCardService.setCacheData(cacheData, function(err) { + $scope.bitpayCardCached = true; if (err) $log.error(err); }); }); diff --git a/src/js/controllers/preferencesBitpayCard.js b/src/js/controllers/preferencesBitpayCard.js index 2abf6a8c4..536d4cde6 100644 --- a/src/js/controllers/preferencesBitpayCard.js +++ b/src/js/controllers/preferencesBitpayCard.js @@ -4,8 +4,8 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService) { $scope.logout = function() { - var title = 'Are you sure you would like to log out of your Bitpay Card account?'; - popupService.showConfirm(title, null, null, null, function(res) { + var msg = 'Are you sure you would like to log out of your BitPay Card account?'; + popupService.showConfirm(null, msg, null, null, function(res) { if (res) logout(); }); }; diff --git a/src/sass/views/bitpayCard.scss b/src/sass/views/bitpayCard.scss index 5d7b045b6..563554f15 100644 --- a/src/sass/views/bitpayCard.scss +++ b/src/sass/views/bitpayCard.scss @@ -3,12 +3,15 @@ width: 100%; text-align: center; padding: 2rem 1rem 1.5rem 1rem; - min-height: 140px; + height: 140px; border-color: #172565; background-color: #1e3186; background-image: linear-gradient(0deg, #172565, #172565 0%, transparent 0%); color: #fff; } + .wallet-details-wallet-info { + bottom: 5px; + } strong { line-height: 100%; } diff --git a/www/views/bitpayCard.html b/www/views/bitpayCard.html index ab8457b30..b5d3cd836 100644 --- a/www/views/bitpayCard.html +++ b/www/views/bitpayCard.html @@ -92,28 +92,30 @@
-
+ ng-if="!bitpayCardCached && !loadingHistory && !bitpayCard.bitpayCardTransactionHistory[0]">

Get started

Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.

-
+
- - - -
- - - - -

- Enter the verification code generated by the authenticator app on your phone. -

- -
- -
- -
- - -
-
- -
-
-
-
-
${{bitpayCard.bitpayCardCurrentBalance}}
- - {{'Add Funds'|translate}} - -
-
- ... -
-
-
- +
+ ...
+
+ +
+
+
+ {{error}} +
+ +
+ +

Get started

+

Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.

+
+ +
+
+ +
- -

Get started

-

Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.

-
+ ng-repeat="tx in bitpayCard.bitpayCardTransactionHistory | orderBy: ['pending','-timestamp']" + class="item row" + ng-init="bitpayCard.getMerchantInfo(tx)"> +
+ +
-
-
- +
+
+ {{tx.merchant.name}} +
+
+ {{tx.merchant.city}}, {{tx.merchant.state}} +
-
- -
- -
-
- {{tx.merchant.name}} -
-
- {{tx.merchant.city}}, {{tx.merchant.state}} -
-
-
- {{desc}} -
-
- - -
-
-
- {{tx.amount | currency:'$':2 }} -
- + ng-init="desc = bitpayCard.processDescription(tx)" + class="col size-12"> + {{desc}} +
+
+ + +
+
+
+ {{tx.amount | currency:'$':2 }}
+
diff --git a/www/views/confirm.html b/www/views/confirm.html index 953dc89fb..9886ca270 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -23,7 +23,16 @@
To - + + +
+
+ {{toName}} +
+ + + {{_paypro.domain}} +
{{toAddress}} diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 531cc72eb..81b5551ca 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -78,7 +78,6 @@ {{wallet.m}}-of-{{wallet.n}}
-

Incomplete @@ -91,15 +90,15 @@

- +

BitPay Card

-

Add funds to get started

- ${{bitpayCard.balance}} +

{{card.lastFourDigits}}

From 9196e07f3a851f75ffb5405bcb4fc94c0a63c3bd Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 7 Oct 2016 11:33:39 -0300 Subject: [PATCH 04/22] Fix card intro --- public/views/bitpayCardIntro.html | 89 +++++++++------------------ src/js/controllers/bitpayCardIntro.js | 34 +--------- src/js/services/bitpayCardService.js | 23 ------- src/sass/views/bitpayCardIntro.scss | 14 +---- www/views/tab-home.html | 12 +++- 5 files changed, 47 insertions(+), 125 deletions(-) diff --git a/public/views/bitpayCardIntro.html b/public/views/bitpayCardIntro.html index d272f3639..7b42f3611 100644 --- a/public/views/bitpayCardIntro.html +++ b/public/views/bitpayCardIntro.html @@ -1,74 +1,45 @@ + + - - - - - - - -
- -
+ +
+ +
+ +

- Turn bitcoin into dollars, swipe anywhere Visa® is accepted. + Turn bitcoin into dollars, swipe anywhere Visa® is accepted.

-
- - -
-
-
- - -
- -
+ +

- Get local cash anywhere you go, from any Visa®-compatible ATM. -

- *ATM bank fees may apply -
+ Get local cash anywhere you go, from any Visa®-compatible ATM. +
+ *ATM bank fees may apply +

-
- - -
-
-
- - -
- -
+ +

- Pay 0% fees to turn bitcoin into dollars. + Pay 0% fees to turn bitcoin into dollars.

-
- - -
-
-
-
+ + +
+ + +
+
diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 042195951..5e26a0218 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -2,16 +2,6 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $state, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { $scope.$on("$ionicView.beforeEnter", function(event, data) { - $scope.data = { - index: 0 - }; - - $scope.options = { - loop: false, - effect: 'flip', - speed: 500, - spaceBetween: 100 - }; if (data.stateParams && data.stateParams.secret) { var obj = { @@ -25,11 +15,13 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f return; } var title = gettextCatalog.getString('Add BitPay Cards?'); - var msg = gettextCatalog.getString('Would you like to add this account to your wallet?'); + var msg = gettextCatalog.getString('Would you like to add this account ({{email}}) to your wallet?', {email: obj.email}); var ok = gettextCatalog.getString('Add cards'); var cancel = gettextCatalog.getString('Go back'); popupService.showConfirm(title, msg, ok, cancel, function(res) { if (res) { + // Set flag for nextStep + storageService.setNextStep('BitpayCard', true, function(err) {}); // Save data bitpayCardService.setBitpayDebitCards(data, function(err) { if (err) return; @@ -71,25 +63,5 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f var target = '_system'; externalLinkService.open(url, target); }; - - $scope.goBack = function() { - if ($scope.data.index != 0) $scope.slider.slidePrev(); - else $state.go('tabs.home'); - }; - - $scope.slideNext = function() { - if ($scope.data.index != 2) $scope.slider.slideNext(); - else $state.go('tabs.home'); - }; - - $scope.$on("$ionicSlides.sliderInitialized", function(event, data) { - $scope.slider = data.slider; - }); - - $scope.$on("$ionicSlides.slideChangeStart", function(event, data) { - $scope.data.index = data.slider.activeIndex; - }); - - $scope.$on("$ionicSlides.slideChangeEnd", function(event, data) {}); }); diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 1bce179f1..e01441220 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -35,27 +35,6 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return error; }; - var _getUser = function(cb) { - _setCredentials(); - storageService.getBitpayCard(credentials.NETWORK, function(err, user) { - if (err) return cb(err); - if (lodash.isString(user)) { - user = JSON.parse(user); - } - return cb(null, user); - }); - }; - - var _setUser = function(user, cb) { - _setCredentials(); - user = JSON.stringify(user); - storageService.setBitpayCard(credentials.NETWORK, user, function(err) { - return cb(err); - }); - // Show pending task from the UI - storageService.setNextStep('BitpayCard', true, function(err) {}); - }; - var _getSession = function(cb) { _setCredentials(); $http({ @@ -179,8 +158,6 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, data: userData }).then(function(data) { $log.info('BitPay Card BitAuth: SUCCESS'); - // Set an UI flag - storageService.setNextStep('BitpayCard', true, function(err) {}); // Get cards _afterBitAuthSuccess(obj, cb); }, function(data) { diff --git a/src/sass/views/bitpayCardIntro.scss b/src/sass/views/bitpayCardIntro.scss index 1405a2f7d..3ce232b0f 100644 --- a/src/sass/views/bitpayCardIntro.scss +++ b/src/sass/views/bitpayCardIntro.scss @@ -1,11 +1,11 @@ #bitpayCard-intro { - .swiper-container-horizontal > .swiper-pagination { - bottom: 150px; + .slider-pager .slider-pager-page { + color: #fff; } .cta-button{ text-align: center; position: absolute; - bottom: 45px; + bottom: 55px; padding: 0 1.5rem; width: 100%; } @@ -34,14 +34,6 @@ border-color: transparent; border:none; } - .swiper-pagination { - &-bullet { - background: rgb(100, 124, 232); - &-active { - background: rgb(100, 124, 232); - } - } - } .button-transparent{ background: none !important; } diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 81b5551ca..f3bbc976a 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -97,10 +97,20 @@
-

BitPay Card

+

BitPay Visa® Card

{{card.lastFourDigits}}

+ + +
+
+

BitPay Visa® Card

+

Add your cards

+ +
From 3f2f169db34392d105db11cf00561dd0af41f9ef Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 7 Oct 2016 13:51:55 -0300 Subject: [PATCH 05/22] Activate caching for bitpay card --- src/js/controllers/bitpayCard.js | 26 +++++++---- src/js/controllers/tab-home.js | 6 +-- src/js/services/bitpayCardService.js | 43 +++++++++++++++++ src/js/services/storageService.js | 12 ++--- www/views/tab-home.html | 69 ++++++++++++++-------------- 5 files changed, 104 insertions(+), 52 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 8dee60315..f92c3e461 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -6,13 +6,15 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.dateRange = 'last30Days'; $scope.network = bitpayCardService.getEnvironment(); - /* - bitpayCardService.getCacheData(function(err, data) { - if (err || lodash.isEmpty(data)) return; - self.bitpayCardTransactionHistory = data.transactions; - self.bitpayCardCurrentBalance = data.balance; - }); - */ + var getFromCache = function() { + bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { + if (err || lodash.isEmpty(data)) return; + $scope.historyCached = true; + self.bitpayCardTransactionHistory = data.transactions; + self.bitpayCardCurrentBalance = data.balance; + $scope.$apply(); + }); + }; var setDateRange = function(preset) { var startDate, endDate; @@ -54,10 +56,17 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi self.bitpayCardTransactionHistory = history.transactionList; self.bitpayCardCurrentBalance = history.currentCardBalance; - var cacheData = { + var cacheHistory = { balance: self.bitpayCardCurrentBalance, transactions: self.bitpayCardTransactionHistory }; + bitpayCardService.setBitpayDebitCardsHistory($scope.cardId, cacheHistory, {}, function(err) { + if (err) $log.error(err); + $scope.historyCached = true; + }); + $timeout(function() { + $scope.$apply(); + }); }); }; @@ -93,6 +102,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $state.go('tabs.home'); popupService.showAlert(null, msg); } else { + getFromCache(); self.update(); } }); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 7e40a4e2c..996226957 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -206,12 +206,10 @@ angular.module('copayApp.controllers').controller('tabHomeController', if (err) return; $scope.bitpayCards = data.cards; }); - /* - bitpayCardService.getCacheData(function(err, data) { + bitpayCardService.getBitpayDebitCardsHistory(null, function(err, data) { if (err ||  lodash.isEmpty(data)) return; - $scope.bitpayCard = data; + $scope.cardsHistory = data; }); - */ }; $scope.onRefresh = function() { diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index e01441220..ca0c26b63 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -278,6 +278,49 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }); }; + root.getBitpayDebitCardsHistory = function(cardId, cb) { + _setCredentials(); + storageService.getBitpayDebitCardsHistory(credentials.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) { + _setCredentials(); + storageService.getBitpayDebitCardsHistory(credentials.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(credentials.NETWORK, inv, function(err) { + return cb(err); + }); + }); + }; + + root.removeBitpayDebitCardsHistory = function(cb) { + _setCredentials(); + storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { + if (err) return cb(err); + return cb(); + }); + }; + root.logout = function(cb) { _setCredentials(); storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index bbbcea5a0..1cce7006a 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -325,16 +325,16 @@ angular.module('copayApp.services') storage.remove('coinbaseTxs-' + network, cb); }; - root.setBitpayCard = function(network, data, cb) { - storage.set('bitpayCard-' + network, data, cb); + root.setBitpayDebitCardsHistory = function(network, data, cb) { + storage.set('bitpayDebitCardsHistory-' + network, data, cb); }; - root.getBitpayCard = function(network, cb) { - storage.get('bitpayCard-' + network, cb); + root.getBitpayDebitCardsHistory = function(network, cb) { + storage.get('bitpayDebitCardsHistory-' + network, cb); }; - root.removeBitpayCard = function(network, cb) { - storage.remove('bitpayCard-' + network, cb); + root.removeBitpayDebitCardsHistory = function(network, cb) { + storage.remove('bitpayDebitCardsHistory-' + network, cb); }; root.setBitpayDebitCards = function(network, data, cb) { diff --git a/www/views/tab-home.html b/www/views/tab-home.html index f3bbc976a..32dfafe21 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -78,40 +78,41 @@ {{wallet.m}}-of-{{wallet.n}} -

- - Incomplete - - - {{wallet.status.availableBalanceStr}} - [Balance Hidden] - -   -

- - - - -
-
-

BitPay Visa® Card

-

{{card.lastFourDigits}}

- -
- - -
-
-

BitPay Visa® Card

-

Add your cards

- -
-
+ + +

+ + Incomplete + + + {{wallet.status.availableBalanceStr}} + [Balance Hidden] + +   +

+ + + + +
+
+

BitPay Visa® Card

+

{{!cardsHistory[card.id].balance ? '$' + cardsHistory[card.id].balance : 'Add funds to get started'|translate}}

+ +
+ + +
+
+

BitPay Visa® Card

+

Add your cards

+ +
From c14a3b065880133ee228c702e3b77331611f2554 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 7 Oct 2016 13:52:55 -0300 Subject: [PATCH 06/22] Fix tab-home --- www/views/tab-home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 32dfafe21..a072aa704 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -100,7 +100,7 @@

BitPay Visa® Card

-

{{!cardsHistory[card.id].balance ? '$' + cardsHistory[card.id].balance : 'Add funds to get started'|translate}}

+

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

Date: Fri, 7 Oct 2016 15:51:15 -0300 Subject: [PATCH 07/22] Removes cards. Fix history. New method getInvoiceHistory --- src/js/controllers/bitpayCard.js | 13 ++--- src/js/controllers/bitpayCardIntro.js | 56 +++++++++++++-------- src/js/controllers/preferencesBitpayCard.js | 19 ++++--- src/js/routes.js | 1 + src/js/services/bitpayCardService.js | 27 ++++++---- www/views/bitpayCard.html | 6 +-- www/views/preferencesBitpayCard.html | 21 +++++--- 7 files changed, 89 insertions(+), 54 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index f92c3e461..56d6750a8 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -6,13 +6,13 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.dateRange = 'last30Days'; $scope.network = bitpayCardService.getEnvironment(); - var getFromCache = function() { + var getFromCache = function(cb) { bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { - if (err || lodash.isEmpty(data)) return; + if (err || lodash.isEmpty(data)) return cb(); $scope.historyCached = true; self.bitpayCardTransactionHistory = data.transactions; self.bitpayCardCurrentBalance = data.balance; - $scope.$apply(); + return cb(); }); }; @@ -53,7 +53,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi return; } - self.bitpayCardTransactionHistory = history.transactionList; + self.bitpayCardTransactionHistory = history.txs; self.bitpayCardCurrentBalance = history.currentCardBalance; var cacheHistory = { @@ -102,8 +102,9 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $state.go('tabs.home'); popupService.showAlert(null, msg); } else { - getFromCache(); - self.update(); + getFromCache(function() { + self.update(); + }); } }); diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 5e26a0218..09ea1a96c 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -1,6 +1,17 @@ 'use strict'; angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $state, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { + var checkOtp = function(obj, cb) { + if (obj.otp) { + var msg = gettextCatalog.getString('Enter Two Factor for BitPay Cards'); + popupService.showPrompt(null, msg, null, function(res) { + cb(res); + }); + } else { + cb(); + } + }; + $scope.$on("$ionicView.beforeEnter", function(event, data) { if (data.stateParams && data.stateParams.secret) { @@ -9,28 +20,31 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f email: data.stateParams.email, otp: data.stateParams.otp }; - bitpayCardService.bitAuthPair(obj, function(err, data) { - if (err) { - popupService.showAlert(null, err); - return; - } - var title = gettextCatalog.getString('Add BitPay Cards?'); - var msg = gettextCatalog.getString('Would you like to add this account ({{email}}) to your wallet?', {email: obj.email}); - var ok = gettextCatalog.getString('Add cards'); - var cancel = gettextCatalog.getString('Go back'); - popupService.showConfirm(title, msg, ok, cancel, function(res) { - if (res) { - // 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'); - }); + checkOtp(obj, function(otp) { + obj.otp = otp; + bitpayCardService.bitAuthPair(obj, function(err, data) { + if (err) { + popupService.showAlert(null, err); + return; } + var title = gettextCatalog.getString('Add BitPay Cards?'); + var msg = gettextCatalog.getString('Would you like to add this account ({{email}}) to your wallet?', {email: obj.email}); + var ok = gettextCatalog.getString('Add cards'); + var cancel = gettextCatalog.getString('Go back'); + popupService.showConfirm(title, msg, ok, cancel, function(res) { + if (res) { + // 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'); + }); + } + }); }); }); } else { diff --git a/src/js/controllers/preferencesBitpayCard.js b/src/js/controllers/preferencesBitpayCard.js index 536d4cde6..0fb74d228 100644 --- a/src/js/controllers/preferencesBitpayCard.js +++ b/src/js/controllers/preferencesBitpayCard.js @@ -1,17 +1,17 @@ 'use strict'; angular.module('copayApp.controllers').controller('preferencesBitpayCardController', - function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService) { + function($scope, $state, $timeout, $ionicHistory, bitpayCardService, popupService, gettextCatalog) { - $scope.logout = function() { - var msg = 'Are you sure you would like to log out of your BitPay Card account?'; + $scope.remove = function() { + var msg = gettextCatalog.getString('Are you sure you would like to remove your BitPay Card account from this device?'); popupService.showConfirm(null, msg, null, null, function(res) { - if (res) logout(); + if (res) remove(); }); }; - var logout = function() { - bitpayCardService.logout(function() { + var remove = function() { + bitpayCardService.remove(function() { $ionicHistory.removeBackView(); $timeout(function() { $state.go('tabs.home'); @@ -19,4 +19,11 @@ angular.module('copayApp.controllers').controller('preferencesBitpayCardControll }); }; + $scope.$on("$ionicView.beforeEnter", function(event, data) { + bitpayCardService.getBitpayDebitCards(function(err, data) { + if (err) return; + $scope.bitpayCards = data.cards; + }); + }); + }); diff --git a/src/js/routes.js b/src/js/routes.js index 72c269060..0a841ebe2 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -887,6 +887,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr url: '/preferences', views: { 'tab-home@tabs': { + controller: 'preferencesBitpayCardController', templateUrl: 'views/preferencesBitpayCard.html' } } diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index ca0c26b63..7c91bc8a4 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -194,15 +194,17 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, root.getHistory = function(cardId, params, cb) { params = params || {}; var json = {}; -// json = { -// method: 'getInvoiceHistory' -// }; + json = { + method: 'getInvoiceHistory', + params: JSON.stringify(params) + }; root.getBitpayDebitCards(function(err, data) { var card = lodash.find(data.cards, {id : cardId}); if (!card) return cb(_setError('No card available')); // Get invoices -// $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { -// var invoices = data.data.data; + $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { + $log.info('BitPay Get Invoices: SUCCESS'); + var invoices = data.data.data; json = { method: 'getTransactionHistory', params: JSON.stringify(params) @@ -211,14 +213,14 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { $log.info('BitPay Get Transactions: SUCCESS'); var history = data.data.data || data.data; -// history['txs'] = _processTransactions(invoices, history.transactionList); + history['txs'] = _processTransactions(invoices, history.transactionList); return cb(null, history); }, function(data) { return cb(_setError('BitPay Card Error: Get Transactions', data)); }); -// }, function(data) { -// return cb(_setError('BitPay Card Error: Get Invoices', data)); -// }); + }, function(data) { + return cb(_setError('BitPay Card Error: Get Invoices', data)); + }); }); }; @@ -321,10 +323,13 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }); }; - root.logout = function(cb) { + root.remove = function(cb) { _setCredentials(); storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { - $log.info('BitPay Logout: SUCCESS'); + storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { + $log.info('BitPay Debit Cards Removed: SUCCESS'); + return cb(); + }); }); }; diff --git a/www/views/bitpayCard.html b/www/views/bitpayCard.html index 12c972d3e..f0bff2c17 100644 --- a/www/views/bitpayCard.html +++ b/www/views/bitpayCard.html @@ -2,7 +2,7 @@ - BitPay Card + BitPay Visa® Card
-
+
diff --git a/www/views/preferencesBitpayCard.html b/www/views/preferencesBitpayCard.html index 12ae0a455..c20545f7b 100644 --- a/www/views/preferencesBitpayCard.html +++ b/www/views/preferencesBitpayCard.html @@ -2,14 +2,21 @@ - Preferences + BitPay Visa® Cards - -
    -
  • - Log out -
  • -
+ +
+
+ Cards +
+
+ xxxx-xxxx-xxxx-{{card.lastFourDigits}} +
+
+
+ Removes all data from this device +
+
From 222fbe57ff31dbcca1b79589ce4739d0c38c9be3 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 7 Oct 2016 19:21:46 -0300 Subject: [PATCH 08/22] Bitpay card config external json --- package.json | 1 + src/js/controllers/bitpayCardIntro.js | 7 +++-- src/js/services/bitpayCardService.js | 21 ++++++++++--- src/js/services/incomingData.js | 1 + util/buildExternalServices.js | 4 +++ www/views/bitpayCardIntro.html | 45 +++++++++++++++++++++++++++ www/views/tab-home.html | 2 +- 7 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 www/views/bitpayCardIntro.html diff --git a/package.json b/package.json index c690d4989..4d770f788 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "angular-mocks": "1.4.10", "bezier-easing": "^2.0.3", "bhttp": "^1.2.1", + "bitauth": "^0.3.2", "bitcore-wallet-client": "4.3.1", "bower": "^1.7.9", "chai": "^3.5.0", diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 09ea1a96c..fe87e4c4e 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, $state, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { +angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { var checkOtp = function(obj, cb) { if (obj.otp) { @@ -48,7 +48,10 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f }); }); } else { - // TODO + // TEST TODO + bitpayCardService.testSession(function(err, session) { + if (err) $log.error(err); + }); } /* diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 7c91bc8a4..3b4c1f7f8 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -1,24 +1,29 @@ 'use strict'; -angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService, bitauthService, platformInfo) { +angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, $window, lodash, storageService, bitauthService, platformInfo) { var root = {}; var credentials = {}; var bpSession = {}; var pubkey, sin; var _setCredentials = function() { + if (!$window.externalServices || !$window.externalServices.bitpayCard) { + return; + } + + var bitpayCard = $window.externalServices.bitpayCard; /* * Development: 'testnet' * Production: 'livenet' */ credentials.NETWORK = 'livenet'; if (credentials.NETWORK == 'testnet') { - credentials.BITPAY_PRIV_KEY = ''; - credentials.BITPAY_API_URL = 'https://test.bitpay.com'; + credentials.BITPAY_PRIV_KEY = bitpayCard.sandbox.secret; + credentials.BITPAY_API_URL = bitpayCard.sandbox.host; } else { - credentials.BITPAY_PRIV_KEY = ''; - credentials.BITPAY_API_URL = 'https://bitpay.com'; + credentials.BITPAY_PRIV_KEY = bitpayCard.production.secret; + credentials.BITPAY_API_URL = bitpayCard.production.host; } try { pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.BITPAY_PRIV_KEY); @@ -87,6 +92,12 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return credentials.BITPAY_API_URL; }; + root.testSession = function(cb) { + _getSession(function(err, session) { + return cb(err, session); + }); + }; + var _postBitAuth = function(endpoint, data) { var dataToSign = credentials.BITPAY_API_URL + endpoint + JSON.stringify(data); var signedData = bitauthService.sign(dataToSign, credentials.BITPAY_PRIV_KEY); diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index 33c2de8a9..53a3c483b 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -70,6 +70,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni // Plain URL } else if (/^https?:\/\//.test(data)) { + if ($state.current.name == 'tabs.bitpayCardIntro' || $state.current.name == 'tabs.buyandsell.glidera') return false; $state.go('tabs.send'); $timeout(function() { $state.transitionTo('tabs.send.confirm', {paypro: data}); diff --git a/util/buildExternalServices.js b/util/buildExternalServices.js index 630d03609..68a338bad 100755 --- a/util/buildExternalServices.js +++ b/util/buildExternalServices.js @@ -24,6 +24,10 @@ if (externalServices.glidera && if (externalServices.glidera && (externalServices.glidera.sandbox.mobile.client_id || externalServices.glidera.sandbox.desktop.client_id)) console.log('Glidera Sandbox Enabled'); +if (externalServices.bitpayCard && externalServices.bitpayCard.production.secret) + console.log('BitPay Card Production Enabled'); +if (externalServices.bitpayCard && externalServices.bitpayCard.sandbox.secret) + console.log('BitPay Card Sandbox Enabled'); var content = 'window.externalServices=' + JSON.stringify(externalServices) + ';'; fs.writeFileSync("./src/js/externalServices.js", content); diff --git a/www/views/bitpayCardIntro.html b/www/views/bitpayCardIntro.html new file mode 100644 index 000000000..7b42f3611 --- /dev/null +++ b/www/views/bitpayCardIntro.html @@ -0,0 +1,45 @@ + + + + + + + + + + +
+ +
+ + +

+ Turn bitcoin into dollars, swipe anywhere Visa® is accepted. +

+
+ +

+ Get local cash anywhere you go, from any Visa®-compatible ATM. +

+ *ATM bank fees may apply +
+

+
+ +

+ Pay 0% fees to turn bitcoin into dollars. +

+
+
+
+ + +
+
+
diff --git a/www/views/tab-home.html b/www/views/tab-home.html index a072aa704..e1754c82e 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -104,7 +104,7 @@
From 252ebf45b3dabde51b66853c04234a6de04542e4 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Mon, 10 Oct 2016 11:12:26 -0300 Subject: [PATCH 09/22] Fix handle URL (mobile). Replaces visa-api by api --- app-template/config-template.xml | 5 +++-- src/js/controllers/bitpayCardIntro.js | 2 +- src/js/services/bitpayCardService.js | 6 +++--- src/js/services/incomingData.js | 14 ++++++++++++-- www/views/bitpayCardIntro.html | 2 +- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 1db63c59a..98c36cf65 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -56,8 +56,9 @@ - - + + + diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index fe87e4c4e..4fc4589be 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -50,7 +50,7 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f } else { // TEST TODO bitpayCardService.testSession(function(err, session) { - if (err) $log.error(err); + if (err) popupService.showAlert(null, err); }); } diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 3b4c1f7f8..bd29fa3c6 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -44,7 +44,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, _setCredentials(); $http({ method: 'GET', - url: credentials.BITPAY_API_URL + '/visa-api/session', + url: credentials.BITPAY_API_URL + '/api/session', headers: { 'content-type': 'application/json' } @@ -154,12 +154,12 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, code: obj.otp }; - var dataToSign = credentials.BITPAY_API_URL + '/visa-api/validateBitAuthPairingCode' + JSON.stringify(userData); + var dataToSign = credentials.BITPAY_API_URL + '/api/validateBitAuthPairingCode' + JSON.stringify(userData); var signedData = bitauthService.sign(dataToSign, credentials.BITPAY_PRIV_KEY); $http({ method: 'POST', - url: credentials.BITPAY_API_URL + '/visa-api/validateBitAuthPairingCode', + url: credentials.BITPAY_API_URL + '/api/validateBitAuthPairingCode', headers: { 'content-type': 'application/json', 'x-csrf-token': session.csrfToken, diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index 53a3c483b..c48157052 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -1,9 +1,18 @@ 'use strict'; -angular.module('copayApp.services').factory('incomingData', function($log, $ionicModal, $state, $window, $timeout, bitcore) { +angular.module('copayApp.services').factory('incomingData', function($log, $ionicModal, $state, $window, $timeout, bitcore, lodash) { var root = {}; + var ignoreState = [ + 'tabs.language', + 'tabs.about.translators', + 'tabs.bitpayCardIntro', + 'tabs.buyandsell.glidera', + 'tabs.giftcards.amazon', + 'tabs.giftcards.amazon.buy' + ]; + root.redir = function(data) { $log.debug('Processing incoming data:' +data); @@ -70,7 +79,8 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni // Plain URL } else if (/^https?:\/\//.test(data)) { - if ($state.current.name == 'tabs.bitpayCardIntro' || $state.current.name == 'tabs.buyandsell.glidera') return false; + var currentState = $state.current.name; + if (lodash.indexOf(ignoreState, currentState) != -1) return false; $state.go('tabs.send'); $timeout(function() { $state.transitionTo('tabs.send.confirm', {paypro: data}); diff --git a/www/views/bitpayCardIntro.html b/www/views/bitpayCardIntro.html index 7b42f3611..262a5f710 100644 --- a/www/views/bitpayCardIntro.html +++ b/www/views/bitpayCardIntro.html @@ -22,7 +22,7 @@

Get local cash anywhere you go, from any Visa®-compatible ATM. -

From c916babe25b3c4ceec4f87c3b40d19fd5bcf422e Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 13 Oct 2016 17:49:48 -0300 Subject: [PATCH 21/22] Minor bug fixes. New bitauth method for getting token --- src/js/controllers/bitpayCard.js | 38 ++++++++----- src/js/controllers/confirm.js | 13 ++++- src/js/controllers/tab-home.js | 12 ++++- src/js/services/bitpayCardService.js | 80 ++++++++++++++++------------ www/views/bitpayCard.html | 24 ++++----- www/views/confirm.html | 7 +-- 6 files changed, 105 insertions(+), 69 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 80d15b697..ef5364b0b 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -3,7 +3,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $timeout, $log, $state, lodash, bitpayCardService, moment, popupService, gettextCatalog, $ionicHistory) { var self = this; - $scope.dateRange = 'last30Days'; + $scope.dateRange = { value: 'last30Days'}; $scope.network = bitpayCardService.getEnvironment(); var getFromCache = function(cb) { @@ -42,7 +42,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi }; this.update = function() { - var dateRange = setDateRange($scope.dateRange); + var dateRange = setDateRange($scope.dateRange.value); $scope.loadingHistory = true; bitpayCardService.getHistory($scope.cardId, dateRange, function(err, history) { @@ -53,39 +53,49 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi return; } - self.bitpayCardTransactionHistory = history.txs; + var txs = lodash.clone(history.txs); + for (var i = 0; i < txs.length; i++) { + txs[i] = _getMerchantInfo(txs[i]); + txs[i].icon = _getIconName(txs[i]); + txs[i].desc = _processDescription(txs[i]); + } + self.bitpayCardTransactionHistory = txs; self.bitpayCardCurrentBalance = history.currentCardBalance; - var cacheHistory = { - balance: self.bitpayCardCurrentBalance, - transactions: self.bitpayCardTransactionHistory - }; - bitpayCardService.setBitpayDebitCardsHistory($scope.cardId, cacheHistory, {}, function(err) { - if (err) $log.error(err); - $scope.historyCached = true; - }); + 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; + }); + } $timeout(function() { $scope.$apply(); }); }); }; - this.getMerchantInfo = function(tx) { + var _getMerchantInfo = function(tx) { var bpTranCodes = bitpayCardService.bpTranCodes; lodash.keys(bpTranCodes).forEach(function(code) { if (tx.type.indexOf(code) === 0) { lodash.assign(tx, bpTranCodes[code]); } }); + return tx; }; - this.getIconName = function(tx) { + var _getIconName = function(tx) { var icon = tx.mcc || tx.category || null; if (!icon) return 'default'; return bitpayCardService.iconMap[icon]; }; - this.processDescription = function(tx) { + var _processDescription = function(tx) { if (lodash.isArray(tx.description)) { return tx.description[0]; } diff --git a/src/js/controllers/confirm.js b/src/js/controllers/confirm.js index 5ee30b1b9..0b8949f3a 100644 --- a/src/js/controllers/confirm.js +++ b/src/js/controllers/confirm.js @@ -374,11 +374,22 @@ angular.module('copayApp.controllers').controller('confirmController', function( }; $scope.onSuccessConfirm = function() { + var previousView = $ionicHistory.viewHistory().backView && $ionicHistory.viewHistory().backView.stateName; + var fromBitPayCard = previousView.match(/tabs.bitpayCard/) ? true : false; + $ionicHistory.nextViewOptions({ disableAnimate: true }); + $ionicHistory.removeBackView(); $scope.sendStatus = ''; - $state.go('tabs.send'); + + if (fromBitPayCard) { + $timeout(function() { + $state.transitionTo('tabs.bitpayCard', {id: $stateParams.cardId}); + }, 100); + } else { + $state.go('tabs.send'); + } }; function publishAndSign(wallet, txp, onSendStatusChange) { diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 3e8f5cdc9..3d67a56f4 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -203,11 +203,19 @@ angular.module('copayApp.controllers').controller('tabHomeController', var bitpayCardCache = function() { bitpayCardService.getBitpayDebitCards(function(err, data) { - if (err || lodash.isEmpty(data)) return; + if (err) return; + if (lodash.isEmpty(data)) { + $scope.bitpayCards = null; + return; + } $scope.bitpayCards = data.cards; }); bitpayCardService.getBitpayDebitCardsHistory(null, function(err, data) { - if (err || lodash.isEmpty(data)) return; + if (err) return; + if (lodash.isEmpty(data)) { + $scope.cardsHistory = null; + return; + } $scope.cardsHistory = data; }); }; diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index b0f9c5882..884b57cbe 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($http, $log, lodash, storageService, bitauthService, platformInfo) { +angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService, bitauthService, platformInfo, moment) { var root = {}; var BITPAY_CARD_NETWORK = 'livenet'; var BITPAY_CARD_API_URL = BITPAY_CARD_NETWORK == 'livenet' ? 'https://bitpay.com' : 'https://test.bitpay.com'; @@ -47,7 +47,6 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; }; - var _post = function(endpoint, json, credentials) { var dataToSign = BITPAY_CARD_API_URL + endpoint + JSON.stringify(json); var signedData = bitauthService.sign(dataToSign, credentials.priv); @@ -64,26 +63,32 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; }; - var _afterBitAuthSuccess = function(obj, credentials, cb) { - var json = { - method: 'getTokens' + var _postAuth = function(endpoint, json, credentials) { + json['params'].signature = bitauthService.sign(JSON.stringify(json.params), credentials.priv); + json['params'].pubkey = credentials.pub; + json['params'] = JSON.stringify(json.params); + + return { + method: 'POST', + url: BITPAY_CARD_API_URL + endpoint, + headers: { + 'content-type': 'application/json' + }, + data: json }; - // Get tokens - $http(_post('/api/v2/', json, credentials)).then(function(data) { - $log.info('BitPay Get Tokens: SUCCESS'); - var token = lodash.find(data.data.data, 'visaUser'); - if (lodash.isEmpty(token)) return cb(_setError('No token for visaUser')); - token = token.visaUser; - json['method'] = 'getDebitCards'; - // Get Debit Cards - $http(_post('/api/v2/' + token, json, credentials)).then(function(data) { - $log.info('BitPay Get Debit Cards: SUCCESS'); - return cb(data.data.error, {token: token, cards: data.data.data, email: obj.email}); - }, function(data) { - return cb(_setError('BitPay Card Error: Get Debit Cards', data)); - }); + }; + + var _afterBitAuthSuccess = function(token, obj, credentials, cb) { + var json = { + method: 'getDebitCards' + }; + // Get Debit Cards + $http(_post('/api/v2/' + token, json, credentials)).then(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: token, cards: data.data.data, email: obj.email}); }, function(data) { - return cb(_setError('BitPay Card Error: Get Token', data)); + return cb(_setError('BitPay Card Error: Get Debit Cards', data)); }); }; @@ -96,16 +101,22 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, matched = true; } } - if (!matched && ['paid', 'confirmed', 'complete'].indexOf(invoices[i].status) > -1) { + var isInvoiceLessThanOneDayOld = moment() < moment(new Date(invoices[i].invoiceTime)).add(1, 'day'); + if (!matched && isInvoiceLessThanOneDayOld) { + var isInvoiceUnderpaid = invoices[i].exceptionStatus === 'paidPartial'; - history.unshift({ - timestamp: invoices[i].invoiceTime, - description: invoices[i].itemDesc, - amount: invoices[i].price, - type: '00611 = Client Funded Deposit', - pending: true, - status: invoices[i].status - }); + if(['paid', 'confirmed', 'complete'].indexOf(invoices[i].status) >= 0 + || (invoices[i].status === 'invalid' || isInvoiceUnderpaid)) { + + history.unshift({ + timestamp: new Date(invoices[i].invoiceTime), + description: invoices[i].itemDesc, + amount: invoices[i].price, + type: '00611 = Client Funded Deposit', + pending: true, + status: invoices[i].status + }); + } } } return history; @@ -139,11 +150,12 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; _getCredentials(function(err, credentials) { if (err) return cb(err); - $http(_post('/api/v2/', json, credentials)).then(function(data) { - $log.info('BitPay Card BitAuth: SUCCESS'); - _afterBitAuthSuccess(obj, credentials, cb); + $http(_postAuth('/api/v2/', json, credentials)).then(function(data) { + if (data && data.data.error) return cb(data.data.error); + $log.info('BitPay Card BitAuth Create Token: SUCCESS'); + _afterBitAuthSuccess(data.data.data, obj, credentials, cb); }, function(data) { - return cb(_setError('BitPay Card Error: BitAuth', data)); + return cb(_setError('BitPay Card Error Create Token: BitAuth', data)); }); }); }; @@ -164,7 +176,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, // Get invoices $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { $log.info('BitPay Get Invoices: SUCCESS'); - invoices = data.data.data; + invoices = data.data.data || []; if (lodash.isEmpty(invoices)) $log.info('No invoices'); json = { method: 'getTransactionHistory', diff --git a/www/views/bitpayCard.html b/www/views/bitpayCard.html index f0bff2c17..557b06869 100644 --- a/www/views/bitpayCard.html +++ b/www/views/bitpayCard.html @@ -21,7 +21,7 @@
${{bitpayCard.bitpayCardCurrentBalance}}
- {{'Add Funds'|translate}} + {{'Add Funds'|translate}}
@@ -45,20 +45,19 @@

Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.

-
+
-
-
- + ng-repeat="tx in bitpayCard.bitpayCardTransactionHistory | orderBy: ['pending','-timestamp']" + class="item row"> +
+
@@ -69,10 +68,8 @@ {{tx.merchant.city}}, {{tx.merchant.state}}
-
- {{desc}} +
+ {{tx.desc}}
@@ -85,7 +82,8 @@ 'text-gray': tx.amount.indexOf('-') == -1 && tx.pending}"> {{tx.amount | currency:'$':2 }}
- + + Pending
diff --git a/www/views/confirm.html b/www/views/confirm.html index 531a397b5..49c70ce85 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -25,11 +25,8 @@ - -
-
- {{toName}} - {{toAddress}} + {{toName}} + {{toAddress}}
From 00ae5f094ed2ca2e5264a21a50ba784e42ea2b24 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 13 Oct 2016 20:11:02 -0300 Subject: [PATCH 22/22] Fix open external link --- src/js/controllers/bitpayCardIntro.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index e2a6dd533..95d5cbfb2 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -61,14 +61,12 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f $scope.orderBitPayCard = function() { var url = 'https://bitpay.com/visa/'; - var target = '_system'; - externalLinkService.open(url, target); + externalLinkService.open(url); }; $scope.connectBitPayCard = function() { var url = 'https://bitpay.com/visa/login'; - var target = '_system'; - externalLinkService.open(url, target); + externalLinkService.open(url); }; });
+
*ATM bank fees may apply

From b82bdaaafc284aa669e86970e056228d9c29592c Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Mon, 10 Oct 2016 15:00:29 -0300 Subject: [PATCH 10/22] Support appUri --- app-template/config-template.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 98c36cf65..faa71f449 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -58,7 +58,7 @@ - + From 87535b3f2430b9a6ea9dffebf1327d882eca4930 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Mon, 10 Oct 2016 18:25:07 -0300 Subject: [PATCH 11/22] Generate local priv key --- src/js/controllers/bitpayCard.js | 4 +- src/js/controllers/tab-home.js | 4 +- src/js/services/bitpayCardService.js | 115 ++++++++++----------------- src/js/services/storageService.js | 12 +++ util/buildExternalServices.js | 4 - 5 files changed, 61 insertions(+), 78 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 56d6750a8..51a1c1b00 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -4,7 +4,9 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi var self = this; $scope.dateRange = 'last30Days'; - $scope.network = bitpayCardService.getEnvironment(); + bitpayCardService.getEnvironment(function(err, network) { + $scope.network = network; + }); var getFromCache = function(cb) { bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index 996226957..3e8f5cdc9 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -203,11 +203,11 @@ angular.module('copayApp.controllers').controller('tabHomeController', var bitpayCardCache = function() { bitpayCardService.getBitpayDebitCards(function(err, data) { - if (err) return; + if (err || lodash.isEmpty(data)) return; $scope.bitpayCards = data.cards; }); bitpayCardService.getBitpayDebitCardsHistory(null, function(err, data) { - if (err ||  lodash.isEmpty(data)) return; + if (err || lodash.isEmpty(data)) return; $scope.cardsHistory = data; }); }; diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index bd29fa3c6..2ddd97c86 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -6,32 +6,38 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, var bpSession = {}; var pubkey, sin; - var _setCredentials = function() { - if (!$window.externalServices || !$window.externalServices.bitpayCard) { - return; - } - - var bitpayCard = $window.externalServices.bitpayCard; + var _setCredentials = function(cb) { /* * Development: 'testnet' * Production: 'livenet' */ - credentials.NETWORK = 'livenet'; + credentials.NETWORK = 'testnet'; if (credentials.NETWORK == 'testnet') { - credentials.BITPAY_PRIV_KEY = bitpayCard.sandbox.secret; - credentials.BITPAY_API_URL = bitpayCard.sandbox.host; + credentials.BITPAY_API_URL = 'https://gustavo.bp:8088'; } else { - credentials.BITPAY_PRIV_KEY = bitpayCard.production.secret; - credentials.BITPAY_API_URL = bitpayCard.production.host; + credentials.BITPAY_API_URL = 'https://bitpay.com'; } - try { - pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.BITPAY_PRIV_KEY); - sin = bitauthService.getSinFromPublicKey(pubkey); - } - catch (e) { - $log.error(e); - }; + storageService.getBitpayDebitCardSin(credentials.NETWORK, function(err, data) { + if (err) return cb(err); + if (lodash.isString(data)) { + data = JSON.parse(data); + } + data = data || {}; + if (lodash.isEmpty(data) || (data && !data.priv)) { + data = bitauthService.generateSin(); + } + try { + credentials.BITPAY_PRIV_KEY = data.priv + pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.BITPAY_PRIV_KEY); + sin = bitauthService.getSinFromPublicKey(pubkey); + storageService.setBitpayDebitCardSin(credentials.NETWORK, JSON.stringify(data), function(err) {}); + } + catch (e) { + $log.error(e); + return cb(e); + }; + }); }; var _setError = function(msg, e) { @@ -41,7 +47,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; var _getSession = function(cb) { - _setCredentials(); + _setCredentials(cb); $http({ method: 'GET', url: credentials.BITPAY_API_URL + '/api/session', @@ -50,15 +56,13 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, } }).then(function(data) { $log.info('BitPay Get Session: SUCCESS'); - bpSession = data.data.data; - return cb(null, bpSession); + return cb(data.data.error, data.data.data); }, function(data) { return cb(_setError('BitPay Card Error: Get Session', data)); }); }; var _getBitPay = function(endpoint) { - _setCredentials(); return { method: 'GET', url: credentials.BITPAY_API_URL + endpoint, @@ -69,33 +73,13 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; }; - var _postBitPay = function(endpoint, data) { - _setCredentials(); - return { - method: 'POST', - url: credentials.BITPAY_API_URL + endpoint, - headers: { - 'Content-Type': 'application/json', - 'x-csrf-token': bpSession.csrfToken - }, - data: data - }; - }; - - root.getEnvironment = function() { - _setCredentials(); - return credentials.NETWORK; - }; - - root.getApiUrl = function() { - _setCredentials(); - return credentials.BITPAY_API_URL; + root.getEnvironment = function(cb) { + _setCredentials(cb); + return cb(null, credentials.NETWORK); }; root.testSession = function(cb) { - _getSession(function(err, session) { - return cb(err, session); - }); + _getSession(cb); }; var _postBitAuth = function(endpoint, data) { @@ -209,6 +193,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, method: 'getInvoiceHistory', params: JSON.stringify(params) }; + _setCredentials(cb); root.getBitpayDebitCards(function(err, data) { var card = lodash.find(data.cards, {id : cardId}); if (!card) return cb(_setError('No card available')); @@ -240,6 +225,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, method: 'generateTopUpInvoice', params: JSON.stringify(params) }; + _setCredentials(cb); root.getBitpayDebitCards(function(err, data) { var card = lodash.find(data.cards, {id : cardId}); if (!card) return cb(_setError('No card available')); @@ -254,6 +240,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.getInvoice = function(id, cb) { + _setCredentials(cb); $http(_getBitPay('/invoices/' + id)).then(function(data) { $log.info('BitPay Get Invoice: SUCCESS'); return cb(null, data.data.data); @@ -263,7 +250,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.getBitpayDebitCards = function(cb) { - _setCredentials(); + _setCredentials(cb); storageService.getBitpayDebitCards(credentials.NETWORK, function(err, data) { if (err) return cb(err); if (lodash.isString(data)) { @@ -275,7 +262,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.setBitpayDebitCards = function(data, cb) { - _setCredentials(); + _setCredentials(cb); data = JSON.stringify(data); storageService.setBitpayDebitCards(credentials.NETWORK, data, function(err) { if (err) return cb(err); @@ -283,16 +270,8 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }); }; - root.removeBitpayDebitCards = function(cb) { - _setCredentials(); - storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { - if (err) return cb(err); - return cb(); - }); - }; - root.getBitpayDebitCardsHistory = function(cardId, cb) { - _setCredentials(); + _setCredentials(cb); storageService.getBitpayDebitCardsHistory(credentials.NETWORK, function(err, data) { if (err) return cb(err); if (lodash.isString(data)) { @@ -305,7 +284,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.setBitpayDebitCardsHistory = function(cardId, data, opts, cb) { - _setCredentials(); + _setCredentials(cb); storageService.getBitpayDebitCardsHistory(credentials.NETWORK, function(err, oldData) { if (lodash.isString(oldData)) { oldData = JSON.parse(oldData); @@ -326,20 +305,14 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }); }; - root.removeBitpayDebitCardsHistory = function(cb) { - _setCredentials(); - storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { - if (err) return cb(err); - return cb(); - }); - }; - root.remove = function(cb) { - _setCredentials(); - storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { - storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { - $log.info('BitPay Debit Cards Removed: SUCCESS'); - return cb(); + _setCredentials(cb); + storageService.removeBitpayDebitCardSin(credentials.NETWORK, function(err) { + storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { + storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { + $log.info('BitPay Debit Cards Removed: SUCCESS'); + return cb(); + }); }); }); }; diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 1cce7006a..665d895a4 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -349,6 +349,18 @@ angular.module('copayApp.services') storage.remove('bitpayDebitCards-' + network, cb); }; + root.setBitpayDebitCardSin = function(network, data, cb) { + storage.set('bitpayDebitCardSin-' + network, data, cb); + }; + + root.getBitpayDebitCardSin = function(network, cb) { + storage.get('bitpayDebitCardSin-' + network, cb); + }; + + root.removeBitpayDebitCardSin = function(network, cb) { + storage.remove('bitpayDebitCardSin-' + network, cb); + }; + root.removeAllWalletData = function(walletId, cb) { root.clearLastAddress(walletId, function(err) { if (err) return cb(err); diff --git a/util/buildExternalServices.js b/util/buildExternalServices.js index 68a338bad..630d03609 100755 --- a/util/buildExternalServices.js +++ b/util/buildExternalServices.js @@ -24,10 +24,6 @@ if (externalServices.glidera && if (externalServices.glidera && (externalServices.glidera.sandbox.mobile.client_id || externalServices.glidera.sandbox.desktop.client_id)) console.log('Glidera Sandbox Enabled'); -if (externalServices.bitpayCard && externalServices.bitpayCard.production.secret) - console.log('BitPay Card Production Enabled'); -if (externalServices.bitpayCard && externalServices.bitpayCard.sandbox.secret) - console.log('BitPay Card Sandbox Enabled'); var content = 'window.externalServices=' + JSON.stringify(externalServices) + ';'; fs.writeFileSync("./src/js/externalServices.js", content); From 7edf1b28941b224456c37cc368a3e76217b1aab2 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Mon, 10 Oct 2016 18:37:07 -0300 Subject: [PATCH 12/22] Fix livenet --- src/js/services/bitpayCardService.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 2ddd97c86..49c9f97a2 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -11,9 +11,9 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, * Development: 'testnet' * Production: 'livenet' */ - credentials.NETWORK = 'testnet'; + credentials.NETWORK = 'livenet'; if (credentials.NETWORK == 'testnet') { - credentials.BITPAY_API_URL = 'https://gustavo.bp:8088'; + credentials.BITPAY_API_URL = 'https://test.bitpay.com'; } else { credentials.BITPAY_API_URL = 'https://bitpay.com'; From 756e1aa48990defe45f962b25c9c9dd7a2f38cfd Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 11 Oct 2016 10:50:43 -0300 Subject: [PATCH 13/22] Adds node-webkit support to package.json, icons/favicon. Fix setup-win syntax. Adds new constants to templates --- app-template/apply.js | 1 + app-template/bitpay/appConfig.json | 3 +- app-template/bitpay/img/favicon.ico | Bin 0 -> 1150 bytes app-template/bitpay/img/icon-128.png | Bin 0 -> 10158 bytes app-template/copay/appConfig.json | 5 ++- app-template/copay/img/favicon.ico | Bin 0 -> 5430 bytes app-template/copay/img/icon-128.png | Bin 0 -> 5774 bytes app-template/package.json | 55 ++++++++++++++++++--------- app-template/setup-win.iss | 2 +- package.json | 35 ++++++++++++++--- webkitbuilds/setup-win.iss | 2 +- www/img/favicon.ico | Bin 5430 -> 1150 bytes www/img/icon-128.png | Bin 0 -> 10158 bytes 13 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 app-template/bitpay/img/favicon.ico create mode 100644 app-template/bitpay/img/icon-128.png create mode 100644 app-template/copay/img/favicon.ico create mode 100644 app-template/copay/img/icon-128.png create mode 100644 www/img/icon-128.png diff --git a/app-template/apply.js b/app-template/apply.js index 14fdaab57..7ecad93d8 100755 --- a/app-template/apply.js +++ b/app-template/apply.js @@ -5,6 +5,7 @@ // var templates = { + 'package.json': '/', 'Makefile': 'cordova/', 'ProjectMakefile': 'cordova/', 'config-template.xml': '/', diff --git a/app-template/bitpay/appConfig.json b/app-template/bitpay/appConfig.json index 79eb58f52..54faf2203 100644 --- a/app-template/bitpay/appConfig.json +++ b/app-template/bitpay/appConfig.json @@ -5,12 +5,13 @@ "purposeLine": "Secure Bitcoin Wallet", "bundleName": "wallet", "appUri": "bitpay", - "name": "bitpay", "nameNoSpace": "bitpay", "nameCase": "BitPay", "nameCaseNoSpace": "BitPay", "gitHubRepoName": "bitpay-wallet", + "gitHubRepoUrl": "git://github.com/bitpay/bitpay-wallet.git", + "gitHubRepoBugs": "https://github.com/bitpay/bitpay-wallet/issues", "disclaimerUrl": "", "url": "https://bitpay.com", "appDescription": "Secure Bitcoin Wallet", diff --git a/app-template/bitpay/img/favicon.ico b/app-template/bitpay/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..166c0bcaf2ec99ad1d4623170ab46258b1195974 GIT binary patch literal 1150 zcmbW1TS${(7{}irlxF7K;oEuclsa|O5VHFqh>f=4OmQA!Ni3&>38ki{h8+mfE{ZZD zFQRS=x(rgh>Zb0x3+tu>ofga>!^r&ieDCM0bIhB*@%!HQd7j_@J6(*iUG!6{8J!(0 zv70f8F;-1bi#kf57RG3%Em7b#odQ-3@(J2B2->s?1?IVah`cQ{2v_J3vQySvhM;L5 z!nBV#q#TEQ>WNHqg%*OSLyu#oQiLsPbo)K%^0^VBYaG=SA?nnVr`vQzrq!W?OqA!aVYtHo#ho|ldX5mqrgy>o-tv*`rdq+;|`nKv`1Dh&`MycWc0 z{^-gi_a9CU;|ODTGJRR8Cx-Z3_C%()$_PP{`f=-C%ydM!pZV|(3v;)T{rrj7)6|b! zOCftAld3kMe}k0QjHE}8p(Za@HopI#->dk$wuXhfH__|XLUwX9=^8U~8K||O&smN) zFP`&zUT+Oxu+fb^S2@yN(>7PmogrUA*$?{dNLouUe``j0=d($iHWp#H!LiK~x#2ns zayeIT$AC+X*)IA9>+5*=_yN++GK^3^*Ax3uzZLn6`E3}fHQ~a+{kVF#5u?5>XDrX3 nsJEdIlMQx^`^*@tF%+DO%oKS$aq&O}WTqNyJ38Wj;D6VDcXRkY literal 0 HcmV?d00001 diff --git a/app-template/bitpay/img/icon-128.png b/app-template/bitpay/img/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..6958667cdab43fc831fa2c55d636159a7a7fe4f0 GIT binary patch literal 10158 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 QFg=d`B5*SiW-Y`12P0^O!~g&Q literal 0 HcmV?d00001 diff --git a/app-template/copay/img/icon-128.png b/app-template/copay/img/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..8624a018909ba87207259a38c979d01c7f716650 GIT binary patch literal 5774 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 literal 5430 zcmd5=|5H>|6n|#FHshbLKQ&Ed+1IK35`G^;16^1cLNpNqOB0t6#}Hca3(6M}kS`&K z8U!U@hE_Hc!hr_FZzPlsXdtF2nLrA`B7C~%(lXEY-oAai!q%C&``$h8obx&N+AUHRC5U-gAt{UYW!=pFISD@ul?s?B}O@&wJ6t zS`TZ`*htnS($%Ubm6PG7?2JZMk_o1$aBK|ng8$Mtr8?ri%;(k1=O8L90EuytD9B94 z$*V;-5BDBw7oIdA8SO2?_xz6dvQ9Nm5jgodXW$l0b_^(*(vd` zlow;e2g^0t>F>Lb!rZjSWGMzURpp2b^?!^n^mEXwtQX7BV z?M8maenq)p{X#{)*oL{Z5SN;MawsR(5x!pzRV{JYyAqoNn_+}pKMw<2E!7&!N&Ux`(~a3OnW|>36p%Fal0AY=98IYkH_4` zbL&$y-zvB>L3?b9=7!c=TZB8B}$HFBV%7I;*6m@e;XFP z=Bj_H*yNYrk~esMIJoC?6y;^0`eYd{UpR~ITU{6#vGTk=Ha3RdKkuRK*UPA{v7oFd zA2}(z5Fh<9{1(6Ns&5YUR(iYy%KgzB0+D2j!m;cFuv8S|LSr4eI<8@GU;w+fZFFcy zE&l(PZ(G?I>CVu4=^Tr53!8&Rc5Z%)^n@K)>+Lb6V=ODmcL^r}oo zs-w04^Z5pjPis8Xute4Fmi4}TUtDc%W@r4{s_++2%+IPEuf1>e|9m=~z z9qo#DELHn-x6(RRdvdhDh=zxTCUsrg!;|tUui7YfOUM(CM{3_upVr`m{yy$P?Wsz) zUJNf&brrghxhCl#AN)GNv;>1pMeJ_`rs zK%!*RR+;@k&)Gaa^qu4?iVHwKX|=CKj_M>L+6&u036k4pc;Nx>q2*!|m&;`Jx)!_6 z$P^#RUi4cd6E)`KB|M z{!^g&XgG5k`G*pbx_diLn@e%~<_&f?^>l>KYa(ajFO~IK_zJdfT8o?myLcU)pOJ_! zB0qwDzNWKpydGmQmD+Vj-&PAUEO*v^wz2a1i)z6Cvi>A|B2g{quqJYGZm8Cg)!(&( QFg=d`B5*SiW-Y`12P0^O!~g&Q diff --git a/www/img/icon-128.png b/www/img/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..6958667cdab43fc831fa2c55d636159a7a7fe4f0 GIT binary patch literal 10158 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 Date: Tue, 11 Oct 2016 14:50:35 -0300 Subject: [PATCH 14/22] New pairing request --- src/js/controllers/bitpayCard.js | 8 +- src/js/controllers/bitpayCardIntro.js | 23 +-- src/js/services/bitpayCardService.js | 266 +++++++++++--------------- src/js/services/storageService.js | 12 +- 4 files changed, 130 insertions(+), 179 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 51a1c1b00..97f1ef402 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -4,9 +4,7 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi var self = this; $scope.dateRange = 'last30Days'; - bitpayCardService.getEnvironment(function(err, network) { - $scope.network = network; - }); + $scope.network = bitpayCardService.getEnvironment(); var getFromCache = function(cb) { bitpayCardService.getBitpayDebitCardsHistory($scope.cardId, function(err, data) { @@ -49,8 +47,8 @@ angular.module('copayApp.controllers').controller('bitpayCardController', functi $scope.loadingHistory = true; bitpayCardService.getHistory($scope.cardId, dateRange, function(err, history) { $scope.loadingHistory = false; - if (err || history.error) { - $log.error(err || history.error); + if (err) { + $log.error(err); $scope.error = gettextCatalog.getString('Could not get transactions'); return; } diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index 4fc4589be..f56f0360c 100644 --- a/src/js/controllers/bitpayCardIntro.js +++ b/src/js/controllers/bitpayCardIntro.js @@ -42,31 +42,22 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f disableAnimate: true }); $state.go('tabs.home'); + if (data.cards[0]) { + $timeout(function() { + $state.transitionTo('tabs.bitpayCard', {id: data.cards[0].id}); + }, 100); + } }); } }); }); }); } else { - // TEST TODO - bitpayCardService.testSession(function(err, session) { + bitpayCardService.getCredentials(function(err, credentials) { if (err) popupService.showAlert(null, err); + else $log.info('BitPay Debit Card Credentials: Ok.'); }); } - - /* - storageService.getNextStep('BitpayCard', function(err, value) { - if (value) { - $ionicHistory.nextViewOptions({ - disableAnimate: true - }); - $state.go('tabs.home'); - $timeout(function() { - $state.transitionTo('tabs.bitpayCard'); - }, 100); - } - }); - */ }); $scope.orderBitPayCard = function() { diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 49c9f97a2..36b8f97ad 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -2,41 +2,32 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, $window, lodash, storageService, bitauthService, platformInfo) { var root = {}; - var credentials = {}; - var bpSession = {}; - var pubkey, sin; + var BITPAY_CARD_NETWORK = 'livenet'; + var BITPAY_CARD_API_URL = BITPAY_CARD_NETWORK == 'livenet' ? 'https://bitpay.com' : 'https://test.bitpay.com'; - var _setCredentials = function(cb) { - /* - * Development: 'testnet' - * Production: 'livenet' - */ - credentials.NETWORK = 'livenet'; - if (credentials.NETWORK == 'testnet') { - credentials.BITPAY_API_URL = 'https://test.bitpay.com'; - } - else { - credentials.BITPAY_API_URL = 'https://bitpay.com'; - } - storageService.getBitpayDebitCardSin(credentials.NETWORK, function(err, data) { + var _getCredentials = function(cb) { + var pubkey, sin, isNew; + storageService.getBitpayCardCredentials(BITPAY_CARD_NETWORK, function(err, data) { if (err) return cb(err); if (lodash.isString(data)) { data = JSON.parse(data); } - data = data || {}; - if (lodash.isEmpty(data) || (data && !data.priv)) { - data = bitauthService.generateSin(); + var credentials = data || {}; + if (lodash.isEmpty(credentials) || (credentials && !credentials.priv)) { + isNew = true; + credentials = bitauthService.generateSin(); } try { - credentials.BITPAY_PRIV_KEY = data.priv - pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.BITPAY_PRIV_KEY); + pubkey = bitauthService.getPublicKeyFromPrivateKey(credentials.priv); sin = bitauthService.getSinFromPublicKey(pubkey); - storageService.setBitpayDebitCardSin(credentials.NETWORK, JSON.stringify(data), function(err) {}); + if (isNew) + storageService.setBitpayCardCredentials(BITPAY_CARD_NETWORK, JSON.stringify(credentials), function(err) {}); } catch (e) { $log.error(e); return cb(e); }; + return cb(null, credentials); }); }; @@ -46,74 +37,48 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return error; }; - var _getSession = function(cb) { - _setCredentials(cb); - $http({ + var _get = function(endpoint) { + return { method: 'GET', - url: credentials.BITPAY_API_URL + '/api/session', + url: BITPAY_CARD_API_URL + endpoint, headers: { 'content-type': 'application/json' } - }).then(function(data) { - $log.info('BitPay Get Session: SUCCESS'); - return cb(data.data.error, data.data.data); - }, function(data) { - return cb(_setError('BitPay Card Error: Get Session', data)); - }); - }; - - var _getBitPay = function(endpoint) { - return { - method: 'GET', - url: credentials.BITPAY_API_URL + endpoint, - headers: { - 'content-type': 'application/json', - 'x-csrf-token': bpSession.csrfToken - } }; }; - root.getEnvironment = function(cb) { - _setCredentials(cb); - return cb(null, credentials.NETWORK); - }; - root.testSession = function(cb) { - _getSession(cb); - }; - - var _postBitAuth = function(endpoint, data) { - var dataToSign = credentials.BITPAY_API_URL + endpoint + JSON.stringify(data); - var signedData = bitauthService.sign(dataToSign, credentials.BITPAY_PRIV_KEY); + var _post = function(endpoint, json, credentials) { + var dataToSign = BITPAY_CARD_API_URL + endpoint + JSON.stringify(json); + var signedData = bitauthService.sign(dataToSign, credentials.priv); return { method: 'POST', - url: credentials.BITPAY_API_URL + endpoint, + url: BITPAY_CARD_API_URL + endpoint, headers: { 'content-type': 'application/json', - 'x-identity': pubkey, + 'x-identity': credentials.pub, 'x-signature': signedData }, - data: data + data: json }; }; - var _afterBitAuthSuccess = function(obj, cb) { - var data = { + var _afterBitAuthSuccess = function(obj, credentials, cb) { + var json = { method: 'getTokens' }; // Get tokens - $http(_postBitAuth('/api/v2/', data)).then(function(data) { + $http(_post('/api/v2/', json, credentials)).then(function(data) { $log.info('BitPay Get Tokens: SUCCESS'); var token = lodash.find(data.data.data, 'visaUser'); if (lodash.isEmpty(token)) return cb(_setError('No token for visaUser')); token = token.visaUser; - data['method'] = 'getDebitCards'; + json['method'] = 'getDebitCards'; // Get Debit Cards - $http(_postBitAuth('/api/v2/' + token, data)).then(function(data) { + $http(_post('/api/v2/' + token, json, credentials)).then(function(data) { $log.info('BitPay Get Debit Cards: SUCCESS'); - var cards = data.data.data; - return cb(null, {token: token, cards: cards, email: obj.email}); + return cb(data.data.error, {token: token, cards: data.data.data, email: obj.email}); }, function(data) { return cb(_setError('BitPay Card Error: Get Debit Cards', data)); }); @@ -122,46 +87,6 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }); }; - root.bitAuthPair = function(obj, cb) { - _getSession(function(err, session) { - if (err) return cb(err); - var deviceName = 'Unknow device'; - if (platformInfo.isNW) { - deviceName = require('os').platform(); - } else if (platformInfo.isCordova) { - deviceName = device.model; - } - var userData = { - csrf: session.csrfToken, - secret: obj.secret, - deviceName: deviceName, - code: obj.otp - }; - - var dataToSign = credentials.BITPAY_API_URL + '/api/validateBitAuthPairingCode' + JSON.stringify(userData); - var signedData = bitauthService.sign(dataToSign, credentials.BITPAY_PRIV_KEY); - - $http({ - method: 'POST', - url: credentials.BITPAY_API_URL + '/api/validateBitAuthPairingCode', - headers: { - 'content-type': 'application/json', - 'x-csrf-token': session.csrfToken, - 'x-identity': pubkey, - 'x-signature': signedData - }, - data: userData - }).then(function(data) { - $log.info('BitPay Card BitAuth: SUCCESS'); - // Get cards - _afterBitAuthSuccess(obj, cb); - }, function(data) { - return cb(_setError('BitPay Card Error: BitAuth', data)); - }); - - }); - }; - var _processTransactions = function(invoices, history) { invoices = invoices || []; for (var i = 0; i < invoices.length; i++) { @@ -186,72 +111,113 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, return history; }; + root.getEnvironment = function() { + return BITPAY_CARD_NETWORK; + }; + + root.getCredentials = function(cb) { + _getCredentials(function(err, credentials) { + return cb(err, credentials); + }); + }; + + root.bitAuthPair = function(obj, cb) { + var deviceName = 'Unknow device'; + if (platformInfo.isNW) { + deviceName = require('os').platform(); + } else if (platformInfo.isCordova) { + deviceName = device.model; + } + var json = { + method: 'registerSinWithSecret', + params: { + secret: obj.secret, + deviceName: deviceName, + code: obj.otp + } + }; + _getCredentials(function(err, credentials) { + if (err) return cb(err); + $http(_post('/api/v2/', json, credentials)).then(function(data) { + $log.info('BitPay Card BitAuth: SUCCESS'); + _afterBitAuthSuccess(obj, credentials, cb); + }, function(data) { + return cb(_setError('BitPay Card Error: BitAuth', data)); + }); + }); + }; + root.getHistory = function(cardId, params, cb) { + var invoices, transactions; params = params || {}; - var json = {}; - json = { + var json = { method: 'getInvoiceHistory', params: JSON.stringify(params) }; - _setCredentials(cb); - root.getBitpayDebitCards(function(err, data) { - var card = lodash.find(data.cards, {id : cardId}); - if (!card) return cb(_setError('No card available')); - // Get invoices - $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { - $log.info('BitPay Get Invoices: SUCCESS'); - var invoices = data.data.data; - json = { - method: 'getTransactionHistory', - params: JSON.stringify(params) - }; - // Get transactions list - $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { - $log.info('BitPay Get Transactions: SUCCESS'); - var history = data.data.data || data.data; - history['txs'] = _processTransactions(invoices, history.transactionList); - return cb(null, history); + _getCredentials(function(err, credentials) { + if (err) return cb(err); + root.getBitpayDebitCards(function(err, data) { + if (err) return cb(err); + var card = lodash.find(data.cards, {id : cardId}); + if (!card) return cb(_setError('Not card found')); + // Get invoices + $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $log.info('BitPay Get Invoices: SUCCESS'); + invoices = data.data.data; + if (lodash.isEmpty(invoices)) $log.info('No invoices'); + json = { + method: 'getTransactionHistory', + params: JSON.stringify(params) + }; + // Get transactions list + $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $log.info('BitPay Get Transactions: SUCCESS'); + transactions = data.data.data || {}; + transactions['txs'] = _processTransactions(invoices, transactions.transactionList); + 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 Transactions', data)); + return cb(_setError('BitPay Card Error: Get Invoices', data)); }); - }, function(data) { - return cb(_setError('BitPay Card Error: Get Invoices', data)); }); }); }; root.topUp = function(cardId, params, cb) { + params = params || {}; var json = { method: 'generateTopUpInvoice', params: JSON.stringify(params) }; - _setCredentials(cb); - root.getBitpayDebitCards(function(err, data) { - var card = lodash.find(data.cards, {id : cardId}); - if (!card) return cb(_setError('No card available')); - $http(_postBitAuth('/api/v2/' + card.token, json)).then(function(data) { - $log.info('BitPay TopUp: SUCCESS'); - var invoiceId = data.data.data.invoice; - return cb(null, invoiceId); - }, function(data) { - return cb(_setError('BitPay Card Error: TopUp', data)); + _getCredentials(function(err, credentials) { + if (err) return cb(err); + root.getBitpayDebitCards(function(err, data) { + if (err) return cb(err); + var card = lodash.find(data.cards, {id : cardId}); + if (!card) return cb(_setError('Not card found')); + $http(_post('/api/v2/' + card.token, json, credentials)).then(function(data) { + $log.info('BitPay TopUp: SUCCESS'); + return cb(data.data.error, data.data.data.invoice); + }, function(data) { + return cb(_setError('BitPay Card Error: TopUp', data)); + }); }); }); }; root.getInvoice = function(id, cb) { - _setCredentials(cb); - $http(_getBitPay('/invoices/' + id)).then(function(data) { + $http(_get('/invoices/' + id)).then(function(data) { $log.info('BitPay Get Invoice: SUCCESS'); - return cb(null, data.data.data); + return cb(data.data.error, data.data.data); }, function(data) { return cb(_setError('BitPay Card Error: Get Invoice', data)); }); }; root.getBitpayDebitCards = function(cb) { - _setCredentials(cb); - storageService.getBitpayDebitCards(credentials.NETWORK, function(err, data) { + storageService.getBitpayDebitCards(BITPAY_CARD_NETWORK, function(err, data) { if (err) return cb(err); if (lodash.isString(data)) { data = JSON.parse(data); @@ -262,17 +228,15 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.setBitpayDebitCards = function(data, cb) { - _setCredentials(cb); data = JSON.stringify(data); - storageService.setBitpayDebitCards(credentials.NETWORK, data, function(err) { + storageService.setBitpayDebitCards(BITPAY_CARD_NETWORK, data, function(err) { if (err) return cb(err); return cb(); }); }; root.getBitpayDebitCardsHistory = function(cardId, cb) { - _setCredentials(cb); - storageService.getBitpayDebitCardsHistory(credentials.NETWORK, function(err, data) { + storageService.getBitpayDebitCardsHistory(BITPAY_CARD_NETWORK, function(err, data) { if (err) return cb(err); if (lodash.isString(data)) { data = JSON.parse(data); @@ -284,8 +248,7 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, }; root.setBitpayDebitCardsHistory = function(cardId, data, opts, cb) { - _setCredentials(cb); - storageService.getBitpayDebitCardsHistory(credentials.NETWORK, function(err, oldData) { + storageService.getBitpayDebitCardsHistory(BITPAY_CARD_NETWORK, function(err, oldData) { if (lodash.isString(oldData)) { oldData = JSON.parse(oldData); } @@ -299,17 +262,16 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, } inv = JSON.stringify(inv); - storageService.setBitpayDebitCardsHistory(credentials.NETWORK, inv, function(err) { + storageService.setBitpayDebitCardsHistory(BITPAY_CARD_NETWORK, inv, function(err) { return cb(err); }); }); }; root.remove = function(cb) { - _setCredentials(cb); - storageService.removeBitpayDebitCardSin(credentials.NETWORK, function(err) { - storageService.removeBitpayDebitCards(credentials.NETWORK, function(err) { - storageService.removeBitpayDebitCardsHistory(credentials.NETWORK, function(err) { + storageService.removeBitpayCardCredentials(BITPAY_CARD_NETWORK, function(err) { + storageService.removeBitpayDebitCards(BITPAY_CARD_NETWORK, function(err) { + storageService.removeBitpayDebitCardsHistory(BITPAY_CARD_NETWORK, function(err) { $log.info('BitPay Debit Cards Removed: SUCCESS'); return cb(); }); diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 665d895a4..60f01a3c8 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -349,16 +349,16 @@ angular.module('copayApp.services') storage.remove('bitpayDebitCards-' + network, cb); }; - root.setBitpayDebitCardSin = function(network, data, cb) { - storage.set('bitpayDebitCardSin-' + network, data, cb); + root.setBitpayCardCredentials = function(network, data, cb) { + storage.set('bitpayCardCredentials-' + network, data, cb); }; - root.getBitpayDebitCardSin = function(network, cb) { - storage.get('bitpayDebitCardSin-' + network, cb); + root.getBitpayCardCredentials = function(network, cb) { + storage.get('bitpayCardCredentials-' + network, cb); }; - root.removeBitpayDebitCardSin = function(network, cb) { - storage.remove('bitpayDebitCardSin-' + network, cb); + root.removeBitpayCardCredentials = function(network, cb) { + storage.remove('bitpayCardCredentials-' + network, cb); }; root.removeAllWalletData = function(walletId, cb) { From bb6b11be783c70a8002a8f1247d0025316edf180 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 11 Oct 2016 17:07:02 -0300 Subject: [PATCH 15/22] Updates package.json --- app-template/package.json | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app-template/package.json b/app-template/package.json index 6b1c77033..a81a37f6d 100644 --- a/app-template/package.json +++ b/app-template/package.json @@ -45,6 +45,7 @@ "adm-zip": "^0.4.7", "angular": "1.4.6", "angular-mocks": "1.4.10", + "bezier-easing": "^2.0.3", "bhttp": "^1.2.1", "bitauth": "^0.3.2", "bitcore-wallet-client": "4.2.1", diff --git a/package.json b/package.json index b9099cefa..fd30b3f2e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "//":" Modify it at app-template/", "name": "bitpay", - "description": "Secure Bitcoin Storage", + "description": "Secure Bitcoin Wallet", "author": "BitPay", "version": "0.14.0", "keywords": [ From 95c0371f9b9ee0021f6e2c015f69c4a5722d743f Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 12 Oct 2016 09:38:41 -0300 Subject: [PATCH 16/22] Ref and clean code --- src/js/controllers/bitpayCard.js | 2 +- src/js/controllers/bitpayCardIntro.js | 11 ++++--- src/js/services/bitpayCardService.js | 2 +- src/js/services/incomingData.js | 42 +++++++++++---------------- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/js/controllers/bitpayCard.js b/src/js/controllers/bitpayCard.js index 97f1ef402..80d15b697 100644 --- a/src/js/controllers/bitpayCard.js +++ b/src/js/controllers/bitpayCard.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $timeout, $log, $state, lodash, bitpayCardService, configService, profileService, walletService, ongoingProcess, moment, popupService, gettextCatalog, bwcError, $ionicHistory) { +angular.module('copayApp.controllers').controller('bitpayCardController', function($scope, $timeout, $log, $state, lodash, bitpayCardService, moment, popupService, gettextCatalog, $ionicHistory) { var self = this; $scope.dateRange = 'last30Days'; diff --git a/src/js/controllers/bitpayCardIntro.js b/src/js/controllers/bitpayCardIntro.js index f56f0360c..e2a6dd533 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, $timeout, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { +angular.module('copayApp.controllers').controller('bitpayCardIntroController', function($scope, $log, $state, $ionicHistory, storageService, externalLinkService, bitpayCardService, gettextCatalog, popupService) { var checkOtp = function(obj, cb) { if (obj.otp) { @@ -41,12 +41,11 @@ angular.module('copayApp.controllers').controller('bitpayCardIntroController', f $ionicHistory.nextViewOptions({ disableAnimate: true }); - $state.go('tabs.home'); - if (data.cards[0]) { - $timeout(function() { + $state.go('tabs.home').then(function() { + if (data.cards[0]) { $state.transitionTo('tabs.bitpayCard', {id: data.cards[0].id}); - }, 100); - } + } + }); }); } }); diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 36b8f97ad..4b5c5b96f 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($http, $log, $window, lodash, storageService, bitauthService, platformInfo) { +angular.module('copayApp.services').factory('bitpayCardService', function($http, $log, lodash, storageService, bitauthService, platformInfo) { var root = {}; var BITPAY_CARD_NETWORK = 'livenet'; var BITPAY_CARD_API_URL = BITPAY_CARD_NETWORK == 'livenet' ? 'https://bitpay.com' : 'https://test.bitpay.com'; diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index c48157052..bb0f3a66d 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('incomingData', function($log, $ionicModal, $state, $window, $timeout, bitcore, lodash) { +angular.module('copayApp.services').factory('incomingData', function($log, $state, $window, bitcore, lodash) { var root = {}; @@ -45,10 +45,9 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni // data extensions for Payment Protocol with non-backwards-compatible request if ((/^bitcoin:\?r=[\w+]/).exec(data)) { data = decodeURIComponent(data.replace('bitcoin:?r=', '')); - $state.go('tabs.send'); - $timeout(function() { + $state.go('tabs.send').then(function() { $state.transitionTo('tabs.send.confirm', {paypro: data}); - }, 100); + }); return true; } @@ -63,8 +62,7 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni var amount = parsed.amount ? parsed.amount : ''; - $state.go('tabs.send'); - $timeout(function() { + $state.go('tabs.send').then(function() { if (parsed.r) { $state.transitionTo('tabs.send.confirm', {paypro: parsed.r}); } else { @@ -74,31 +72,28 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni $state.transitionTo('tabs.send.amount', {toAddress: addr}); } } - }, 100); + }); return true; // Plain URL } else if (/^https?:\/\//.test(data)) { var currentState = $state.current.name; if (lodash.indexOf(ignoreState, currentState) != -1) return false; - $state.go('tabs.send'); - $timeout(function() { + $state.go('tabs.send').then(function() { $state.transitionTo('tabs.send.confirm', {paypro: data}); - }, 100); + }); return true; // Plain Address } else if (bitcore.Address.isValid(data, 'livenet')) { - $state.go('tabs.send'); - $timeout(function() { + $state.go('tabs.send').then(function() { $state.transitionTo('tabs.send.amount', {toAddress: data}); - }, 100); + }); return true; } else if (bitcore.Address.isValid(data, 'testnet')) { - $state.go('tabs.send'); - $timeout(function() { + $state.go('tabs.send').then(function() { $state.transitionTo('tabs.send.amount', {toAddress: data}); - }, 100); + }); return true; // Protocol @@ -112,30 +107,27 @@ angular.module('copayApp.services').factory('incomingData', function($log, $ioni var secret = getParameterByName('secret', data); var email = getParameterByName('email', data); var otp = getParameterByName('otp', data); - $state.go('tabs.home'); - $timeout(function() { + $state.go('tabs.home').then(function() { $state.transitionTo('tabs.bitpayCardIntro', { secret: secret, email: email, otp: otp }); - }, 100); + }); return true; // Join } else if (data && data.match(/^copay:[0-9A-HJ-NP-Za-km-z]{70,80}$/)) { - $state.go('tabs.home'); - $timeout(function() { + $state.go('tabs.home').then(function() { $state.transitionTo('tabs.add.join', {url: data}); - }, 100); + }); return true; // Old join } else if (data && data.match(/^[0-9A-HJ-NP-Za-km-z]{70,80}$/)) { - $state.go('tabs.home'); - $timeout(function() { + $state.go('tabs.home').then(function() { $state.transitionTo('tabs.add.join', {url: data}); - }, 100); + }); return true; } From 4ef66f65160c350b07bf023786a6aa46100360b1 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 12 Oct 2016 11:58:24 -0300 Subject: [PATCH 17/22] Updates package.json --- app-template/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-template/package.json b/app-template/package.json index a81a37f6d..ce57f4461 100644 --- a/app-template/package.json +++ b/app-template/package.json @@ -48,7 +48,7 @@ "bezier-easing": "^2.0.3", "bhttp": "^1.2.1", "bitauth": "^0.3.2", - "bitcore-wallet-client": "4.2.1", + "bitcore-wallet-client": "4.3.1", "bower": "^1.7.9", "chai": "^3.5.0", "cordova": "5.4.1", From b2086701d801707be4a186bf6cc9331244a2d661 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 12 Oct 2016 12:00:35 -0300 Subject: [PATCH 18/22] Not necessary anymore --- src/js/services/incomingData.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index bb0f3a66d..b157704b8 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -4,15 +4,6 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat var root = {}; - var ignoreState = [ - 'tabs.language', - 'tabs.about.translators', - 'tabs.bitpayCardIntro', - 'tabs.buyandsell.glidera', - 'tabs.giftcards.amazon', - 'tabs.giftcards.amazon.buy' - ]; - root.redir = function(data) { $log.debug('Processing incoming data:' +data); @@ -77,8 +68,6 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat // Plain URL } else if (/^https?:\/\//.test(data)) { - var currentState = $state.current.name; - if (lodash.indexOf(ignoreState, currentState) != -1) return false; $state.go('tabs.send').then(function() { $state.transitionTo('tabs.send.confirm', {paypro: data}); }); From 9b32e50bb0d449561dd2dc8732cd84bb5aa5215f Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Wed, 12 Oct 2016 15:32:05 -0300 Subject: [PATCH 19/22] Updates bitauth pairing. Updates package.json --- app-template/package.json | 10 ++++------ src/js/services/bitpayCardService.js | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app-template/package.json b/app-template/package.json index ce57f4461..6f535b9d5 100644 --- a/app-template/package.json +++ b/app-template/package.json @@ -51,8 +51,8 @@ "bitcore-wallet-client": "4.3.1", "bower": "^1.7.9", "chai": "^3.5.0", - "cordova": "5.4.1", "cordova-android": "5.1.1", + "cordova-custom-config": "^3.0.5", "cordova-plugin-qrscanner": "^2.3.1", "coveralls": "^2.11.9", "express": "^4.11.2", @@ -112,12 +112,10 @@ "clean-all": "git clean -dfx && npm install" }, "devDependencies": { - "androidmanifest": "^2.0.0", - "cordova": "^5.4.1", - "globby": "^6.0.0", + "cordova": "^6.3.1", + "grunt": "^1.0.1", "ionic": "^2.1.0", - "plist": "^2.0.1", "trash-cli": "^1.4.0", - "xcode": "^0.8.2" + "lodash": "^4.3.0" } } diff --git a/src/js/services/bitpayCardService.js b/src/js/services/bitpayCardService.js index 4b5c5b96f..b0f9c5882 100644 --- a/src/js/services/bitpayCardService.js +++ b/src/js/services/bitpayCardService.js @@ -129,9 +129,10 @@ angular.module('copayApp.services').factory('bitpayCardService', function($http, deviceName = device.model; } var json = { - method: 'registerSinWithSecret', + method: 'createToken', params: { secret: obj.secret, + version: 2, deviceName: deviceName, code: obj.otp } From 8ee033436f696381ed13d5c2838a5fb5af3a66be Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 13 Oct 2016 14:41:37 -0300 Subject: [PATCH 20/22] Fix conflict --- www/views/confirm.html | 5 +-- www/views/tab-home.html | 68 ++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/www/views/confirm.html b/www/views/confirm.html index 9886ca270..531a397b5 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -23,17 +23,18 @@