decorate tx history with notes
This commit is contained in:
parent
a5c172af15
commit
fa1c63ac66
|
@ -15,8 +15,8 @@ TxNote.create = function(opts) {
|
||||||
x.walletId = opts.walletId;
|
x.walletId = opts.walletId;
|
||||||
x.txid = opts.txid;
|
x.txid = opts.txid;
|
||||||
x.body = opts.body;
|
x.body = opts.body;
|
||||||
x.lastEditedOn = now;
|
x.editedOn = now;
|
||||||
x.lastEditedBy = opts.copayerId;
|
x.editedBy = opts.copayerId;
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
|
@ -29,16 +29,16 @@ TxNote.fromObj = function(obj) {
|
||||||
x.walletId = obj.walletId;
|
x.walletId = obj.walletId;
|
||||||
x.txid = obj.txid;
|
x.txid = obj.txid;
|
||||||
x.body = obj.body;
|
x.body = obj.body;
|
||||||
x.lastEditedOn = obj.lastEditedOn;
|
x.editedOn = obj.editedOn;
|
||||||
x.lastEditedBy = obj.lastEditedBy;
|
x.editedBy = obj.editedBy;
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
|
|
||||||
TxNote.prototype.edit = function(body, copayerId) {
|
TxNote.prototype.edit = function(body, copayerId) {
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.lastEditedBy = copayerId;
|
this.editedBy = copayerId;
|
||||||
this.lastEditedOn = Math.floor(Date.now() / 1000);
|
this.editedOn = Math.floor(Date.now() / 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
TxNote.prototype.toObject = function() {
|
TxNote.prototype.toObject = function() {
|
||||||
|
|
|
@ -2033,6 +2033,8 @@ WalletService.prototype.getTx = function(opts, cb) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (!txp) return cb(Errors.TX_NOT_FOUND);
|
if (!txp) return cb(Errors.TX_NOT_FOUND);
|
||||||
|
|
||||||
|
if (!txp.txid) return cb(null, txp);
|
||||||
|
|
||||||
self.storage.fetchTxNote(self.walletId, txp.txid, function(err, note) {
|
self.storage.fetchTxNote(self.walletId, txp.txid, function(err, note) {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.warn('Error fetching tx note for ' + txp.txid);
|
log.warn('Error fetching tx note for ' + txp.txid);
|
||||||
|
@ -2542,10 +2544,11 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
|
||||||
if (opts.limit > Defaults.HISTORY_LIMIT)
|
if (opts.limit > Defaults.HISTORY_LIMIT)
|
||||||
return cb(Errors.HISTORY_LIMIT_EXCEEDED);
|
return cb(Errors.HISTORY_LIMIT_EXCEEDED);
|
||||||
|
|
||||||
function decorate(txs, addresses, proposals) {
|
function decorate(txs, addresses, proposals, notes) {
|
||||||
|
|
||||||
var indexedAddresses = _.indexBy(addresses, 'address');
|
var indexedAddresses = _.indexBy(addresses, 'address');
|
||||||
var indexedProposals = _.indexBy(proposals, 'txid');
|
var indexedProposals = _.indexBy(proposals, 'txid');
|
||||||
|
var indexedNotes = _.indexBy(notes, 'txid');
|
||||||
|
|
||||||
function sum(items, isMine, isChange) {
|
function sum(items, isMine, isChange) {
|
||||||
var filter = {};
|
var filter = {};
|
||||||
|
@ -2659,6 +2662,11 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
|
||||||
//newTx.paymentAckMemo = proposal.paymentAckMemo;
|
//newTx.paymentAckMemo = proposal.paymentAckMemo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var note = indexedNotes[tx.txid];
|
||||||
|
if (note) {
|
||||||
|
newTx.note = _.pick(note, ['body', 'editedBy', 'editedByName', 'editedOn']);
|
||||||
|
}
|
||||||
|
|
||||||
return newTx;
|
return newTx;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2675,10 +2683,7 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
|
||||||
async.parallel([
|
async.parallel([
|
||||||
|
|
||||||
function(next) {
|
function(next) {
|
||||||
self.storage.fetchTxs(self.walletId, {}, function(err, txps) {
|
self.storage.fetchTxs(self.walletId, {}, next);
|
||||||
if (err) return next(err);
|
|
||||||
next(null, txps);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
var from = opts.skip || 0;
|
var from = opts.skip || 0;
|
||||||
|
@ -2688,13 +2693,17 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
|
||||||
next(null, self._normalizeTxHistory(txs));
|
next(null, self._normalizeTxHistory(txs));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
function(next) {
|
||||||
|
self.storage.fetchTxNotes(self.walletId, next);
|
||||||
|
},
|
||||||
], function(err, res) {
|
], function(err, res) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
var proposals = res[0];
|
var proposals = res[0];
|
||||||
var txs = res[1];
|
var txs = res[1];
|
||||||
|
var notes = res[2];
|
||||||
|
|
||||||
txs = decorate(txs, addresses, proposals);
|
txs = decorate(txs, addresses, proposals, notes);
|
||||||
|
|
||||||
return cb(null, txs);
|
return cb(null, txs);
|
||||||
});
|
});
|
||||||
|
|
|
@ -630,6 +630,33 @@ Storage.prototype.fetchTxNote = function(walletId, txid, cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: should be done client-side
|
||||||
|
Storage.prototype._completeTxNotesData = function(walletId, notes, cb) {
|
||||||
|
var notesList = [].concat(notes);
|
||||||
|
this.fetchWallet(walletId, function(err, wallet) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
_.each(notesList, function(note) {
|
||||||
|
note.editedByName = wallet.getCopayer(note.editedBy).name;
|
||||||
|
});
|
||||||
|
return cb(null, notes);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Storage.prototype.fetchTxNotes = function(walletId, cb) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.db.collection(collections.TX_NOTES).find({
|
||||||
|
walletId: walletId,
|
||||||
|
}).toArray(function(err, result) {
|
||||||
|
if (err) return cb(err);
|
||||||
|
var notes = _.compact(_.map(result, function(note) {
|
||||||
|
if (!note.body) return;
|
||||||
|
return Model.TxNote.fromObj(note);
|
||||||
|
}));
|
||||||
|
return self._completeTxNotesData(walletId, notes, cb);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
Storage.prototype.storeTxNote = function(txNote, cb) {
|
Storage.prototype.storeTxNote = function(txNote, cb) {
|
||||||
this.db.collection(collections.TX_NOTES).update({
|
this.db.collection(collections.TX_NOTES).update({
|
||||||
txid: txNote.txid,
|
txid: txNote.txid,
|
||||||
|
|
|
@ -3858,8 +3858,8 @@ describe('Wallet service', function() {
|
||||||
note.txid.should.equal('123');
|
note.txid.should.equal('123');
|
||||||
note.walletId.should.equal(wallet.id);
|
note.walletId.should.equal(wallet.id);
|
||||||
note.body.should.equal('note body');
|
note.body.should.equal('note body');
|
||||||
note.lastEditedBy.should.equal(server.copayerId);
|
note.editedBy.should.equal(server.copayerId);
|
||||||
note.createdOn.should.equal(note.lastEditedOn);
|
note.createdOn.should.equal(note.editedOn);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3876,9 +3876,9 @@ describe('Wallet service', function() {
|
||||||
}, function(err, note) {
|
}, function(err, note) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(note);
|
should.exist(note);
|
||||||
note.lastEditedBy.should.equal(server.copayerId);
|
note.editedBy.should.equal(server.copayerId);
|
||||||
note.createdOn.should.equal(note.lastEditedOn);
|
note.createdOn.should.equal(note.editedOn);
|
||||||
var creator = note.lastEditedBy;
|
var creator = note.editedBy;
|
||||||
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
||||||
clock.tick(60 * 1000);
|
clock.tick(60 * 1000);
|
||||||
server.editTxNote({
|
server.editTxNote({
|
||||||
|
@ -3891,9 +3891,9 @@ describe('Wallet service', function() {
|
||||||
}, function(err, note) {
|
}, function(err, note) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(note);
|
should.exist(note);
|
||||||
note.lastEditedBy.should.equal(server.copayerId);
|
note.editedBy.should.equal(server.copayerId);
|
||||||
note.createdOn.should.be.below(note.lastEditedOn);
|
note.createdOn.should.be.below(note.editedOn);
|
||||||
creator.should.not.equal(note.lastEditedBy);
|
creator.should.not.equal(note.editedBy);
|
||||||
clock.restore();
|
clock.restore();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -3935,7 +3935,7 @@ describe('Wallet service', function() {
|
||||||
txp.note.txid.should.equal(txp.txid);
|
txp.note.txid.should.equal(txp.txid);
|
||||||
txp.note.walletId.should.equal(wallet.id);
|
txp.note.walletId.should.equal(wallet.id);
|
||||||
txp.note.body.should.equal('note body');
|
txp.note.body.should.equal('note body');
|
||||||
txp.note.lastEditedBy.should.equal(server.copayerId);
|
txp.note.editedBy.should.equal(server.copayerId);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3954,8 +3954,8 @@ describe('Wallet service', function() {
|
||||||
}, function(err, note) {
|
}, function(err, note) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(note);
|
should.exist(note);
|
||||||
note.lastEditedBy.should.equal(server.copayerId);
|
note.editedBy.should.equal(server.copayerId);
|
||||||
var creator = note.lastEditedBy;
|
var creator = note.editedBy;
|
||||||
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
|
||||||
server.getTxNote({
|
server.getTxNote({
|
||||||
txid: '123',
|
txid: '123',
|
||||||
|
@ -3963,7 +3963,7 @@ describe('Wallet service', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(note);
|
should.exist(note);
|
||||||
note.body.should.equal('note body');
|
note.body.should.equal('note body');
|
||||||
note.lastEditedBy.should.equal(creator);
|
note.editedBy.should.equal(creator);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3997,6 +3997,43 @@ describe('Wallet service', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('should include the note in tx history listing', function(done) {
|
||||||
|
helpers.createAddresses(server, wallet, 1, 1, function(mainAddresses, changeAddress) {
|
||||||
|
server._normalizeTxHistory = sinon.stub().returnsArg(0);
|
||||||
|
var txs = [{
|
||||||
|
txid: '123',
|
||||||
|
confirmations: 1,
|
||||||
|
fees: 100,
|
||||||
|
time: 20,
|
||||||
|
inputs: [{
|
||||||
|
address: 'external',
|
||||||
|
amount: 500,
|
||||||
|
}],
|
||||||
|
outputs: [{
|
||||||
|
address: mainAddresses[0].address,
|
||||||
|
amount: 200,
|
||||||
|
}],
|
||||||
|
}];
|
||||||
|
helpers.stubHistory(txs);
|
||||||
|
server.editTxNote({
|
||||||
|
txid: '123',
|
||||||
|
body: 'just some note'
|
||||||
|
}, function(err) {
|
||||||
|
should.not.exist(err);
|
||||||
|
server.getTxHistory({}, function(err, txs) {
|
||||||
|
should.not.exist(err);
|
||||||
|
should.exist(txs);
|
||||||
|
txs.length.should.equal(1);
|
||||||
|
var tx = txs[0];
|
||||||
|
should.exist(tx.note);
|
||||||
|
tx.note.body.should.equal('just some note');
|
||||||
|
tx.note.editedBy.should.equal(server.copayerId);
|
||||||
|
should.exist(tx.note.editedOn);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue