fix tests
This commit is contained in:
parent
344fc525e0
commit
5b3671b079
|
@ -64,6 +64,7 @@ TxProposal.create = function(opts) {
|
||||||
x.inputPaths = [];
|
x.inputPaths = [];
|
||||||
x.requiredSignatures = opts.requiredSignatures;
|
x.requiredSignatures = opts.requiredSignatures;
|
||||||
x.requiredRejections = opts.requiredRejections;
|
x.requiredRejections = opts.requiredRejections;
|
||||||
|
x.walletN = opts.walletN;
|
||||||
x.status = 'pending';
|
x.status = 'pending';
|
||||||
x.actions = [];
|
x.actions = [];
|
||||||
x.fee = null;
|
x.fee = null;
|
||||||
|
@ -100,6 +101,7 @@ TxProposal.fromObj = function(obj) {
|
||||||
x.inputs = obj.inputs;
|
x.inputs = obj.inputs;
|
||||||
x.requiredSignatures = obj.requiredSignatures;
|
x.requiredSignatures = obj.requiredSignatures;
|
||||||
x.requiredRejections = obj.requiredRejections;
|
x.requiredRejections = obj.requiredRejections;
|
||||||
|
x.walletN = obj.walletN;
|
||||||
x.status = obj.status;
|
x.status = obj.status;
|
||||||
x.txid = obj.txid;
|
x.txid = obj.txid;
|
||||||
x.broadcastedOn = obj.broadcastedOn;
|
x.broadcastedOn = obj.broadcastedOn;
|
||||||
|
@ -169,14 +171,14 @@ TxProposal.prototype.getRawTx = function() {
|
||||||
return t.uncheckedSerialize();
|
return t.uncheckedSerialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
TxProposal.prototype.estimateFee = function(walletN) {
|
TxProposal.prototype.estimateFee = function() {
|
||||||
// Note: found empirically based on all multisig P2SH inputs and within m & n allowed limits.
|
// Note: found empirically based on all multisig P2SH inputs and within m & n allowed limits.
|
||||||
var safetyMargin = 0.05;
|
var safetyMargin = 0.05;
|
||||||
|
|
||||||
var walletM = this.requiredSignatures;
|
var walletM = this.requiredSignatures;
|
||||||
|
|
||||||
var overhead = 4 + 4 + 9 + 9;
|
var overhead = 4 + 4 + 9 + 9;
|
||||||
var inputSize = walletM * 72 + walletN * 36 + 44;
|
var inputSize = walletM * 72 + this.walletN * 36 + 44;
|
||||||
var outputSize = 34;
|
var outputSize = 34;
|
||||||
var nbInputs = this.inputs.length;
|
var nbInputs = this.inputs.length;
|
||||||
var nbOutputs = (_.isArray(this.outputs) ? this.outputs.length : 1) + 1;
|
var nbOutputs = (_.isArray(this.outputs) ? this.outputs.length : 1) + 1;
|
||||||
|
|
|
@ -796,7 +796,7 @@ WalletService.prototype.getFeeLevels = function(opts, cb) {
|
||||||
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks'));
|
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks'));
|
||||||
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) {
|
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) {
|
||||||
var values = _.map(levels, function(level) {
|
var values = _.map(levels, function(level) {
|
||||||
var result = {
|
var result = {
|
||||||
level: level.name,
|
level: level.name,
|
||||||
};
|
};
|
||||||
if (err || feeSamples[level.nbBlocks] < 0) {
|
if (err || feeSamples[level.nbBlocks] < 0) {
|
||||||
|
@ -875,9 +875,12 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
|
||||||
if (total >= txp.getTotalAmount()) {
|
if (total >= txp.getTotalAmount()) {
|
||||||
try {
|
try {
|
||||||
txp.setInputs(selected);
|
txp.setInputs(selected);
|
||||||
|
txp.estimateFee();
|
||||||
bitcoreTx = txp.getBitcoreTx();
|
bitcoreTx = txp.getBitcoreTx();
|
||||||
bitcoreError = bitcoreTx.getSerializationError({
|
bitcoreError = bitcoreTx.getSerializationError({
|
||||||
disableIsFullySigned: true,
|
disableIsFullySigned: true,
|
||||||
|
disableSmallFees: true,
|
||||||
|
disableLargeFees: true,
|
||||||
});
|
});
|
||||||
if (!bitcoreError) {
|
if (!bitcoreError) {
|
||||||
txp.fee = bitcoreTx.getFee();
|
txp.fee = bitcoreTx.getFee();
|
||||||
|
@ -901,7 +904,6 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
WalletService.prototype._canCreateTx = function(copayerId, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.backoffOffset, function(err, txs) {
|
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.backoffOffset, function(err, txs) {
|
||||||
|
@ -972,7 +974,7 @@ WalletService.prototype.createTx = function(opts, cb) {
|
||||||
valid: false
|
valid: false
|
||||||
})) return;
|
})) return;
|
||||||
|
|
||||||
var feePerKb = opts.feePerKb || 10000;
|
var feePerKb = opts.feePerKb || WalletUtils.DEFAULT_FEE_PER_KB;
|
||||||
if (feePerKb < WalletUtils.MIN_FEE_PER_KB || feePerKb > WalletUtils.MAX_FEE_PER_KB)
|
if (feePerKb < WalletUtils.MIN_FEE_PER_KB || feePerKb > WalletUtils.MAX_FEE_PER_KB)
|
||||||
return cb(new ClientError('Invalid fee per KB value'));
|
return cb(new ClientError('Invalid fee per KB value'));
|
||||||
|
|
||||||
|
@ -1047,6 +1049,7 @@ WalletService.prototype.createTx = function(opts, cb) {
|
||||||
payProUrl: opts.payProUrl,
|
payProUrl: opts.payProUrl,
|
||||||
requiredSignatures: wallet.m,
|
requiredSignatures: wallet.m,
|
||||||
requiredRejections: Math.min(wallet.m, wallet.n - wallet.m + 1),
|
requiredRejections: Math.min(wallet.m, wallet.n - wallet.m + 1),
|
||||||
|
walletN: wallet.n,
|
||||||
excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
|
excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1516,10 +1516,10 @@ describe('Wallet service', function() {
|
||||||
}));
|
}));
|
||||||
fees.priority.feePerKB.should.equal(50000);
|
fees.priority.feePerKB.should.equal(50000);
|
||||||
should.not.exist(fees.priority.nbBlocks);
|
should.not.exist(fees.priority.nbBlocks);
|
||||||
|
|
||||||
fees.normal.feePerKB.should.equal(18000);
|
fees.normal.feePerKB.should.equal(18000);
|
||||||
fees.normal.nbBlocks.should.equal(4);
|
fees.normal.nbBlocks.should.equal(4);
|
||||||
|
|
||||||
fees.economy.feePerKB.should.equal(0);
|
fees.economy.feePerKB.should.equal(0);
|
||||||
fees.economy.nbBlocks.should.equal(12);
|
fees.economy.nbBlocks.should.equal(12);
|
||||||
done();
|
done();
|
||||||
|
@ -1613,7 +1613,8 @@ describe('Wallet service', function() {
|
||||||
tx.isAccepted().should.equal.false;
|
tx.isAccepted().should.equal.false;
|
||||||
tx.isRejected().should.equal.false;
|
tx.isRejected().should.equal.false;
|
||||||
tx.amount.should.equal(helpers.toSatoshi(80));
|
tx.amount.should.equal(helpers.toSatoshi(80));
|
||||||
tx.fee.should.equal(Bitcore.Transaction.FEE_PER_KB);
|
var estimatedFee = WalletUtils.DEFAULT_FEE_PER_KB * 400 / 1000; // fully signed tx should have about 400 bytes
|
||||||
|
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||||
server.getPendingTxs({}, function(err, txs) {
|
server.getPendingTxs({}, function(err, txs) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
txs.length.should.equal(1);
|
txs.length.should.equal(1);
|
||||||
|
@ -1836,8 +1837,8 @@ describe('Wallet service', function() {
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 3.5, null, TestData.copayers[0].privKey_1H_0);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 3.5, null, TestData.copayers[0].privKey_1H_0);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.getBitcoreTx()._estimateSize().should.be.within(1001, 1999);
|
var estimatedFee = WalletUtils.DEFAULT_FEE_PER_KB * 1300 / 1000; // fully signed tx should have about 1300 bytes
|
||||||
tx.fee.should.equal(20000);
|
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1845,16 +1846,18 @@ describe('Wallet service', function() {
|
||||||
|
|
||||||
it('should be possible to use a smaller fee', function(done) {
|
it('should be possible to use a smaller fee', function(done) {
|
||||||
helpers.stubUtxos(server, wallet, 1, function() {
|
helpers.stubUtxos(server, wallet, 1, function() {
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0, 80000);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.exist(err);
|
should.exist(err);
|
||||||
err.code.should.equal('INSUFFICIENTFUNDS');
|
err.code.should.equal('INSUFFICIENTFUNDS');
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0, 5000);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0, 5000);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
tx.fee.should.equal(5000);
|
var estimatedFee = 5000 * 400 / 1000; // fully signed tx should have about 400 bytes
|
||||||
var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey);
|
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||||
|
|
||||||
// Sign it to make sure Bitcore doesn't complain about the fees
|
// Sign it to make sure Bitcore doesn't complain about the fees
|
||||||
|
var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey);
|
||||||
server.signTx({
|
server.signTx({
|
||||||
txProposalId: tx.id,
|
txProposalId: tx.id,
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
|
@ -1881,11 +1884,11 @@ describe('Wallet service', function() {
|
||||||
|
|
||||||
it('should fail to create tx that would return change for dust amount', function(done) {
|
it('should fail to create tx that would return change for dust amount', function(done) {
|
||||||
helpers.stubUtxos(server, wallet, [1], function() {
|
helpers.stubUtxos(server, wallet, [1], function() {
|
||||||
var fee = 10000 / 1e8;
|
var fee = 4095 / 1e8; // The exact fee of the resulting tx
|
||||||
var change = 0.00000001;
|
var change = 100 / 1e8; // Below dust
|
||||||
var amount = 1 - fee - change;
|
var amount = 1 - fee - change;
|
||||||
|
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0, 10000);
|
||||||
server.createTx(txOpts, function(err, tx) {
|
server.createTx(txOpts, function(err, tx) {
|
||||||
should.exist(err);
|
should.exist(err);
|
||||||
err.code.should.equal('DUSTAMOUNT');
|
err.code.should.equal('DUSTAMOUNT');
|
||||||
|
@ -1918,7 +1921,7 @@ describe('Wallet service', function() {
|
||||||
|
|
||||||
it('should create tx with 0 change output', function(done) {
|
it('should create tx with 0 change output', function(done) {
|
||||||
helpers.stubUtxos(server, wallet, [1], function() {
|
helpers.stubUtxos(server, wallet, [1], function() {
|
||||||
var fee = Bitcore.Transaction.FEE_PER_KB / 1e8;
|
var fee = 4100 / 1e8; // The exact fee of the resulting tx
|
||||||
var amount = 1 - fee;
|
var amount = 1 - fee;
|
||||||
|
|
||||||
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0);
|
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0);
|
||||||
|
@ -2097,7 +2100,8 @@ describe('Wallet service', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(tx);
|
should.exist(tx);
|
||||||
tx.amount.should.equal(max);
|
tx.amount.should.equal(max);
|
||||||
tx.fee.should.equal(3 * 10000);
|
var estimatedFee = 2900 * 10000 / 1000; // estimated size = 2900 bytes
|
||||||
|
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||||
server.getBalance({}, function(err, balance) {
|
server.getBalance({}, function(err, balance) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
balance.lockedAmount.should.equal(helpers.toSatoshi(9));
|
balance.lockedAmount.should.equal(helpers.toSatoshi(9));
|
||||||
|
@ -2124,7 +2128,8 @@ describe('Wallet service', function() {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
should.exist(tx);
|
should.exist(tx);
|
||||||
tx.amount.should.equal(max);
|
tx.amount.should.equal(max);
|
||||||
tx.fee.should.equal(2 * 2000);
|
var estimatedFee = 1650 * 2000 / 1000; // estimated size = 1650 bytes
|
||||||
|
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
|
||||||
server.getBalance({}, function(err, balance) {
|
server.getBalance({}, function(err, balance) {
|
||||||
should.not.exist(err);
|
should.not.exist(err);
|
||||||
balance.lockedAmount.should.equal(helpers.toSatoshi(9));
|
balance.lockedAmount.should.equal(helpers.toSatoshi(9));
|
||||||
|
|
|
@ -197,9 +197,11 @@ var aTXP = function(type) {
|
||||||
"inputPaths": ["m/2147483647/0/1"],
|
"inputPaths": ["m/2147483647/0/1"],
|
||||||
"requiredSignatures": 2,
|
"requiredSignatures": 2,
|
||||||
"requiredRejections": 1,
|
"requiredRejections": 1,
|
||||||
|
"walletN": 2,
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"outputOrder": [0, 1],
|
"outputOrder": [0, 1],
|
||||||
|
"fee": 10000,
|
||||||
};
|
};
|
||||||
if (type == TxProposal.Types.MULTIPLEOUTPUTS) {
|
if (type == TxProposal.Types.MULTIPLEOUTPUTS) {
|
||||||
txp.outputs = [{
|
txp.outputs = [{
|
||||||
|
|
Loading…
Reference in New Issue