From 9eadda0ed30b6921adfa419de77118fcb0d2e8a3 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 9 Apr 2014 02:20:28 -0300 Subject: [PATCH] adds PublicKeyRing syncing to the new classes schema --- index.html | 16 ++- js/controllers/signin.js | 20 +++- js/models/CopayPeer.js | 45 ++++---- js/models/PublicKeyRing.js | 37 ++++--- js/services/network.js | 216 ++++++++++++++++++++++++------------- js/services/storage.js | 62 +++++++++-- 6 files changed, 270 insertions(+), 126 deletions(-) diff --git a/index.html b/index.html index 2297c3ad9..872b83cbc 100644 --- a/index.html +++ b/index.html @@ -61,7 +61,19 @@
-

Join wallet

+

Open a Existing Wallet

+ +
+
+ +
+
+
+
+
+

Join a Network Wallet

@@ -71,7 +83,7 @@
-

Create a new wallet

+

Create a New Wallet

diff --git a/js/controllers/signin.js b/js/controllers/signin.js index 588b47e1d..4fcc7ce26 100644 --- a/js/controllers/signin.js +++ b/js/controllers/signin.js @@ -2,27 +2,43 @@ angular.module('copay.signin').controller('SigninController', function($scope, $rootScope, $location, Network, Storage) { - var peerData = Storage.get('peerData'); + + var peerData = Storage.get($rootScope.walletId, 'peerData'); $scope.loading = false; $rootScope.peerId = peerData ? peerData.peerId : null; + $scope.listWalletIds = function() { + return Storage.getWalletIds(); + }; + $scope.create = function() { $scope.loading = true; + Network.createWallet(); Network.init(function() { $location.path('peer'); $rootScope.$digest(); }); }; + $scope.open = function(walletId) { + $scope.loading = true; + + if (Network.openWallet(walletId)) { + Network.init(function() { + $location.path('peer'); + $rootScope.$digest(); + }); + } + }; + $scope.join = function(cid) { $scope.loading = true; if (cid) { Network.init(function() { Network.connect(cid, function() { -console.log('[signin.js.26] REDIR'); //TODO $location.path('peer'); $rootScope.$digest(); }); diff --git a/js/models/CopayPeer.js b/js/models/CopayPeer.js index e0e2a3aa7..c4c7309f6 100644 --- a/js/models/CopayPeer.js +++ b/js/models/CopayPeer.js @@ -2,6 +2,18 @@ var imports = require('soop').imports(); var EventEmitter= imports.EventEmitter || require('events').EventEmitter; +/* + * Emits + * 'networkChange' + * when network layout has change (new/lost peers, etc) + * + * 'data' + * when an unknown data type arrives + * + * Provides + * send(toPeerIds, {data}, cb?) + * + */ function CopayPeer(opts) { opts = opts || {}; @@ -63,7 +75,6 @@ CopayPeer.prototype._connectToPeers = function(peerIds) { var ret = false; var arrayDiff1= CopayPeer._arrayDiff(peerIds, this.connectedPeers); var arrayDiff = CopayPeer._arrayDiff(arrayDiff1, [this.peerId]); -console.log('[CopayPeer.js.65:arrayDiff:] DIFFFFF',arrayDiff, this.connectedPeers); //TODO arrayDiff.forEach(function(peerId) { console.log('### CONNECTING TO:', peerId); self.connectTo(peerId); @@ -78,29 +89,22 @@ CopayPeer.prototype._onData = function(data, isInbound) { switch(obj.data.type) { case 'peerList': - var hasChanged = this._connectToPeers(obj.data.peers); - // if (hasChanged && !obj.data.isBroadcast) { - // }; + this._connectToPeers(obj.data.peers); this._notify(); break; case 'disconnect': this._onClose(obj.sender); - break; + break; + default: + this.emit('data', obj.sender, obj.data, isInbound); } }; CopayPeer.prototype._sendPeers = function(peerIds) { - var isBroadcast = false; - if (!peerIds) { - peerIds = this.connectedPeers; - isBroadcast = true; - }; - console.log('#### SENDING PEER LIST: ', this.connectedPeers, ' TO ', peerIds); this.send(peerIds, { type: 'peerList', peers: this.connectedPeers, - isBroadcast: isBroadcast, }); }; @@ -119,7 +123,6 @@ CopayPeer.prototype._addPeer = function(peerId, isInbound) { } }; - CopayPeer.prototype._setupConnectionHandlers = function(dataConn, isInbound, openCallback) { var self=this; @@ -130,7 +133,7 @@ CopayPeer.prototype._setupConnectionHandlers = function(dataConn, isInbound, ope dataConn.peer, isInbound); self._addPeer(dataConn.peer, isInbound); - self._notify(); + self._notify( isInbound ? dataConn.peer : null); if (typeof openCallback === 'function') openCallback(); } }); @@ -148,9 +151,9 @@ CopayPeer.prototype._setupConnectionHandlers = function(dataConn, isInbound, ope }); }; -CopayPeer.prototype._notify = function() { +CopayPeer.prototype._notify = function(newPeer) { this._showConnectedPeers(); - this.emit('update'); + this.emit('networkChange', newPeer); }; CopayPeer.prototype._setupPeerHandlers = function(openCallback) { @@ -205,10 +208,15 @@ CopayPeer.prototype._sendToOne = function(peerId, data, cb) { if (typeof cb === 'function') cb(); }; - CopayPeer.prototype.send = function(peerIds, data, cb) { var self=this; + if (!peerIds) { + peerIds = this.connectedPeers; + data.isBroadcast = 1; + } +console.log('[CopayPeer.js.216:SENDD:]',data); //TODO + if (Array.isArray(peerIds)) { var l = peerIds.length; var i = 0; @@ -240,7 +248,7 @@ CopayPeer.prototype.connectTo = function(peerId, cb) { CopayPeer.prototype.disconnect = function(peerId, cb) { var self = this; - this.send(this.connectedPeers, { type: 'disconnect' }, function() { + this.send(null, { type: 'disconnect' }, function() { self.connectedPeers = []; self.peerId = null; if (self.peer) { @@ -252,5 +260,4 @@ CopayPeer.prototype.disconnect = function(peerId, cb) { }); }; - module.exports = require('soop')(CopayPeer); diff --git a/js/models/PublicKeyRing.js b/js/models/PublicKeyRing.js index df6cb2254..ec159403b 100644 --- a/js/models/PublicKeyRing.js +++ b/js/models/PublicKeyRing.js @@ -59,22 +59,8 @@ PublicKeyRing.encrypt = function (passphrase, payload) { return payload; }; -PublicKeyRing.read = function (id, passphrase) { - var encPayload = storage.get(id); - if (!encPayload) - throw new Error('Could not find wallet data'); - var data; - try { - data = JSON.parse( PublicKeyRing.decrypt( passphrase, encPayload )); - } catch (e) { - throw new Error('error in storage: '+ e.toString()); - return; - }; - - if (data.id !== id) - throw new Error('Wrong id in data'); - - var config = { networkName: data.networkName }; +PublicKeyRing.fromObj = function (data) { + var config = { networkName: data.networkName || 'livenet' }; var w = new PublicKeyRing(config); @@ -93,6 +79,25 @@ PublicKeyRing.read = function (id, passphrase) { return w; }; +PublicKeyRing.read = function (id, passphrase) { + var encPayload = storage.get(id); + if (!encPayload) + throw new Error('Could not find wallet data'); + var data; + try { + data = JSON.parse( PublicKeyRing.decrypt( passphrase, encPayload )); + } catch (e) { + throw new Error('error in storage: '+ e.toString()); + return; + }; + + if (data.id !== id) + throw new Error('Wrong id in data'); + + + return PublicKeyRing.fromObj(data); +}; + PublicKeyRing.prototype.toObj = function() { return { id: this.id, diff --git a/js/services/network.js b/js/services/network.js index 11940fab4..05f064b47 100644 --- a/js/services/network.js +++ b/js/services/network.js @@ -3,100 +3,160 @@ angular.module('copay.network') .factory('Network', function($rootScope, Storage) { var peer; -// $rootScope.connectedPeers = []; -// $rootScope.peerId = null; - - // case 'publicKeyRing': - // console.log('### RECEIVED PKR FROM:', obj.sender); - - // if ($rootScope.publicKeyRing.merge(obj.data.publicKeyRing, true)) { - // //TODO Remove log - // console.log('### BROADCASTING PRK'); - // _send( $rootScope.connectedPeers, { - // type: 'publicKeyRing', - // publicKeyRing: $rootScope.publicKeyRing.toObj(), - // isBroadcast: 1, - // }); - // $rootScope.$digest(); - // } - // else if (!isOutbound && !obj.data.isBroadcast) { - // // replying always to connecting peer - // console.log('### REPLYING PRK TO:', obj.sender ); - // _send( obj.sender, { - // type: 'publicKeyRing', - // publicKeyRing: $rootScope.publicKeyRing.toObj(), - // }); - - // } - - // //TODO Remove log - // console.log('*** PRK:', $rootScope.publicKeyRing.toObj()); - // break; - // } - - // // TODO - // $rootScope.publicKeyRing = new copay.PublicKeyRing({ - // network: config.networkName, - // }); - // $rootScope.publicKeyRing.addCopayer(); - // console.log('### PublicKeyRing Initialized'); - // - // // - - // console.log('#### SENDING PKR '); - // _send(dataConn.peer, { - // type: 'publicKeyRing', - // publicKeyRing: $rootScope.publicKeyRing.toObj(), - // }); - - // if (typeof cb === 'function') cb(); - // - // $rootScope.$digest(); - // }); + var _refreshUx = function() { + var cp = $rootScope.cp; + console.log('*** UPDATING UX'); //TODO + $rootScope.peerId = cp.peerId; + $rootScope.connectedPeers = cp.connectedPeers; + $rootScope.$digest(); + }; + var _store = function() { + Storage.set($rootScope.walletId, 'peerData', { + peerId: $rootScope.peerId, + connectedPeers: $rootScope.connectedPeers + }); + }; + + // set new inbound connections + var _setNewPeer = function(newPeer) { + var cp = $rootScope.cp; + console.log('#### SENDING PKR 1111 '); + cp.send(newPeer, { + type: 'publicKeyRing', + publicKeyRing: $rootScope.publicKeyRing.toObj(), + }); + }; + + var _handleNetworkChange = function(newPeer) { + var cp = $rootScope.cp; + + if (newPeer) + _setNewPeer(newPeer); + + _store(); + _refreshUx(); + }; + + // TODO -> probably not in network.js + var createWallet = function(walletId) { + console.log('### CREATING WALLET. ID:' + walletId); + + //TODO create a wallet and WalletId, not only pkr + var pkr = new copay.PublicKeyRing({ + network: config.networkName, + id: walletId, + }); + pkr.addCopayer(); + console.log('\t### PublicKeyRing Initialized:'); + Storage.addWalletId(pkr.id); + Storage.set(pkr.id, 'publicKeyRing', pkr.toObj()); + + $rootScope.walletId = pkr.id; + $rootScope.publicKeyRing = pkr; + }; + + var openWallet = function (walletId) { + var ret = false; + var pkr = Storage.get(walletId, 'publicKeyRing'); + + if (pkr) { + console.log('### WALLET OPENED:', walletId, pkr); + $rootScope.walletId = walletId; + $rootScope.publicKeyRing = new copay.PublicKeyRing.fromObj(pkr); + ret = true; + } + return ret; + }; + + var closeWallet = function() { + console.log('### CLOSING WALLET'); + $rootScope.walletId = null; + $rootScope.publicKeyRing = null; + //TODO + }; + + var _checkWallet = function(walletId) { + console.log('[network.js.79:_checkWallet:]',walletId); //TODO + + if ($rootScope.walletId && $rootScope.walletId !== walletId) + closeWallet(); + + if ($rootScope.walletId) + return; + + if (!openWallet(walletId)) { + createWallet(walletId); + } + }; + + var _handleData = function(senderId, data, isInbound) { + var cp = $rootScope.cp; + + switch(data.type) { + case 'publicKeyRing': + + console.log('[network.js.91:data:]',data); //TODO + + _checkWallet(data.publicKeyRing.id); + var shouldSend = false; + + var recipients, pkr = $rootScope.publicKeyRing; + console.log('### RECEIVED PKR FROM:', senderId); + if (pkr.merge(data.publicKeyRing, true) && !data.isBroadcast) { + console.log('### BROADCASTING PKR'); + recipients = null; + shouldSend = true; + } + else if (isInbound && !data.isBroadcast) { + // always replying to connecting peer + console.log('### REPLYING PKR TO:', senderId); + recipients = senderId; + shouldSend = true; + } + + if (shouldSend) { + console.log('### SENDING PKR TO:', recipients); + cp.send( recipients, { + type: 'publicKeyRing', + publicKeyRing: $rootScope.publicKeyRing.toObj(), + }); + } + +console.log('[network.js.126] END'); //TODO + _refreshUx(); + break; + } + }; + var _setupHandlers = function () { + var cp = $rootScope.cp; + cp.on('networkChange', _handleNetworkChange); + cp.on('data', _handleData); + }; // public methods var init = function(cb) { - var opts = { - //peerId: + var cp = $rootScope.cp = new copay.CopayPeer({ apiKey: config.p2pApiKey, debug: config.p2pDebug, - }; - var cp = $rootScope.cp = new copay.CopayPeer(opts); - - cp.on('update', function() { - - console.log('*** UPDATING UX'); //TODO - - $rootScope.peerId = cp.peerId; - $rootScope.connectedPeers = cp.connectedPeers; - - Storage.set('peerData', { - peerId: $rootScope.peerId, - connectedPeers: $rootScope.connectedPeers - }); - - $rootScope.$digest(); - }); + }); + _setupHandlers(); // inicia session cp.start(function(peerId) { - console.log('[kkkk.7] START: SOY', peerId); //TODO -// networkPubKeyRing.setUpHandlers(cp); -// networkTransactionProposal.setUpHandlers(cp); return cb(); }); }; - var connect = function(peerId, cb) { - $rootScope.cp.connectTo(peerId, function(id) { - console.log('CONNECTTO CALLBACK SOY:', id); //TODO + if ($rootScope.cp) { + $rootScope.cp.connectTo(peerId, cb); + } + else return cb(); - }); }; var disconnect = function(cb) { @@ -109,7 +169,9 @@ angular.module('copay.network') return { init: init, connect: connect, - disconnect: disconnect + disconnect: disconnect, + createWallet: createWallet, + openWallet: openWallet, } }); diff --git a/js/services/storage.js b/js/services/storage.js index d315ded79..b35cf499e 100644 --- a/js/services/storage.js +++ b/js/services/storage.js @@ -2,21 +2,63 @@ angular.module('copay.storage') .factory('Storage', function($rootScope) { + + + var _key = function(walletId, key) { + return walletId + '::' + key; + }; + + var _pushKey = function(walletId, key) { + var keys = localStorage.getItem(walletId); + localStorage.setItem(walletId, (keys?keys+',':'') +key); + }; + return { - get: function(key) { + getGlobal: function( key) { return JSON.parse(localStorage.getItem(key)); }, - - set: function(key, data) { + setGlobal: function( key, data) { localStorage.setItem(key, JSON.stringify(data)); }, - - remove: function(key) { - localStorage.removeItem(key); + get: function(walletId, key) { + if (!walletId) return; + return JSON.parse(localStorage.getItem(_key(walletId,key))); + }, + set: function(walletId, key, data) { + if (!walletId) return; + var k = _key(walletId,key); + localStorage.setItem(k, JSON.stringify(data)); + _pushKey(walletId, k); + }, + remove: function(walletId, key) { + localStorage.removeItem(_key(walletId,key)); + }, + clearAll: function(walletId){ + var keys = localStorage.getItem(walletId); + keys.split(',').forEach(function(k){ + localStorage.removeItem(key); + }); + }, + addWalletId: function(walletId) { + var ids = localStorage.getItem('walletIds'); + localStorage.setItem('walletIds', (ids?ids+',':'') + walletId); + }, + delWalletId: function(walletId) { + var ids = localStorage.getItem('walletIds'); + if (ids) { + var is = ids.split(','); + var newIds = []; + is.forEach(function(i) { + if (i != walletId) { + newIds.push(i); + } + }); + localStorage.setItem('walletIds', newIds.join(',') ); + } + }, + getWalletIds: function() { + var ids = localStorage.getItem('walletIds'); + return ids ? ids.split(',') : []; }, - - clearAll: function() { - localStorage.clear(); - } }; });