better handing of errors + prevent joining the same wallet more that once

This commit is contained in:
Matias Alejo Garcia 2015-08-12 11:08:33 -03:00
commit 033f7c163f
7 changed files with 167 additions and 79 deletions

View file

@ -76,7 +76,7 @@
<div class="amount" ng-style="{'background-color':index.backgroundColor}">
<div ng-if="!index.anyOnGoingProcess && !index.notAuthorized">
<div ng-show="index.updateError" ng-click='index.openWallet(); index.updateTxHistory()'>
<span class="size-12 db m10b" translate>Could not update Wallet</span>
<span class="size-12 db m10b" translate>{{index.updateError}}</span>
<button class="outline white tiny round" translate>Tap to retry</button>
</div>

View file

@ -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);

View file

@ -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
}

View file

@ -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)

View file

@ -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);
});

125
src/js/services/bwsError.js Normal file
View file

@ -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;
});

View file

@ -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();