From b5b7acd5a46da33c9c3de916d48b35bae3e0186d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 9 Sep 2014 15:30:21 -0300 Subject: [PATCH] move blockchain event handles to wallet --- js/models/blockchain/Insight.js | 7 +- js/models/core/Wallet.js | 49 +++++++-- js/models/network/Async.js | 49 +++++---- js/services/controllerUtils.js | 185 +++++++++++++++----------------- 4 files changed, 160 insertions(+), 130 deletions(-) diff --git a/js/models/blockchain/Insight.js b/js/models/blockchain/Insight.js index 67b95fd7c..14825963d 100644 --- a/js/models/blockchain/Insight.js +++ b/js/models/blockchain/Insight.js @@ -124,7 +124,12 @@ Insight.prototype.requestPost = function(path, data, cb) { } Insight.prototype.destroy = function() { - this.getSocket().destroy(); + +console.log('[Insight.js.127] INSIGHT destroy' ); //TODO + var socket = this.getSocket(); + this.socket.disconnect(); + this.socket.removeAllListeners(); + this.socket = null; this.subscribed = {}; this.status = this.STATUS.DESTROYED; this.removeAllListeners(); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 60e2a6ca5..1b35a85ba 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -633,7 +633,7 @@ Wallet.decodeSecret = function(secretB) { var secretNumber = secret.slice(33, 38); return { pubKey: pubKeyBuf.toString('hex'), - secretNumber : secretNumber.toString('hex') + secretNumber: secretNumber.toString('hex') } }; @@ -645,6 +645,24 @@ Wallet.prototype._lockIncomming = function() { this.network.lockIncommingConnections(this.publicKeyRing.getAllCopayerIds()); }; + + +Wallet.prototype._setBlockchainListeners = function() { + var self = this; + this.blockchain.on('connect', self.emit.bind(self,'networkReconnected')); + this.blockchain.on('disconnect', self.emit.bind(self,'networkError')); + + this.blockchain.on('tx', function(tx) { + self.emit('tx', tx.address); + }); + + if (!self.spendUnconfirmed) { + self.blockchain.on('block', self.emit.bind(self,'balanceUpdated')); + } +} + + + /** * @desc Sets up the networking with other peers. * @@ -682,7 +700,12 @@ Wallet.prototype.netStart = function() { this._lockIncomming(); } + net.on('connect_error', function() { + self.emit('connectionError'); + }); + net.start(startOpts, function() { + self._setBlockchainListeners(); self.emit('ready', net.getPeer()); setTimeout(function() { self.emit('publicKeyRingUpdated', true); @@ -866,7 +889,7 @@ Wallet.prototype.send = function(recipients, obj) { */ Wallet.prototype.sendAllTxProposals = function(recipients) { var ntxids = this.txProposals.getNtxids(), - that = this; + that = this; _.each(ntxids, function(ntxid, key) { that.sendTxProposal(ntxid, recipients); }); @@ -1872,7 +1895,9 @@ Wallet.prototype.getAddressesInfo = function(opts) { */ Wallet.prototype.addressIsOwn = function(addrStr, opts) { var addrList = this.getAddressesStr(opts); - return _.any(addrList, function(value) { return value === addrStr; }); + return _.any(addrList, function(value) { + return value === addrStr; + }); }; @@ -1973,7 +1998,7 @@ Wallet.prototype.getUnspent = function(cb) { Wallet.prototype.removeTxWithSpentInputs = function(cb) { var self = this; - cb = cb || function () {}; + cb = cb || function() {}; var txps = []; var maxRejectCount = this.maxRejectCount(); @@ -1986,9 +2011,13 @@ Wallet.prototype.removeTxWithSpentInputs = function(cb) { } var inputs = []; - txps.forEach(function (txp) { - txp.builder.utxos.forEach(function (utxo) { - inputs.push({ ntxid: txp.ntxid, txid: utxo.txid, vout: utxo.vout }); + txps.forEach(function(txp) { + txp.builder.utxos.forEach(function(utxo) { + inputs.push({ + ntxid: txp.ntxid, + txid: utxo.txid, + vout: utxo.vout + }); }); }); if (inputs.length === 0) @@ -1999,13 +2028,13 @@ Wallet.prototype.removeTxWithSpentInputs = function(cb) { this.blockchain.getUnspent(this.getAddressesStr(), function(err, unspentList) { if (err) return cb(err); - unspentList.forEach(function (unspent) { - inputs.forEach(function (input) { + unspentList.forEach(function(unspent) { + inputs.forEach(function(input) { input.unspent = input.unspent || (input.txid === unspent.txid && input.vout === unspent.vout); }); }); - inputs.forEach(function (input) { + inputs.forEach(function(input) { if (!input.unspent) { proposalsChanged = true; self.txProposals.deleteOne(input.ntxid); diff --git a/js/models/network/Async.js b/js/models/network/Async.js index ad4a5630e..52b434e12 100644 --- a/js/models/network/Async.js +++ b/js/models/network/Async.js @@ -33,14 +33,14 @@ Network.prototype.cleanUp = function() { this.allowedCopayerIds = null; this.isInboundPeerAuth = []; this.copayerForPeer = {}; - this.connections = {}; this.criticalErr = ''; - this.removeAllListeners(); if (this.socket) { - this.socket.removeAllListeners(); +console.log('[Async.js.39] DISCONNECT'); //TODO this.socket.disconnect(); + this.socket.removeAllListeners(); this.socket = null; } + this.removeAllListeners(); }; Network.parent = EventEmitter; @@ -86,11 +86,6 @@ Network.prototype._sendHello = function(copayerId,secretNumber) { Network.prototype._deletePeer = function(peerId) { delete this.isInboundPeerAuth[peerId]; delete this.copayerForPeer[peerId]; - - if (this.connections[peerId]) { - this.connections[peerId].close(); - } - delete this.connections[peerId]; this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers); }; @@ -219,9 +214,27 @@ Network.prototype._onMessage = function(enc) { } }; -Network.prototype._setupConnectionHandlers = function(cb) { +Network.prototype._setupConnectionHandlers = function(opts, cb) { preconditions.checkState(this.socket); var self = this; + + self.socket.on('connect_error', function(m) { + + // If socket is not started, destroy it and emit and error + // If it is started, socket.io will try to reconnect. + if (!self.started) { + self.emit('connect_error'); + self.cleanUp(); + } + }); + + self.socket.on('subscribed', function(m) { + var fromTs = (opts.lastTimestamp||0) + 1; + self.socket.emit('sync', fromTs); + self.started = true; + }); + + self.socket.on('message', function(m) { // delay execution, to improve error handling setTimeout(function() { @@ -233,14 +246,17 @@ Network.prototype._setupConnectionHandlers = function(cb) { self.socket.on('no messages', self.emit.bind(self, 'no messages')); self.socket.on('connect', function() { + var pubkey = self.getKey().public.toString('hex'); + self.socket.emit('subscribe', pubkey); self.socket.on('disconnect', function() { - var pubKey = self.getKey().public.toString('hex'); - self.socket.emit('subscribe', pubKey); + self.socket.emit('subscribe', pubkey); }); if (typeof cb === 'function') cb(); }); + + }; Network.prototype._onError = function(err) { @@ -293,20 +309,11 @@ Network.prototype.start = function(opts, openCallback) { if (this.started) return openCallback(); this.privkey = opts.privkey; - var pubkey = this.getKey().public.toString('hex'); this.setCopayerId(opts.copayerId); this.maxPeers = opts.maxPeers || this.maxPeers; this.socket = this.createSocket(); - this._setupConnectionHandlers(openCallback); - this.socket.emit('subscribe', pubkey); - - var fromTs = opts.lastTimestamp + 1; - var self = this; - self.socket.on('subscribed', function(m) { - self.socket.emit('sync', fromTs); - self.started = true; - }); + this._setupConnectionHandlers(opts, openCallback); }; Network.prototype.createSocket = function() { diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index a5ecf83d2..71bd5ced4 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -40,15 +40,96 @@ angular.module('copayApp.services') } }; - root.installStartupHandlers = function(wallet, $scope) { - wallet.on('connectionError', function() { - var message = "Looks like you are already connected to this wallet, please logout and try importing it again."; - notification.error('PeerJS Error', message); + root.installWalletHandlers = function(w, $scope) { + w.on('connectionError', function() { + var message = "Could not connect to the Insight server. Check your settings and network configuration"; + notification.error('Networking Error', message); root.onErrorDigest($scope); }); - wallet.on('ready', function() { + w.on('ready', function() { $scope.loading = false; }); + + + w.on('corrupt', function(peerId) { + notification.error('Error', 'Received corrupt message from ' + peerId); + }); + w.on('ready', function(myPeerID) { + $rootScope.wallet = w; + if ($rootScope.pendingPayment) { + $location.path('send'); + } else { + $location.path('receive'); + } + }); + + w.on('publicKeyRingUpdated', function(dontDigest) { + root.updateGlobalAddresses(); + if (!dontDigest) { + $rootScope.$digest(); + } + }); + + w.on('tx', function() { + notification.funds('Funds received!', tx.address); + root.updateBalance(function() { + $rootScope.$digest(); + }); + }); + + w.on('balanceUpdated', function() { + root.updateBalance(function() { + $rootScope.$digest(); + }); + }); + + w.on('networkReconnected', function() { + $rootScope.reconnecting = false; + root.updateBalance(function() { + $rootScope.$digest(); + }); + }); + + w.on('networkError', function() { + $rootScope.reconnecting = true; + $rootScope.$digest(); + }); + + w.on('txProposalsUpdated', function(dontDigest) { + root.updateTxs(); + // give sometime to the tx to propagate. + $timeout(function() { + root.updateBalance(function() { + if (!dontDigest) { + $rootScope.$digest(); + } + }); + }, 3000); + }); + w.on('txProposalEvent', function(e) { + var user = w.publicKeyRing.nicknameForCopayer(e.cId); + switch (e.type) { + case 'signed': + notification.info('Transaction Update', 'A transaction was signed by ' + user); + break; + case 'rejected': + notification.info('Transaction Update', 'A transaction was rejected by ' + user); + break; + case 'corrupt': + notification.error('Transaction Error', 'Received corrupt transaction from ' + user); + break; + } + }); + w.on('addressBookUpdated', function(dontDigest) { + if (!dontDigest) { + $rootScope.$digest(); + } + }); + w.on('connect', function(peerID) { + $rootScope.$digest(); + }); + w.on('close', root.onErrorDigest); + w.on('locked', root.onErrorDigest.bind(this)); }; root.setupRootVariables = function() { @@ -88,69 +169,9 @@ angular.module('copayApp.services') root.startNetwork = function(w, $scope) { root.setupRootVariables(); - root.installStartupHandlers(w, $scope); + root.installWalletHandlers(w, $scope); root.updateGlobalAddresses(); - notification.enableHtml5Mode(); // for chrome: if support, enable it - - w.on('corrupt', function(peerId) { - notification.error('Error', 'Received corrupt message from ' + peerId); - }); - w.on('ready', function(myPeerID) { - $rootScope.wallet = w; - root.setConnectionListeners($rootScope.wallet); - - if ($rootScope.pendingPayment) { - $location.path('send'); - } else { - $location.path('receive'); - } - }); - - w.on('publicKeyRingUpdated', function(dontDigest) { - root.updateGlobalAddresses(); - if (!dontDigest) { - $rootScope.$digest(); - } - }); - w.on('txProposalsUpdated', function(dontDigest) { - root.updateTxs(); - // give sometime to the tx to propagate. - $timeout(function() { - root.updateBalance(function() { - if (!dontDigest) { - $rootScope.$digest(); - } - }); - }, 3000); - }); - w.on('txProposalEvent', function(e) { - var user = w.publicKeyRing.nicknameForCopayer(e.cId); - switch (e.type) { - case 'signed': - notification.info('Transaction Update', 'A transaction was signed by ' + user); - break; - case 'rejected': - notification.info('Transaction Update', 'A transaction was rejected by ' + user); - break; - case 'corrupt': - notification.error('Transaction Error', 'Received corrupt transaction from ' + user); - break; - } - }); - w.on('addressBookUpdated', function(dontDigest) { - if (!dontDigest) { - $rootScope.$digest(); - } - }); - w.on('connectionError', function(msg) { - root.onErrorDigest(null, msg); - }); - w.on('connect', function(peerID) { - $rootScope.$digest(); - }); - w.on('close', root.onErrorDigest); - w.on('locked', root.onErrorDigest.bind(this)); w.netStart(); }; @@ -272,38 +293,6 @@ angular.module('copayApp.services') }); } - root.setConnectionListeners = function(wallet) { - wallet.blockchain.on('connect', function(attempts) { - if (attempts == 0) return; - notification.success('Networking restored', 'Connection to Insight re-established'); - $rootScope.reconnecting = false; - root.updateBalance(function() { - $rootScope.$digest(); - }); - }); - - wallet.blockchain.on('disconnect', function() { - notification.error('Networking problem', 'Connection to Insight lost, trying to reconnect...'); - $rootScope.reconnecting = true; - $rootScope.$digest(); - }); - - wallet.blockchain.on('tx', function(tx) { - notification.funds('Funds received!', tx.address); - root.updateBalance(function() { - $rootScope.$digest(); - }); - }); - - if (!$rootScope.wallet.spendUnconfirmed) { - wallet.blockchain.on('block', function(block) { - root.updateBalance(function() { - $rootScope.$digest(); - }); - }); - } - } - root.updateGlobalAddresses = function() { if (!$rootScope.wallet) return;