test rejection flow
This commit is contained in:
parent
d96634f951
commit
bcdd807395
|
@ -132,21 +132,16 @@ TxProposal.prototype.getActors = function() {
|
|||
* @return {Object} type / createdOn
|
||||
*/
|
||||
TxProposal.prototype.getActionBy = function(copayerId) {
|
||||
var a = this.actions[copayerId];
|
||||
if (!a) return null;
|
||||
|
||||
return {
|
||||
type: a.type,
|
||||
createdOn: a.createdOn,
|
||||
};
|
||||
return this.actions[copayerId];
|
||||
};
|
||||
|
||||
TxProposal.prototype.addAction = function(copayerId, type, signatures, xpub) {
|
||||
TxProposal.prototype.addAction = function(copayerId, type, comment, signatures, xpub) {
|
||||
var action = new TxProposalAction({
|
||||
copayerId: copayerId,
|
||||
type: type,
|
||||
signatures: signatures,
|
||||
xpub: xpub,
|
||||
comment: comment,
|
||||
});
|
||||
this.actions[copayerId] = action;
|
||||
this._updateStatus();
|
||||
|
@ -191,19 +186,19 @@ TxProposal.prototype.sign = function(copayerId, signatures, xpub) {
|
|||
var t = this._getBitcoreTx();
|
||||
try {
|
||||
this._addSignaturesToBitcoreTx(t, signatures, xpub);
|
||||
this.addAction(copayerId, 'accept', signatures, xpub);
|
||||
this.addAction(copayerId, 'accept', null, signatures, xpub);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
TxProposal.prototype.reject = function(copayerId) {
|
||||
this.addAction(copayerId, 'reject');
|
||||
TxProposal.prototype.reject = function(copayerId, reason) {
|
||||
this.addAction(copayerId, 'reject', reason);
|
||||
};
|
||||
|
||||
TxProposal.prototype.isPending = function() {
|
||||
return !_.any(['boradcasted', 'rejected'], this.status);
|
||||
return !_.contains(['boradcasted', 'rejected'], this.status);
|
||||
};
|
||||
|
||||
TxProposal.prototype.isAccepted = function() {
|
||||
|
|
|
@ -8,6 +8,7 @@ function TxProposalAction(opts) {
|
|||
this.type = opts.type || (opts.signatures ? 'accept' : 'reject');
|
||||
this.signatures = opts.signatures;
|
||||
this.xpub = opts.xpub;
|
||||
this.comment = opts.comment;
|
||||
};
|
||||
|
||||
TxProposalAction.fromObj = function(obj) {
|
||||
|
@ -18,6 +19,7 @@ TxProposalAction.fromObj = function (obj) {
|
|||
x.type = obj.type;
|
||||
x.signatures = obj.signatures;
|
||||
x.xpub = obj.xpub;
|
||||
x.comment = obj.comment;
|
||||
|
||||
return x;
|
||||
};
|
||||
|
|
|
@ -686,7 +686,7 @@ CopayServer.prototype.rejectTx = function(opts, cb) {
|
|||
if (txp.status != 'pending')
|
||||
return cb(new ClientError('TXNOTPENDING', 'The transaction proposal is not pending'));
|
||||
|
||||
txp.reject(self.copayerId);
|
||||
txp.reject(self.copayerId, opts.reason);
|
||||
|
||||
self.storage.storeTx(self.walletId, txp, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
|
|
@ -877,6 +877,7 @@ describe('Copay server', function() {
|
|||
|
||||
server.rejectTx({
|
||||
txProposalId: txid,
|
||||
reason: 'some reason',
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
server.getPendingTxs({}, function(err, txs) {
|
||||
|
@ -887,8 +888,9 @@ describe('Copay server', function() {
|
|||
var actors = tx.getActors();
|
||||
actors.length.should.equal(1);
|
||||
actors[0].should.equal(wallet.copayers[0].id);
|
||||
tx.getActionBy(wallet.copayers[0].id).type.should.equal('reject');
|
||||
|
||||
var action = tx.getActionBy(wallet.copayers[0].id);
|
||||
action.type.should.equal('reject');
|
||||
action.comment.should.equal('some reason');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1120,14 +1122,14 @@ describe('Copay server', function() {
|
|||
});
|
||||
|
||||
describe('Tx proposal workflow', function() {
|
||||
var server, wallet, utxos;
|
||||
var server, wallet;
|
||||
beforeEach(function(done) {
|
||||
helpers.createAndJoinWallet(2, 3, function(s, w) {
|
||||
server = s;
|
||||
wallet = w;
|
||||
server.createAddress({}, function(err, address) {
|
||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(inutxos) {
|
||||
utxos = inutxos;
|
||||
helpers.createUtxos(server, wallet, _.range(1, 9), function(utxos) {
|
||||
helpers.stubBlockExplorer(server, utxos);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1135,7 +1137,6 @@ describe('Copay server', function() {
|
|||
});
|
||||
|
||||
it('other copayers should see pending proposal created by one copayer', function(done) {
|
||||
helpers.stubBlockExplorer(server, utxos);
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, 'some message', TestData.copayers[0].privKey);
|
||||
server.createTx(txOpts, function(err, txp) {
|
||||
should.not.exist(err);
|
||||
|
@ -1152,15 +1153,94 @@ describe('Copay server', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it.skip('tx proposals should not be broadcast until quorum is reached', function(done) {
|
||||
it.skip('tx proposals should not be broadcast until quorum is reached', function(done) {});
|
||||
|
||||
it('tx proposals should accept as many rejections as possible without finally rejecting', function(done) {
|
||||
var txpId;
|
||||
async.series([
|
||||
|
||||
function(next) {
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 10, 'some message', TestData.copayers[0].privKey);
|
||||
server.createTx(txOpts, function(err, txp) {
|
||||
txpId = txp.id;
|
||||
should.not.exist(err);
|
||||
should.exist.txp;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getPendingTxs({}, function(err, txps) {
|
||||
should.not.exist(err);
|
||||
txps.length.should.equal(1);
|
||||
var txp = txps[0];
|
||||
_.keys(txp.actions).should.be.empty;
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.rejectTx({
|
||||
txProposalId: txpId,
|
||||
reason: 'just because'
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getPendingTxs({}, function(err, txps) {
|
||||
should.not.exist(err);
|
||||
txps.length.should.equal(1);
|
||||
var txp = txps[0];
|
||||
txp.isPending().should.be.true;
|
||||
txp.isRejected().should.be.false;
|
||||
txp.isAccepted().should.be.false;
|
||||
_.keys(txp.actions).length.should.equal(1);
|
||||
var action = txp.actions[wallet.copayers[0].id];
|
||||
action.type.should.equal('reject');
|
||||
action.comment.should.equal('just because');
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
helpers.getAuthServer(wallet.copayers[1].id, function(server, wallet) {
|
||||
server.rejectTx({
|
||||
txProposalId: txpId,
|
||||
reason: 'some other reason'
|
||||
}, function(err) {
|
||||
should.not.exist(err);
|
||||
next();
|
||||
});
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getPendingTxs({}, function(err, txps) {
|
||||
should.not.exist(err);
|
||||
txps.length.should.equal(0);
|
||||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
server.getTx({
|
||||
id: txpId
|
||||
}, function(err, txp) {
|
||||
should.not.exist(err);
|
||||
txp.isPending().should.be.false;
|
||||
txp.isRejected().should.be.true;
|
||||
txp.isAccepted().should.be.false;
|
||||
_.keys(txp.actions).length.should.equal(2);
|
||||
next();
|
||||
});
|
||||
},
|
||||
],
|
||||
function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('tx proposals should accept as many rejections as possible without finally rejecting', function(done) {});
|
||||
|
||||
it.skip('proposal creator should be able to delete proposal if there are no other signatures', function(done) {});
|
||||
});
|
||||
|
||||
|
||||
describe('#getTxs', function() {
|
||||
var server, wallet, clock;
|
||||
|
||||
|
@ -1256,8 +1336,6 @@ describe('Copay server', function() {
|
|||
var server, wallet;
|
||||
|
||||
beforeEach(function(done) {
|
||||
if (server) return done();
|
||||
console.log('\tCreating TXS...');
|
||||
helpers.createAndJoinWallet(1, 1, function(s, w) {
|
||||
server = s;
|
||||
wallet = w;
|
||||
|
@ -1304,9 +1382,6 @@ describe('Copay server', function() {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
it('should pull the first 5 notifications after wallet creation', function(done) {
|
||||
server.getNotifications({
|
||||
minTs: 0,
|
||||
|
|
Loading…
Reference in New Issue