diff --git a/src/js/controllers/index.js b/src/js/controllers/index.js index 657ee5927..4f5c44b7a 100644 --- a/src/js/controllers/index.js +++ b/src/js/controllers/index.js @@ -1463,20 +1463,6 @@ angular.module('copayApp.controllers').controller('indexController', function($r self.setTab(tab, reset); }); - $rootScope.$on('Local/RequestTouchid', function(event, cb) { - window.plugins.touchid.verifyFingerprint( - gettextCatalog.getString('Scan your fingerprint please'), - function(msg) { - // OK - return cb(); - }, - function(msg) { - // ERROR - return cb(gettext('Error with Touch ID:') + msg); - } - ); - }); - $rootScope.$on('Local/NeedsPassword', function(event, isSetup, cb) { self.askPassword = { isSetup: isSetup, diff --git a/src/js/controllers/sellGlidera.js b/src/js/controllers/sellGlidera.js index cbae3f8f3..a789274c8 100644 --- a/src/js/controllers/sellGlidera.js +++ b/src/js/controllers/sellGlidera.js @@ -1,7 +1,7 @@ 'use strict'; -angular.module('copayApp.controllers').controller('sellGlideraController', - function($scope, $timeout, $log, $modal, configService, profileService, addressService, feeService, glideraService, bwsError, lodash, isChromeApp, animationService) { +angular.module('copayApp.controllers').controller('sellGlideraController', + function($scope, $timeout, $log, $modal, configService, profileService, addressService, feeService, glideraService, bwsError, lodash, isChromeApp, animationService, txSignService) { var self = this; var config = configService.getSync(); @@ -38,7 +38,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController', }, 100); } }); - } catch(e) { + } catch (e) { $log.debug(e); }; }; @@ -57,12 +57,14 @@ angular.module('copayApp.controllers').controller('sellGlideraController', $scope.selectWallet = function(walletId, walletName) { if (!profileService.getClient(walletId).isComplete()) { - self.error = bwsError.msg({'code': 'WALLET_NOT_COMPLETE'}, 'Could not choose the wallet'); + self.error = bwsError.msg({ + 'code': 'WALLET_NOT_COMPLETE' + }, 'Could not choose the wallet'); $modalInstance.dismiss('cancel'); return; } $modalInstance.close({ - 'walletId': walletId, + 'walletId': walletId, 'walletName': walletName, }); }; @@ -70,8 +72,8 @@ angular.module('copayApp.controllers').controller('sellGlideraController', var modalInstance = $modal.open({ templateUrl: 'views/modals/glidera-wallets.html', - windowClass: animationService.modalAnimated.slideUp, - controller: ModalInstanceCtrl, + windowClass: animationService.modalAnimated.slideUp, + controller: ModalInstanceCtrl, }); modalInstance.result.finally(function() { @@ -101,12 +103,11 @@ angular.module('copayApp.controllers').controller('sellGlideraController', self.gettingSellPrice = false; if (err) { self.error = 'Could not get exchange information. Please, try again.'; - } - else { + } else { self.error = null; self.sellPrice = sellPrice; } - }); + }); }; this.get2faCode = function(token) { @@ -117,8 +118,7 @@ angular.module('copayApp.controllers').controller('sellGlideraController', self.loading = null; if (err) { self.error = 'Could not send confirmation code to your phone'; - } - else { + } else { self.show2faCodeInput = sent; } }); @@ -129,107 +129,86 @@ angular.module('copayApp.controllers').controller('sellGlideraController', var self = this; self.error = null; - this.loading = 'Selling Bitcoin...'; - $timeout(function() { - addressService.getAddress(fc.credentials.walletId, null, function(err, refundAddress) { - if (!refundAddress) { - self.loading = null; - self.error = bwsError.msg(err, 'Could not create address'); - return; - } - glideraService.getSellAddress(token, function(error, sellAddress) { - if (!sellAddress) { + + txSignService.prepare(function(err) { + if (err) { + self.error = err; + return; + } + this.loading = 'Selling Bitcoin...'; + $timeout(function() { + addressService.getAddress(fc.credentials.walletId, null, function(err, refundAddress) { + if (!refundAddress) { self.loading = null; - self.error = 'Could not get the destination bitcoin address'; + self.error = bwsError.msg(err, 'Could not create address'); return; } - var amount = parseInt((self.sellPrice.qty * 100000000).toFixed(0)); + glideraService.getSellAddress(token, function(error, sellAddress) { + if (!sellAddress) { + self.loading = null; + self.error = 'Could not get the destination bitcoin address'; + return; + } + var amount = parseInt((self.sellPrice.qty * 100000000).toFixed(0)); - feeService.getCurrentFeeValue(self.currentFeeLevel, function(err, feePerKb) { - if (err) $log.debug(err); - fc.sendTxProposal({ - toAddress: sellAddress, - amount: amount, - message: 'Glidera transaction', - customData: {'glideraToken': token}, - payProUrl: null, - feePerKb: feePerKb, - excludeUnconfirmedUtxos: self.currentSpendUnconfirmed ? false : true - }, function(err, txp) { - if (err) { - profileService.lockFC(); - $log.error(err); - $timeout(function() { - self.loading = null; - self.error = bwsError.msg(err, 'Error'); - }, 1); - return; - } - - if (!fc.canSign()) { - self.loading = null; - $log.info('No signing proposal: No private key'); - return; - } - - _signTx(txp, function(err, txp, rawTx) { - profileService.lockFC(); + feeService.getCurrentFeeValue(self.currentFeeLevel, function(err, feePerKb) { + if (err) $log.debug(err); + fc.sendTxProposal({ + toAddress: sellAddress, + amount: amount, + message: 'Glidera transaction', + customData: { + 'glideraToken': token + }, + payProUrl: null, + feePerKb: feePerKb, + excludeUnconfirmedUtxos: self.currentSpendUnconfirmed ? false : true + }, function(err, txp) { if (err) { - self.loading = null; - self.error = err; - $scope.$apply(); - } - else { - var data = { - refundAddress: refundAddress, - signedTransaction: rawTx, - priceUuid: self.sellPrice.priceUuid, - useCurrentPrice: self.sellPrice.priceUuid ? false : true, - ip: null - }; - glideraService.sell(token, twoFaCode, data, function(err, data) { + profileService.lockFC(); + $log.error(err); + $timeout(function() { self.loading = null; - if (err) { - self.error = err; - fc.removeTxProposal(txp, function(err, txpb) { - $timeout(function() { - $scope.$emit('Local/GlideraError'); - }, 100); - }); - } - else { - self.success = data; - $scope.$emit('Local/GlideraTx'); - } - }); + self.error = bwsError.msg(err, 'Error'); + }, 1); + return; } + + txSignService.sign(tx, function(err, txp) { + if (err) { + self.loading = null; + self.error = err; + $scope.$apply(); + } else { + var rawTx = txp.raw; + var data = { + refundAddress: refundAddress, + signedTransaction: rawTx, + priceUuid: self.sellPrice.priceUuid, + useCurrentPrice: self.sellPrice.priceUuid ? false : true, + ip: null + }; + glideraService.sell(token, twoFaCode, data, function(err, data) { + self.loading = null; + if (err) { + self.error = err; + fc.removeTxProposal(txp, function(err, txpb) { + $timeout(function() { + $scope.$emit('Local/GlideraError'); + }, 100); + }); + } else { + self.success = data; + $scope.$emit('Local/GlideraTx'); + } + }); + } + }); }); }); }); }); - }); - - }, 100); - - }; - - var _signTx = function(txp, cb) { - var self = this; - fc.signTxProposal(txp, function(err, signedTx) { - profileService.lockFC(); - if (err) { - err = bwsError.msg(err, 'Could not accept payment'); - return cb(err); - } - else { - if (signedTx.status == 'accepted') { - return cb(null, txp, signedTx.raw); - - } else { - return cb('The transaction could not be signed'); - } - } + }, 100); }); }; - }); diff --git a/src/js/controllers/walletHome.js b/src/js/controllers/walletHome.js index 8d63f80f4..8bd468743 100644 --- a/src/js/controllers/walletHome.js +++ b/src/js/controllers/walletHome.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, isMobile, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService) { +angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, isMobile, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, ledger, bwsError, confirmDialog, txFormatService, animationService, addressbookService, go, feeService, txSignService) { var self = this; window.ignoreMobilePause = false; @@ -87,16 +87,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi $rootScope.hideMenuBar = false; }); - var requestTouchid = function(cb) { - var fc = profileService.focusedClient; - config.touchIdFor = config.touchIdFor || {}; - if (window.touchidAvailable && config.touchIdFor[fc.credentials.walletId]) { - $rootScope.$emit('Local/RequestTouchid', cb); - } else { - return cb(); - } - }; - this.onQrCodeScanned = function(data) { if (data) go.send(); $rootScope.$emit('dataScanned', data); @@ -336,72 +326,25 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi $scope.sign = function(txp) { var fc = profileService.focusedClient; $scope.error = null; - - if (!fc.canSign() && !fc.isPrivKeyExternal()) - return; - $scope.loading = true; - $timeout(function() { - requestTouchid(function(err) { - if (err) { - $scope.loading = false; - $scope.error = err; - $timeout(function() { - $scope.$digest(); - }); - return; - } + txSignService.prepareAndSignAndBroadcast(txp, { + reporterFn: self.setOngoingProcess.bind(self) + }, function(err, txp) { + $scope.loading = false; + $scope.$emit('UpdateTx'); - profileService.unlockFC(function(err) { - if (err) { - $scope.loading = false; - $scope.error = bwsError.msg(err); - $timeout(function() { - $scope.$digest(); - }); - return; - } - - self._setOngoingForSigning(); - profileService.signTxProposal(txp, function(err, txpsi) { - self.setOngoingProcess(); - if (err) { - $scope.$emit('UpdateTx'); - $scope.loading = false; - $scope.error = bwsError.msg(err, gettextCatalog.getString('Could not accept payment')); - $scope.$digest(); - } else { - //if txp has required signatures then broadcast it - var txpHasRequiredSignatures = txpsi.status == 'accepted'; - if (txpHasRequiredSignatures) { - self.setOngoingProcess(gettextCatalog.getString('Broadcasting transaction')); - $scope.loading = true; - fc.broadcastTxProposal(txpsi, function(err, txpsb, memo) { - self.setOngoingProcess(); - $scope.loading = false; - if (err) { - $scope.$emit('UpdateTx'); - $scope.error = bwsError.msg(err, gettextCatalog.getString('Could not broadcast payment')); - $scope.$digest(); - } else { - $log.debug('Transaction signed and broadcasted') - if (memo) - $log.info(memo); - - refreshUntilItChanges = true; - $modalInstance.close(txpsb); - } - }); - } else { - $scope.loading = false; - $modalInstance.close(txpsi); - } - } - }); + if (err) { + $scope.error = err; + $timeout(function() { + $scope.$digest(); }); - }); - }, 100); + return; + } + refreshUntilItChanges = true; + $modalInstance.close(txp); + return; + }); }; $scope.reject = function(txp) { @@ -845,7 +788,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi if (form.$invalid) { this.error = gettext('Unable to send transaction proposal'); return; - } + } var comment = form.comment.$modelValue; @@ -871,57 +814,52 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi address = form.address.$modelValue; amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0)); - requestTouchid(function(err) { + txSignService.prepare(function(err) { if (err) { - self.error = err; - $timeout(function() { - $scope.$digest(); - }, 1); - return; + return self.setSendError(err); } + self.setOngoingProcess(gettextCatalog.getString('Creating transaction')); + getFee(function(err, feePerKb) { + if (err) $log.debug(err); + fc.sendTxProposal({ + toAddress: address, + amount: amount, + message: comment, + payProUrl: paypro ? paypro.url : null, + feePerKb: feePerKb, + excludeUnconfirmedUtxos: currentSpendUnconfirmed ? false : true + }, function(err, txp) { + if (err) { + self.setOngoingProcess(); + return self.setSendError(err); + } - profileService.unlockFC(function(err) { - if (err) { - return self.setSendError(err); - } - - self.setOngoingProcess(gettextCatalog.getString('Creating transaction')); - getFee(function(err, feePerKb) { - if (err) $log.debug(err); - fc.sendTxProposal({ - toAddress: address, - amount: amount, - message: comment, - payProUrl: paypro ? paypro.url : null, - feePerKb: feePerKb, - excludeUnconfirmedUtxos: currentSpendUnconfirmed ? false : true - }, function(err, txp) { - if (err) { - self.setOngoingProcess(); - return self.setSendError(err); - } - - if (!fc.canSign() && !fc.isPrivKeyExternal()) { - $log.info('No signing proposal: No private key') - self.setOngoingProcess(); - self.resetForm(); - txStatus.notify(txp, function() { - return $scope.$emit('Local/TxProposalAction'); - }); - return; - } - - self.signAndBroadcast(txp, function(err) { - self.setOngoingProcess(); - self.resetForm(); - if (err) { - self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen'); - $scope.$emit('Local/TxProposalAction'); - $timeout(function() { - $scope.$digest(); - }, 1); - } else go.walletHome(); + if (!fc.canSign() && !fc.isPrivKeyExternal()) { + self.setOngoingProcess(); + $log.info('No signing proposal: No private key') + self.resetForm(); + txStatus.notify(txp, function() { + return $scope.$emit('Local/TxProposalAction'); }); + return; + } + + txSignService.signAndBroadcast(txp, { + reporterFn: self.setOngoingProcess.bind(self) + }, function(err, txp) { + self.resetForm(); + if (err) { + self.error = err.message ? err.message : gettext('The payment was created but could not be completed. Please try again from home screen'); + $scope.$emit('Local/TxProposalAction'); + $timeout(function() { + $scope.$digest(); + }, 1); + } else { + go.walletHome(); + txStatus.notify(txp, function() { + $scope.$emit('Local/TxProposalAction', true); + }); + }; }); }); }); @@ -929,56 +867,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }, 100); }; - this._setOngoingForSigning = function() { - var fc = profileService.focusedClient; - - if (fc.isPrivKeyExternal() && fc.getPrivKeyExternalSourceName() == 'ledger') { - self.setOngoingProcess(gettextCatalog.getString('Requesting Ledger Wallet to sign')); - } else { - self.setOngoingProcess(gettextCatalog.getString('Signing payment')); - } - }; - - this.signAndBroadcast = function(txp, cb) { - var fc = profileService.focusedClient; - - this._setOngoingForSigning(); - profileService.signTxProposal(txp, function(err, signedTx) { - self.setOngoingProcess(); - if (err) { - if (!lodash.isObject(err)) { - err = { message: err}; - } - err.message = bwsError.msg(err, gettextCatalog.getString('The payment was created but could not be signed. Please try again from home screen')); - return cb(err); - } - - if (signedTx.status == 'accepted') { - self.setOngoingProcess(gettextCatalog.getString('Broadcasting transaction')); - fc.broadcastTxProposal(signedTx, function(err, btx, memo) { - self.setOngoingProcess(); - if (err) { - err.message = bwsError.msg(err, gettextCatalog.getString('The payment was signed but could not be broadcasted. Please try again from home screen')); - return cb(err); - } - if (memo) - $log.info(memo); - - txStatus.notify(btx, function() { - $scope.$emit('Local/TxProposalAction', true); - return cb(); - }); - }); - } else { - self.setOngoingProcess(); - txStatus.notify(signedTx, function() { - $scope.$emit('Local/TxProposalAction'); - return cb(); - }); - } - }); - }; - this.setForm = function(to, amount, comment) { var form = $scope.sendForm; if (to) { diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index d39a382c9..37ff6a700 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -1,6 +1,6 @@ 'use strict'; angular.module('copayApp.services') - .factory('profileService', function profileServiceFactory($rootScope, $location, $timeout, $filter, $log, lodash, storageService, bwcService, configService, notificationService, isChromeApp, isCordova, gettext, gettextCatalog, nodeWebkit, bwsError, uxLanguage, ledger, bitcore, trezor) { + .factory('profileService', function profileServiceFactory($rootScope, $location, $timeout, $filter, $log, lodash, storageService, bwcService, configService, notificationService, isChromeApp, isCordova, gettext, gettextCatalog, nodeWebkit, bwsError, uxLanguage, bitcore) { var root = {}; @@ -683,59 +683,5 @@ angular.module('copayApp.services') return lodash.sortBy(ret, 'name'); }; - root._signWithLedger = function(txp, cb) { - var fc = root.focusedClient; - $log.info('Requesting Ledger Chrome app to sign the transaction'); - - ledger.signTx(txp, fc.credentials.account, function(result) { - $log.debug('Ledger response', result); - if (!result.success) - return cb(result.message || result.error); - - txp.signatures = lodash.map(result.signatures, function(s) { - return s.substring(0, s.length - 2); - }); - return fc.signTxProposal(txp, cb); - }); - }; - - - root._signWithTrezor = function(txp, cb) { - var fc = root.focusedClient; - $log.info('Requesting Trezor to sign the transaction'); - - var xPubKeys = lodash.pluck(fc.credentials.publicKeyRing, 'xPubKey'); - trezor.signTx(xPubKeys, txp, fc.credentials.account, function(err, result) { - if (err) return cb(err); - - $log.debug('Trezor response', result); - txp.signatures = result.signatures; - return fc.signTxProposal(txp, cb); - }); - }; - - - root.signTxProposal = function(txp, cb) { - var fc = root.focusedClient; - - if (fc.isPrivKeyExternal()) { - switch (fc.getPrivKeyExternalSourceName()) { - case 'ledger': - return root._signWithLedger(txp, cb); - case 'trezor': - return root._signWithTrezor(txp, cb); - default: - var msg = 'Unsupported External Key:' + fc.getPrivKeyExternalSourceName(); - $log.error(msg); - return cb(msg); - } - } else { - return fc.signTxProposal(txp, function(err, signedTxp) { - root.lockFC(); - return cb(err, signedTxp); - }); - } - }; - return root; });