From 033f7c163fcd6d47d898adbb3644170195088ea2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 12 Aug 2015 11:08:33 -0300 Subject: [PATCH] better handing of errors + prevent joining the same wallet more that once --- public/views/walletHome.html | 2 +- src/js/controllers/index.js | 4 +- src/js/controllers/join.js | 2 +- src/js/controllers/walletHome.js | 73 +++++------------ src/js/services/addressService.js | 5 +- src/js/services/bwsError.js | 125 ++++++++++++++++++++++++++++++ src/js/services/profileService.js | 35 ++++----- 7 files changed, 167 insertions(+), 79 deletions(-) create mode 100644 src/js/services/bwsError.js diff --git a/public/views/walletHome.html b/public/views/walletHome.html index 02d459b87..12d3bcba6 100644 --- a/public/views/walletHome.html +++ b/public/views/walletHome.html @@ -76,7 +76,7 @@
- Could not update Wallet + {{index.updateError}}
diff --git a/src/js/controllers/index.js b/src/js/controllers/index.js index 50935294a..00a6c50d7 100644 --- a/src/js/controllers/index.js +++ b/src/js/controllers/index.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit, addonManager, feeService, isChromeApp) { +angular.module('copayApp.controllers').controller('indexController', function($rootScope, $scope, $log, $filter, $timeout, lodash, go, profileService, configService, isCordova, rateService, storageService, addressService, gettextCatalog, gettext, amMoment, nodeWebkit, addonManager, feeService, isChromeApp, bwsError) { var self = this; self.isCordova = isCordova; self.onGoingProcess = {}; @@ -243,7 +243,7 @@ angular.module('copayApp.controllers').controller('indexController', function($r self.updateError = false; return fc.getStatus(function(err, ret) { if (err) { - self.updateError = true; + self.updateError = bwsError.msg(err, 'Could not update Wallet'); } else { if (!opts.quiet) self.setOngoingProcess('scanning', ret.wallet.scanning); diff --git a/src/js/controllers/join.js b/src/js/controllers/join.js index 948cfe176..1ca442f8c 100644 --- a/src/js/controllers/join.js +++ b/src/js/controllers/join.js @@ -153,7 +153,7 @@ angular.module('copayApp.controllers').controller('joinController', }, function(err) { if (err) { self.loading = false; - self.error = gettext('Could not join wallet: ') + (err.message ? err.message : err); + self.error = err; $rootScope.$apply(); return } diff --git a/src/js/controllers/walletHome.js b/src/js/controllers/walletHome.js index ff1d59536..9b19db9c2 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, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, feeService) { +angular.module('copayApp.controllers').controller('walletHomeController', function($scope, $rootScope, $timeout, $filter, $modal, $log, notification, txStatus, isCordova, profileService, lodash, configService, rateService, storageService, bitcore, isChromeApp, gettext, gettextCatalog, nodeWebkit, addressService, feeService, bwsError) { var self = this; $rootScope.hideMenuBar = false; @@ -94,24 +94,6 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi var cancel_msg = gettextCatalog.getString('Cancel'); var confirm_msg = gettextCatalog.getString('Confirm'); - // walletHome - - - var parseError = function(err) { - if (!err) return; - - if (err.message) { - // TODO : this is not used anymore? - if (err.message.indexOf('CORS') >= 0) { - err.message = gettext('Could not connect wallet service. Check your Internet connection and your wallet service configuration.'); - } - - if (err.message.indexOf('TIMEDOUT') >= 0) { - err.message = gettext('Wallet service timed out. Check your Internet connection and your wallet service configuration.'); - } - } - }; - $scope.openCopayersModal = function(copayers, copayerId) { var fc = profileService.focusedClient; @@ -152,13 +134,14 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi }); addressService.getAddress(walletId, false, function(err, addr) { $scope.gettingAddress = false; - if (!err || addr) - $modalInstance.close(addr); - else { - parseError(err); + + if (err) { self.error = err; $modalInstance.dismiss('cancel'); + return; } + + $modalInstance.close(addr); }); }; }; @@ -247,8 +230,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi if (fc.isPrivKeyEncrypted()) { profileService.unlockFC(function(err) { if (err) { - parseError(err); - $scope.error = err; + $scope.error = bwsError.msg(err); return; } return $scope.sign(txp); @@ -265,8 +247,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi self.setOngoingProcess(); if (err) { $scope.loading = false; - parseError(err); - $scope.error = err.message || gettext('Could not accept payment. Check your Internet connection and try again'); + $scope.error = bwsError.msg(err, gettext('Could not accept payment')); $scope.$digest(); } else { //if txp has required signatures then broadcast it @@ -278,8 +259,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi self.setOngoingProcess(); $scope.loading = false; if (err) { - parseError(err); - $scope.error = gettext('Could not broadcast payment. Check your Internet connection and try again'); + $scope.error = bwsError.msg('Could not broadcast payment'); $scope.$digest(); } else { $log.debug('Transaction signed and broadcasted') @@ -308,8 +288,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi self.setOngoingProcess(); $scope.loading = false; if (err) { - parseError(err); - $scope.error = err.message || gettext('Could not reject payment. Check your Internet connection and try again'); + $scope.error = bwsError.msg(err,gettext('Could not reject payment')); $scope.$digest(); } else { $modalInstance.close(txpr); @@ -330,8 +309,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi // Hacky: request tries to parse an empty response if (err && !(err.message && err.message.match(/Unexpected/))) { - parseError(err); - $scope.error = err.message || gettext('Could not delete payment proposal. Check your Internet connection and try again'); + $scope.error = bwsError.msg(err, gettext('Could not delete payment proposal')); $scope.$digest(); return; } @@ -349,8 +327,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi self.setOngoingProcess(); $scope.loading = false; if (err) { - parseError(err); - $scope.error = err.message || gettext('Could not broadcast payment. Check your Internet connection and try again'); + $scope.error = bwsError.msg(gettext('Could not broadcast payment')); $scope.$digest(); } else { @@ -420,14 +397,13 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi addressService.getAddress(fc.credentials.walletId, forceNew, function(err, addr) { self.generatingAddress = false; - if (err) { - parseError(err); - self.addrError = err.message || gettext('Could not create address. Check your Internet connection and try again'); + if (err) { + self.addrError = err; + } else { + if (addr) + self.addr[fc.credentials.walletId] = addr; } - if (addr) - self.addr[fc.credentials.walletId] = addr; - $scope.$digest(); }); }); @@ -678,16 +654,10 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi this.setSendError = function(err) { var fc = profileService.focusedClient; - $log.warn(err); - parseError(err); - var errMessage = + var prefix = fc.credentials.m > 1 ? gettext('Could not create payment proposal') : gettext('Could not send payment'); - //This are abnormal situations, but still err message will not be translated - //(the should) we should switch using err.code and use proper gettext messages - errMessage = errMessage + '. ' + (err.message ? err.message : gettext('Check your Internet connection and try again')); - - this.error = errMessage; + this.error = bwsError.msg(err, prefix); $timeout(function() { $scope.$digest(); @@ -802,8 +772,7 @@ console.log('[walletHome.js.757:amount:]',amount, feePerKb); //TODO profileService.lockFC(); self.setOngoingProcess(); if (err) { - $log.debug('Sign error:', err); - err.message = gettext('The payment was created but could not be signed. Please try again from home screen.') + (err.message ? ' ' + err.message : ''); + err.message = bwsError.msg(err, gettext('The payment was created but could not be signed. Please try again from home screen')); return cb(err); } @@ -812,7 +781,7 @@ console.log('[walletHome.js.757:amount:]',amount, feePerKb); //TODO fc.broadcastTxProposal(signedTx, function(err, btx, memo) { self.setOngoingProcess(); if (err) { - err.message = gettext('The payment was signed but could not be broadcasted. Please try again from home screen.') + (err.message ? ' ' + err.message : ''); + err.message = bwsError.msg(err, gettext('The payment was signed but could not be broadcasted. Please try again from home screen')); return cb(err); } if (memo) diff --git a/src/js/services/addressService.js b/src/js/services/addressService.js index 39978f94a..b0432d00a 100644 --- a/src/js/services/addressService.js +++ b/src/js/services/addressService.js @@ -1,7 +1,7 @@ 'use strict'; 'use strict'; angular.module('copayApp.services') - .factory('addressService', function(storageService, profileService, $log, $timeout, lodash) { + .factory('addressService', function(storageService, profileService, $log, $timeout, lodash, bwsError, gettext) { var root = {}; @@ -34,8 +34,7 @@ angular.module('copayApp.services') root._createAddress(walletId, cb); }, 5000); } - $log.debug('Creating address ERROR:', err); - return cb(err); + return bwsError.cb(err, gettext('Could not create address'), cb); } return cb(null, addr.address); }); diff --git a/src/js/services/bwsError.js b/src/js/services/bwsError.js new file mode 100644 index 000000000..a8e513f18 --- /dev/null +++ b/src/js/services/bwsError.js @@ -0,0 +1,125 @@ +'use strict'; +angular.module('copayApp.services') + .factory('bwsError', function bwcErrorService($log, gettext) { + var root = {}; + + root.msg = function(err, prefix) { + var body = ''; + prefix = prefix || ''; + + if (err && err.code) { + switch(err.code) { + case 'CONNECTION_ERROR': + body = gettext('Network connection error'); + break; + ;; + case 'NOT_FOUND': + body = gettext('Wallet service not found'); + break; + ;; + case 'BAD_SIGNATURES': + body = gettext('Signatures rejected by server'); + break; + ;; + case 'COPAYER_DATA_MISMATCH': + body = gettext('Copayer data mismatch'); + break; + ;; + case 'COPAYER_IN_WALLET': + body = gettext('Copayer already in this wallet'); + break; + ;; + case 'COPAYER_REGISTERED': + body = gettext('Copayer already registered'); + break; + ;; + case 'COPAYER_VOTED': + body = gettext('Copayer already voted on this spend proposal'); + break; + ;; + case 'DUST_AMOUNT': + body = gettext('Amount below dust threshold'); + break; + ;; + case 'INCORRECT_ADDRESS_NETWORK': + body = gettext('Incorrect address network'); + break; + ;; + case 'INSUFFICIENT_FUNDS': + body = gettext('Insufficient funds'); + break; + ;; + case 'INSUFFICIENT_FUNDS_FOR_FEE': + body = gettext('Insufficient funds for fee'); + break; + ;; + case 'INVALID_ADDRESS': + body = gettext('Invalid address'); + break; + ;; + case 'LOCKED_FUNDS': + body = gettext('Funds are locked by pending spend proposals'); + break; + ;; + case 'NOT_AUTHORIZED': + body = gettext('Not authorized'); + break; + ;; + case 'TX_ALREADY_BROADCASTED': + body = gettext('Transaction already broadcasted'); + break; + ;; + case 'TX_CANNOT_CREATE': + body = gettext('Locktime in effect. Please wait to create a new spend proposal'); + break; + ;; + case 'TX_CANNOT_REMOVE': + body = gettext('Locktime in effect. Please wait to remove this spend proposal'); + break; + ;; + case 'TX_NOT_ACCEPTED': + body = gettext('Spend proposal is not accepted'); + break; + ;; + case 'TX_NOT_FOUND': + body = gettext('Spend proposal not found'); + break; + ;; + case 'TX_NOT_PENDING': + body = gettext('The spend proposal is not pending'); + break; + ;; + case 'UPGRADE_NEEDED': + body = gettext('Please upgrade Copay to perform this action'); + break; + ;; + case 'WALLET_ALREADY_EXISTS': + body = gettext('Wallet already exists'); + break; + ;; + case 'WALLET_FULL': + body = gettext('Wallet is full'); + break; + ;; + case 'WALLET_NOT_COMPLETE': + body = gettext('Wallet is not complete'); + break; + ;; + case 'WALLET_NOT_FOUND': + body = gettext('Wallet not found'); + break; + ;; + } + } + + var msg = prefix + ( body ? ': ' + body : ''); + $log.warn("BWC ERROR:" + msg); + return msg; + }; + + root.cb = function (err,prefix, cb) { + return cb(root.msg(err, prefix)) + }; + + return root; + }); diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index bbb75921c..3d9c03373 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, nodeWebkit) { + .factory('profileService', function profileServiceFactory($rootScope, $location, $timeout, $filter, $log, lodash, storageService, bwcService, configService, notificationService, isChromeApp, isCordova, gettext, nodeWebkit, bwsError) { var root = {}; @@ -11,22 +11,6 @@ angular.module('copayApp.services') root.getUtils = function() { return bwcService.getUtils(); }; - - root.errorCb = function(err, prefix, cb) { - var body = ''; - - prefix = gettext(prefix); - if (!err || !err.code) return cb(prefix); - - switch(err.code) { - case 'CONNECTION_ERROR': - body = gettext('Network connection error'); - ;; - } - - return cb(prefix + ( body ? ': ' + body : '')); - }; - root.formatAmount = function(amount) { var config = configService.getSync().wallet.settings; if (config.unitCode == 'sat') return amount; @@ -191,7 +175,7 @@ angular.module('copayApp.services') walletClient.createWallet('Personal Wallet', 'me', 1, 1, { network: 'livenet' }, function(err) { - if (err) return root.errorCb(err, 'Error creating wallet', cb); + if (err) return bwsError.cb(err, gettext('Error creating wallet'), cb); var p = Profile.create({ credentials: [JSON.parse(walletClient.export())], }); @@ -213,7 +197,7 @@ angular.module('copayApp.services') walletClient.createWallet(opts.name, opts.myName || 'me', opts.m, opts.n, { network: opts.networkName }, function(err, secret) { - if (err) return root.errorCb(err, 'Error creating wallet', cb); + if (err) return bwsError.cb(err, gettext('Error creating wallet'), cb); root.profile.credentials.push(JSON.parse(walletClient.export())); root.setWalletClients(); @@ -236,8 +220,19 @@ angular.module('copayApp.services') return cb(gettext('Could not join using the specified extended private key')); } } + + + try { + var walletData = this.getUtils().fromSecret(opts.secret); + if (root.walletClients[walletData.walletId]) + return cb(gettext('Cannot join the same wallet more that once')); + + } catch (ex) { + return cb(gettext('Bad wallet invitation')); + } + walletClient.joinWallet(opts.secret, opts.myName || 'me', function(err) { - if (err) return cb(err); + if (err) return bwsError.cb(err, gettext('Could not join wallet'), cb); root.profile.credentials.push(JSON.parse(walletClient.export())); root.setWalletClients();