diff --git a/js/controllers/copayers.js b/js/controllers/copayers.js index 551a1cf60..f94cab1b2 100644 --- a/js/controllers/copayers.js +++ b/js/controllers/copayers.js @@ -1,7 +1,8 @@ 'use strict'; angular.module('copayApp.controllers').controller('CopayersController', - function($scope, $rootScope, $location, controllerUtils) { + function($scope, $rootScope, $location) { + if (!$rootScope.wallet.isReady()) { $rootScope.title = 'Waiting copayers for ' + $rootScope.wallet.getName(); } @@ -9,9 +10,7 @@ angular.module('copayApp.controllers').controller('CopayersController', $scope.secret = $rootScope.wallet.getSecret(); $scope.goToWallet = function() { - controllerUtils.updateAddressList(); $location.path('/homeWallet'); - }; $scope.copayersList = function() { diff --git a/js/controllers/create.js b/js/controllers/create.js index 64ee88bcf..72d356fb3 100644 --- a/js/controllers/create.js +++ b/js/controllers/create.js @@ -1,10 +1,9 @@ 'use strict'; angular.module('copayApp.controllers').controller('CreateController', - function($scope, $rootScope, $location, $timeout, controllerUtils, backupService, notification, defaults) { + function($scope, $rootScope, $location, $timeout, identityService, backupService, notification, defaults) { $rootScope.fromSetup = true; - $rootScope.starting = false; $scope.loading = false; $scope.walletPassword = $rootScope.walletPassword; $scope.isMobile = !!window.cordova; @@ -53,10 +52,8 @@ angular.module('copayApp.controllers').controller('CreateController', privateKeyHex: $scope.private, networkName: $scope.networkName, }; - $rootScope.iden.createWallet(opts, function(err, w) { + identityService.createWallet(opts, function(){ $scope.loading = false; - controllerUtils.installWalletHandlers($scope, w); - controllerUtils.setFocusedWallet(w); }); }; }); diff --git a/js/controllers/createProfile.js b/js/controllers/createProfile.js index 824c9a0ce..1f2938493 100644 --- a/js/controllers/createProfile.js +++ b/js/controllers/createProfile.js @@ -1,14 +1,15 @@ 'use strict'; -angular.module('copayApp.controllers').controller('CreateProfileController', function($scope, $rootScope, $location, notification, controllerUtils, pluginManager, identityService) { - controllerUtils.redirIfLogged(); +angular.module('copayApp.controllers').controller('CreateProfileController', function($scope, $rootScope, $location, notification, pluginManager, identityService) { + + identityService.goWalletHome(); + $scope.loading = false; $scope.createProfile = function(form) { if (form && form.$invalid) { $scope.error('Error', 'Please enter the required fields'); return; } - $rootScope.starting = true; identityService.create($scope, form); } diff --git a/js/controllers/head.js b/js/controllers/head.js index 33c296d79..ce1da9149 100644 --- a/js/controllers/head.js +++ b/js/controllers/head.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('HeadController', function($scope, $rootScope, $filter, $timeout, notification, controllerUtils) { +angular.module('copayApp.controllers').controller('HeadController', function($scope, $rootScope, $filter, $timeout, notification, identityService, balanceService) { $scope.username = $rootScope.iden.getName(); $scope.hoverMenu = false; @@ -14,7 +14,7 @@ angular.module('copayApp.controllers').controller('HeadController', function($sc $scope.signout = function() { $rootScope.signingOut = true; - controllerUtils.logout(); + identityService.logout(); }; $scope.refresh = function() { @@ -23,12 +23,10 @@ angular.module('copayApp.controllers').controller('HeadController', function($sc if (w.isReady()) { w.sendWalletReady(); - if ($rootScope.addrInfos.length > 0) { - controllerUtils.clearBalanceCache(w); - controllerUtils.updateBalance(w, function() { - $rootScope.$digest(); - }); - } + balanceService.clearBalanceCache(w); + balanceService.update(w, function() { + $rootScope.$digest(); + }, true); } }; diff --git a/js/controllers/history.js b/js/controllers/history.js index 2328a1de9..8a592f370 100644 --- a/js/controllers/history.js +++ b/js/controllers/history.js @@ -2,9 +2,7 @@ var bitcore = require('bitcore'); angular.module('copayApp.controllers').controller('HistoryController', - function($scope, $rootScope, $timeout, controllerUtils, notification, rateService) { - controllerUtils.redirIfNotComplete(); - + function($scope, $rootScope) { var w = $rootScope.wallet; $rootScope.title = 'History'; @@ -19,15 +17,11 @@ angular.module('copayApp.controllers').controller('HistoryController', $scope.blockchain_txs = []; $scope.alternativeCurrency = []; - - $scope.selectPage = function(page) { $scope.currentPage = page; $scope.update(); }; - - $scope.downloadHistory = function() { var w = $rootScope.wallet; if (!w) return; diff --git a/js/controllers/home.js b/js/controllers/home.js index 2e529109f..e39da6827 100644 --- a/js/controllers/home.js +++ b/js/controllers/home.js @@ -1,8 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $location, notification, controllerUtils, pluginManager, identityService, Compatibility) { - controllerUtils.redirIfLogged(); - +angular.module('copayApp.controllers').controller('HomeController', function($scope, $rootScope, $location, notification, identityService, Compatibility) { // This is only for backwards compat, insight api should link to #!/confirmed directly if (getParam('confirmed')) { var hashIndex = window.location.href.indexOf('/?'); @@ -24,7 +22,6 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc $scope.error = 'Please enter the required fields'; return; } - $rootScope.starting = true; identityService.open($scope, form); } diff --git a/js/controllers/homeWallet.js b/js/controllers/homeWallet.js index ad25cd973..146fc2fae 100644 --- a/js/controllers/homeWallet.js +++ b/js/controllers/homeWallet.js @@ -1,11 +1,13 @@ 'use strict'; angular.module('copayApp.controllers').controller('HomeWalletController', - function($scope, $rootScope, $timeout, $modal, controllerUtils) { - - controllerUtils.redirIfNotComplete(); - $rootScope.starting = false; + function($scope, $rootScope) { $rootScope.title = 'Home'; + $scope.addr = _.last($rootScope.wallet.getReceiveAddresses()); + // This is necesarry, since wallet can change in homeWallet, without running init() again. + $rootScope.$watch('wallet', function() { + $scope.addr = _.last($rootScope.wallet.getReceiveAddresses()); + }); } ); diff --git a/js/controllers/import.js b/js/controllers/import.js index b7ecf09bc..895bc5790 100644 --- a/js/controllers/import.js +++ b/js/controllers/import.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('ImportController', - function($scope, $rootScope, $location, controllerUtils, notification, isMobile, Compatibility) { + function($scope, $rootScope, $location, identityService, notification, isMobile, Compatibility) { $rootScope.title = 'Import wallet'; $scope.importStatus = 'Importing wallet - Reading backup...'; @@ -18,28 +18,18 @@ angular.module('copayApp.controllers').controller('ImportController', $scope.$digest(); } - $scope._doImport = function(encryptedObj, password) { - updateStatus('Importing wallet - Procesing backup...'); - - copay.Compatibility.importEncryptedWallet($rootScope.iden, encryptedObj, - $scope.password, $scope.importOpts, function(err, wallet) { - if (err) { - $scope.loading = false; - $scope.error = 'Could not read wallet. Please check your password'; - } else { - controllerUtils.installWalletHandlers($scope, wallet); - controllerUtils.setFocusedWallet(wallet); - } - } - ); - }; - $scope.getFile = function() { // If we use onloadend, we need to check the readyState. reader.onloadend = function(evt) { if (evt.target.readyState == FileReader.DONE) { // DONE == 2 var encryptedObj = evt.target.result; - $scope._doImport(encryptedObj, $scope.password); + updateStatus('Importing wallet - Procesing backup...'); + identityService.importWallet(encryptedObj, $scope.password, {}, function(err){ + if (err) { + $scope.loading = false; + $scope.error = 'Could not read wallet. Please check your password'; + } + }); } }; }; @@ -85,8 +75,14 @@ angular.module('copayApp.controllers').controller('ImportController', if (backupFile) { reader.readAsBinaryString(backupFile); } else { - $scope._doImport(backupText, $scope.password); - copay.Compatibility.deleteOldWallet(backupOldWallet); + updateStatus('Importing wallet - Procesing backup...'); + identityService.importWallet(encryptedObj, $scope.password, $scope.importOpts, function(err){ + if (err) { + $scope.loading = false; + $scope.error = 'Could not read wallet. Please check your password'; + } + copay.Compatibility.deleteOldWallet(backupOldWallet); + }); } }; }); diff --git a/js/controllers/importProfile.js b/js/controllers/importProfile.js index 016308052..b9f07e7cb 100644 --- a/js/controllers/importProfile.js +++ b/js/controllers/importProfile.js @@ -1,9 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('ImportProfileController', - function($scope, $rootScope, $location, controllerUtils, notification, isMobile, pluginManager, identityService) { - controllerUtils.redirIfLogged(); - + function($scope, $rootScope, $location, notification, isMobile, pluginManager, identityService) { $scope.title = 'Import a backup'; $scope.importStatus = 'Importing wallet - Reading backup...'; $scope.hideAdv = true; @@ -41,7 +39,7 @@ angular.module('copayApp.controllers').controller('ImportProfileController', } else { var firstWallet = iden.getLastFocusedWallet(); - controllerUtils.bindProfile($scope, iden, firstWallet); + root.bind($scope, iden, firstWallet); } }); }; diff --git a/js/controllers/join.js b/js/controllers/join.js index 89d33da99..ce3f989c5 100644 --- a/js/controllers/join.js +++ b/js/controllers/join.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('JoinController', - function($scope, $rootScope, $timeout, isMobile, controllerUtils, notification) { + function($scope, $rootScope, $timeout, isMobile, notification) { $rootScope.fromSetup = false; $scope.loading = false; $scope.isMobile = isMobile.any(); @@ -119,31 +119,12 @@ angular.module('copayApp.controllers').controller('JoinController', } $scope.loading = true; - - $rootScope.iden.joinWallet({ + identityService.joinWallet({ secret: $scope.connectionId, nickname: $scope.nickname, privateHex: $scope.private, - }, function(err, w) { - + }, function(err) { $scope.loading = false; - if (err || !w) { - if (err === 'joinError') - notification.error('Fatal error connecting to Insight server'); - else if (err === 'walletFull') - notification.error('The wallet is full'); - else if (err === 'badNetwork') - notification.error('Network Error', 'Wallet network configuration missmatch'); - else if (err === 'badSecret') - notification.error('Bad secret', 'The secret string you entered is invalid'); - else { - notification.error('Error', err.message || err); - } - controllerUtils.onErrorDigest(); - } else { - controllerUtils.installWalletHandlers($scope, w); - controllerUtils.setFocusedWallet(w); - } }); } }); diff --git a/js/controllers/more.js b/js/controllers/more.js index 7d57c7a89..f3068922a 100644 --- a/js/controllers/more.js +++ b/js/controllers/more.js @@ -1,8 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('MoreController', - function($scope, $rootScope, $location, $filter, controllerUtils, notification, rateService) { - controllerUtils.redirIfNotComplete(); + function($scope, $rootScope, $location, $filter, balanceService, notification, rateService) { var w = $rootScope.wallet; $scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; @@ -76,7 +75,7 @@ angular.module('copayApp.controllers').controller('MoreController', alternativeIsoCode: $scope.selectedAlternative.isoCode, }); notification.success('Success', $filter('translate')('settings successfully updated')); - controllerUtils.updateBalance(w, function() { + balanceService.update(w, function() { $rootScope.$digest(); }); }; @@ -84,9 +83,9 @@ angular.module('copayApp.controllers').controller('MoreController', $scope.purge = function(deleteAll) { var removed = w.purgeTxProposals(deleteAll); if (removed) { - controllerUtils.updateBalance(w, function() { + balanceService.update(w, function() { $rootScope.$digest(); - }); + }, true); } notification.info('Transactions Proposals Purged', removed + ' ' + $filter('translate')('transaction proposal purged')); }; @@ -99,12 +98,11 @@ angular.module('copayApp.controllers').controller('MoreController', if (err) { notification.error('Error', $filter('translate')('Error updating indexes: ') + err); } - controllerUtils.updateAddressList(); - controllerUtils.updateBalance(w, function() { + balanceService.update(w, function() { notification.info('Finished', 'The balance is updated using the derived addresses'); w.sendIndexes(); $rootScope.$digest(); - }); + }, true); }); }; }); diff --git a/js/controllers/paymentIntent.js b/js/controllers/paymentIntent.js index 93a40f5ce..a575383f6 100644 --- a/js/controllers/paymentIntent.js +++ b/js/controllers/paymentIntent.js @@ -1,26 +1,17 @@ 'use strict'; -var bitcore = require('bitcore'); - -angular.module('copayApp.controllers').controller('PaymentIntentController', function($rootScope, $scope, $modal, $location, controllerUtils) { +angular.module('copayApp.controllers').controller('PaymentIntentController', function($rootScope, $scope, $modal, $location, balanceService) { $scope.wallets = []; $rootScope.title = 'Payment intent'; - $rootScope.starting = true; + $scope.wallets = rootScope.iden.listWallets(); - var wids = _.pluck($rootScope.iden.listWallets(), 'id'); - _.each(wids, function(wid) { - var w = $rootScope.iden.getWalletById(wid); - if (w && w.isReady()) { - - $scope.wallets.push(w); - $rootScope.starting = false; - controllerUtils.clearBalanceCache(w); - controllerUtils.updateBalance(w, function() { + var l = $scope.wallet.length; + _.each($scope.wallets, function(w, i) { + balanceService.update(w, function(){ + if (i === l-1) $rootScope.$digest(); - }, true); - - } + }); }); $scope.open = function() { @@ -39,10 +30,10 @@ angular.module('copayApp.controllers').controller('PaymentIntentController', fun // 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, items, controllerUtils) { + var ModalInstanceCtrl = function($scope, $modalInstance, items, identityService) { $scope.wallets = items; $scope.ok = function(selectedItem) { - controllerUtils.setPaymentWallet(selectedItem); + identityService.setPaymentWallet(selectedItem); $modalInstance.close(); }; diff --git a/js/controllers/profile.js b/js/controllers/profile.js index 1d5280968..ef8a471a7 100644 --- a/js/controllers/profile.js +++ b/js/controllers/profile.js @@ -1,5 +1,5 @@ 'use strict'; -angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, controllerUtils, backupService) { +angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, backupService) { $scope.username = $rootScope.iden.getName(); $scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; @@ -14,28 +14,11 @@ angular.module('copayApp.controllers').controller('ProfileController', function( $scope.hideViewProfileBackup = true; }; - $scope.getWallets = function() { - if (!$rootScope.iden) return; - $scope.wallets = []; - var wids = _.pluck($rootScope.iden.listWallets(), 'id'); - _.each(wids, function(wid) { - var w = $rootScope.iden.getWalletById(wid); - $scope.wallets.push(w); - controllerUtils.updateBalance(w, function() { - $rootScope.$digest(); - }, true); - }); - }; - $scope.deleteWallet = function(w) { if (!w) return; $scope.loading = w.id; - controllerUtils.deleteWallet($scope, w, function() { - if ($rootScope.wallet.id === w.id) { - $rootScope.wallet = null; - var lastFocused = $rootScope.iden.getLastFocusedWallet(); - controllerUtils.bindProfile($scope, $rootScope.iden, lastFocused); - } + + identityService.deleteWallet(w.id,function() { $scope.loading = false; $scope.getWallets(); }); diff --git a/js/controllers/receive.js b/js/controllers/receive.js index a3a34e49c..9401aa1e2 100644 --- a/js/controllers/receive.js +++ b/js/controllers/receive.js @@ -1,9 +1,7 @@ 'use strict'; angular.module('copayApp.controllers').controller('ReceiveController', - function($scope, $rootScope, $timeout, $modal, controllerUtils) { - controllerUtils.redirIfNotComplete(); - + function($scope, $rootScope, $timeout, $modal) { $rootScope.title = 'Receive'; $scope.loading = false; $scope.showAll = false; @@ -15,7 +13,6 @@ angular.module('copayApp.controllers').controller('ReceiveController', $scope.isNewAddr = false; w.generateAddress(null); $timeout(function() { - controllerUtils.updateAddressList(); $scope.loading = false; $scope.isNewAddr = true; }, 1); @@ -74,20 +71,22 @@ angular.module('copayApp.controllers').controller('ReceiveController', $scope.addressList = function() { $scope.addresses = []; + var w = $rootScope.wallet; + var balance = $rootScope.balanceByAddr; - if ($rootScope.addrInfos) { - var addrInfos = $rootScope.addrInfos; - $scope.addrLength = addrInfos.length; - for (var i = 0; i < addrInfos.length; i++) { - var addrinfo = addrInfos[i]; + var addresses = w.getAddresses(); + if (addresses) { + $scope.addrLength = addresses.length; + _.each(addresses, function(address, index){ $scope.addresses.push({ - 'index': i, - 'address': addrinfo.addressStr, - 'balance': $rootScope.balanceByAddr ? $rootScope.balanceByAddr[addrinfo.addressStr] : 0, - 'isChange': addrinfo.isChange, - 'owned': addrinfo.owned + 'index': index, + 'address': address, + 'balance': balance ? balance[address] : 0, + 'isChange': w.addressIsChange(address), + // TODO + 'owned': w.addressIsOwn(address), }); - } + }); $scope.addresses = $scope.limitAddress($scope.addresses, $scope.isNewAddr); } }; diff --git a/js/controllers/send.js b/js/controllers/send.js index d6b1aecb2..4b98044e7 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -3,10 +3,7 @@ var bitcore = require('bitcore'); var preconditions = require('preconditions').singleton(); angular.module('copayApp.controllers').controller('SendController', - function($scope, $rootScope, $window, $timeout, $modal, isMobile, notification, controllerUtils, rateService) { - - controllerUtils.redirIfNotComplete(); - + function($scope, $rootScope, $window, $timeout, $modal, isMobile, notification, rateService) { var w = $rootScope.wallet; preconditions.checkState(w); preconditions.checkState(w.settings.unitToSatoshi); @@ -33,6 +30,34 @@ angular.module('copayApp.controllers').controller('SendController', $scope.$digest(); }); + $scope.setAlternativeAmount = function(w, tx, cb) { + rateService.whenAvailable(function() { + _.each(tx.outs, function(out) { + var valueSat = out.value * w.settings.unitToSatoshi; + out.alternativeAmount = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); + out.alternativeIsoCode = w.settings.alternativeIsoCode; + }); + if (cb) return cb(tx); + }); + }; + + $scope.updateTxs = function() { + var w = $rootScope.wallet; + if (!w) return; + + var res = w.getPendingTxProposals(); + _.each(res.txs, function(tx) { + $scope.setAlternativeAmount(w, tx); + if (tx.merchant) { + var url = tx.merchant.request_url; + var domain = /^(?:https?)?:\/\/([^\/:]+).*$/.exec(url)[1]; + tx.merchant.domain = domain; + } + }); + $scope.txps = res.txs; +// TODO +// $rootScope.pendingTxCount = res.pendingForUs; + }; /** * Setting the two related amounts as properties prevents an infinite @@ -76,7 +101,7 @@ angular.module('copayApp.controllers').controller('SendController', $scope.loadTxs = function() { - controllerUtils.updateTxs(); + $scope.updateTxs(); setTimeout(function() { $scope.loading = false; $rootScope.$digest(); diff --git a/js/controllers/settings.js b/js/controllers/settings.js index 2756f55d3..3c24d3604 100644 --- a/js/controllers/settings.js +++ b/js/controllers/settings.js @@ -1,8 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('SettingsController', function($scope, $rootScope, $window, $route, $location, $anchorScroll, controllerUtils, notification) { - controllerUtils.redirIfLogged(); - +angular.module('copayApp.controllers').controller('SettingsController', function($scope, $rootScope, $window, $route, $location, $anchorScroll, notification) { $scope.title = 'Settings'; $scope.defaultLanguage = config.defaultLanguage || 'en'; $scope.insightLivenet = config.network.livenet.url; diff --git a/js/controllers/sidebar.js b/js/controllers/sidebar.js index e64de73db..760c15739 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, controllerUtils) { +angular.module('copayApp.controllers').controller('SidebarController', function($scope, $rootScope, $location, $timeout, identityService) { $scope.menu = [{ 'title': 'Home', @@ -24,21 +24,6 @@ angular.module('copayApp.controllers').controller('SidebarController', function( 'link': 'more' }]; - $scope.refresh = function() { - var w = $rootScope.wallet; - if (!w) return; - - if (w.isReady()) { - w.sendWalletReady(); - if ($rootScope.addrInfos.length > 0) { - controllerUtils.clearBalanceCache(w); - controllerUtils.updateBalance(w, function() { - $rootScope.$digest(); - }); - } - } - }; - $scope.signout = function() { $scope.$emit('signout'); }; @@ -47,35 +32,32 @@ angular.module('copayApp.controllers').controller('SidebarController', function( return item.link && item.link == $location.path().split('/')[1]; }; - if ($rootScope.wallet) { - $rootScope.$watch('wallet.id', function() { - $scope.walletSelection = false; - $scope.getWallets(); - }); - } - $scope.switchWallet = function(wid) { - controllerUtils.setFocusedWallet(wid); + identityService.setFocusedWallet(wid); }; $scope.toggleWalletSelection = function() { $scope.walletSelection = !$scope.walletSelection; if (!$scope.walletSelection) return; - - $scope.getWallets(); + $scope.setWallets(); }; - $scope.getWallets = function() { + + $scope.init = function() { + if ($rootScope.wallet) { + $rootScope.$watch('wallet', function() { + $scope.walletSelection = false; + $scope.setWallets(); + }); + } + }; + + + $scope.setWallets = function() { if (!$rootScope.iden) return; - $scope.wallets = []; - var wids = _.pluck($rootScope.iden.listWallets(), 'id'); - _.each(wids, function(wid) { - if (controllerUtils.isFocusedWallet(wid)) return; - var w = $rootScope.iden.getWalletById(wid); - $scope.wallets.push(w); - controllerUtils.updateBalance(w, function() { - $rootScope.$digest(); - }) + var ret = _.filter($rootScope.iden.listWallets(), function(w) { + return !identityService.isFocused(w.getId()); }); + $scope.wallets = ret; }; }); diff --git a/js/controllers/warning.js b/js/controllers/warning.js index 75f19ff56..175c0f6c9 100644 --- a/js/controllers/warning.js +++ b/js/controllers/warning.js @@ -1,16 +1,14 @@ 'use strict'; -angular.module('copayApp.controllers').controller('WarningController', function($scope, $rootScope, $location, controllerUtils) { - +angular.module('copayApp.controllers').controller('WarningController', function($scope, $rootScope, $location, identityService) { $scope.checkLock = function() { if (!$rootScope.tmp || !$rootScope.tmp.getLock()) { - controllerUtils.redirIfLogged(); + console.log('[warning.js.7] TODO LOCK'); //TODO } }; - $scope.signout = function() { - controllerUtils.logout(); + identityService.logout(); }; $scope.ignoreLock = function() { @@ -22,7 +20,8 @@ angular.module('copayApp.controllers').controller('WarningController', function( } else { w.ignoreLock = 1; $scope.loading = true; - controllerUtils.startNetwork(w, $scope); + //controllerUtils.startNetwork(w, $scope); + // TODO } }; }); diff --git a/js/models/Identity.js b/js/models/Identity.js index 5b4fa72d3..8b93af888 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -172,11 +172,7 @@ Identity.prototype.retrieveWalletFromStorage = function(walletId, opts, callback blockchainOpts: self.blockchainOpts, skipFields: [] }; - - return callback(null, importFunction(walletData, readOpts)); - } catch (e) { - log.debug("ERROR: ", e.message); if (e && e.message && e.message.indexOf('MISSOPTS') !== -1) { return callback(new Error('WERROR: Could not read: ' + walletId + ': ' + e.message)); @@ -184,6 +180,7 @@ Identity.prototype.retrieveWalletFromStorage = function(walletId, opts, callback return callback(e); } } + return callback(null, importFunction(walletData, readOpts)); }); }; @@ -564,6 +561,9 @@ Identity.prototype.listWallets = function() { Identity.prototype.deleteWallet = function(walletId, cb) { var self = this; + var w = this.getWalletById(walletId); + w.close(); + delete this.wallets[walletId]; this.storage.removeItem(Wallet.getStorageKey(walletId), function(err) { if (err) { diff --git a/js/models/Insight.js b/js/models/Insight.js index 0dd6182a2..d0de500cd 100644 --- a/js/models/Insight.js +++ b/js/models/Insight.js @@ -200,8 +200,6 @@ Insight.prototype.subscribe = function(addresses) { addresses = Array.isArray(addresses) ? addresses : [addresses]; var self = this; -console.log('[Insight.js.202] subscribe STARTED'); //TODO - function handlerFor(self, address) { return function(txid) { // verify the address is still subscribed @@ -293,6 +291,7 @@ Insight.prototype.getTransactions = function(addresses, from, to, cb) { }; Insight.prototype.getUnspent = function(addresses, cb) { +console.log('[Insight.js.296:addresses:]',addresses); //TODO preconditions.shouldBeArray(addresses); preconditions.shouldBeFunction(cb); diff --git a/js/models/PublicKeyRing.js b/js/models/PublicKeyRing.js index c12220ff4..083708bac 100644 --- a/js/models/PublicKeyRing.js +++ b/js/models/PublicKeyRing.js @@ -518,6 +518,20 @@ PublicKeyRing.prototype.getAddresses = function() { return ret; }; +/** + * @desc + * Gets information about addresses for a copayer + * + * @param {Object} opts + * @returns {AddressInfo[]} + */ +PublicKeyRing.prototype.getReceiveAddresses = function() { + this._checkAndRebuildCache(); + var ret = this.cache.receiveAddresses; + return ret; +}; + + /** * @desc @@ -526,43 +540,43 @@ PublicKeyRing.prototype.getAddresses = function() { * @param {string} path - the BIP32 path * @return {Buffer[]} the public keys, in buffer format */ -PublicKeyRing.prototype.getForPath = function(path) { +PublicKeyRing.prototype._getForPath = function(path) { var p = HDPath.indexesForPath(path); return this.getPubKeys(p.addressIndex, p.isChange, p.copayerIndex); }; -/** - * @desc - * Retrieve the public keys for all cosigners for multiple paths - * @see PublicKeyRing#getForPath - * - * @param {string[]} paths - the BIP32 paths - * @return {Array[]} the public keys, in buffer format (matrix of Buffer, Buffer[][]) - */ -PublicKeyRing.prototype.getForPaths = function(paths) { - preconditions.checkArgument(!_.isUndefined(paths)); - preconditions.checkArgument(_.isArray(paths)); - preconditions.checkArgument(_.all(paths, _.isString)); - - return paths.map(this.getForPath.bind(this)); -}; /** * @desc * Retrieve the public keys for derived addresses and the public keys for copayers * - * @TODO: Should this exist? A user should just call getForPath(paths) + * @TODO: Should this exist? A user should just call _getForPath(paths) * * @param {string[]} paths - the paths to be derived * @return {Object} with keys pubKeys and copayerIds */ PublicKeyRing.prototype.forPaths = function(paths) { return { - pubKeys: paths.map(this.getForPath.bind(this)), + pubKeys: paths.map(this._getForPath.bind(this)), copayerIds: this.copayerIds, } }; +/** + * @desc + * Retrieve the public keys for all cosigners for multiple paths + * + * @param {string[]} paths - the BIP32 paths + * @return {Array[]} the public keys, in buffer format (matrix of Buffer, Buffer[][]) + */ +PublicKeyRing.prototype._getForPaths = function(paths) { + preconditions.checkArgument(!_.isUndefined(paths)); + preconditions.checkArgument(_.isArray(paths)); + preconditions.checkArgument(_.all(paths, _.isString)); + + return paths.map(this._getForPath.bind(this)); +}; + /** * @desc * Returns a map from a pubkey of an address to the id that generated it @@ -580,7 +594,7 @@ PublicKeyRing.prototype.copayersForPubkeys = function(pubkeys, paths) { inKeyMap[pubkeys[i]] = 1; }; - var keys = this.getForPaths(paths); + var keys = this._getForPaths(paths); for (var i in keys) { for (var copayerIndex in keys[i]) { var kHex = keys[i][copayerIndex].toString('hex'); diff --git a/js/models/Wallet.js b/js/models/Wallet.js index f9def93a7..a97e96888 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -915,6 +915,8 @@ Wallet.prototype._setBlockchainListeners = function() { } } + + /** * @desc Sets up the networking with other peers. * @@ -1983,29 +1985,25 @@ Wallet.prototype.addSeenToTxProposals = function() { /** * @desc Alias for {@link PublicKeyRing#getAddresses} - * @TODO: remove this method and use getAddressesInfo everywhere * @return {Buffer[]} */ -Wallet.prototype.getAddresses = function(opts) { - return this.publicKeyRing.getAddresses(opts); +Wallet.prototype.getAddresses = function() { + return this.publicKeyRing.getAddresses(); }; /** - * @desc Retrieves all addresses as strings. - * - * @param {Object} opts - Same options as {@link PublicKeyRing#getAddresses} - * @return {string[]} + * @desc Alias for {@link PublicKeyRing#getAddresses} + * @return {Buffer[]} */ -Wallet.prototype.getAddressesStr = function(opts) { - return this.getAddresses(opts).map(function(a) { - return a.toString(); - }); +Wallet.prototype.getReceiveAddresses = function() { + return this.publicKeyRing.getReceiveAddresses(); }; + Wallet.prototype.subscribeToAddresses = function() { if (!this.publicKeyRing.isComplete()) return; - var addresses = this.publicKeyRing.getAddresses(); + var addresses = this.getAddresses(); this.blockchain.subscribe(addresses); log.debug('Subscribed to ' + addresses.length + ' addresses'); }; @@ -2442,7 +2440,9 @@ Wallet.prototype.indexDiscovery = function(start, change, copayerIndex, gap, cb) * @desc Closes the wallet and disconnects all services */ Wallet.prototype.close = function(cb) { + this.network.removeAllListeners(); this.network.cleanUp(); + this.blockchain.removeAllListeners(); this.blockchain.destroy(); log.debug('## CLOSING Wallet: ' + this.id); @@ -2664,10 +2664,9 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) { }; if (addresses.length > 0) { - var addressesStr = _.pluck(addresses, 'addressStr'); var from = (opts.currentPage - 1) * opts.itemsPerPage; var to = opts.currentPage * opts.itemsPerPage; - self.blockchain.getTransactions(addressesStr, from, to, function(err, res) { + self.blockchain.getTransactions(addresses, from, to, function(err, res) { if (err) return cb(err); _.each(res.items, function(tx) { diff --git a/js/routes.js b/js/routes.js index a9e0a59e7..35f4f1ddd 100644 --- a/js/routes.js +++ b/js/routes.js @@ -47,26 +47,32 @@ angular }) .when('/homeWallet', { templateUrl: 'views/homeWallet.html', + walletShouldBeReady: true, logged: true }) .when('/receive', { templateUrl: 'views/receive.html', + walletShouldBeReady: true, logged: true }) .when('/history', { templateUrl: 'views/history.html', + walletShouldBeReady: true, logged: true }) .when('/send', { templateUrl: 'views/send.html', + walletShouldBeReady: true, logged: true }) .when('/more', { templateUrl: 'views/more.html', + walletShouldBeReady: true, logged: true }) .when('/settings', { templateUrl: 'views/settings.html', + walletShouldBeReady: true, logged: false }) .when('/warning', { @@ -119,6 +125,9 @@ angular $idle.unwatch(); $location.path('/'); } + if ($rootScope.wallet && !$rootScope.wallet.isReady() && next.walletShouldBeReady) { + $location.path('/copayers'); + } } }); }) diff --git a/js/services/balanceService.js b/js/services/balanceService.js new file mode 100644 index 000000000..49a008f3f --- /dev/null +++ b/js/services/balanceService.js @@ -0,0 +1,84 @@ +'use strict'; +var bitcore = require('bitcore'); + +angular.module('copayApp.services') + .factory('balanceService', function($rootScope, $sce, $location, $filter, notification, $timeout, rateService) { + var root = {}; + var _balanceCache = {}; + root.clearBalanceCache = function(w) { + delete _balanceCache[w.getId()]; + }; + + root._fetchBalance = function(w, cb) { + cb = cb || function() {}; + var satToUnit = 1 / w.settings.unitToSatoshi; + var COIN = bitcore.util.COIN; + + console.log('[balanceS.js.257] FETCH BALANCE: ', w.getName()); //TODO + w.getBalance(function(err, balanceSat, balanceByAddrSat, safeBalanceSat, safeUnspentCount) { + if (err) return cb(err); + + var r = {}; + r.totalBalance = balanceSat * satToUnit; + r.totalBalanceBTC = (balanceSat / COIN); + r.availableBalance = safeBalanceSat * satToUnit; + r.availableBalanceBTC = (safeBalanceSat / COIN); + r.safeUnspentCount = safeUnspentCount; + + r.lockedBalance = (balanceSat - safeBalanceSat) * satToUnit; + r.lockedBalanceBTC = (balanceSat - safeBalanceSat) / COIN; + + + if (r.safeUnspentCount) { + var estimatedFee = copay.Wallet.estimatedFee(r.safeUnspentCount); + r.topAmount = (((r.availableBalance * w.settings.unitToSatoshi).toFixed(0) - estimatedFee) / w.settings.unitToSatoshi); + } + + var balanceByAddr = {}; + for (var ii in balanceByAddrSat) { + balanceByAddr[ii] = balanceByAddrSat[ii] * satToUnit; + } + r.balanceByAddr = balanceByAddr; + + if (rateService.isAvailable()) { + r.totalBalanceAlternative = rateService.toFiat(balanceSat, w.settings.alternativeIsoCode); + r.alternativeIsoCode = w.settings.alternativeIsoCode; + r.lockedBalanceAlternative = rateService.toFiat(balanceSat - safeBalanceSat, w.settings.alternativeIsoCode); + r.alternativeConversionRate = rateService.toFiat(100000000, w.settings.alternativeIsoCode); + r.alternativeBalanceAvailable = true; + }; + + r.updatingBalance = false; + + return cb(null, r) + }); + }; + + root.update = function(w, cb, isFocused) { + console.log(' UPDATE BALANCE!!!!', w ? w.getName() : 'current'); //TODO + + w = w || $rootScope.wallet; + if (!w || !w.isReady()) return; + + console.log('DO UPDATE BALANCE!!!!', w.getName()); //TODO + var wid = w.getId(); + + if (_balanceCache[wid]) { + w.balanceInfo = _balanceCache[wid]; + } else { + $rootScope.updatingBalance = true; + } + + root._fetchBalance(w, function(err, res) { + if (err) throw err; + w.balanceInfo=_balanceCache[wid] = res; + $rootScope.updatingBalance = false; + if (isFocused) { + _.extend($rootScope, w.balanceInfo); + } + if (cb) cb(); + }); + }; + + return root; + }); diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js deleted file mode 100644 index 07d157720..000000000 --- a/js/services/controllerUtils.js +++ /dev/null @@ -1,396 +0,0 @@ -'use strict'; -var bitcore = require('bitcore'); - -angular.module('copayApp.services') - .factory('controllerUtils', function($rootScope, $sce, $location, $filter, notification, $timeout, rateService) { - var root = {}; - - - root.redirIfNotComplete = function() { - var w = $rootScope.wallet; - if (w) { - if (!w.isReady()) { - $location.path('/copayers'); - } - } else { - $location.path('/'); - } - }; - - - root.redirIfLogged = function() { - var w = $rootScope.wallet; - if (w) { - if (!w.isReady()) { - $location.path('/copayers'); - } else { - $location.path('homeWallet'); - } - } - }; - - root.logout = function() { - - if ($rootScope.iden) { - $rootScope.iden.store(null, function() { - $rootScope.iden.close(); - - delete $rootScope['wallet']; - delete $rootScope['iden']; - - // Go home reloading the application - var hashIndex = window.location.href.indexOf('#!/'); - window.location = window.location.href.substr(0, hashIndex); - }); - } - }; - - root.onError = function(scope) { - if (scope) { - scope.loading = false; - } - } - - root.onErrorDigest = function(scope, msg) { - root.onError(scope); - if (msg) { - notification.error('Error', msg); - } - }; - - - root.isFocusedWallet = function(wid) { - return $rootScope.wallet && wid === $rootScope.wallet.getId(); - }; - - - - root.installWalletHandlers = function($scope, w) { - - var wid = w.getId(); - w.on('connectionError', function() { - if (root.isFocusedWallet(wid)) { - var message = "Could not connect to the Insight server. Check your settings and network configuration"; - notification.error('Networking Error', message); - root.onErrorDigest($scope); - } - }); - - w.on('corrupt', function(peerId) { - if (root.isFocusedWallet(wid)) { - notification.error('Error', $filter('translate')('Received corrupt message from ') + peerId); - } - }); - w.on('ready', function(myPeerID) { - $scope.loading = false; - if ($rootScope.initialConnection) { - $rootScope.initialConnection = false; - if ($rootScope.pendingPayment) { - $location.path('paymentIntent'); - } else { - root.redirIfLogged(); - } - } - }); - - w.on('tx', function(address, isChange) { - if (!isChange) { - notification.funds('Funds received on ' + w.getName(), address); - } - root.updateBalance(w, function() { - $rootScope.$digest(); - }); - }); - - w.on('balanceUpdated', function() { - root.updateBalance(w, function() { - $rootScope.$digest(); - }); - }); - - w.on('insightReconnected', function() { - $rootScope.reconnecting = false; - root.updateAddressList(w.getId()); - root.updateBalance(w, function() { - $rootScope.$digest(); - }); - }); - - w.on('insightError', function() { - if (root.isFocusedWallet(wid)) { - $rootScope.reconnecting = true; - $rootScope.$digest(); - } - }); - w.on('newAddresses', function() { - root.updateBalance(w); - }); - - w.on('txProposalsUpdated', function() { - if (root.isFocusedWallet(wid)) { - root.updateTxs(); - } - }); - - w.on('paymentACK', function(memo) { - notification.success('Payment Acknowledged', memo); - }); - - w.on('txProposalEvent', function(e) { - - if (root.isFocusedWallet(wid)) { - root.updateTxs(); - } - - // TODO: add wallet name notification - var user = w.publicKeyRing.nicknameForCopayer(e.cId); - var name = w.getName(); - switch (e.type) { - case 'new': - notification.info('[' + name + '] New Transaction', - $filter('translate')('You received a transaction proposal from') + ' ' + user); - break; - case 'signed': - notification.info('[' + name + '] Transaction Signed', - $filter('translate')('A transaction was signed by') + ' ' + user); - break; - case 'signedAndBroadcasted': - notification.info('[' + name + '] Transaction Approved', - $filter('translate')('A transaction was signed and broadcasted by') + ' ' + user); - break; - case 'rejected': - notification.info('[' + name + '] Transaction Rejected', - $filter('translate')('A transaction was rejected by') + ' ' + user); - break; - case 'corrupt': - notification.error('[' + name + '] Transaction Error', - $filter('translate')('Received corrupt transaction from') + ' ' + user); - break; - } - $rootScope.$digest(); - }); - w.on('addressBookUpdated', function(dontDigest) { - if (root.isFocusedWallet(wid)) { - if (!dontDigest) { - $rootScope.$digest(); - } - } - }); - w.on('connect', function(peerID) { - $rootScope.$digest(); - }); - w.on('close', root.onErrorDigest); - w.on('locked', root.onErrorDigest.bind(this)); - - }; - - root.setupGlobalVariables = function(iden) { - notification.enableHtml5Mode(); // for chrome: if support, enable it - $rootScope.unitName = config.unitName; - $rootScope.pendingTxCount = 0; - $rootScope.initialConnection = true; - $rootScope.reconnecting = false; - $rootScope.isCollapsed = true; - - $rootScope.iden = iden; - }; - - - root.rebindWallets = function($scope, iden) { - _.each(iden.listWallets(), function(wallet) { - preconditions.checkState(wallet); - root.installWalletHandlers($scope, wallet); - }); - }; - - root.setPaymentWallet = function(w) { - root.setFocusedWallet(w); - $location.path('/send'); - }; - - root.setFocusedWallet = function(w) { - if (!_.isObject(w)) - w = $rootScope.iden.getWalletById(w); - - preconditions.checkState(w && _.isObject(w)); - - $rootScope.wallet = w; - w.updateFocusedTimestamp(Date.now()); - root.redirIfLogged(); - $timeout(function(){ - $rootScope.$digest(); - },1) - // root.updateTxs(); - // root.updateBalance(w, function() { - // $rootScope.$digest(); - // }) - }; - - root.bindProfile = function($scope, iden, w) { - -console.log('[controllerUtils.js.230] bindProfile Globals'); //TODO - root.setupGlobalVariables(iden); -console.log('[controllerUtils.js.230] bindProfile Wallets'); //TODO - root.rebindWallets($scope, iden); - if (w) { -console.log('[controllerUtils.js.230] bindProfile set Focus'); //TODO - root.setFocusedWallet(w); - } else { - $location.path('/create'); - } - $timeout(function() { - -console.log('[controllerUtils.js.242] DIGEST'); //TODO - $rootScope.$digest() -console.log('[controllerUtils.js.242] DIGEST DONE'); //TODO - }, 1); - }; - - // On the focused wallet - root.updateAddressList = function(wid) { - - if (!wid || root.isFocusedWallet(wid)) { - var w = $rootScope.wallet; - - if (w && w.isReady()) { - $rootScope.addrInfos = w.getAddressesInfo(); - } - } - }; - - var _balanceCache = {}; - root.clearBalanceCache = function(w) { - delete _balanceCache[w.getId()]; - }; - - - root._fetchBalance = function(w, cb) { - cb = cb || function() {}; - var satToUnit = 1 / w.settings.unitToSatoshi; - var COIN = bitcore.util.COIN; - - w.getBalance(function(err, balanceSat, balanceByAddrSat, safeBalanceSat, safeUnspentCount) { - if (err) return cb(err); - - var r = {}; - r.totalBalance = balanceSat * satToUnit; - r.totalBalanceBTC = (balanceSat / COIN); - r.availableBalance = safeBalanceSat * satToUnit; - r.availableBalanceBTC = (safeBalanceSat / COIN); - r.safeUnspentCount = safeUnspentCount; - - r.lockedBalance = (balanceSat - safeBalanceSat) * satToUnit; - r.lockedBalanceBTC = (balanceSat - safeBalanceSat) / COIN; - - - if (r.safeUnspentCount) { - var estimatedFee = copay.Wallet.estimatedFee(r.safeUnspentCount); - r.topAmount = (((r.availableBalance * w.settings.unitToSatoshi).toFixed(0) - estimatedFee) / w.settings.unitToSatoshi); - } - - var balanceByAddr = {}; - for (var ii in balanceByAddrSat) { - balanceByAddr[ii] = balanceByAddrSat[ii] * satToUnit; - } - r.balanceByAddr = balanceByAddr; - root.updateAddressList(); - - - - if (rateService.isAvailable()) { - r.totalBalanceAlternative = rateService.toFiat(balanceSat, w.settings.alternativeIsoCode); - r.alternativeIsoCode = w.settings.alternativeIsoCode; - r.lockedBalanceAlternative = rateService.toFiat(balanceSat - safeBalanceSat, w.settings.alternativeIsoCode); - r.alternativeConversionRate = rateService.toFiat(100000000, w.settings.alternativeIsoCode); - r.alternativeBalanceAvailable = true; - }; - - r.updatingBalance = false; - - return cb(null, r) - }); - }; - - root._updateScope = function(w, data, scope, cb) { - _.each(data, function(v, k) { - scope[k] = data[k]; - }) - if (cb) return cb(); - }; - - root.updateBalance = function(w, cb, refreshAll) { - - return - cb?cb(): null; - - - w = w || $rootScope.wallet; - if (!w) return root.onErrorDigest(); - if (!w.isReady()) return; - - w.balanceInfo = {}; - var scope = root.isFocusedWallet(w.id) && !refreshAll ? $rootScope : w.balanceInfo; - - var wid = w.getId(); - - if (_balanceCache[wid]) { - root._updateScope(w, _balanceCache[wid], scope, function() { - if (root.isFocusedWallet(w.id) && !refreshAll) { - setTimeout(function() { - $rootScope.$digest(); - }, 1); - } - }); - } else { - scope.updatingBalance = true; - } - - root._fetchBalance(w, function(err, res) { - if (err) throw err; - _balanceCache[wid] = res; - root._updateScope(w, _balanceCache[wid], scope, function() { - scope.updatingBalance = false; - if (cb) cb(); - }); - }); - }; - - root.setAlternativeAmount = function(w, tx, cb) { - rateService.whenAvailable(function() { - _.each(tx.outs, function(out) { - var valueSat = out.value * w.settings.unitToSatoshi; - out.alternativeAmount = rateService.toFiat(valueSat, w.settings.alternativeIsoCode); - out.alternativeIsoCode = w.settings.alternativeIsoCode; - }); - if (cb) return cb(tx); - }); - }; - - root.updateTxs = function() { - var w = $rootScope.wallet; - if (!w) return; - - var res = w.getPendingTxProposals(); - _.each(res.txs, function(tx) { - root.setAlternativeAmount(w, tx); - if (tx.merchant) { - var url = tx.merchant.request_url; - var domain = /^(?:https?)?:\/\/([^\/:]+).*$/.exec(url)[1]; - tx.merchant.domain = domain; - } - }); - $rootScope.txps = res.txs; - $rootScope.pendingTxCount = res.pendingForUs; - }; - - root.deleteWallet = function($scope, w, cb) { - if (!w) return root.onErrorDigest(); - var name = w.getName(); - $rootScope.iden.deleteWallet(w.id, function() { - notification.info(name + ' deleted', $filter('translate')('This wallet was deleted')); - return cb(); - }); - }; - - return root; - }); diff --git a/js/services/identityService.js b/js/services/identityService.js index 492bf0f4b..734722552 100644 --- a/js/services/identityService.js +++ b/js/services/identityService.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('copayApp.services') - .factory('identityService', function($rootScope, $location, $timeout, pluginManager, controllerUtils) { + .factory('identityService', function($rootScope, $location, $timeout, $filter, pluginManager, notification, pendingTxsService, balanceService) { var root = {}; root.check = function(scope) { @@ -22,7 +22,23 @@ angular.module('copayApp.services') }); }; + root.goWalletHome = function() { + var w = $rootScope.wallet; + if (w) { + if (!w.isReady()) { + $location.path('/copayers'); + } else { + if ($rootScope.pendingPayment) { + $location.path('paymentIntent'); + } else { + $location.path('homeWallet'); + } + } + } + }; + root.create = function(scope, form) { + $rootScope.starting = true; copay.Identity.create({ email: form.email.$modelValue, password: form.password.$modelValue, @@ -43,7 +59,7 @@ angular.module('copayApp.services') $rootScope.starting = false; $timeout(function() { $rootScope.$digest() - }, 1); + }, 1); return; } var walletOptions = { @@ -64,7 +80,7 @@ angular.module('copayApp.services') }, 1); return; } - controllerUtils.bindProfile(scope, iden, wallet.id); + root.bind(scope, iden, wallet.id); }); }); @@ -72,6 +88,7 @@ angular.module('copayApp.services') root.open = function(scope, form) { + $rootScope.starting = true; copay.Identity.open({ email: form.email.$modelValue, password: form.password.$modelValue, @@ -81,24 +98,269 @@ angular.module('copayApp.services') walletDefaults: config.wallet, passphraseConfig: config.passphraseConfig, }, function(err, iden) { + $rootScope.starting = false; if (err && !iden) { if ((err.toString() || '').match('PNOTFOUND')) { scope.error = 'Invalid email or password'; } else { scope.error = 'Unknown error'; } - $rootScope.starting = false; $timeout(function() { $rootScope.$digest() - }, 1); + }, 1); } else { -console.log('[identityService.js.95] LISTO OPEN!!'); //TODO + console.log('[identityService.js.95] LISTO OPEN!!'); //TODO var firstWallet = iden.getLastFocusedWallet(); - controllerUtils.bindProfile(scope, iden, firstWallet); + root.bind(scope, iden, firstWallet); } }); }; + root.deleteWallet = function($scope, iden, w) { + $rootScope.iden.deleteWallet(w.id, function() { + notification.info(name + ' deleted', $filter('translate')('This wallet was deleted')); + if ($rootScope.wallet.id === w.id) { + $rootScope.wallet = null; + var lastFocused = $rootScope.iden.getLastFocusedWallet(); + root.bind($scope, $rootScope.iden, lastFocused); + } + }); + }; + + root.isFocused = function(wid) { + return $rootScope.wallet && wid === $rootScope.wallet.getId(); + }; + + root.setupGlobalVariables = function(iden) { + notification.enableHtml5Mode(); // for chrome: if support, enable it + $rootScope.unitName = config.unitName; + $rootScope.pendingTxCount = 0; + $rootScope.initialConnection = true; + $rootScope.reconnecting = false; + $rootScope.isCollapsed = true; + + $rootScope.iden = iden; + }; + + root.setPaymentWallet = function(w) { + root.setFocusedWallet(w); + $location.path('/send'); + }; + + root.setFocusedWallet = function(w) { + if (!_.isObject(w)) + w = $rootScope.iden.getWalletById(w); + + preconditions.checkState(w && _.isObject(w)); + $rootScope.wallet = w; + w.updateFocusedTimestamp(Date.now()); + root.goWalletHome(); + pendingTxsService.update(); + + console.log('[controllerUtils.js.221] SET FOCUS'); //TODO + balanceService.update(w, function() { + $rootScope.$digest(); + }, true) + }; + + root.installWalletHandlers = function($scope, w) { + var wid = w.getId(); + w.on('connectionError', function() { + console.log('err', w.getName()); //TODO + if (root.isFocused(wid)) { + var message = "Could not connect to the Insight server. Check your settings and network configuration"; + notification.error('Networking Error', message); + } + }); + + w.on('corrupt', function(peerId) { + console.log('corr', w.getName()); //TODO + if (root.isFocused(wid)) { + notification.error('Error', $filter('translate')('Received corrupt message from ') + peerId); + } + }); + w.on('ready', function() { + console.log('read', w.getName()); //TODO + $scope.loading = false; + if ($rootScope.initialConnection) { + $rootScope.initialConnection = false; + root.goWalletHome(); + } + }); + + w.on('tx', function(address, isChange) { + console.log('tx', w.getName()); //TODO + if (!isChange) { + notification.funds('Funds received on ' + w.getName(), address); + } + balanceService.update(w, function() { + $rootScope.$digest(); + }, root.isFocused(wid)); + }); + + w.on('balanceUpdated', function() { + console.log('b', w.getName()); //TODO + balanceService.update(w, function() { + $rootScope.$digest(); + }, root.isFocused(wid)); + }); + + w.on('insightReconnected', function() { + console.log('i', w.getName()); //TODO + $rootScope.reconnecting = false; + balanceService.update(w, function() { + $rootScope.$digest(); + }, root.isFocused(wid)); + }); + + w.on('insightError', function() { + console.log('i', w.getName()); //TODO + if (root.isFocused(wid)) { + $rootScope.reconnecting = true; + $rootScope.$digest(); + } + }); + w.on('newAddresses', function() { + console.log('newAddress', w.getName()); //TODO + }); + + w.on('txProposalsUpdated', function() { + if (root.isFocused(wid)) { + pendingTxsService.update(); + } + }); + + w.on('paymentACK', function(memo) { + notification.success('Payment Acknowledged', memo); + }); + + w.on('txProposalEvent', function(e) { + if (root.isFocused(wid)) { + pendingTxsService.update(); + } + + // TODO: add wallet name notification + var user = w.publicKeyRing.nicknameForCopayer(e.cId); + var name = w.getName(); + switch (e.type) { + case 'new': + notification.info('[' + name + '] New Transaction', + $filter('translate')('You received a transaction proposal from') + ' ' + user); + break; + case 'signed': + notification.info('[' + name + '] Transaction Signed', + $filter('translate')('A transaction was signed by') + ' ' + user); + break; + case 'signedAndBroadcasted': + notification.info('[' + name + '] Transaction Approved', + $filter('translate')('A transaction was signed and broadcasted by') + ' ' + user); + break; + case 'rejected': + notification.info('[' + name + '] Transaction Rejected', + $filter('translate')('A transaction was rejected by') + ' ' + user); + break; + case 'corrupt': + notification.error('[' + name + '] Transaction Error', + $filter('translate')('Received corrupt transaction from') + ' ' + user); + break; + } + $rootScope.$digest(); + }); + w.on('addressBookUpdated', function(dontDigest) { + if (root.isFocused(wid)) { + if (!dontDigest) { + $rootScope.$digest(); + } + } + }); + w.on('connect', function(peerID) { + $rootScope.$digest(); + }); + // TODO? + // w.on('close', ); + // w.on('locked',); + }; + + root.rebindWallets = function($scope, iden) { + _.each(iden.listWallets(), function(wallet) { + preconditions.checkState(wallet); + root.installWalletHandlers($scope, wallet); + }); + }; + + root.bind = function($scope, iden, w) { + console.log('ident bind Globals'); //TODO + root.setupGlobalVariables(iden); + root.rebindWallets($scope, iden); + if (w) { + root.setFocusedWallet(w); + } else { + $location.path('/create'); + } + $timeout(function() { + console.log('[controllerUtils.js.242] DIGEST'); //TODO + $rootScope.$digest() + console.log('[controllerUtils.js.242] DIGEST DONE'); //TODO + }, 1); + }; + + root.logout = function() { + if ($rootScope.iden) { + $rootScope.iden.store(null, function() { + $rootScope.iden.close(); + + delete $rootScope['wallet']; + delete $rootScope['iden']; + + // Go home reloading the application + var hashIndex = window.location.href.indexOf('#!/'); + window.location = window.location.href.substr(0, hashIndex); + }); + } + }; + + root.createWallet = function(opts, cb) { + $rootScope.iden.createWallet(opts, function(err, w) { + root.installWalletHandlers($scope, w); + root.setFocusedWallet(w); + return cb(); + }); + }; + + root.importWallet = function(encryptedObj, pass, opts, cb) { + copay.Compatibility.importEncryptedWallet($rootScope.iden, encryptedObj, + pass, opts, function(err, wallet) { + if (err) return cb(err); + root.installWalletHandlers($scope, wallet); + root.setFocusedWallet(wallet); + return cb(); + }); + }; + + root.joinWallet = function(opts, cb) { + $rootScope.iden.joinWallet(opts, function(err, w) { + $scope.loading = false; + if (err || !w) { + if (err === 'joinError') + notification.error('Fatal error connecting to Insight server'); + else if (err === 'walletFull') + notification.error('The wallet is full'); + else if (err === 'badNetwork') + notification.error('Network Error', 'Wallet network configuration missmatch'); + else if (err === 'badSecret') + notification.error('Bad secret', 'The secret string you entered is invalid'); + else { + notification.error('Error', err.message || err); + } + } else { + root.installWalletHandlers($scope, w); + root.setFocusedWallet(w); + } + return cb(err); + }); + }; + + return root; }); diff --git a/test/PublicKeyRing.js b/test/PublicKeyRing.js index ca0a8d648..39f7d0491 100644 --- a/test/PublicKeyRing.js +++ b/test/PublicKeyRing.js @@ -439,6 +439,33 @@ describe('PublicKeyRing model', function() { }); + it('#fromObj old backup ', function() { + var pkr = PublicKeyRing.fromObj(JSON.parse(obj)); + should.exist(pkr); + pkr.isComplete().should.equal(true); + pkr.requiredCopayers.should.equal(2); + pkr.totalCopayers.should.equal(2); + }); + + it('#fromObj #toObj rountrip', function() { + var obj2 = PublicKeyRing.fromObj(JSON.parse(obj)).toObj(); + var pkr = PublicKeyRing.fromObj(obj2); + pkr.isComplete().should.equal(true); + pkr.requiredCopayers.should.equal(2); + pkr.totalCopayers.should.equal(2); + }); + + it('#fromUntrustedObj #toObj rountrip', function() { + var obj2 = PublicKeyRing.fromUntrustedObj(JSON.parse(obj)).toObj(); + var pkr = PublicKeyRing.fromUntrustedObj(obj2); + pkr.isComplete().should.equal(true); + pkr.requiredCopayers.should.equal(2); + pkr.totalCopayers.should.equal(2); + }); + + + + it('#getHDParams should return the right one', function() { var config = { networkName: 'livenet', @@ -482,15 +509,15 @@ describe('PublicKeyRing model', function() { }); }); - it('#getForPath should return 5 pubkeys', function() { + it('#_getForPath should return 5 pubkeys', function() { var w = getCachedW().w; - var pubkeys = w.getForPath('m/45\'/2147483647/1/0'); + var pubkeys = w._getForPath('m/45\'/2147483647/1/0'); pubkeys.length.should.equal(5); }); - it('#getForPaths should return 2 arrays of 5 pubkey ', function() { + it('#_getForPaths should return 2 arrays of 5 pubkey ', function() { var w = getCachedW().w; - var pubkeys = w.getForPaths(['m/45\'/2147483647/1/0', 'm/45\'/2147483647/1/1']); + var pubkeys = w._getForPaths(['m/45\'/2147483647/1/0', 'm/45\'/2147483647/1/1']); pubkeys.length.should.equal(2); pubkeys[0].length.should.equal(5); pubkeys[1].length.should.equal(5); @@ -505,4 +532,8 @@ describe('PublicKeyRing model', function() { ret.pubKeys[1].length.should.equal(5); }); + + }); + +var obj = '{"walletId":"0a903a2eb33793d1","networkName":"testnet","requiredCopayers":2,"totalCopayers":2,"indexes":[{"copayerIndex":2147483647,"changeIndex":0,"receiveIndex":1},{"copayerIndex":0,"changeIndex":39,"receiveIndex":0},{"copayerIndex":1,"changeIndex":102,"receiveIndex":39}],"copayersExtPubKeys":["tpubD9peJo88ArhgmJNqRkQmhHt4zAGTYVowsHrDj385xyXyMy4RhWZpV5Qx2mMDUVzpbAD5V9jci5D7cZaHhjLYP8gEkngmTKtSF4Y7V3qkAsy","tpubD8udwzKWwNUgoE2WG7LYsXKf5m1eRtJ1Etp43vnoxViFmrmZ1ND2CkdqGyQtuidcN1CiqdBUvbKegbdsMQaj5VLY2hbA4LEnLDrqkgSzikz"],"nicknameFor":{"03338b105850c7126f1f5b0439b357765b17ead8eed15bcdfdbd28d0e3915b696f":"5@queparece","0286b376d65cc4af0de5932fb8299cbef2ca9ed37ec9fdb0edfd4e9cb74eac45da":"4@queparece"}}'; diff --git a/test/Wallet.js b/test/Wallet.js index db1c437b6..f99c5121d 100644 --- a/test/Wallet.js +++ b/test/Wallet.js @@ -318,7 +318,7 @@ describe('Wallet model', function() { it('#addressIsOwn', function() { var wallet = cachedCreateW2(); - var allAddresses = wallet.getAddressesStr(); + var allAddresses = wallet.getAddresses(); for (var i = 0; i < allAddresses.length; i++) { wallet.addressIsOwn(allAddresses[i]).should.equal(true); } diff --git a/views/homeWallet.html b/views/homeWallet.html index 1680c8b93..fa7346bbe 100644 --- a/views/homeWallet.html +++ b/views/homeWallet.html @@ -41,10 +41,10 @@

Quick receive

- +
-

{{$root.addrInfos[0].addressStr}}

+

{{addr}}

diff --git a/views/includes/sidebar.html b/views/includes/sidebar.html index da182e7b8..54cf5a8ce 100644 --- a/views/includes/sidebar.html +++ b/views/includes/sidebar.html @@ -1,9 +1,9 @@ -
+
{{$root.wallet.getName() | limitTo: 1}}
-