diff --git a/js/controllers/header.js b/js/controllers/header.js index db906ca53..91f00d863 100644 --- a/js/controllers/header.js +++ b/js/controllers/header.js @@ -41,7 +41,6 @@ angular.module('copay.header').controller('HeaderController', w.disconnect(); delete $rootScope['wallet']; $location.path('signin'); - $rootScope.$digest(); } }; diff --git a/js/controllers/signin.js b/js/controllers/signin.js index 13f0dcbf9..122cdc02a 100644 --- a/js/controllers/signin.js +++ b/js/controllers/signin.js @@ -46,6 +46,14 @@ console.log('[signin.js.42:create:]'); //TODO $scope.join = function(cid) { console.log('[signin.js.42:join:]'); //TODO $scope.loading = true; + walletFactory.connectTo(cid, function(w) { +console.log('[signin.js.50]'); //TODO + _setupUxHandlers(w); + w.netStart(); + }); + }; + + // // if (cid) { // var w = walletFactory.(walletId); @@ -62,7 +70,6 @@ console.log('[signin.js.42:join:]'); //TODO // }); // }); // } - }; // if (peerData && peerData.peerId && peerData.connectedPeers.length > 0) { // $rootScope.peerId = peerData.peerId; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 0a6493192..1d2141117 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -39,7 +39,6 @@ Wallet.getRandomId = function() { }; Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { - this.openWalletId(data.walletId); this.log('RECV PUBLICKEYRING:',data); var shouldSend = false; @@ -66,7 +65,6 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) { - this.openWalletId(data.walletId); this.log('RECV TXPROPOSAL:',data); //TODO var shouldSend = false; @@ -94,6 +92,11 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) { }; Wallet.prototype._handleData = function(senderId, data, isInbound) { + + if (this.id !== data.walletId) + throw new Error('wrong message received: Bad wallet ID'); + + switch(data.type) { case 'publicKeyRing': this._handlePublicKeyRing(senderId, data, isInbound); @@ -108,9 +111,13 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) { }; Wallet.prototype._handleNetworkChange = function(newPeer) { + +console.log('[Wallet.js.112:newPeer:]',newPeer); //TODO if (!newPeer) return; +console.log('[Wallet.js.112:newPeer:]',newPeer); //TODO this.log('#### Setting new PEER:', newPeer); + this.sendWalletId(newPeer); this.sendPublicKeyRing(newPeer); this.sendTxProposals(newPeer); }; @@ -118,8 +125,8 @@ Wallet.prototype._handleNetworkChange = function(newPeer) { Wallet.prototype.netStart = function() { var self = this; var net = this.network; - net.on('networkChange', function() { self._handleNetworkChange(); } ); - net.on('data', function() { self._handleData();}); + net.on('networkChange', self._handleNetworkChange.bind(self) ); + net.on('data', self._handleData.bind(self) ); net.on('open', function() {}); // TODO net.on('close', function() {}); // TODO net.start(function(peerId) { @@ -151,6 +158,17 @@ Wallet.prototype.sendTxProposals = function(recipients) { this.emit('txProposalsUpdated', this.txProposals); }; + +Wallet.prototype.sendWalletId = function(recipients) { + this.log('### SENDING walletId TO:', recipients||'All', this.walletId); + + this.network.send(recipients, { + type: 'walletId', + walletId: this.id, + }); +}; + + Wallet.prototype.sendPublicKeyRing = function(recipients) { this.log('### SENDING publicKeyRing TO:', recipients||'All', this.publicKeyRing.toObj()); @@ -308,8 +326,13 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) { }; Wallet.prototype.connectTo = function(peerId) { - this.network.connectTo(peerId); + throw new Error('Wallet.connectTo.. not yet implemented!'); }; + +Wallet.prototype.disconnect = function() { + this.network.disconnect(); +}; + // // HERE? not sure // Wallet.prototype.cleanPeers = function() { // this.storage.remove('peerData'); diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 05865d93c..baef0b27c 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -60,6 +60,7 @@ WalletFactory.prototype.read = function(walletId) { opts.storage = this.storage; opts.network = this.network; opts.blockchain = this.blockchain; + opts.verbose = this.verbose; var w = new Wallet(opts); @@ -102,6 +103,8 @@ WalletFactory.prototype.create = function(opts) { opts.storage = this.storage; opts.network = this.network; opts.blockchain = this.blockchain; + opts.verbose = this.verbose; + opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed; opts.requiredCopayers = requiredCopayers; opts.totalCopayers = totalCopayers; @@ -112,9 +115,44 @@ WalletFactory.prototype.create = function(opts) { }; WalletFactory.prototype.open = function(walletId) { - if(!WalletFactory.read(walletId)) { - WalletFactory.create({id: walletId}); - } + var w = this.read(walletId) || this.create({id: walletId}); + return w; +}; + +WalletFactory.prototype.openRemote = function(peedId) { + var s = WalletFactory.storage; + opts = opts || {}; + this.log('### CREATING NEW WALLET.' + (opts.id ? ' USING ID: ' + opts.id : ' NEW ID')); + + opts.privateKey = opts.privateKey || new PrivateKey({ networkName: this.networkName }); + this.log('\t### PrivateKey Initialized'); + + var requiredCopayers = opts.requiredCopayers || this.walletDefaults.requiredCopayers; + var totalCopayers = opts.totalCopayers || this.walletDefaults.totalCopayers; + + opts.publicKeyRing = opts.publicKeyRing || new PublicKeyRing({ + networkName: this.networkName, + requiredCopayers: requiredCopayers, + totalCopayers: totalCopayers, + }); + opts.publicKeyRing.addCopayer(opts.privateKey.getBIP32().extendedPublicKeyString()); + this.log('\t### PublicKeyRing Initialized'); + + opts.txProposals = opts.txProposals || new TxProposals({ + networkName: this.networkName, + }); + this.log('\t### TxProposals Initialized'); + + opts.storage = this.storage; + opts.network = this.network; + opts.blockchain = this.blockchain; + opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed; + opts.requiredCopayers = requiredCopayers; + opts.totalCopayers = totalCopayers; + var w = new Wallet(opts); + w.store(); + this.addWalletId(w.id); + return w; }; WalletFactory.prototype.getWalletIds = function() { @@ -142,4 +180,16 @@ WalletFactory.prototype.addWalletId = function(walletId) { this.storage.setGlobal('walletIds', ids); }; + +WalletFactory.prototype.connectTo = function(peerId, cb) { + var self=this; + self.network.start(function() { + self.network.connectTo(peerId) + self.network.on('walletId', function(walletId) { +console.log('[WalletFactory.js.187]'); //TODO + return cb(self.open(walletId)); + }); + }); +}; + module.exports = require('soop')(WalletFactory); diff --git a/js/models/network/WebRTC.js b/js/models/network/WebRTC.js index bb125fce1..9160cc857 100644 --- a/js/models/network/WebRTC.js +++ b/js/models/network/WebRTC.js @@ -103,6 +103,9 @@ Network.prototype._onData = function(data, isInbound) { case 'disconnect': this._onClose(obj.sender); break; + case 'walletId': + this.emit('walletId', obj.data.walletId); + break; default: this.emit('data', obj.sender, obj.data, isInbound); } @@ -158,7 +161,6 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) { dataConn.on('close', function() { if (self.closing) return; console.log('### CLOSE RECV FROM:', dataConn.peer); - self._onClose(dataConn.peer); this.emit('close'); }); @@ -166,6 +168,8 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) { Network.prototype._notify = function(newPeer) { this._showConnectedPeers(); + +console.log('[WebRTC.js.172]', newPeer); //TODO this.emit('networkChange', newPeer); }; @@ -269,7 +273,7 @@ Network.prototype.connectTo = function(peerId) { }; -Network.prototype.disconnect = function(peerId, cb) { +Network.prototype.disconnect = function(cb) { var self = this; self.closing = 1; diff --git a/test/test.Wallet.js b/test/test.Wallet.js index e4f36e522..87423c7ee 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -3,12 +3,10 @@ var chai = chai || require('chai'); var should = chai.should(); var copay = copay || require('../copay'); -var Wallet = require('soop').load('../js/models/core/Wallet', { - Storage: require('./mocks/FakeStorage'), - Network: copay.WebRTC, - Blockchain: copay.Insight -}); - +var Wallet = require('../js/models/core/Wallet'); +var Storage= require('./mocks/FakeStorage'); +var Network= copay.WebRTC; +var Blockchain= copay.Insight; var addCopayers = function (w) { for(var i=0; i<4; i++) { @@ -17,73 +15,65 @@ var addCopayers = function (w) { }; describe('Wallet model', function() { + var config = { - wallet: { - requiredCopayers: 3, - totalCopayers: 5, - }, + requiredCopayers: 3, + totalCopayers: 5, + spendUnconfirmed: 1, blockchain: { host: 'test.insight.is', port: 80 }, + networkName: 'testnet', }; - var opts = {}; + it('should fail to create an instance', function () { + (function(){new Wallet(config)}).should.throw(); + }); + + var createW = function () { + var c = JSON.parse(JSON.stringify(config)); + + c.privateKey = new copay.PrivateKey({ networkName: c.networkName }); + + c.publicKeyRing = new copay.PublicKeyRing({ + networkName: c.networkName, + requiredCopayers: c.requiredCopayers, + totalCopayers: c.totalCopayers, + }); + c.publicKeyRing.addCopayer(c.privateKey.getBIP32().extendedPublicKeyString()); + + c.txProposals = new copay.TxProposals({ + networkName: c.networkName, + }); + c.storage = new Storage(config.storage); + c.network = new Network(config.network); + c.blockchain = new Blockchain(config.blockchain); + + c.networkName = config.networkName; + c.verbose = config.verbose; + + return new Wallet(c); + } it('should create an instance', function () { - var opts = {}; - var w = new Wallet(config); + var w = createW(); should.exist(w); - }); - - - it('should fail to load', function () { - var opts = {}; - var w = new Wallet(config); - w.load(123); - should.not.exist(w.id); - }); - - - it('should create', function () { - var opts = {}; - var w = new Wallet(config); - w.create(); + w.publicKeyRing.walletId.should.equal(w.id); + w.txProposals.walletId.should.equal(w.id); + w.requiredCopayers.should.equal(3); should.exist(w.id); should.exist(w.publicKeyRing); should.exist(w.privateKey); should.exist(w.txProposals); }); - it('should list unspent', function (done) { + it('should provide some basic features', function () { var opts = {}; - var w = new Wallet(config); - w.create(); + var w = createW(); addCopayers(w); w.publicKeyRing.generateAddress(false); - - should.exist(w.id); w.publicKeyRing.isComplete().should.equal(true); - - w.listUnspent(function(utxos) { - utxos.length.should.equal(0); - done(); - }); - }); - - describe('factory', function() { - it('should create the factory', function() { - should.exist(Wallet.factory); - }); - it('should be able to create wallets', function() { - var w = Wallet.factory.create(config, opts); - should.exist(w); - }); - it.skip('should be able to get wallets', function() { - var w = Wallet.factory.create(config, opts); - var v = Wallet.factory.get(config, w.id); - should.exist(w); - }); }); var unspentTest = [ @@ -97,9 +87,8 @@ describe('Wallet model', function() { } ]; - var createWallet = function (bip32s) { - var w = new Wallet(config); - w.create(); + var createW2 = function (bip32s) { + var w = createW(); should.exist(w); var pkr = w.publicKeyRing; @@ -125,12 +114,12 @@ describe('Wallet model', function() { it('#create, 1 sign', function () { - var w = createWallet(); + var w = createW2(); unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); - w.createTx( + w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', unspentTest @@ -148,14 +137,14 @@ describe('Wallet model', function() { it('#create. Signing with derivate keys', function () { - var w = createWallet(); + var w = createW2(); var ts = Date.now(); for (var isChange=0; isChange<2; isChange++) { for (var index=0; index<3; index++) { unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); - w.createTx( + w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', unspentTest @@ -172,25 +161,4 @@ describe('Wallet model', function() { } }); - // TODO: when sign is implemented - it.skip('#create, signing with wrong key', function () { - var w1 = createWallet(); - - unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); - unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); - - var priv = new PrivateKey(config); - w.create( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', - unspentTest - ); - var tx = w.txps[0].builder.build(); - should.exist(tx); - tx.isComplete().should.equal(false); - Object.keys(w.txps[0].signedBy).length.should.equal(0); - Object.keys(w.txps[0].seenBy).length.should.equal(1); - }); - - }); diff --git a/test/test.walletfactory.js b/test/test.walletfactory.js index d3b7c7044..38fe165f8 100644 --- a/test/test.walletfactory.js +++ b/test/test.walletfactory.js @@ -5,7 +5,7 @@ var should = chai.should(); var WebRTC = require('../js/models/network/WebRTC'); var Insight = require('../js/models/blockchain/Insight'); -var FakeStorage = require('./FakeStorage'); +var FakeStorage = require('./mocks/FakeStorage'); var WalletFactory = typeof copay === 'undefined' ? require('soop').load('../js/models/core/WalletFactory',{ Network: WebRTC,