From b6280348e56f2c038c72907c71791570c758637e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 23 Apr 2014 02:01:54 -0300 Subject: [PATCH] reject button working --- index.html | 17 ++++++---- js/controllers/send.js | 15 ++++----- js/controllers/transactions.js | 9 +++++ js/models/core/PublicKeyRing.js | 3 +- js/models/core/TxProposals.js | 44 ++++++++++++++++++++++-- js/models/core/Wallet.js | 60 +++++++++++++++------------------ 6 files changed, 99 insertions(+), 49 deletions(-) diff --git a/index.html b/index.html index a88a9fb03..16b278635 100644 --- a/index.html +++ b/index.html @@ -244,7 +244,7 @@
-

Pending transactions ({{txs.length}})

+

Transactions proposals ({{txs.length}})

@@ -284,6 +284,7 @@ + @@ -301,16 +302,20 @@
Signed by you already
-
+
-
+ + Transaction finally rejected + + Transaction ready.
diff --git a/js/controllers/send.js b/js/controllers/send.js index 276468464..46000b937 100644 --- a/js/controllers/send.js +++ b/js/controllers/send.js @@ -23,16 +23,15 @@ angular.module('copay.send').controller('SendController', var w = $rootScope.wallet; w.createTx( address, amount,function() { + + // reset fields + $scope.address = null; + $scope.amount = null; + form.address.$pristine = true; + form.amount.$pristine = true; + $rootScope.flashMessage = { message: 'The transaction proposal has been created', type: 'success'}; $rootScope.$digest(); }); - // reset fields - $scope.address = null; - $scope.amount = null; - form.address.$pristine = true; - form.amount.$pristine = true; - - // TODO: check if createTx has an error. - $rootScope.flashMessage = { message: 'Your transaction proposal has been sent successfully', type: 'success'}; }; }); diff --git a/js/controllers/transactions.js b/js/controllers/transactions.js index 7cc47598e..59f58f150 100644 --- a/js/controllers/transactions.js +++ b/js/controllers/transactions.js @@ -70,5 +70,14 @@ angular.module('copay.transactions').controller('TransactionsController', } }; + + $scope.reject = function (ntxid) { + var w = $rootScope.wallet; + w.reject(ntxid); + $rootScope.flashMessage = {type:'warning', message: 'Transaction rejected by you'}; + _updateTxs(); + $rootScope.$digest(); + }; + _updateTxs(); }); diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 14f611d8b..a9a1327d5 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -274,6 +274,8 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) { var self = this; var hasChanged = false; var l= self.copayersBIP32.length; + if (self.isComplete()) + return; inPKR.copayersBIP32.forEach( function(b) { var haveIt = false; @@ -286,7 +288,6 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) { } if (!haveIt) { if (self.isComplete()) { - //console.log('[PublicKeyRing.js.318] REPEATED KEY', epk); //TODO throw new Error('trying to add more pubkeys, when PKR isComplete at merge'); } self.copayersBIP32.push(new BIP32(epk)); diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js index 772faefe4..bbef94908 100644 --- a/js/models/core/TxProposals.js +++ b/js/models/core/TxProposals.js @@ -18,6 +18,7 @@ function TxProposal(opts) { this.createdTs = opts.createdTs; this.seenBy = opts.seenBy || {}; this.signedBy = opts.signedBy || {}; + this.rejectedBy = opts.rejectedBy || {}; this.builder = opts.builder; this.sentTs = opts.sentTs || null; this.sentTxid = opts.sentTxid || null; @@ -120,6 +121,7 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) { }; }; +// TODO add signatures. TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { var toMerge = mergeInfo.toMerge; @@ -130,7 +132,7 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { var v1 = toMerge[hash]; Object.keys(v1.seenBy).forEach(function(k) { - if (!v0.seenBy[k] || v0.seenBy[k] !== v1.seenBy[k]) { + if (!v0.seenBy[k]) { v0.seenBy[k] = v1.seenBy[k]; hasChanged++; } @@ -143,6 +145,13 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) { } }); + Object.keys(v1.rejectedBy).forEach(function(k) { + if (!v0.rejectedBy[k]) { + v0.rejectedBy[k] = v1.rejectedBy[k]; + hasChanged++; + } + }); + if (!v0.sentTxid && v1.sentTxid) { v0.sentTs = v1.sentTs; v0.sentTxid = v1.sentTxid; @@ -181,10 +190,41 @@ TxProposals.prototype.setSent = function(ntxid,txid) { this.txps[ntxid].setSent(txid); }; -TxProposals.prototype.getUsedUnspent = function() { + +TxProposals.prototype.getTxProposal = function(ntxid) { + var txp = this.txps[ntxid]; + var i = JSON.parse(JSON.stringify(txp)); + i.builder = txp.builder; + i.ntxid = ntxid; + i.peerActions = {}; + for(var p in txp.seenBy){ + i.peerActions[p]={seen: txp.seenBy[p]}; + } + for(var p in txp.signedBy){ + i.peerActions[p]= i.peerActions[p] || {}; + i.peerActions[p].sign = txp.signedBy[p]; + } + var r=0; + for(var p in txp.rejectedBy){ + i.peerActions[p]= i.peerActions[p] || {}; + i.peerActions[p].rejected = txp.rejectedBy[p]; + r++; + } + i.rejectCount=r; + + var c = txp.creator; + i.peerActions[c] = i.peerActions[c] || {}; + i.peerActions[c].create = txp.createdTs; + return i; +}; + +TxProposals.prototype.getUsedUnspent = function(maxRejectCount) { var ret = []; for(var i in this.txps) { var u = this.txps[i].builder.getSelectedUnspent(); + if (this.getTxProposal(i).rejectCount>maxRejectCount) + continue; + for (var j in u){ ret.push(u[j].txid); } diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index b966e295a..b90b71040 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -274,46 +274,38 @@ Wallet.prototype.generateAddress = function(isChange) { return addr; }; -// TODO : sort by time... / signed. + Wallet.prototype.getTxProposals = function() { var ret = []; for(var k in this.txProposals.txps) { - var txp = this.txProposals.txps[k]; - var i = JSON.parse(JSON.stringify(txp)); - i.builder = txp.builder; - i.ntxid = k; - i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false; - - i.peerActions = {}; - for(var p in txp.seenBy){ - i.peerActions[p]={seen: txp.seenBy[p]}; - } - for(var p in txp.signedBy){ - i.peerActions[p]= i.peerActions[p] || {}; - i.peerActions[p].sign = txp.signedBy[p]; - } - var c = txp.creator; - i.peerActions[c] = i.peerActions[c] || {}; - i.peerActions[c].create = txp.createdTs; - + var i = this.txProposals.getTxProposal(k); + i.signedByUs = i.signedBy[this.getMyPeerId()]?true:false; + i.rejectedByUs = i.rejectedBy[this.getMyPeerId()]?true:false; + if (this.totalCopayers-i.rejectCount < this.requiredCopayers) + i.finallyRejected=true; ret.push(i); } return ret; }; -Wallet.prototype.getTxProposal = function(ntxid) { + +Wallet.prototype.reject = function(ntxid) { + var myId=this.getMyPeerId(); var txp = this.txProposals.txps[ntxid]; - var i = {txp:txp}; - i.ntxid = ntxid; - i.signedByUs = txp.signedBy[this.getMyPeerId()]?true:false; - return i; + if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return; + + txp.rejectedBy[myId] = Date.now(); + this.sendTxProposals(); + this.store(true); }; + Wallet.prototype.sign = function(ntxid) { var self = this; + var myId=this.getMyPeerId(); var txp = self.txProposals.txps[ntxid]; - if (!txp) return; + if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return; var pkr = self.publicKeyRing; var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex); @@ -324,7 +316,7 @@ Wallet.prototype.sign = function(ntxid) { var ret = false; if (b.signaturesAdded > before) { - txp.signedBy[self.getMyPeerId()] = Date.now(); + txp.signedBy[myId] = Date.now(); this.sendTxProposals(); this.store(true); ret = true; @@ -371,7 +363,6 @@ Wallet.prototype.addSeenToTxProposals = function() { return ret; }; - Wallet.prototype.getAddresses = function(onlyMain) { return this.publicKeyRing.getAddresses(onlyMain); }; @@ -438,7 +429,8 @@ Wallet.prototype.getSafeUnspent = function(cb) { this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) { var ret=[]; - var uu = self.txProposals.getUsedUnspent(); + var maxRejectCount = self.totalCopayers - self.requiredCopayers; + var uu = self.txProposals.getUsedUnspent(maxRejectCount); for(var i in unspentList){ if (uu.indexOf(unspentList[i].txid) === -1) @@ -497,21 +489,25 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) { if (priv) { b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) ); } - var me = {}; var myId = this.getMyPeerId(); var now = Date.now(); - if (priv) me[myId] = now; + var me = {}; + if (priv && b.signaturesAdded) me[myId] = now; + + var meSeen = {}; + if (priv) meSeen[myId] = now; var data = { - signedBy: (priv && b.signaturesAdded ? me : {}), - seenBy: (priv ? me : {}), + signedBy: me, + seenBy: meSeen, creator: myId, createdTs: now, builder: b, }; this.txProposals.add(data); + return true; }; Wallet.prototype.connectTo = function(peerId) {