From 48a16dfc941a0f8c140c002719aaca203f0e5c2a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Sun, 7 Dec 2014 21:01:31 -0300 Subject: [PATCH 01/15] v0.8.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b53ed4117..1a1edbae9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "copay", "description": "A multisignature wallet", "author": "BitPay", - "version": "0.8.3", + "version": "0.8.4", "keywords": [ "wallet", "copay", From 7f42d60d5d20a1fcfa10f94ac66bdf5e0ffd195e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Dec 2014 11:05:16 -0300 Subject: [PATCH 02/15] fix comment of: https://github.com/bitpay/copay/issues/2045 --- views/send.html | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/views/send.html b/views/send.html index 6036838e0..03771d58e 100644 --- a/views/send.html +++ b/views/send.html @@ -80,7 +80,7 @@
-
-
-

This is a payment protocol transaction

+
+

This is a payment protocol transaction

- Payment to: {{$root.merchant.pr.pd.memo || address}}

@@ -148,11 +147,6 @@ {{ alternative }} {{ alternativeIsoCode }} - - (Including fee of - {{defaultFee}} - {{$root.wallet.settings.unitName}}) -

Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] From 2fe6ec4c6a81c9692c03768a41eebcaa29610c0a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Dec 2014 18:26:18 -0300 Subject: [PATCH 03/15] send working. Refactor paypro and payment intents --- TODO | 12 +- css/src/main.css | 11 +- js/controllers/copayers.js | 10 +- js/controllers/createProfile.js | 5 +- js/controllers/home.js | 4 +- js/controllers/paymentIntent.js | 49 --- js/controllers/paymentUri.js | 19 + js/controllers/send.js | 534 ++++++++++++----------------- js/controllers/sidebar.js | 4 +- js/controllers/uriPayment.js | 22 -- js/controllers/walletForPayment.js | 57 +++ js/models/Wallet.js | 9 +- js/routes.js | 9 +- js/services/go.js | 34 +- js/services/identityService.js | 23 +- views/copayers.html | 2 - views/modals/paypro.html | 28 ++ views/modals/walletSelection.html | 29 ++ views/paymentIntent.html | 32 -- views/send.html | 20 +- views/uri-payment.html | 16 - 21 files changed, 431 insertions(+), 498 deletions(-) delete mode 100644 js/controllers/paymentIntent.js create mode 100644 js/controllers/paymentUri.js delete mode 100644 js/controllers/uriPayment.js create mode 100644 js/controllers/walletForPayment.js create mode 100644 views/modals/paypro.html create mode 100644 views/modals/walletSelection.html delete mode 100644 views/paymentIntent.html delete mode 100644 views/uri-payment.html diff --git a/TODO b/TODO index 53967d2d9..b47a45bfe 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,2 @@ +- join. on walletComplete! - - homeWallet address...e sta ok? -- receive controller .. owned --- -// pkr.cache = opts.cache; - -(en send.js) -// $rootScope.pendingTxCount = res.pendingForUs; - --- probar payment intent - -// TODO refrescar en 'add' diff --git a/css/src/main.css b/css/src/main.css index 0bcd192a0..1c76dbe45 100644 --- a/css/src/main.css +++ b/css/src/main.css @@ -99,8 +99,17 @@ header .alt-currency { font-weight: 700; } +.green { + color: #1abc9c; +} + +.red { + color: #A02F23; +} + + .alt-currency.green { - background: #1ABC9C; + background: #1abc9c; } .alt-currency.red { diff --git a/js/controllers/copayers.js b/js/controllers/copayers.js index 0fd363eeb..10e011c18 100644 --- a/js/controllers/copayers.js +++ b/js/controllers/copayers.js @@ -3,14 +3,10 @@ angular.module('copayApp.controllers').controller('CopayersController', function($scope, $rootScope, $location) { - if (!$rootScope.wallet.isComplete()) { + $scope.init = function() { $rootScope.title = 'Waiting copayers for ' + $rootScope.wallet.getName(); - } - $scope.loading = false; - $scope.secret = $rootScope.wallet.getSecret(); - - $scope.goToWallet = function() { - $location.path('/homeWallet'); + $scope.loading = false; + $scope.secret = $rootScope.wallet.getSecret(); }; $scope.copayersList = function() { diff --git a/js/controllers/createProfile.js b/js/controllers/createProfile.js index 13dcd9dd5..9a8989ef0 100644 --- a/js/controllers/createProfile.js +++ b/js/controllers/createProfile.js @@ -5,7 +5,10 @@ angular.module('copayApp.controllers').controller('CreateProfileController', fun var _credentials, _firstpin; $scope.init = function() { - identityService.goWalletHome(); + + if ($rootScope.wallet) + go.walletHome(); + $scope.isMobile = isMobile.any(); $scope.createStep = 'storage'; diff --git a/js/controllers/home.js b/js/controllers/home.js index 9a2d99e17..8048343ec 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -25,8 +25,8 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc $rootScope.fromEmailConfirmation = false; } - if ($rootScope.iden) { - identityService.goWalletHome(); + if ($rootScope.wallet) { + go.walletHome(); } Compatibility.check($scope); diff --git a/js/controllers/paymentIntent.js b/js/controllers/paymentIntent.js deleted file mode 100644 index 73021c785..000000000 --- a/js/controllers/paymentIntent.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -angular.module('copayApp.controllers').controller('PaymentIntentController', function($rootScope, $scope, $modal, $location, $timeout, balanceService) { - - $rootScope.title = 'Payment intent'; - - $scope.open = function() { - var modalInstance = $modal.open({ - templateUrl: 'myModalContent.html', - controller: ModalInstanceCtrl - }); - }; - - - // Please note that $modalInstance represents a modal window (instance) dependency. - // It is not the same as the $modal service used above. - - var ModalInstanceCtrl = function($scope, $modalInstance, identityService) { - $scope.loading = true; - $scope.setWallets = function() { - if (!$rootScope.iden) return; - var ret = _.filter($rootScope.iden.listWallets(), function(w) { - return w.balanceInfo && w.balanceInfo.totalBalanceBTC; - }); - $timeout(function() { - $scope.wallets = ret; - $scope.loading = false; - $scope.$digest(); - }, 1000); - }; - if ($rootScope.iden) { - var iden = $rootScope.iden; - iden.on('newWallet', function() { - $scope.setWallets(); - }); - } - $scope.ok = function(selectedItem) { - identityService.setPaymentWallet(selectedItem); - $modalInstance.close(); - }; - - $scope.cancel = function() { - $rootScope.pendingPayment = null; - $modalInstance.close(); - $location.path('/homeWallet'); - }; - }; - -}); diff --git a/js/controllers/paymentUri.js b/js/controllers/paymentUri.js new file mode 100644 index 000000000..9e8ba6da6 --- /dev/null +++ b/js/controllers/paymentUri.js @@ -0,0 +1,19 @@ +var bitcore = require('bitcore'); + +angular.module('copayApp.controllers').controller('paymentUriController', function($rootScope, $scope, $routeParams, $location, go) { + + // Build bitcoinURI with querystring + var query = []; + angular.forEach($location.search(), function(value, key) { + query.push(key + "=" + value); + }); + var queryString = query ? "?" + query.join("&") : ""; + var bitcoinURI = $routeParams.data + queryString; + var uri = new bitcore.BIP21(bitcoinURI); + + if (uri.isValid()) { + $rootScope.pendingPayment = bitcoinURI; + } + + go.home(); +}); diff --git a/js/controllers/send.js b/js/controllers/send.js index af50a2edb..b45130788 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -4,106 +4,116 @@ var preconditions = require('preconditions').singleton(); angular.module('copayApp.controllers').controller('SendController', function($scope, $rootScope, $window, $timeout, $modal, $filter, $location, isMobile, notification, rateService) { - var w = $rootScope.wallet; - preconditions.checkState(w); - preconditions.checkState(w.settings.unitToSatoshi); - - $rootScope.title = w.isShared() ? 'Create Transaction Proposal' : 'Send'; - $scope.loading = false; - $scope.error = $scope.success = null; - var satToUnit = 1 / w.settings.unitToSatoshi; - $scope.defaultFee = bitcore.TransactionBuilder.FEE_PER_1000B_SAT * satToUnit; - $scope.unitToBtc = w.settings.unitToSatoshi / bitcore.util.COIN; - $scope.unitToSatoshi = w.settings.unitToSatoshi; - - $scope.alternativeName = w.settings.alternativeName; - $scope.alternativeIsoCode = w.settings.alternativeIsoCode; - - $scope.isRateAvailable = false; - $scope.rateService = rateService; - $scope.showScanner = false; - $scope.myId = w.getMyCopayerId(); - $scope.isMobile = isMobile.any(); - - rateService.whenAvailable(function() { - $scope.isRateAvailable = true; - $scope.$digest(); - }); - - $scope.setAlternativeAmount = function(w, tx, cb) { - rateService.whenAvailable(function() { - _.each(tx.outs, function(out) { - var valueSat = out.valueSat * w.settings.unitToSatoshi; - out.alternativeAmount = $filter('noFractionNumber')(rateService.toFiat(valueSat, $scope.alternativeIsoCode), 2); - out.alternativeIsoCode = $scope.alternativeIsoCode; - }); - if (cb) return cb(tx); - }); - }; - - /** - * Setting the two related amounts as properties prevents an infinite - * recursion for watches while preserving the original angular updates - * - */ - Object.defineProperty($scope, - "alternative", { - get: function() { - return this._alternative; - }, - set: function(newValue) { - this._alternative = newValue; - if (typeof(newValue) === 'number' && $scope.isRateAvailable) { - this._amount = parseFloat( - (rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed(w.settings.unitDecimals), 10); - } else { - this._amount = 0; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty($scope, - "amount", { - get: function() { - return this._amount; - }, - set: function(newValue) { - this._amount = newValue; - if (typeof(newValue) === 'number' && $scope.isRateAvailable) { - - this._alternative = parseFloat( - (rateService.toFiat(newValue * w.settings.unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10); - } else { - this._alternative = 0; - } - }, - enumerable: true, - configurable: true - }); - Object.defineProperty($scope, - "address", { - get: function() { - return this._address; - }, - set: function(newValue) { - this._address = newValue; - _onChanged(); - }, - enumerable: true, - configurable: true - }); + var satToUnit, unitToSat, w; $scope.init = function() { - // Empty - }; + w = $rootScope.wallet; + preconditions.checkState(w); + preconditions.checkState(w.settings.unitToSatoshi); - navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; + $rootScope.title = w.isShared() ? 'Create Transaction Proposal' : 'Send'; + $scope.loading = false; + $scope.error = $scope.success = null; + + unitToSat = w.settings.unitToSatoshi; + satToUnit = 1 / w.settings.unitToSatoshi; + + $scope.alternativeName = w.settings.alternativeName; + $scope.alternativeIsoCode = w.settings.alternativeIsoCode; + + $scope.isPayUri = false; + $scope.isRateAvailable = false; + $scope.rateService = rateService; + $scope.showScanner = false; + $scope.myId = w.getMyCopayerId(); + $scope.isMobile = isMobile.any(); + + if ($rootScope.pendingPayment) { + var value; + var pp = $rootScope.pendingPayment; + var amount = (pp.data && pp.data.amount) ? + pp.data.amount * 100000000 * satToUnit : 0; + $scope.setForm(pp.address, amount, pp.data.message) + _onAddressChange(pp); + } + + $scope.setInputs(); + $scope.setScanner(); + + rateService.whenAvailable(function() { + $scope.isRateAvailable = true; + $scope.$digest(); + }); + } + + $scope.setInputs = function() { + /** + * Setting the two related amounts as properties prevents an infinite + * recursion for watches while preserving the original angular updates + * + */ + Object.defineProperty($scope, + "alternative", { + get: function() { + return this._alternative; + }, + set: function(newValue) { + this._alternative = newValue; + if (typeof(newValue) === 'number' && $scope.isRateAvailable) { + this._amount = parseFloat( + (rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed(w.settings.unitDecimals), 10); + } else { + this._amount = 0; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty($scope, + "amount", { + get: function() { + return this._amount; + }, + set: function(newValue) { + this._amount = newValue; + if (typeof(newValue) === 'number' && $scope.isRateAvailable) { + + this._alternative = parseFloat( + (rateService.toFiat(newValue * unitToSat, $scope.alternativeIsoCode)).toFixed(2), 10); + } else { + this._alternative = 0; + } + }, + enumerable: true, + configurable: true + }); + + Object.defineProperty($scope, + "address", { + get: function() { + return this._address; + }, + set: function(newValue) { + this._address = newValue; + _onAddressChange(); + }, + enumerable: true, + configurable: true + }); + }; + + $scope.setScanner = function() { + navigator.getUserMedia = navigator.getUserMedia || + navigator.webkitGetUserMedia || navigator.mozGetUserMedia || + navigator.msGetUserMedia; + window.URL = window.URL || window.webkitURL || + window.mozURL || window.msURL; + + if (!window.cordova && !navigator.getUserMedia) + $scope.disableScanner = 1; + }; - if (!window.cordova && !navigator.getUserMedia) - $scope.disableScanner = 1; $scope._showError = function(err) { copay.logger.error(err); @@ -112,12 +122,8 @@ angular.module('copayApp.controllers').controller('SendController', if (msg.match('BIG')) msg = 'The transaction have too many inputs. Try creating many transactions for smaller amounts' - if (msg.match('totalNeededAmount')) - msg = 'Not enough funds' - - - if (msg.match('unspent not set')) - msg = 'Not enough funds' + if (msg.match('totalNeededAmount') || msg.match('unspent not set')) + msg = 'Insufficient funds' var message = 'The transaction' + (w.isShared() ? ' proposal' : '') + ' could not be created: ' + msg; @@ -135,7 +141,7 @@ angular.module('copayApp.controllers').controller('SendController', $scope.loading = true; var address = form.address.$modelValue; - var amount = parseInt((form.amount.$modelValue * w.settings.unitToSatoshi).toFixed(0)); + var amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); var commentText = form.comment.$modelValue; @@ -148,12 +154,6 @@ angular.module('copayApp.controllers').controller('SendController', }; } - // If we're setting the domain, ignore the change. - if ($rootScope.merchant && $rootScope.merchant.domain && address === $rootScope.merchant.domain) { - payInfo = { - merchant: $rootScope.merchant.request_url - }; - } w.spend({ toAddress: address, amountSat: amount, @@ -339,48 +339,30 @@ angular.module('copayApp.controllers').controller('SendController', $scope.notifyStatus(status); if (cb) return cb(); }); - }; - - $scope.clearMerchant = function(callback) { - // TODO: Find a better way of detecting - // whether we're in the Send scope or not. - if (!$scope.sendForm || !$scope.sendForm.address) { - delete $rootScope.merchant; - $rootScope.merchantError = false; - $scope.isPayUri = false; - if (callback) callback(); - return; - } - var val = $scope.sendForm.address.$viewValue || ''; - var uri; - // If we're setting the domain, ignore the change. - if ($rootScope.merchant && $rootScope.merchant.domain && val === $rootScope.merchant.domain) { - uri = { - merchant: $rootScope.merchant.request_url - }; - } - if (val.indexOf('bitcoin:') === 0) { - uri = new bitcore.BIP21(val).data; - } else if (/^https?:\/\//.test(val)) { - uri = { - merchant: val - }; - } - if (!uri || !uri.merchant) { - delete $rootScope.merchant; - $scope.sendForm.amount.$setViewValue(''); - $scope.sendForm.amount.$render(); - if (callback) callback(); - if ($rootScope.$$phase !== '$apply' && $rootScope.$$phase !== '$digest') { - $rootScope.$apply(); - } - } }; - $scope.cancelSend = function(form) { - delete $rootScope.merchant; - $rootScope.merchantError = false; - $scope.isPayUri = false; + $scope.setForm = function(to, amount, comment) { + var form = $scope.sendForm; + form.address.$setViewValue(merchantData.domain); + form.address.$render(); + form.address.$isValid = true; + + form.amount.$setViewValue(merchantData.unitTotal); + form.amount.$render(); + form.amount.$isValid = true; + + if (comment) + $scope.commentText = comment; + }; + + $scope.cancelSend = function(error) { + var form = $scope.sendForm; + + if (error) + $scope.error = error; + + $scope.fetchingURL = null; + $scope.isPayUri = null; form.address.$setViewValue(''); form.address.$render(); form.amount.$setViewValue(''); @@ -388,41 +370,37 @@ angular.module('copayApp.controllers').controller('SendController', form.comment.$setViewValue(''); form.comment.$render(); form.$setPristine(); - }; + }; - var _onChanged = function(pp) { + + $scope.openPPModal = function(pp) { + var ModalInstanceCtrl = function($scope, $modalInstance) { + $scope.pp = pp; + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + }; + $modal.open({ + templateUrl: 'views/modals/paypro.html', + windowClass: 'tiny', + controller: ModalInstanceCtrl, + }); + }; + + + + var _onAddressChange = function(pp) { var value; - - if (pp) { - $scope.isPayUri = true; - var amount = (pp.data && pp.data.amount) ? pp.data.amount * 100000000 * satToUnit : 0; - $scope.commentText = pp.data.message; - if (pp.data.merchant) { - value = 'bitcoin:' + pp.address.data + '?amount=' + amount + '&r=' + pp.data.r; - } - else { - value = pp.address + ''; - $timeout(function() { - $scope.amount = amount; - }, 1000); - $scope.address = value; - } - } - value = value || $scope.address || ''; var uri; $scope.error = $scope.success = null; - // If we're setting the domain, ignore the change. - if ($rootScope.merchant && $rootScope.merchant.domain && value === $rootScope.merchant.domain) { - return; - } if (value.indexOf('bitcoin:') === 0) { uri = new bitcore.BIP21(value); } else if (/^https?:\/\//.test(value)) { uri = { - data : { + data: { merchant: value } }; @@ -433,7 +411,7 @@ angular.module('copayApp.controllers').controller('SendController', var amount = (uri.data && uri.data.amount) ? uri.data.amount * 100000000 * satToUnit : 0; var address = uri.address.data; if (amount && address) { - $scope.isPayUri = true; + $scope.isPayUri = {fixedAmount: true} ; } $timeout(function() { $scope.amount = amount; @@ -444,178 +422,106 @@ angular.module('copayApp.controllers').controller('SendController', return; } - var apply = function() { - if ($rootScope.$$phase !== '$apply' && $rootScope.$$phase !== '$digest') { - $rootScope.$apply(); - } - }; - $scope.fetchingURL = uri.data.merchant; $scope.loading = true; - apply(); - var timeout = setTimeout(function() { - timeout = null; - $scope.fetchingURL = null; - $scope.loading = false; - $scope.sendForm.address.$setViewValue(''); - $scope.sendForm.address.$render(); - $scope.sendForm.address.$isValid = false; - $scope.error = 'Payment server timed out'; - apply(); - }, 10 * 1000); + + var balance = w.balanceInfo.availableBalance; + var available = +(balance * unitToSat).toFixed(0); // Payment Protocol URI (BIP-72) $scope.wallet.fetchPaymentRequest({ url: uri.data.merchant }, function(err, merchantData) { - if (!timeout) return; - clearTimeout(timeout); - $scope.loading = false; $scope.fetchingURL = null; - apply(); - - var balance = $rootScope.availableBalance; - var available = +(balance * w.settings.unitToSatoshi).toFixed(0); - if (merchantData && available < +merchantData.total) { - err = new Error('Insufficient funds.'); - err.amount = merchantData.total; - } if (err) { - if (err.amount) { - $scope.sendForm.amount.$setViewValue(+err.amount / w.settings.unitToSatoshi); - $scope.sendForm.amount.$render(); - $scope.sendForm.amount.$isValid = false; - $scope.notEnoughAmount = true; - $rootScope.merchantError = true; - var lastAddr = $scope.sendForm.address.$viewValue; - var unregister = $scope.$watch('address', function() { - if ($scope.sendForm.address.$viewValue !== lastAddr) { - delete $rootScope.merchantError; - $scope.isPayUri = false; - $scope.sendForm.amount.$setViewValue(''); - $scope.sendForm.amount.$render(); - unregister(); - apply(); - } - }); + if (err.match('TIMEOUT')) { + $scope.cancelSend('Payment server timed out'); } else { - $scope.sendForm.address.$setViewValue(''); - $scope.sendForm.address.$render(); + $scope.cancelSend(err.toString()); } - $scope.sendForm.address.$isValid = false; - copay.logger.error(err); - $scope.error = 'Could not fetch payment request'; - - apply(); - return; + } else if (merchantData && available < +merchantData.total) { + $scope.cancelSend(err.toString('Insufficient funds')); + } else { + $scope.setForm(merchantData.domain, merchantData.unitTotal) } - - var url = merchantData.request_url; - var domain = /^(?:https?)?:\/\/([^\/:]+).*$/.exec(url)[1]; - - merchantData.unitTotal = (+merchantData.total / w.settings.unitToSatoshi) + ''; - merchantData.expiration = new Date( - merchantData.pr.pd.expires * 1000); - merchantData.domain = domain; - - $rootScope.merchant = merchantData; - - $scope.sendForm.address.$setViewValue(domain); - $scope.sendForm.address.$render(); - $scope.sendForm.address.$isValid = true; - - $scope.sendForm.amount.$setViewValue(merchantData.unitTotal); - $scope.sendForm.amount.$render(); - $scope.sendForm.amount.$isValid = true; - - // If the address changes to a non-payment-protocol one, - // delete the `merchant` property from the scope. - var unregister = $rootScope.$watch(function() { - $scope.clearMerchant(unregister); - }); - - apply(); + $timeout(function() { + $scope.$digest(); + }, 1); }); }; - if ($rootScope.pendingPayment) { - var value; - var pp = $rootScope.pendingPayment; - _onChanged(pp); - } - $scope.openAddressBook = function() { var modalInstance = $modal.open({ templateUrl: 'views/modals/address-book.html', - windowClass: 'large', - controller: function($scope, $modalInstance) { + windowClass: 'large', + controller: function($scope, $modalInstance) { - $scope.showForm = null; - $scope.addressBook = w.addressBook; + $scope.showForm = null; + $scope.addressBook = w.addressBook; - $scope.hasEntry = function() { - return _.keys($scope.addressBook).length > 0 ? true : false; - }; + $scope.hasEntry = function() { + return _.keys($scope.addressBook).length > 0 ? true : false; + }; - $scope.toggleAddressBookEntry = function(key) { - w.toggleAddressBookEntry(key); - }; + $scope.toggleAddressBookEntry = function(key) { + w.toggleAddressBookEntry(key); + }; - $scope.copyToSend = function(addr) { - $modalInstance.close(addr); - }; + $scope.copyToSend = function(addr) { + $modalInstance.close(addr); + }; - $scope.cancel = function() { - $scope.error = $scope.success = null; - $scope.toggleForm(); - }; + $scope.cancel = function() { + $scope.error = $scope.success = null; + $scope.toggleForm(); + }; - $scope.toggleForm = function() { - $scope.showForm = !$scope.showForm; - }; - - $scope.submitAddressBook = function(form) { - if (form.$invalid) { - return; - } - $timeout(function() { - var errorMsg; - var entry = { - "address": form.newaddress.$modelValue, - "label": form.newlabel.$modelValue - }; - try { - w.setAddressBook(entry.address, entry.label); - } catch (e) { - console.log('[send.js:583]',e); //TODO - errorMsg = e.message; - } - - if (errorMsg) { - $scope.error = errorMsg; - } else { - $scope.toggleForm(); - $scope.success = 'New entry has been created'; - } - $rootScope.$digest(); - }, 500); - - $timeout(function() { - $scope.error = $scope.success = null; - }, 5000); + $scope.toggleForm = function() { + $scope.showForm = !$scope.showForm; + }; + $scope.submitAddressBook = function(form) { + if (form.$invalid) { return; - - }; + } + $timeout(function() { + var errorMsg; + var entry = { + "address": form.newaddress.$modelValue, + "label": form.newlabel.$modelValue + }; + try { + w.setAddressBook(entry.address, entry.label); + } catch (e) { + console.log('[send.js:583]', e); //TODO + errorMsg = e.message; + } - $scope.close = function() { - $modalInstance.dismiss('cancel'); - }; - }, + if (errorMsg) { + $scope.error = errorMsg; + } else { + $scope.toggleForm(); + $scope.success = 'New entry has been created'; + } + $rootScope.$digest(); + }, 500); + + $timeout(function() { + $scope.error = $scope.success = null; + }, 5000); + + return; + + }; + + $scope.close = function() { + $modalInstance.dismiss('cancel'); + }; + }, }); modalInstance.result.then(function(addr) { diff --git a/js/controllers/sidebar.js b/js/controllers/sidebar.js index b14d23d93..aeba65e86 100644 --- a/js/controllers/sidebar.js +++ b/js/controllers/sidebar.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('SidebarController', function($scope, $rootScope, $location, $timeout, identityService, isMobile) { +angular.module('copayApp.controllers').controller('SidebarController', function($scope, $rootScope, $location, $timeout, identityService, isMobile, go) { $scope.isMobile = isMobile.any() @@ -37,7 +37,7 @@ angular.module('copayApp.controllers').controller('SidebarController', function( $scope.switchWallet = function(wid) { $scope.walletSelection = false; identityService.setFocusedWallet(wid); - identityService.goWalletHome(); + go.walletHome(); }; $scope.toggleWalletSelection = function() { diff --git a/js/controllers/uriPayment.js b/js/controllers/uriPayment.js deleted file mode 100644 index 486a09be7..000000000 --- a/js/controllers/uriPayment.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -var bitcore = require('bitcore'); - -angular.module('copayApp.controllers').controller('UriPaymentController', function($rootScope, $scope, $routeParams, $timeout, $location) { - // Build bitcoinURI with querystring - var query = []; - angular.forEach($location.search(), function(value, key) { - query.push(key + "=" + value); - }); - var queryString = query ? "?" + query.join("&") : ""; - var bitcoinURI = $routeParams.data + queryString; - - $rootScope.pendingPayment = new bitcore.BIP21(bitcoinURI); - - $timeout(function() { - console.log('Redirecting to /paymentIntent'); - $location.path('/paymentIntent'); - }, 1000); - - -}); diff --git a/js/controllers/walletForPayment.js b/js/controllers/walletForPayment.js new file mode 100644 index 000000000..12a8fa9e7 --- /dev/null +++ b/js/controllers/walletForPayment.js @@ -0,0 +1,57 @@ +var bitcore = require('bitcore'); + +angular.module('copayApp.controllers').controller('walletForPaymentController', function($rootScope, $scope, $modal, go) { + +console.log('[walletForPayment.js.4]'); //TODO + if (!$rootScope.pendingPayment) { + go.walletHome(); + } else { + +console.log('[walletForPayment.js.9]'); //TODO + $scope.selectWallet(function(w) { + if (w) { + identityService.setFocusedWallet(w); + go.send(); + } else { + go.walletHome(); + } + }); + } + + $scope.selectWallet = function(cb) { + +console.log('[walletForPayment.js.22]'); //TODO + var ModalInstanceCtrl = function($scope, $modalInstance, $identityService) { + $scope.loading = true; + preconditions.checkState($rootScope.iden); + + var iden = $rootScope.iden; + iden.on('newWallet', function() { + $scope.setWallets(); + }); + + $scope.setWallets = function() { + $scope.wallets = _.filter($rootScope.iden.listWallets(), function(w) { + return w.balanceInfo && w.balanceInfo.totalBalanceBTC; + }); + }; + + $scope.ok = function(w) { + $modalInstance.close(); + return cb(w); + }; + + $scope.cancel = function() { + $modalInstance.close(); + return cb(); + }; + }; + +console.log('[walletForPayment.js.49]'); //TODO + $modal.open({ + templateUrl: 'views/modals/walletSelect.html', + windowClass: 'tiny', + controller: ModalInstanceCtrl, + }); + }; +}); diff --git a/js/models/Wallet.js b/js/models/Wallet.js index 44543c349..43993fa27 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -1793,6 +1793,7 @@ Wallet.prototype.parsePaymentRequest = function(options, rawData) { var payment_url = pd.get('payment_url'); var merchant_data = pd.get('merchant_data'); + var total = bignum('0', 10).toString(10); var merchantData = { pr: { payment_details_version: ver, @@ -1826,8 +1827,12 @@ Wallet.prototype.parsePaymentRequest = function(options, rawData) { }, expires: expires, request_url: options.url, - total: bignum('0', 10).toString(10), + domain: /^(?:https?)?:\/\/([^\/:]+).*$/.exec(options.url)[1], + total: total, + unitTotal: total ? (+total / w.settings.unitToSatoshi) + '' : null, + expirationDate: expires ? new Date(expires * 1000) : null, }; + this._addOutputsToMerchantData(merchantData, options.amount); return merchantData; }; @@ -2546,7 +2551,7 @@ Wallet.prototype.isComplete = function() { /** * @desc Sets the version of this wallet object - * + * * @param {string} version - the new version for the wallet */ Wallet.prototype.setVersion = function(version) { diff --git a/js/routes.js b/js/routes.js index c295994b4..d6f3e7245 100644 --- a/js/routes.js +++ b/js/routes.js @@ -22,11 +22,14 @@ angular template: " ", // just fire controller controller: 'EmailConfirmationController', }) + // Payment intents come here. .when('/uri-payment/:data', { - templateUrl: 'views/uri-payment.html' + template: " ", // just fire controller + controller: 'paymentUriController', }) - .when('/paymentIntent', { - templateUrl: 'views/paymentIntent.html', + .when('/selectWalletForPayment', { + template: " ", // just fire controller + controller: 'walletForPaymentController', logged: true }) .when('/join', { diff --git a/js/services/go.js b/js/services/go.js index 550693288..5159c8a90 100644 --- a/js/services/go.js +++ b/js/services/go.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('go', function($window, $location) { +angular.module('copayApp.services').factory('go', function($window, $rootScope, $location) { var root = {}; var hideSidebars = function() { @@ -44,7 +44,7 @@ angular.module('copayApp.services').factory('go', function($window, $location) { var ref = window.open(url, '_blank', 'location=no'); }; - root.go = function(path) { + root.path = function(path) { var parts = path.split('#'); $location.path(parts[0]); if (parts[1]) @@ -56,5 +56,35 @@ angular.module('copayApp.services').factory('go', function($window, $location) { toggleSidebar(invert); }; + root.walletHome = function() { +console.log('[go.js.25:walletHome:]'); //TODO + var w = $rootScope.wallet; + preconditions.checkState(w); + $rootScope.starting = false; + if (!w.isComplete()) { + root.path('copayers'); + } else { + if ($rootScope.pendingPayment) { + root.path('selectWalletForPayment'); + } else { + +console.log('[go.js.36]'); //TODO + root.path('homeWallet'); + } + } + }; + + root.home = function() { + if ($rootScope.iden) + root.walletHome(); + else + root.path('/'); + }; + + + root.send = function() { + $location.path('send'); + }; + return root; }); diff --git a/js/services/identityService.js b/js/services/identityService.js index 5620e8e49..3ec89d4c5 100644 --- a/js/services/identityService.js +++ b/js/services/identityService.js @@ -27,23 +27,6 @@ angular.module('copayApp.services') }); }; - // TODO should be on 'walletService' or 'go' - root.goWalletHome = function() { - var w = $rootScope.wallet; - if (w) { - $rootScope.starting = false; - if (!w.isComplete()) { - go.go('copayers'); - } else { - if ($rootScope.pendingPayment) { - go.go('paymentIntent'); - } else { - go.go('homeWallet'); - } - } - } - }; - root.create = function(email, password, cb) { copay.Identity.create({ email: email, @@ -133,10 +116,6 @@ angular.module('copayApp.services') $rootScope.iden = iden; }; - root.setPaymentWallet = function(w) { - root.setFocusedWallet(w); - $location.path('/send'); - }; root.noFocusedWallet = function() { $rootScope.wallet = null; @@ -296,7 +275,7 @@ angular.module('copayApp.services') if (wid == iden.getLastFocusedWalletId()) { copay.logger.debug('GOT Focused wallet:', w.getName()); root.setFocusedWallet(w, true); - root.goWalletHome(); + go.walletHome(); } // At the end (after all handlers are in place)...start the wallet. diff --git a/views/copayers.html b/views/copayers.html index 12c4a6a04..f2477315b 100644 --- a/views/copayers.html +++ b/views/copayers.html @@ -1,6 +1,4 @@

-
-

diff --git a/views/modals/paypro.html b/views/modals/paypro.html new file mode 100644 index 000000000..399a6ab16 --- /dev/null +++ b/views/modals/paypro.html @@ -0,0 +1,28 @@ +× + +
+

Payment Protocol Request

+ +

+ Signature: + {{$root.merchant.pr.ca}} + Untrusted +

+ Merchant Message: + {{$root.merchant.pr.pd.memo || address}} +

+ +

+ Merchant Message: + {{amount}} {{$root.wallet.settings.unitName}} + + {{ alternative }} {{ alternativeIsoCode }} + +

+ Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] +

+
+ +

+ + diff --git a/views/modals/walletSelection.html b/views/modals/walletSelection.html new file mode 100644 index 000000000..092bc9d87 --- /dev/null +++ b/views/modals/walletSelection.html @@ -0,0 +1,29 @@ + × + +

Select a wallet to make the payment

+Loading... + + diff --git a/views/paymentIntent.html b/views/paymentIntent.html deleted file mode 100644 index 4a1fb750a..000000000 --- a/views/paymentIntent.html +++ /dev/null @@ -1,32 +0,0 @@ -
- -
diff --git a/views/send.html b/views/send.html index 03771d58e..e5db67f6d 100644 --- a/views/send.html +++ b/views/send.html @@ -48,7 +48,7 @@
-
@@ -87,7 +87,7 @@
@@ -112,8 +112,7 @@
@@ -136,10 +135,13 @@
-

This is a payment protocol transaction

-
+

Payment Protocol Request

+

- {{$root.merchant.pr.pd.memo || address}} + {{$root.merchant.pr.ca}} + Untrusted + + {{$root.merchant.pr.pd.memo || address}}

@@ -150,9 +152,7 @@

Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] - {{$root.merchant.pr.ca}} - Untrusted -

+

diff --git a/views/uri-payment.html b/views/uri-payment.html deleted file mode 100644 index 6d7de2b45..000000000 --- a/views/uri-payment.html +++ /dev/null @@ -1,16 +0,0 @@ -
- -
-
-
-
 
-
 
-
 
-
 
-
- Preparing payment... -
-
- -
- From 80e22c59a03160d54813b9012b39b7de74a0becb Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Dec 2014 19:31:15 -0300 Subject: [PATCH 04/15] bitcoin: working. paypro todo --- TODO | 2 +- js/controllers/home.js | 2 +- js/controllers/send.js | 120 +++++++++++++++++++++-------------------- views/send.html | 10 ++-- 4 files changed, 68 insertions(+), 66 deletions(-) diff --git a/TODO b/TODO index b47a45bfe..2d468a2e6 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,2 @@ - join. on walletComplete! - +- paypro fetch-> return TIMEOUT diff --git a/js/controllers/home.js b/js/controllers/home.js index 8048343ec..2807a6570 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -5,7 +5,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc // Global go. This should be in a better place TODO // We dont do a 'go' directive, to use the benefits of ng-touch with ng-click $rootScope.go = function (path) { - go.go(path); + go.path(path); }; var _credentials, _firstpin; diff --git a/js/controllers/send.js b/js/controllers/send.js index b45130788..28badc215 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -30,12 +30,7 @@ angular.module('copayApp.controllers').controller('SendController', $scope.isMobile = isMobile.any(); if ($rootScope.pendingPayment) { - var value; - var pp = $rootScope.pendingPayment; - var amount = (pp.data && pp.data.amount) ? - pp.data.amount * 100000000 * satToUnit : 0; - $scope.setForm(pp.address, amount, pp.data.message) - _onAddressChange(pp); + $scope.setFromUri($rootScope.pendingPayment) } $scope.setInputs(); @@ -95,8 +90,7 @@ angular.module('copayApp.controllers').controller('SendController', return this._address; }, set: function(newValue) { - this._address = newValue; - _onAddressChange(); + this._address = $scope.onAddressChange(newValue); }, enumerable: true, configurable: true @@ -104,10 +98,10 @@ angular.module('copayApp.controllers').controller('SendController', }; $scope.setScanner = function() { - navigator.getUserMedia = navigator.getUserMedia || - navigator.webkitGetUserMedia || navigator.mozGetUserMedia || + navigator.getUserMedia = navigator.getUserMedia || + navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - window.URL = window.URL || window.webkitURL || + window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL; if (!window.cordova && !navigator.getUserMedia) @@ -343,16 +337,21 @@ angular.module('copayApp.controllers').controller('SendController', $scope.setForm = function(to, amount, comment) { var form = $scope.sendForm; - form.address.$setViewValue(merchantData.domain); + form.address.$setViewValue(to); form.address.$render(); form.address.$isValid = true; + $scope.lockAddress = true; - form.amount.$setViewValue(merchantData.unitTotal); - form.amount.$render(); - form.amount.$isValid = true; + if (amount) { + form.amount.$setViewValue(amount); + form.amount.$render(); + form.amount.$isValid = true; + $scope.lockAmount = true; + } - if (comment) - $scope.commentText = comment; + if (comment) { + form.commentText.$setViewValue(comment); + } }; $scope.cancelSend = function(error) { @@ -388,50 +387,18 @@ angular.module('copayApp.controllers').controller('SendController', }; + $scope.setFromPayPro = function(uri) { + console.log('[send.js.391:uri:]', uri); //TODO - var _onAddressChange = function(pp) { - var value; - value = value || $scope.address || ''; - var uri; - - $scope.error = $scope.success = null; - - if (value.indexOf('bitcoin:') === 0) { - uri = new bitcore.BIP21(value); - } else if (/^https?:\/\//.test(value)) { - uri = { - data: { - merchant: value - } - }; - } - - if (!uri || !uri.data.merchant) { - if (uri && uri.address) { - var amount = (uri.data && uri.data.amount) ? uri.data.amount * 100000000 * satToUnit : 0; - var address = uri.address.data; - if (amount && address) { - $scope.isPayUri = {fixedAmount: true} ; - } - $timeout(function() { - $scope.amount = amount; - }, 1000); - $scope.commentText = uri.data.message; - $scope.address = address; - } - return; - } - - $scope.fetchingURL = uri.data.merchant; + $scope.fetchingURL = uri; $scope.loading = true; - var balance = w.balanceInfo.availableBalance; var available = +(balance * unitToSat).toFixed(0); // Payment Protocol URI (BIP-72) - $scope.wallet.fetchPaymentRequest({ - url: uri.data.merchant + w.fetchPaymentRequest({ + url: uri }, function(err, merchantData) { $scope.loading = false; $scope.fetchingURL = null; @@ -442,18 +409,53 @@ angular.module('copayApp.controllers').controller('SendController', } else { $scope.cancelSend(err.toString()); } - } else if (merchantData && available < +merchantData.total) { - $scope.cancelSend(err.toString('Insufficient funds')); + $scope.cancelSend('Insufficient funds'); } else { $scope.setForm(merchantData.domain, merchantData.unitTotal) } - $timeout(function() { - $scope.$digest(); - }, 1); }); }; + $scope.setFromUri = function(uri) { + var form = $scope.sendForm; + + var parsed = new bitcore.BIP21(uri); + if (!parsed.isValid() || !parsed.address.isValid()) { + $scope.error = 'Invalid bitcoin URL'; + form.address.$isValid = false; + return uri; + }; + + var addr = parsed.address.toString(); + +console.log('[send.js.430:parsed:]',addr,parsed.data); //TODO + + if (parsed.data.merchant) + return $scope.setFromPayPro(parsed.data.merchant); + + var amount = (parsed.data && parsed.data.amount) ? + parsed.data.amount * 100000000 * satToUnit : 0; + + $scope.setForm(addr, amount, parsed.data.message, true); + return addr; + }; + + $scope.onAddressChange = function(value) { + var addr; + console.log('[send.js.391:value:]', value); //TODO + + $scope.error = $scope.success = null; + if (!value) return ''; + + if (value.indexOf('bitcoin:') === 0) { + return $scope.setFromUri(value); + } else if (/^https?:\/\//.test(value)) { + return $scope.setFromPayPro(value); + } + return value; + }; + $scope.openAddressBook = function() { var modalInstance = $modal.open({ templateUrl: 'views/modals/address-book.html', diff --git a/views/send.html b/views/send.html index e5db67f6d..8489b35ee 100644 --- a/views/send.html +++ b/views/send.html @@ -48,7 +48,7 @@
-
@@ -87,7 +87,7 @@
@@ -112,7 +112,7 @@
@@ -173,10 +173,10 @@
From 97c93e7909ef431364d7e55f403ed37700c9ff92 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 8 Dec 2014 23:45:34 -0300 Subject: [PATCH 05/15] send working with uris --- js/controllers/send.js | 104 ++++++------- js/directives.js | 14 +- views/send.html | 342 ++++++++++++++++++++--------------------- 3 files changed, 223 insertions(+), 237 deletions(-) diff --git a/js/controllers/send.js b/js/controllers/send.js index 28badc215..e3052dd50 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -22,7 +22,6 @@ angular.module('copayApp.controllers').controller('SendController', $scope.alternativeName = w.settings.alternativeName; $scope.alternativeIsoCode = w.settings.alternativeIsoCode; - $scope.isPayUri = false; $scope.isRateAvailable = false; $scope.rateService = rateService; $scope.showScanner = false; @@ -31,6 +30,7 @@ angular.module('copayApp.controllers').controller('SendController', if ($rootScope.pendingPayment) { $scope.setFromUri($rootScope.pendingPayment) + $rootScope.pendingPayment = null; } $scope.setInputs(); @@ -49,12 +49,12 @@ angular.module('copayApp.controllers').controller('SendController', * */ Object.defineProperty($scope, - "alternative", { + "_alternative", { get: function() { - return this._alternative; + return this.__alternative; }, set: function(newValue) { - this._alternative = newValue; + this.__alternative = newValue; if (typeof(newValue) === 'number' && $scope.isRateAvailable) { this._amount = parseFloat( (rateService.fromFiat(newValue, $scope.alternativeIsoCode) * satToUnit).toFixed(w.settings.unitDecimals), 10); @@ -66,18 +66,18 @@ angular.module('copayApp.controllers').controller('SendController', configurable: true }); Object.defineProperty($scope, - "amount", { + "_amount", { get: function() { - return this._amount; + return this.__amount; }, set: function(newValue) { - this._amount = newValue; + this.__amount = newValue; if (typeof(newValue) === 'number' && $scope.isRateAvailable) { - this._alternative = parseFloat( + this.__alternative = parseFloat( (rateService.toFiat(newValue * unitToSat, $scope.alternativeIsoCode)).toFixed(2), 10); } else { - this._alternative = 0; + this.__alternative = 0; } }, enumerable: true, @@ -85,12 +85,12 @@ angular.module('copayApp.controllers').controller('SendController', }); Object.defineProperty($scope, - "address", { + "_address", { get: function() { - return this._address; + return this.__address; }, set: function(newValue) { - this._address = $scope.onAddressChange(newValue); + this.__address = $scope.onAddressChange(newValue); }, enumerable: true, configurable: true @@ -109,8 +109,8 @@ angular.module('copayApp.controllers').controller('SendController', }; - $scope._showError = function(err) { - copay.logger.error(err); + $scope.setError = function(err) { + copay.logger.warn(err); var msg = err.toString(); if (msg.match('BIG')) @@ -123,7 +123,10 @@ angular.module('copayApp.controllers').controller('SendController', ' could not be created: ' + msg; $scope.error = message; - $scope.loading = false; + + $timeout(function(){ + $scope.$digest(); + },1); }; $scope.submitForm = function(form) { @@ -134,35 +137,23 @@ angular.module('copayApp.controllers').controller('SendController', $scope.loading = true; + var url = $scope._url; var address = form.address.$modelValue; var amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); - var commentText = form.comment.$modelValue; - - - var payInfo; - if (address.indexOf('bitcoin:') === 0) { - payInfo = (new bitcore.BIP21(address)).data; - } else if (/^https?:\/\//.test(address)) { - payInfo = { - merchant: address - }; - } + var comment = form.comment.$modelValue; w.spend({ toAddress: address, amountSat: amount, - comment: commentText, - url: (payInfo && payInfo.merchant) ? payInfo.merchant : null, + comment: comment, + url: url, }, function(err, txid, status) { $scope.loading = false; - // reset fields - $scope.address = $scope.amount = $scope.commentText = null; - form.address.$pristine = form.amount.$pristine = true; - $rootScope.pendingPayment = null; - $scope.isPayUri = null; - if (err) return $scope._showError(err); - $scope.notifyStatus(status); + if (err) + return $scope.setError(err); + + $scope.resetForm(status); }); }; @@ -303,7 +294,10 @@ angular.module('copayApp.controllers').controller('SendController', } $scope.setTopAmount = function() { - $scope.amount = $rootScope.topAmount; + var form = $scope.sendForm; + form.amount.$setViewValue(w.balanceInfo.topAmount); + form.amount.$render(); + form.amount.$isValid = true; }; $scope.notifyStatus = function(status) { @@ -316,7 +310,7 @@ angular.module('copayApp.controllers').controller('SendController', else if (status == copay.Wallet.TX_SIGNED_AND_BROADCASTED) $scope.success = 'Transaction signed and broadcasted!'; else - $scope.error = 'Unknown error occured'; + $scope.error = status; $timeout(function() { $scope.$digest(); @@ -330,7 +324,7 @@ angular.module('copayApp.controllers').controller('SendController', $rootScope.txAlertCount = 0; w.issueTx(ntxid, function(err, txid, status) { $scope.loading = false; - $scope.notifyStatus(status); + $scope.resetForm(status); if (cb) return cb(); }); }; @@ -338,30 +332,31 @@ angular.module('copayApp.controllers').controller('SendController', $scope.setForm = function(to, amount, comment) { var form = $scope.sendForm; form.address.$setViewValue(to); - form.address.$render(); form.address.$isValid = true; + form.address.$render(); $scope.lockAddress = true; if (amount) { - form.amount.$setViewValue(amount); - form.amount.$render(); + form.amount.$setViewValue(""+amount); form.amount.$isValid = true; + form.amount.$render(); $scope.lockAmount = true; } if (comment) { - form.commentText.$setViewValue(comment); + form.comment.$setViewValue(comment); + form.comment.$isValid = true; + form.comment.$render(); } }; - $scope.cancelSend = function(error) { + $scope.resetForm = function(status) { var form = $scope.sendForm; - if (error) - $scope.error = error; - + form.address.$pristine = form.amount.$pristine = true; $scope.fetchingURL = null; - $scope.isPayUri = null; + $scope.lockAddress = false; + $scope.lockAmount = false; form.address.$setViewValue(''); form.address.$render(); form.amount.$setViewValue(''); @@ -369,6 +364,11 @@ angular.module('copayApp.controllers').controller('SendController', form.comment.$setViewValue(''); form.comment.$render(); form.$setPristine(); + + $scope.notifyStatus(status); + $timeout(function(){ + $rootScope.$digest(); + },1); }; @@ -405,12 +405,12 @@ angular.module('copayApp.controllers').controller('SendController', if (err) { if (err.match('TIMEOUT')) { - $scope.cancelSend('Payment server timed out'); + $scope.resetForm('Payment server timed out'); } else { - $scope.cancelSend(err.toString()); + $scope.resetForm(err.toString()); } } else if (merchantData && available < +merchantData.total) { - $scope.cancelSend('Insufficient funds'); + $scope.resetForm('Insufficient funds'); } else { $scope.setForm(merchantData.domain, merchantData.unitTotal) } @@ -435,7 +435,7 @@ console.log('[send.js.430:parsed:]',addr,parsed.data); //TODO return $scope.setFromPayPro(parsed.data.merchant); var amount = (parsed.data && parsed.data.amount) ? - parsed.data.amount * 100000000 * satToUnit : 0; + (parsed.data.amount * 100000000).toFixed(0) * satToUnit : 0; $scope.setForm(addr, amount, parsed.data.message, true); return addr; @@ -527,7 +527,7 @@ console.log('[send.js.430:parsed:]',addr,parsed.data); //TODO }); modalInstance.result.then(function(addr) { - $scope.address = addr; + $scope._address = addr; }); }; diff --git a/js/directives.js b/js/directives.js index ca4f76b2d..1723cd329 100644 --- a/js/directives.js +++ b/js/directives.js @@ -32,12 +32,6 @@ angular.module('copayApp.directives') link: function(scope, elem, attrs, ctrl) { var validator = function(value) { - // If we're setting the domain, ignore the change. - if ($rootScope.merchant && $rootScope.merchant.domain && value === $rootScope.merchant.domain) { - ctrl.$setValidity('validAddress', true); - return value; - } - // Regular url if (/^https?:\/\//.test(value)) { ctrl.$setValidity('validAddress', true); @@ -53,6 +47,11 @@ angular.module('copayApp.directives') return value; } + if (typeof value == 'undefined') { + ctrl.$pristine = true; + return; + } + // Regular Address var a = new Address(value); ctrl.$setValidity('validAddress', a.isValid() && a.network().name === $rootScope.wallet.getNetworkName()); @@ -111,14 +110,11 @@ angular.module('copayApp.directives') var str_value = ('' + value).substring(sep_index + 1); if (sep_index > 0 && str_value.length > decimals) { ctrl.$setValidity('validAmount', false); - scope.notValidAmount = true; } else { ctrl.$setValidity('validAmount', true); - scope.notValidAmount = null; } } else { ctrl.$setValidity('validAmount', false); - scope.notValidAmount = null; } return value; } diff --git a/views/send.html b/views/send.html index 8489b35ee..16f116f72 100644 --- a/views/send.html +++ b/views/send.html @@ -1,202 +1,192 @@ -
+
-
-
-

{{$root.title}}

-
+
+
+

{{$root.title}}

+
-
-
-
-
+
+
+ +
-
-
- -
- +
+
+ +
+ {{error|translate}} -
+
-
-
- -
- +
+
+ +
+ {{success|translate}} -
+
-
- - - - Not valid +
+
+ + + + + + + - -
+ Not valid + + + + + +
-
- - -
- +
+ + +
+ +
+
+ +
+
+
+
+ {{_url}} +
+
+ +
+
+
+ + + +
+
+
+ + + Not valid + + + +
-
- -
-
+
+
-
-
+ - -
-
-
- - - Not valid - - -
-
-
- - - - -
- {{$root.wallet.settings.unitName}} +
+
+ +
-
-
-
- -
-
- - -
-
-
- {{alternativeIsoCode}} -
+
+ {{$root.wallet.settings.unitName}}
-
- -
-
-

- - Fetching payment -

-

From {{fetchingURL}} -

- -
-

Payment Protocol Request

-
-

- {{$root.merchant.pr.ca}} - Untrusted - - {{$root.merchant.pr.pd.memo || address}} -

- -

- {{amount}} {{$root.wallet.settings.unitName}} - - {{ alternative }} {{ alternativeIsoCode }} - -

- Expires {{$root.merchant.expiration | amTimeAgo }} - [{{$root.merchant.domain}}] -

+
+
+ +
+
+ + +
+
+
+ {{alternativeIsoCode}} +
- -
-
- -
- - -
-
-
- -
- -
- -
-
- -
-
- -
-
- - 1 BTC = {{$root.wallet.balanceInfo.alternativeConversionRate}} {{alternativeIsoCode}} -
-
+ +
+
+

+ + Fetching payment +

+

From {{fetchingURL}} +

+ +
+

Payment Protocol Request

+
+

+ {{$root.merchant.pr.ca}} + Untrusted + {{$root.merchant.pr.pd.memo || address}} TODO ADDRESS +

+ +

TODO AMOUNT + {{amount}} {{$root.wallet.settings.unitName}} + + TODO ALT + {{ alternative }} {{ alternativeIsoCode }} + +

+ Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] +

+
+
+
+ +
+
+ +
+ + +
+
+
+ +
+ +
+ +
+
+
+ +
+
+ + +
+
+ 1 BTC = {{$root.wallet.balanceInfo.alternativeConversionRate}} {{alternativeIsoCode}} +
+
From 5f6c9482b464ad9a557dc474666b5c06fc3bce7a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Dec 2014 01:29:06 -0300 Subject: [PATCH 06/15] paypro working 1-1 --- TODO | 2 + css/src/main.css | 9 ++-- js/controllers/send.js | 79 ++++++++++++++++++++------------- js/models/Wallet.js | 36 ++++++++++----- views/modals/paypro.html | 19 ++++---- views/send.html | 96 ++++++++++++++++------------------------ 6 files changed, 127 insertions(+), 114 deletions(-) diff --git a/TODO b/TODO index 2d468a2e6..809f8701e 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,4 @@ - join. on walletComplete! - paypro fetch-> return TIMEOUT +- yellow lock on paypro +- attack: change paypro ->no! in is cached diff --git a/css/src/main.css b/css/src/main.css index 1c76dbe45..2f476cf86 100644 --- a/css/src/main.css +++ b/css/src/main.css @@ -99,15 +99,14 @@ header .alt-currency { font-weight: 700; } -.green { - color: #1abc9c; +.color-greeni { + color: #1abc9c !important; } -.red { - color: #A02F23; +.color-yellowi { + color: yellow !important; } - .alt-currency.green { background: #1abc9c; } diff --git a/js/controllers/send.js b/js/controllers/send.js index e3052dd50..b2cb0e421 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -119,38 +119,44 @@ angular.module('copayApp.controllers').controller('SendController', if (msg.match('totalNeededAmount') || msg.match('unspent not set')) msg = 'Insufficient funds' + if (msg.match('expired')) + msg = 'The payment request has expired'; + var message = 'The transaction' + (w.isShared() ? ' proposal' : '') + ' could not be created: ' + msg; $scope.error = message; - $timeout(function(){ + $timeout(function() { $scope.$digest(); - },1); + }, 1); }; $scope.submitForm = function(form) { + if (form.$invalid) { $scope.error = 'Unable to send transaction proposal'; return; } $scope.loading = true; - - var url = $scope._url; - var address = form.address.$modelValue; - var amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); var comment = form.comment.$modelValue; + var merchantData = $scope._merchantData; + var address, amount; + if (!merchantData) { + address = form.address.$modelValue; + amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); + } w.spend({ + merchantData: merchantData, toAddress: address, amountSat: amount, comment: comment, - url: url, }, function(err, txid, status) { $scope.loading = false; - if (err) + if (err) return $scope.setError(err); $scope.resetForm(status); @@ -331,13 +337,15 @@ angular.module('copayApp.controllers').controller('SendController', $scope.setForm = function(to, amount, comment) { var form = $scope.sendForm; - form.address.$setViewValue(to); - form.address.$isValid = true; - form.address.$render(); - $scope.lockAddress = true; + if (to) { + form.address.$setViewValue(to); + form.address.$isValid = true; + form.address.$render(); + $scope.lockAddress = true; + } if (amount) { - form.amount.$setViewValue(""+amount); + form.amount.$setViewValue("" + amount); form.amount.$isValid = true; form.amount.$render(); $scope.lockAmount = true; @@ -353,28 +361,42 @@ angular.module('copayApp.controllers').controller('SendController', $scope.resetForm = function(status) { var form = $scope.sendForm; - form.address.$pristine = form.amount.$pristine = true; $scope.fetchingURL = null; + $scope._merchantData = $scope._domain = null; + $scope.lockAddress = false; $scope.lockAmount = false; - form.address.$setViewValue(''); - form.address.$render(); + + $scope._amount = $scope._address = null; + + form.amount.$pristine = true; form.amount.$setViewValue(''); form.amount.$render(); + form.comment.$setViewValue(''); form.comment.$render(); form.$setPristine(); $scope.notifyStatus(status); - $timeout(function(){ + $timeout(function() { + if (form.address) { + form.address.$pristine = true; + form.address.$setViewValue(''); + form.address.$render(); + } + $rootScope.$digest(); - },1); + }, 1); }; - - $scope.openPPModal = function(pp) { + var $oscope = $scope; + $scope.openPPModal = function(merchantData) { var ModalInstanceCtrl = function($scope, $modalInstance) { - $scope.pp = pp; + $scope.md = merchantData; + $scope.alternative = $oscope._alternative; + $scope.alternativeIsoCode = $oscope.alternativeIsoCode; + $scope.isRateAvailable = $oscope.isRateAvailable; + $scope.cancel = function() { $modalInstance.dismiss('cancel'); }; @@ -393,9 +415,6 @@ angular.module('copayApp.controllers').controller('SendController', $scope.fetchingURL = uri; $scope.loading = true; - var balance = w.balanceInfo.availableBalance; - var available = +(balance * unitToSat).toFixed(0); - // Payment Protocol URI (BIP-72) w.fetchPaymentRequest({ url: uri @@ -404,15 +423,16 @@ angular.module('copayApp.controllers').controller('SendController', $scope.fetchingURL = null; if (err) { - if (err.match('TIMEOUT')) { + copay.logger.warn(err); + if (err.toString().match('TIMEOUT')) { $scope.resetForm('Payment server timed out'); } else { $scope.resetForm(err.toString()); } - } else if (merchantData && available < +merchantData.total) { - $scope.resetForm('Insufficient funds'); } else { - $scope.setForm(merchantData.domain, merchantData.unitTotal) + $scope._merchantData = merchantData; + $scope._domain = merchantData.domain; + $scope.setForm(null, merchantData.unitTotal); } }); }; @@ -428,9 +448,6 @@ angular.module('copayApp.controllers').controller('SendController', }; var addr = parsed.address.toString(); - -console.log('[send.js.430:parsed:]',addr,parsed.data); //TODO - if (parsed.data.merchant) return $scope.setFromPayPro(parsed.data.merchant); diff --git a/js/models/Wallet.js b/js/models/Wallet.js index 43993fa27..2855a9812 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -1747,9 +1747,11 @@ Wallet.prototype._addOutputsToMerchantData = function(merchantData) { // If user is granted the privilege of choosing // their own amount, add it to the tx. - if (merchantData.total === 0 && options.amount) { - merchant.outs[0].amountSatStr = merchantData.total = outions.amount; + if (merchantData.total == "0" && options.amount) { + merchant.outs[0].amountSatStr = merchantData.total = options.amount; } + + merchantData.unitTotal = merchantData.total ? (+merchantData.total / this.settings.unitToSatoshi) + '' : 0; }; /** @@ -1829,11 +1831,11 @@ Wallet.prototype.parsePaymentRequest = function(options, rawData) { request_url: options.url, domain: /^(?:https?)?:\/\/([^\/:]+).*$/.exec(options.url)[1], total: total, - unitTotal: total ? (+total / w.settings.unitToSatoshi) + '' : null, expirationDate: expires ? new Date(expires * 1000) : null, }; this._addOutputsToMerchantData(merchantData, options.amount); + return merchantData; }; @@ -2178,9 +2180,21 @@ Wallet.prototype.spend = function(opts, cb) { var toAddress = opts.toAddress; var amountSat = opts.amountSat; var comment = opts.comment; - var url = opts.url; + var merchantData = opts.merchantData; + + + // PayPro? With given merchant data + if (opts.merchantData && !opts.toAddress) { + if (!merchantData.outs[0].address) + return cb(new Error('BADPAYPRO')); + + opts.toAddress = merchantData.outs[0].address; + opts.amountSat = parseInt(merchantData.outs[0].amountSatStr); + return self.spend(opts, cb); + } // PayPro? Fetch payment data and recurse + var url = opts.url; if (url && !opts.merchantData) { return self.fetchPaymentRequest({ url: url, @@ -2189,8 +2203,6 @@ Wallet.prototype.spend = function(opts, cb) { }, function(err, merchantData) { if (err) return cb(err); opts.merchantData = merchantData; - opts.toAddress = merchantData.outs[0].address; - opts.amountSat = parseInt(merchantData.outs[0].amountSatStr); return self.spend(opts, cb); }); } @@ -2208,13 +2220,13 @@ Wallet.prototype.spend = function(opts, cb) { try { txp = self._createTxProposal(toAddress, amountSat, comment, safeUnspent, opts.builderOpts); - } catch (e) { - log.error(e); - return cb(e); - } - if (opts.merchantData) { - txp.addMerchantData(opts.merchantData); + if (opts.merchantData) { + txp.addMerchantData(opts.merchantData); + } + } catch (e) { + log.warn(e); + return cb(e); } var ntxid = self.txProposals.add(txp); diff --git a/views/modals/paypro.html b/views/modals/paypro.html index 399a6ab16..5d8fdff56 100644 --- a/views/modals/paypro.html +++ b/views/modals/paypro.html @@ -1,25 +1,26 @@ ×
-

Payment Protocol Request

+

Payment Request

- Signature: - {{$root.merchant.pr.ca}} - Untrusted + Signature: {{md.domain}} + {{md.pr.ca}} + Untrusted

Merchant Message: - {{$root.merchant.pr.pd.memo || address}} +
+ {{md.pr.pd.memo || address}}

- Merchant Message: - {{amount}} {{$root.wallet.settings.unitName}} + Amount: + {{md.unitTotal}} {{$root.wallet.settings.unitName}} {{ alternative }} {{ alternativeIsoCode }} -

- Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] +

+ Expires {{md.expiration | amTimeAgo }}

diff --git a/views/send.html b/views/send.html index 16f116f72..fefad6bd1 100644 --- a/views/send.html +++ b/views/send.html @@ -29,47 +29,52 @@
-
-
+
+
- + - + - Not valid - - + Not valid + + - -
- -
- - -
- +
-
- + +
+ + +
+ +
+
+ +
+
+
-
-
- {{_url}} -
-
+
+
-
-
-
- + +
+ + +
+
+
@@ -118,34 +123,11 @@
-
-
-

+
+
+

>> - Fetching payment -

-

From {{fetchingURL}} -

- -
-

Payment Protocol Request

-
-

- {{$root.merchant.pr.ca}} - Untrusted - {{$root.merchant.pr.pd.memo || address}} TODO ADDRESS -

- -

TODO AMOUNT - {{amount}} {{$root.wallet.settings.unitName}} - - TODO ALT - {{ alternative }} {{ alternativeIsoCode }} - -

- Expires {{$root.merchant.expiration | amTimeAgo }} [{{$root.merchant.domain}}] -

-
+ Fetching payment request
@@ -164,10 +146,10 @@
From 475f6ea29e1a4fe75917a209574dbc873b55c3a8 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Dec 2014 11:52:01 -0300 Subject: [PATCH 07/15] fix copayers --- js/controllers/copayers.js | 27 ++++++++++++++----- js/controllers/homeWallet.js | 16 ++++++----- js/controllers/receive.js | 4 +-- js/models/Identity.js | 3 +++ js/routes.js | 14 +++++----- js/services/go.js | 7 ++--- test/mocks/FakeBlockchainSocket.js | 2 +- views/copayers.html | 11 ++++++-- views/homeWallet.html | 4 +-- .../includes/{copayer.html => copayers.html} | 4 +-- views/includes/head.html | 2 +- 11 files changed, 62 insertions(+), 32 deletions(-) rename views/includes/{copayer.html => copayers.html} (82%) diff --git a/js/controllers/copayers.js b/js/controllers/copayers.js index 10e011c18..a6b38989c 100644 --- a/js/controllers/copayers.js +++ b/js/controllers/copayers.js @@ -1,18 +1,33 @@ 'use strict'; angular.module('copayApp.controllers').controller('CopayersController', - function($scope, $rootScope, $location) { + function($scope, $rootScope, $timeout, go) { + + console.log('[copayers.js.5]'); //TODO $scope.init = function() { + var w = $rootScope.wallet; $rootScope.title = 'Waiting copayers for ' + $rootScope.wallet.getName(); $scope.loading = false; $scope.secret = $rootScope.wallet.getSecret(); + + w.on('publicKeyRingUpdated', $scope.updateList); + w.on('ready', $scope.updateList); + $scope.updateList(); }; - $scope.copayersList = function() { - if ($rootScope.wallet) { - $scope.copayers = $rootScope.wallet.getRegisteredPeerIds(); + $scope.updateList = function() { + var w = $rootScope.wallet; + + $scope.copayers = $rootScope.wallet.getRegisteredPeerIds(); + if (w.isComplete()) { + + w.removeListener('publicKeyRingUpdated', $scope.updateList); + w.removeListener('ready', $scope.updateList); + go.walletHome(); } - return $scope.copayers; - } + $timeout(function() { + $rootScope.$digest(); + }, 1); + }; }); diff --git a/js/controllers/homeWallet.js b/js/controllers/homeWallet.js index f2e1d51bd..ef0658492 100644 --- a/js/controllers/homeWallet.js +++ b/js/controllers/homeWallet.js @@ -1,15 +1,17 @@ 'use strict'; angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope, $timeout, $filter, $location, rateService, notification, identityService) { - $scope.init = function() { + $scope.initHome = function() { + var w = $rootScope.wallet; + $rootScope.title = 'Home'; - - $scope.rateService = rateService; $scope.isRateAvailable = false; - var w = $rootScope.wallet; - w.on('txProposalEvent', _updateTxs); + if (w.isShared()) + $scope.copayers = w.getRegisteredPeerIds(); + + w.on('txProposalEvent', _updateTxs); _updateTxs(); rateService.whenAvailable(function() { @@ -18,7 +20,9 @@ angular.module('copayApp.controllers').controller('HomeWalletController', functi }); }; - // This is necesarry, since wallet can change in homeWallet, without running init() again. + // This is necessary, since wallet can change in homeWallet, + // without running init() again. + var removeWatch; removeWatch = $rootScope.$watch('wallet.id', function(newWallet, oldWallet) { if ($rootScope.wallet && $rootScope.wallet.isComplete() && newWallet !== oldWallet) { diff --git a/js/controllers/receive.js b/js/controllers/receive.js index 660a02417..8f5038f83 100644 --- a/js/controllers/receive.js +++ b/js/controllers/receive.js @@ -21,10 +21,8 @@ angular.module('copayApp.controllers').controller('ReceiveController', var lastAddr = _.first(w.getAddressesOrderer()); var balance = w.balanceInfo.balanceByAddr; - if (balance[lastAddr]>0) - $scope.loading = true; - while (balance && balance[lastAddr] > 0) { + $scope.loading = true; $scope.newAddr(); lastAddr = w.generateAddress(null); }; diff --git a/js/models/Identity.js b/js/models/Identity.js index 85c568508..253af0d1c 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -509,6 +509,9 @@ Identity.prototype.bindWallet = function(w) { w.on('publicKeyRingUpdated', function() { Identity.storeWalletDebounced(self, w); }); + w.on('ready', function() { + Identity.storeWalletDebounced(self, w); + }); this.emitAndKeepAlive('newWallet', w.getId()); }; diff --git a/js/routes.js b/js/routes.js index d6f3e7245..9708f0276 100644 --- a/js/routes.js +++ b/js/routes.js @@ -22,11 +22,11 @@ angular template: " ", // just fire controller controller: 'EmailConfirmationController', }) - // Payment intents come here. - .when('/uri-payment/:data', { - template: " ", // just fire controller - controller: 'paymentUriController', - }) + // Payment intents come here. + .when('/uri-payment/:data', { + template: " ", // just fire controller + controller: 'paymentUriController', + }) .when('/selectWalletForPayment', { template: " ", // just fire controller controller: 'walletForPaymentController', @@ -127,6 +127,7 @@ angular } $rootScope.$on('$routeChangeStart', function(event, next, current) { + if (!ls || ls.length < 1) { $location.path('unsupported'); } else { @@ -134,7 +135,8 @@ angular $idle.unwatch(); $location.path('/'); } - if ($rootScope.wallet && !$rootScope.wallet.isComplete() && next.walletShouldBeComplete) { + if ($rootScope.wallet && !$rootScope.wallet.isComplete() + && next.walletShouldBeComplete) { $location.path('/copayers'); } } diff --git a/js/services/go.js b/js/services/go.js index 5159c8a90..ffd2b951e 100644 --- a/js/services/go.js +++ b/js/services/go.js @@ -57,24 +57,23 @@ angular.module('copayApp.services').factory('go', function($window, $rootScope, }; root.walletHome = function() { -console.log('[go.js.25:walletHome:]'); //TODO var w = $rootScope.wallet; preconditions.checkState(w); $rootScope.starting = false; + if (!w.isComplete()) { root.path('copayers'); } else { if ($rootScope.pendingPayment) { root.path('selectWalletForPayment'); } else { - -console.log('[go.js.36]'); //TODO root.path('homeWallet'); } } }; root.home = function() { +console.log('[go.js.48:home:]'); //TODO if ($rootScope.iden) root.walletHome(); else @@ -83,6 +82,8 @@ console.log('[go.js.36]'); //TODO root.send = function() { + +console.log('[go.js.58]'); //TODO $location.path('send'); }; diff --git a/test/mocks/FakeBlockchainSocket.js b/test/mocks/FakeBlockchainSocket.js index 941013ae6..f888c8150 100644 --- a/test/mocks/FakeBlockchainSocket.js +++ b/test/mocks/FakeBlockchainSocket.js @@ -26,7 +26,7 @@ var inherits = function(ctor, superCtor) { inherits(FakeSocket, EventEmitter); -FakeSocket.prototype.removeEventListener = function() { +FakeSocket.prototype.removeListener = function() { return; } diff --git a/views/copayers.html b/views/copayers.html index f2477315b..efea1ce53 100644 --- a/views/copayers.html +++ b/views/copayers.html @@ -1,4 +1,4 @@ -
+

@@ -12,6 +12,13 @@

Share this secret with your other copayers +
+ Personal Wallet + + Multisignature wallet [{{$root.wallet.requiredCopayers}} of {{$root.wallet.totalCopayers}} ] + + in TESTNET +

@@ -22,7 +29,7 @@
-
+

diff --git a/views/homeWallet.html b/views/homeWallet.html index 74a12a80f..45e9b65b4 100644 --- a/views/homeWallet.html +++ b/views/homeWallet.html @@ -1,4 +1,4 @@ -

+

Home

@@ -63,7 +63,7 @@

Copayers

-
+
diff --git a/views/includes/copayer.html b/views/includes/copayers.html similarity index 82% rename from views/includes/copayer.html rename to views/includes/copayers.html index be9e159ed..42ec854ce 100644 --- a/views/includes/copayer.html +++ b/views/includes/copayers.html @@ -1,5 +1,5 @@ -
-
+
+
diff --git a/views/includes/head.html b/views/includes/head.html index dce39e37c..b01b875db 100644 --- a/views/includes/head.html +++ b/views/includes/head.html @@ -2,7 +2,7 @@

{{$root.title}} - + From bba7b505392b6273cd11727de48c426ef9d1a71a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Dec 2014 12:47:19 -0300 Subject: [PATCH 08/15] views/modals/tx-status.html --- js/controllers/send.js | 72 +++++++++++++++++++++++++----------------- views/send.html | 10 +++--- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/js/controllers/send.js b/js/controllers/send.js index b2cb0e421..9250b3421 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -3,7 +3,7 @@ var bitcore = require('bitcore'); var preconditions = require('preconditions').singleton(); angular.module('copayApp.controllers').controller('SendController', - function($scope, $rootScope, $window, $timeout, $modal, $filter, $location, isMobile, notification, rateService) { + function($scope, $rootScope, $window, $timeout, $modal, $filter, notification, isMobile, rateService) { var satToUnit, unitToSat, w; @@ -154,11 +154,17 @@ angular.module('copayApp.controllers').controller('SendController', amountSat: amount, comment: comment, }, function(err, txid, status) { + console.log('[send.js.156:txid:]', txid); //TODO + console.log('[send.js.156:status:]', status); //TODO $scope.loading = false; + console.log('[send.js.158]'); //TODO if (err) return $scope.setError(err); + + console.log('[send.js.162:status:]', status); //TODO + $scope.resetForm(status); }); }; @@ -307,20 +313,21 @@ angular.module('copayApp.controllers').controller('SendController', }; $scope.notifyStatus = function(status) { - if (status == copay.Wallet.TX_BROADCASTED) - $scope.success = 'Transaction broadcasted!'; - else if (status == copay.Wallet.TX_PROPOSAL_SENT) - $scope.success = 'Transaction proposal created'; - else if (status == copay.Wallet.TX_SIGNED) - $scope.success = 'Transaction proposal was signed'; - else if (status == copay.Wallet.TX_SIGNED_AND_BROADCASTED) - $scope.success = 'Transaction signed and broadcasted!'; - else - $scope.error = status; + var msg; - $timeout(function() { - $scope.$digest(); - }); + if (status == copay.Wallet.TX_BROADCASTED) + msg = 'Transaction broadcasted!'; + else if (status == copay.Wallet.TX_PROPOSAL_SENT) + msg = 'Transaction proposal created'; + else if (status == copay.Wallet.TX_SIGNED) + msg = 'Transaction proposal was signed'; + else if (status == copay.Wallet.TX_SIGNED_AND_BROADCASTED) + msg = 'Transaction signed and broadcasted!'; + + if (msg) + $scope.openTxStatusModal(msg); + else + $scope.error = status; }; @@ -377,14 +384,13 @@ angular.module('copayApp.controllers').controller('SendController', form.comment.$render(); form.$setPristine(); + if (form.address) { + form.address.$pristine = true; + form.address.$setViewValue(''); + form.address.$render(); + } $scope.notifyStatus(status); $timeout(function() { - if (form.address) { - form.address.$pristine = true; - form.address.$setViewValue(''); - form.address.$render(); - } - $rootScope.$digest(); }, 1); }; @@ -408,6 +414,19 @@ angular.module('copayApp.controllers').controller('SendController', }); }; + $scope.openTxStatusModal = function(statusStr) { + var ModalInstanceCtrl = function($scope, $modalInstance) { + $scope.statusStr = statusStr; + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + }; + $modal.open({ + templateUrl: 'views/modals/tx-status.html', + windowClass: 'tiny', + controller: ModalInstanceCtrl, + }); + }; $scope.setFromPayPro = function(uri) { console.log('[send.js.391:uri:]', uri); //TODO @@ -503,6 +522,7 @@ angular.module('copayApp.controllers').controller('SendController', $scope.showForm = !$scope.showForm; }; + // TODO change to modal $scope.submitAddressBook = function(form) { if (form.$invalid) { return; @@ -516,7 +536,7 @@ angular.module('copayApp.controllers').controller('SendController', try { w.setAddressBook(entry.address, entry.label); } catch (e) { - console.log('[send.js:583]', e); //TODO + copay.logger.warn(e); errorMsg = e.message; } @@ -524,17 +544,11 @@ angular.module('copayApp.controllers').controller('SendController', $scope.error = errorMsg; } else { $scope.toggleForm(); - $scope.success = 'New entry has been created'; + notification.success('Entry created', 'New addressbook entry created') } $rootScope.$digest(); - }, 500); - - $timeout(function() { - $scope.error = $scope.success = null; - }, 5000); - + }, 1); return; - }; $scope.close = function() { diff --git a/views/send.html b/views/send.html index fefad6bd1..08a6fc141 100644 --- a/views/send.html +++ b/views/send.html @@ -10,23 +10,21 @@
-
- {{error|translate}} - + {{error|translate}} +
-
- {{success|translate}} - + {{success|translate}} +
From 583be2ca1978018ec64d2731e2667b1df60fd66f Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Dec 2014 12:47:27 -0300 Subject: [PATCH 09/15] tx status modal --- views/modals/tx-status.html | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 views/modals/tx-status.html diff --git a/views/modals/tx-status.html b/views/modals/tx-status.html new file mode 100644 index 000000000..5cc79f165 --- /dev/null +++ b/views/modals/tx-status.html @@ -0,0 +1,19 @@ + +
+ +
+
+ +
+
+ + +
+ {{statusStr}} +
+
+ OKAY +
+
+ + From 5f5d74944f0c2d16751360059029da124c4b6ada Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Dec 2014 14:27:09 -0300 Subject: [PATCH 10/15] better tx details --- css/src/main.css | 14 ------ js/controllers/home.js | 2 +- js/controllers/homeWallet.js | 26 +++++++++- views/history.html | 4 +- views/includes/transaction.html | 84 ++++++++++++--------------------- views/modals/tx-details.html | 22 +++++---- 6 files changed, 71 insertions(+), 81 deletions(-) diff --git a/css/src/main.css b/css/src/main.css index 2f476cf86..c09fb9e0e 100644 --- a/css/src/main.css +++ b/css/src/main.css @@ -417,20 +417,6 @@ a:hover { border-radius: 3px 3px 0 3px; } -a.missing-copayers { - background: #7A8C9E; - position: absolute; - display: block; - right: -1px; - bottom: -18px; - padding: 0.2rem 0.5rem; - font-size: 10px; - border-radius: 0 0 3px 3px; - text-transform: uppercase; - color: #fff; - font-weight: 700; -} - ul.tx-copayers { background: #E4E8EC; padding: 0.3rem 0.8rem; diff --git a/js/controllers/home.js b/js/controllers/home.js index 2807a6570..9c45b5278 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -174,7 +174,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc } } }); - } + }; function getParam(sname) { var params = location.search.substr(location.search.indexOf("?") + 1); diff --git a/js/controllers/homeWallet.js b/js/controllers/homeWallet.js index ef0658492..ee67815a5 100644 --- a/js/controllers/homeWallet.js +++ b/js/controllers/homeWallet.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope, $timeout, $filter, $location, rateService, notification, identityService) { +angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope, $timeout, $filter, $modal, rateService, notification, identityService) { $scope.initHome = function() { var w = $rootScope.wallet; @@ -125,4 +125,28 @@ angular.module('copayApp.controllers').controller('HomeWalletController', functi _updateTxs(); }; + + $scope.openTxModal = function(btx) { + var ModalInstanceCtrl = function($scope, $modalInstance) { + $scope.btx = btx; + + $scope.getShortNetworkName = function() { + var w = $rootScope.wallet; + return w.getNetworkName().substring(0, 4); + }; + + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + }; + + $modal.open({ + templateUrl: 'views/modals/tx-details.html', + windowClass: 'tiny', + controller: ModalInstanceCtrl, + }); + }; + + + }); diff --git a/views/history.html b/views/history.html index 5ef7cb102..8ad75677f 100644 --- a/views/history.html +++ b/views/history.html @@ -13,8 +13,8 @@
-
-
+
+
diff --git a/views/includes/transaction.html b/views/includes/transaction.html index a440de365..390f25a97 100644 --- a/views/includes/transaction.html +++ b/views/includes/transaction.html @@ -1,5 +1,4 @@ - -
+
@@ -22,25 +21,21 @@
-
- +
+
+ {{tx.merchant.domain}} + {{tx.merchant.domain}} + +
+
-
-
- {{tx.merchant.pr.pd.memo}}
- Expires {{tx.merchant.pr.pd.expires * 1000 | amTimeAgo }} - [{{tx.merchant.domain}}] - {{tx.merchant.pr.ca}} - Untrusted -
-
-
+