edit/retrieve notes + tests

This commit is contained in:
Ivan Socolsky 2016-05-17 13:13:21 -03:00
parent 5ca8663c96
commit 5abe6fac51
No known key found for this signature in database
GPG Key ID: FAECE6A05FAA4F56
4 changed files with 211 additions and 4 deletions

View File

@ -6,14 +6,17 @@ function TxNote() {};
TxNote.create = function(opts) {
opts = opts || {};
var now = Math.floor(Date.now() / 1000);
var x = new TxNote();
x.version = 1;
x.createdOn = now;
x.walletId = opts.walletId;
x.txid = opts.txid;
x.body = opts.body;
x.lastEditedOn = Math.floor(Date.now() / 1000);
x.lastEditedById = opts.lastEditedById;
x.lastEditedOn = now;
x.lastEditedBy = opts.copayerId;
return x;
};
@ -22,13 +25,24 @@ TxNote.fromObj = function(obj) {
var x = new TxNote();
x.version = obj.version;
x.createdOn = obj.createdOn;
x.walletId = obj.walletId;
x.txid = obj.txid;
x.body = obj.body;
x.lastEditedOn = obj.lastEditedOn;
x.lastEditedById = obj.lastEditedById;
x.lastEditedBy = obj.lastEditedBy;
return x;
};
TxNote.prototype.edit = function(body, copayerId) {
this.body = body;
this.lastEditedBy = copayerId;
this.lastEditedOn = Math.floor(Date.now() / 1000);
};
TxNote.prototype.toObject = function() {
return this;
};
module.exports = TxNote;

View File

@ -2032,10 +2032,61 @@ WalletService.prototype.getTx = function(opts, cb) {
self.storage.fetchTx(self.walletId, opts.txProposalId, function(err, txp) {
if (err) return cb(err);
if (!txp) return cb(Errors.TX_NOT_FOUND);
return cb(null, txp);
self.storage.fetchTxNote(self.walletId, txp.txid, function(err, note) {
if (err) {
log.warn('Error fetching tx note for ' + txp.txid);
}
txp.note = note;
return cb(null, txp);
});
});
};
/**
* Edit note associated to a txid.
* @param {Object} opts
* @param {string} opts.txid - The txid of the tx on the blockchain.
* @param {string} opts.body - The contents of the note.
*/
WalletService.prototype.editTxNote = function(opts, cb) {
var self = this;
if (!Utils.checkRequired(opts, ['txid']))
return cb(new ClientError('Required argument missing'));
self._runLocked(cb, function(cb) {
self.storage.fetchTxNote(self.walletId, opts.txid, function(err, note) {
if (err) return cb(err);
if (!note) {
note = Model.TxNote.create({
walletId: self.walletId,
txid: opts.txid,
copayerId: self.copayerId,
body: opts.body,
});
} else {
note.edit(opts.body, self.copayerId);
}
self.storage.storeTxNote(note, cb);
});
});
};
/**
* Get tx notes.
* @param {Object} opts
* @param {string} opts.txid - The txid associated with the note.
*/
WalletService.prototype.getTxNote = function(opts, cb) {
var self = this;
if (!Utils.checkRequired(opts, ['txid']))
return cb(new ClientError('Required argument missing'));
self.storage.fetchTxNote(self.walletId, opts.txid, cb);
};
/**
* removeWallet

View File

@ -22,6 +22,7 @@ var collections = {
EMAIL_QUEUE: 'email_queue',
CACHE: 'cache',
FIAT_RATES: 'fiat_rates',
TX_NOTES: 'tx_notes',
};
var Storage = function(opts) {
@ -69,6 +70,11 @@ Storage.prototype._createIndexes = function() {
this.db.collection(collections.ADDRESSES).dropIndex({
walletId: 1
});
this.db.collection(collections.TX_NOTES).dropIndex({
walletId: 1,
txid: 1,
});
};
Storage.prototype.connect = function(opts, cb) {
@ -611,6 +617,29 @@ Storage.prototype.fetchFiatRate = function(providerName, code, ts, cb) {
});
};
Storage.prototype.fetchTxNote = function(walletId, txid, cb) {
var self = this;
this.db.collection(collections.TX_NOTES).findOne({
walletId: walletId,
txid: txid,
}, function(err, result) {
if (err) return cb(err);
if (!result || !result.body) return cb();
return cb(null, Model.TxNote.fromObj(result));
});
};
Storage.prototype.storeTxNote = function(txNote, cb) {
this.db.collection(collections.TX_NOTES).update({
txid: txNote.txid,
walletId: txNote.walletId
}, txNote.toObject(), {
w: 1,
upsert: true,
}, cb);
};
Storage.prototype._dump = function(cb, fn) {
fn = fn || console.log;
cb = cb || function() {};

View File

@ -3833,6 +3833,119 @@ describe('Wallet service', function() {
});
});
});
describe.only('#editTxNote', function(done) {
var server, wallet;
beforeEach(function(done) {
helpers.createAndJoinWallet(1, 2, function(s, w) {
server = s;
wallet = w;
done();
});
});
it('should edit a note for an arbitrary txid', function(done) {
server.editTxNote({
txid: '123',
body: 'note body'
}, function(err) {
should.not.exist(err);
server.getTxNote({
txid: '123',
}, function(err, note) {
should.not.exist(err);
should.exist(note);
note.txid.should.equal('123');
note.walletId.should.equal(wallet.id);
note.body.should.equal('note body');
note.lastEditedBy.should.equal(server.copayerId);
note.createdOn.should.equal(note.lastEditedOn);
done();
});
});
});
it('should preserve last edit', function(done) {
var clock = sinon.useFakeTimers('Date');
server.editTxNote({
txid: '123',
body: 'note body'
}, function(err) {
should.not.exist(err);
server.getTxNote({
txid: '123',
}, function(err, note) {
should.not.exist(err);
should.exist(note);
note.lastEditedBy.should.equal(server.copayerId);
note.createdOn.should.equal(note.lastEditedOn);
var creator = note.lastEditedBy;
helpers.getAuthServer(wallet.copayers[1].id, function(server) {
clock.tick(60 * 1000);
server.editTxNote({
txid: '123',
body: 'edited text'
}, function(err) {
should.not.exist(err);
server.getTxNote({
txid: '123',
}, function(err, note) {
should.not.exist(err);
should.exist(note);
note.lastEditedBy.should.equal(server.copayerId);
note.createdOn.should.be.below(note.lastEditedOn);
creator.should.not.equal(note.lastEditedBy);
clock.restore();
done();
});
});
});
});
});
});
it('should edit a note for an outgoing tx and retrieve it', function(done) {
helpers.stubUtxos(server, wallet, 2, function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
message: 'some message',
feePerKb: 100e2,
};
helpers.createAndPublishTx(server, txOpts, TestData.copayers[0].privKey_1H_0, function(txp) {
should.exist(txp);
var signatures = helpers.clientSign(txp, TestData.copayers[0].xPrivKey_44H_0H_0H);
server.signTx({
txProposalId: txp.id,
signatures: signatures,
}, function(err, txp) {
should.not.exist(err);
should.exist(txp);
should.exist(txp.txid);
server.editTxNote({
txid: txp.txid,
body: 'note body'
}, function(err) {
should.not.exist(err);
server.getTx({
txProposalId: txp.id,
}, function(err, txp) {
should.not.exist(err);
should.exist(txp.note);
txp.note.txid.should.equal(txp.txid);
txp.note.walletId.should.equal(wallet.id);
txp.note.body.should.equal('note body');
txp.note.lastEditedBy.should.equal(server.copayerId);
done();
});
});
});
});
});
});
it.skip('should share notes between copayers', function(done) {});
it.skip('should be possible to remove a note', function(done) {});
});
});
describe('#getSendMaxInfo', function() {