'use strict'; var imports = require('soop').imports(); var bitcore = require('bitcore'); var coinUtil = bitcore.util; var buffertools = bitcore.buffertools; var Builder = bitcore.TransactionBuilder; var http = require('http'); var EventEmitter= imports.EventEmitter || require('events').EventEmitter; var copay = copay || require('../../../copay'); function Wallet(opts) { var self = this; //required params ['storage', 'network', 'blockchain', 'requiredCopayers', 'totalCopayers', 'spendUnconfirmed', 'publicKeyRing', 'txProposals', 'privateKey' ].forEach( function(k){ if (typeof opts[k] === 'undefined') throw new Error('missing key:' + k); self[k] = opts[k]; }); this.log('creating '+opts.requiredCopayers+' of '+opts.totalCopayers+' wallet'); this.id = opts.id || Wallet.getRandomId(); this.verbose = opts.verbose; this.publicKeyRing.walletId = this.id; this.txProposals.walletId = this.id; } Wallet.parent=EventEmitter; Wallet.prototype.log = function(){ if (!this.verbose) return; console.log(arguments); }; Wallet.getRandomId = function() { var r = buffertools.toHex(coinUtil.generateNonce()); return r; }; Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { this.log('RECV PUBLICKEYRING:',data); var shouldSend = false; var recipients, pkr = this.publicKeyRing; var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing); var hasChanged = pkr.merge(inPKR, true); if (hasChanged && !data.isBroadcast) { this.log('### BROADCASTING PKR'); recipients = null; shouldSend = true; } else if (isInbound && !data.isBroadcast) { // always replying to connecting peer this.log('### REPLYING PKR TO:', senderId); recipients = senderId; shouldSend = true; } if (shouldSend) { this.sendPublicKeyRing(recipients); } this.store(); }; Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) { this.log('RECV TXPROPOSAL:',data); //TODO var shouldSend = false; var recipients; var inTxp = copay.TxProposals.fromObj(data.txProposals); var mergeInfo = this.txProposals.merge(inTxp, true); var addSeen = this.addSeenToTxProposals(); if ((mergeInfo.merged && !data.isBroadcast) || addSeen) { this.log('### BROADCASTING txProposals. ' ); recipients = null; shouldSend = true; } else if (isInbound && !data.isBroadcast) { // always replying to connecting peer this.log('### REPLYING txProposals TO:', senderId); recipients = senderId; shouldSend = true; } if (shouldSend) this.sendTxProposals(recipients); this.store(); }; Wallet.prototype._handleData = function(senderId, data, isInbound) { if (this.id !== data.walletId) { this.emit('badMessage',senderId); this.log('badMessage FROM:', senderId); //TODO return; } this.log('[Wallet.js.98]' , data.type); //TODO switch(data.type) { case 'publicKeyRing': this._handlePublicKeyRing(senderId, data, isInbound); break; case 'txProposals': this._handleTxProposals(senderId, data, isInbound); break; } }; Wallet.prototype._handleNetworkChange = function(newPeer) { if (newPeer) { this.log('#### Setting new PEER:', newPeer); console.log('sending wallet id'); this.sendWalletId(newPeer); console.log('sending pubkeyring'); this.sendPublicKeyRing(newPeer); console.log('sending tx proposals'); this.sendTxProposals(newPeer); } this.emit('refresh'); }; Wallet.prototype._optsToObj = function () { var obj = { id: this.id, spendUnconfirmed: this.spendUnconfirmed, requiredCopayers: this.requiredCopayers, totalCopayers: this.totalCopayers, }; return obj; }; Wallet.prototype.generatePeerId = function(index) { var idBuf = new Buffer(this.id); if (typeof index === 'undefined') { // return my own peerId var gen = this.privateKey.getId(idBuf); return gen; } // return peer number 'index' peerId return this.publicKeyRing.getCopayerId(index, idBuf); }; Wallet.prototype.netStart = function() { var self = this; var net = this.network; net.removeAllListeners(); net.on('networkChange', self._handleNetworkChange.bind(self) ); net.on('data', self._handleData.bind(self) ); net.on('open', function() {}); // TODO net.on('openError', function() { self.log('[Wallet.js.132:openError:] GOT openError'); //TODO self.emit('openError'); }); net.on('close', function() { self.emit('close'); }); var startOpts = { peerId: self.generatePeerId() } console.log('STARTING NETWORK WITH PEER ID: '+startOpts.peerId); net.start(function(peerId) { self.emit('created'); console.log('CREATEEEEEEEEEEEEEEEEEEEEEEd'); var myId = self.generatePeerId(); for (var i=0; i