diff --git a/index.html b/index.html
index caf3c0eb1..f96b27ae7 100644
--- a/index.html
+++ b/index.html
@@ -529,7 +529,7 @@
No pending transactions proposals.
No transactions proposals yet.
-
+
Last transactions
diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js
index 4bc4f2fa9..c9a5bcf3c 100644
--- a/js/models/core/TxProposals.js
+++ b/js/models/core/TxProposals.js
@@ -97,11 +97,13 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
fromTheirs = 0,
merged = 0;
var toMerge = {},
- ready = {};
+ ready = {},
+ events = [];
for (var hash in theirTxps) {
if (!myTxps[hash]) {
ready[hash] = theirTxps[hash]; // only in theirs;
+ events.push({type: 'new', cid: theirTxps[hash].creator, tx: hash});
fromTheirs++;
} else {
toMerge[hash] = theirTxps[hash]; // need Merging
@@ -124,6 +126,7 @@ TxProposals.prototype._startMerge = function(myTxps, theirTxps) {
},
ready: ready,
toMerge: toMerge,
+ events: events
};
};
@@ -132,6 +135,7 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
var toMerge = mergeInfo.toMerge;
var hasChanged = 0;
+ var events = [];
Object.keys(toMerge).forEach(function(hash) {
var v0 = myTxps[hash];
@@ -140,32 +144,36 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
Object.keys(v1.seenBy).forEach(function(k) {
if (!v0.seenBy[k]) {
v0.seenBy[k] = v1.seenBy[k];
- hasChanged++;
+ events.push({type: 'seen', cId: k, txId: hash});
}
});
Object.keys(v1.signedBy).forEach(function(k) {
if (!v0.signedBy[k]) {
v0.signedBy[k] = v1.signedBy[k];
- hasChanged++;
+ events.push({type: 'signed', cId: k, txId: hash});
}
});
Object.keys(v1.rejectedBy).forEach(function(k) {
if (!v0.rejectedBy[k]) {
v0.rejectedBy[k] = v1.rejectedBy[k];
- hasChanged++;
+ events.push({type: 'rejected', cId: k, txId: hash});
}
});
if (!v0.sentTxid && v1.sentTxid) {
v0.sentTs = v1.sentTs;
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)
throw new Error('network mismatch in:', t);
- var res = [];
- var hasChanged = 0;
-
var myTxps = this.txps;
var theirTxps = t.txps;
var mergeInfo = this._startMerge(myTxps, theirTxps);
- hasChanged += this._mergeMetadata(myTxps, theirTxps, mergeInfo);
- hasChanged += this._mergeBuilder(myTxps, theirTxps, mergeInfo);
+ var result = this._mergeMetadata(myTxps, theirTxps, mergeInfo);
+ result.hasChanged += this._mergeBuilder(myTxps, theirTxps, mergeInfo);
Object.keys(mergeInfo.toMerge).forEach(function(hash) {
mergeInfo.ready[hash] = myTxps[hash];
});
- mergeInfo.stats.hasChanged = hasChanged;
+ mergeInfo.stats.hasChanged = result.hasChanged;
+ mergeInfo.stats.events = result.events;
this.txps = mergeInfo.ready;
return mergeInfo.stats;
diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js
index 4dfd7708d..2bb53df60 100644
--- a/js/models/core/Wallet.js
+++ b/js/models/core/Wallet.js
@@ -117,7 +117,7 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
var inTxp = copay.TxProposals.fromObj(data.txProposals);
var ids = inTxp.getNtxids();
- if (ids.lenght > 1) {
+ if (ids.length > 1) {
this.emit('badMessage', senderId);
this.log('Received BAD TxProposal messsage FROM:', senderId); //TODO
return;
@@ -135,6 +135,9 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
this.emit('txProposalsUpdated');
this.store();
}
+ for (var i = 0; i < mergeInfo.events.length; i++) {
+ this.emit('txProposalEvent', mergeInfo.events[i]);
+ }
};
Wallet.prototype._handleData = function(senderId, data, isInbound) {
diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js
index a512d5fd6..5a7c6817d 100644
--- a/js/services/controllerUtils.js
+++ b/js/services/controllerUtils.js
@@ -122,6 +122,18 @@ angular.module('copayApp.services')
});
}, 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) {
root.onErrorDigest(null, msg);
});
diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js
index 9ae69412c..59beb4822 100644
--- a/test/test.TxProposals.js
+++ b/test/test.TxProposals.js
@@ -215,7 +215,9 @@ describe('TxProposals model', function() {
(w.txps[k].signedBy[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);
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].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);
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].seenBy[priv.id] - ts > 0).should.equal(true);
- w.merge(w2);
- Object.keys(w.txps).length.should.equal(1);
+ var info = w.merge(w2);
+ info.events.length.should.equal(1);
+ info.events[0].type.should.equal('signed');
tx = w.txps[ntxid].builder.build();
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].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);
(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].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);
var tx = w.txps[k].builder.build();
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.merge(w3);
+ var info = w.merge(w3);
+ info.events.length.should.equal(0);
+
var tx = w.txps[k].builder.build();
tx.isComplete().should.equal(true);
tx.countInputMissingSignatures(0).should.equal(0);