edit/retrieve notes + tests
This commit is contained in:
parent
5ca8663c96
commit
5abe6fac51
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {};
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue