Merge pull request #678 from yemel/feature/sign-notification

Feature/sign notification
This commit is contained in:
Matias Alejo Garcia 2014-06-16 15:56:53 -03:00
commit bde2ae8576
5 changed files with 54 additions and 21 deletions

View File

@ -529,7 +529,7 @@
</div> </div>
<p ng-show="onlyPending && txs.length == 0">No pending transactions proposals.</p> <p ng-show="onlyPending && txs.length == 0">No pending transactions proposals.</p>
<p ng-show="!onlyPending && txs.length == 0">No transactions proposals yet.</p> <p ng-show="!onlyPending && txs.length == 0">No transactions proposals yet.</p>
<pagination ng-show="!onlyPending && txs.length > 0" total-items="txs.length" items-per-page="txpItemsPerPage" page="txpCurrentPage" on-select-page="show()" class="pagination-small primary"></pagination> <pagination ng-show="!onlyPending && txs.length > txpItemsPerPage" total-items="txs.length" items-per-page="txpItemsPerPage" page="txpCurrentPage" on-select-page="show()" class="pagination-small primary"></pagination>
</div> </div>
<div class="large-12 columns"> <div class="large-12 columns">
<h4>Last transactions</h4> <h4>Last transactions</h4>

View File

@ -97,11 +97,13 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
fromTheirs = 0, fromTheirs = 0,
merged = 0; merged = 0;
var toMerge = {}, var toMerge = {},
ready = {}; ready = {},
events = [];
for (var hash in theirTxps) { for (var hash in theirTxps) {
if (!myTxps[hash]) { if (!myTxps[hash]) {
ready[hash] = theirTxps[hash]; // only in theirs; ready[hash] = theirTxps[hash]; // only in theirs;
events.push({type: 'new', cid: theirTxps[hash].creator, tx: hash});
fromTheirs++; fromTheirs++;
} else { } else {
toMerge[hash] = theirTxps[hash]; // need Merging toMerge[hash] = theirTxps[hash]; // need Merging
@ -124,6 +126,7 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
}, },
ready: ready, ready: ready,
toMerge: toMerge, toMerge: toMerge,
events: events
}; };
}; };
@ -132,6 +135,7 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
var toMerge = mergeInfo.toMerge; var toMerge = mergeInfo.toMerge;
var hasChanged = 0; var hasChanged = 0;
var events = [];
Object.keys(toMerge).forEach(function(hash) { Object.keys(toMerge).forEach(function(hash) {
var v0 = myTxps[hash]; var v0 = myTxps[hash];
@ -140,32 +144,36 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
Object.keys(v1.seenBy).forEach(function(k) { Object.keys(v1.seenBy).forEach(function(k) {
if (!v0.seenBy[k]) { if (!v0.seenBy[k]) {
v0.seenBy[k] = v1.seenBy[k]; v0.seenBy[k] = v1.seenBy[k];
hasChanged++; events.push({type: 'seen', cId: k, txId: hash});
} }
}); });
Object.keys(v1.signedBy).forEach(function(k) { Object.keys(v1.signedBy).forEach(function(k) {
if (!v0.signedBy[k]) { if (!v0.signedBy[k]) {
v0.signedBy[k] = v1.signedBy[k]; v0.signedBy[k] = v1.signedBy[k];
hasChanged++; events.push({type: 'signed', cId: k, txId: hash});
} }
}); });
Object.keys(v1.rejectedBy).forEach(function(k) { Object.keys(v1.rejectedBy).forEach(function(k) {
if (!v0.rejectedBy[k]) { if (!v0.rejectedBy[k]) {
v0.rejectedBy[k] = v1.rejectedBy[k]; v0.rejectedBy[k] = v1.rejectedBy[k];
hasChanged++; events.push({type: 'rejected', cId: k, txId: hash});
} }
}); });
if (!v0.sentTxid && v1.sentTxid) { if (!v0.sentTxid && v1.sentTxid) {
v0.sentTs = v1.sentTs; v0.sentTs = v1.sentTs;
v0.sentTxid = v1.sentTxid; v0.sentTxid = v1.sentTxid;
hasChanged++; events.push({type: 'broadcast', txId: hash});
} }
}); });
return hasChanged;
return {
events: events.concat(mergeInfo.events),
hasChanged: events.length
};
}; };
@ -255,21 +263,19 @@ TxProposals.prototype.merge = function(t) {
if (this.network.name !== t.network.name) if (this.network.name !== t.network.name)
throw new Error('network mismatch in:', t); throw new Error('network mismatch in:', t);
var res = [];
var hasChanged = 0;
var myTxps = this.txps; var myTxps = this.txps;
var theirTxps = t.txps; var theirTxps = t.txps;
var mergeInfo = this._startMerge(myTxps, theirTxps); var mergeInfo = this._startMerge(myTxps, theirTxps);
hasChanged += this._mergeMetadata(myTxps, theirTxps, mergeInfo); var result = this._mergeMetadata(myTxps, theirTxps, mergeInfo);
hasChanged += this._mergeBuilder(myTxps, theirTxps, mergeInfo); result.hasChanged += this._mergeBuilder(myTxps, theirTxps, mergeInfo);
Object.keys(mergeInfo.toMerge).forEach(function(hash) { Object.keys(mergeInfo.toMerge).forEach(function(hash) {
mergeInfo.ready[hash] = myTxps[hash]; mergeInfo.ready[hash] = myTxps[hash];
}); });
mergeInfo.stats.hasChanged = hasChanged; mergeInfo.stats.hasChanged = result.hasChanged;
mergeInfo.stats.events = result.events;
this.txps = mergeInfo.ready; this.txps = mergeInfo.ready;
return mergeInfo.stats; return mergeInfo.stats;

View File

@ -117,7 +117,7 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
var inTxp = copay.TxProposals.fromObj(data.txProposals); var inTxp = copay.TxProposals.fromObj(data.txProposals);
var ids = inTxp.getNtxids(); var ids = inTxp.getNtxids();
if (ids.lenght > 1) { if (ids.length > 1) {
this.emit('badMessage', senderId); this.emit('badMessage', senderId);
this.log('Received BAD TxProposal messsage FROM:', senderId); //TODO this.log('Received BAD TxProposal messsage FROM:', senderId); //TODO
return; return;
@ -135,6 +135,9 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
this.emit('txProposalsUpdated'); this.emit('txProposalsUpdated');
this.store(); this.store();
} }
for (var i = 0; i < mergeInfo.events.length; i++) {
this.emit('txProposalEvent', mergeInfo.events[i]);
}
}; };
Wallet.prototype._handleData = function(senderId, data, isInbound) { Wallet.prototype._handleData = function(senderId, data, isInbound) {

View File

@ -122,6 +122,18 @@ angular.module('copayApp.services')
}); });
}, 3000); }, 3000);
}); });
w.on('txProposalEvent', function(e){
switch (e.type) {
case 'signed':
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
$notification.info('Transaction Update', 'A transaction was signed by ' + user);
break;
case 'rejected':
var user = w.publicKeyRing.nicknameForCopayer(e.cId);
$notification.info('Transaction Update', 'A transaction was rejected by ' + user);
break;
}
});
w.on('connectionError', function(msg) { w.on('connectionError', function(msg) {
root.onErrorDigest(null, msg); root.onErrorDigest(null, msg);
}); });

View File

@ -215,7 +215,9 @@ describe('TxProposals model', function() {
(w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
(w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
w.merge(w); var info = w.merge(w);
info.events.length.should.equal(0);
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
@ -287,7 +289,10 @@ describe('TxProposals model', function() {
(w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true);
(w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); (w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true);
w.merge(w2); var info = w.merge(w2);
info.events.length.should.equal(1);
info.events[0].type.should.equal('signed');
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
var tx = w.txps[k].builder.build(); var tx = w.txps[k].builder.build();
@ -392,8 +397,9 @@ describe('TxProposals model', function() {
(w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
(w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
w.merge(w2); var info = w.merge(w2);
Object.keys(w.txps).length.should.equal(1); info.events.length.should.equal(1);
info.events[0].type.should.equal('signed');
tx = w.txps[ntxid].builder.build(); tx = w.txps[ntxid].builder.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
@ -421,7 +427,9 @@ describe('TxProposals model', function() {
(w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
(w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
w.merge(w3); var info = w.merge(w3);
info.events.length.should.equal(0);
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
@ -510,7 +518,9 @@ describe('TxProposals model', function() {
(w3.txps[k].signedBy[priv3.id] - ts > 0).should.equal(true); (w3.txps[k].signedBy[priv3.id] - ts > 0).should.equal(true);
(w3.txps[k].seenBy[priv3.id] - ts > 0).should.equal(true); (w3.txps[k].seenBy[priv3.id] - ts > 0).should.equal(true);
w.merge(w2); var info = w.merge(w2);
info.events.length.should.equal(0);
Object.keys(w.txps).length.should.equal(1); Object.keys(w.txps).length.should.equal(1);
var tx = w.txps[k].builder.build(); var tx = w.txps[k].builder.build();
tx.isComplete().should.equal(false); tx.isComplete().should.equal(false);
@ -521,7 +531,9 @@ describe('TxProposals model', function() {
(w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); (w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true);
w.merge(w3); var info = w.merge(w3);
info.events.length.should.equal(0);
var tx = w.txps[k].builder.build(); var tx = w.txps[k].builder.build();
tx.isComplete().should.equal(true); tx.isComplete().should.equal(true);
tx.countInputMissingSignatures(0).should.equal(0); tx.countInputMissingSignatures(0).should.equal(0);