fix tx creation
This commit is contained in:
parent
4092847ff5
commit
88fb2ad628
|
@ -477,14 +477,11 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
|
|||
|
||||
var balance = self._totalizeUtxos(utxos);
|
||||
|
||||
var txMinAmount = txp.amount + Bitcore.Transaction.FEE_PER_KB;
|
||||
if (balance.totalAmount < txMinAmount)
|
||||
return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds' + (balance.totalAmount >= txp.amount ? ' for fee' : '')));
|
||||
|
||||
if ((balance.totalAmount - balance.lockedAmount) < txMinAmount)
|
||||
if (balance.totalAmount < txp.amount)
|
||||
return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds'));
|
||||
if ((balance.totalAmount - balance.lockedAmount) < txp.amount)
|
||||
return cb(new ClientError('LOCKEDFUNDS', 'Funds are locked by pending transaction proposals'));
|
||||
|
||||
|
||||
utxos = _.reject(utxos, {
|
||||
locked: true
|
||||
});
|
||||
|
@ -493,30 +490,39 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
|
|||
var total = 0;
|
||||
var selected = [];
|
||||
var inputs = _.sortBy(utxos, 'amount');
|
||||
var bitcoreTx;
|
||||
var bitcoreTx, bitcoreError;
|
||||
|
||||
while (i < inputs.length) {
|
||||
selected.push(inputs[i]);
|
||||
total += inputs[i].satoshis;
|
||||
i++;
|
||||
|
||||
if (total >= txMinAmount) {
|
||||
if (total >= txp.amount) {
|
||||
try {
|
||||
// Check if there are enough fees
|
||||
txp.inputs = selected;
|
||||
bitcoreTx = txp.getBitcoreTx();
|
||||
txp.inputPaths = _.pluck(txp.inputs, 'path');
|
||||
txp.fee = bitcoreTx.getFee();
|
||||
return cb();
|
||||
} catch (ex) {
|
||||
if (ex.name != 'bitcore.ErrorTransactionFeeError') {
|
||||
return cb(ex);
|
||||
bitcoreError = bitcoreTx.getSerializationError({
|
||||
disableIsFullySigned: true,
|
||||
});
|
||||
if (!bitcoreError) {
|
||||
txp.inputPaths = _.pluck(txp.inputs, 'path');
|
||||
txp.fee = bitcoreTx.getFee();
|
||||
return cb();
|
||||
}
|
||||
} catch (ex) {
|
||||
return cb(ex);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
};
|
||||
|
||||
return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds for fee'));
|
||||
if (bitcoreError instanceof Bitcore.errors.Transaction.FeeError) {
|
||||
return cb(new ClientError('INSUFFICIENTFUNDS', 'Insufficient funds for fee'));
|
||||
}
|
||||
if (bitcoreError instanceof Bitcore.errors.Transaction.DustOutputs) {
|
||||
return cb(new ClientError('DUSTAMOUNT', 'Amount below dust threshold'));
|
||||
}
|
||||
|
||||
return cb(error);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -956,6 +956,22 @@ describe('Copay server', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should fail to create tx that would return change for dust amount', function(done) {
|
||||
helpers.stubUtxos(server, wallet, [1], function() {
|
||||
var fee = Bitcore.Transaction.FEE_PER_KB / 1e8;
|
||||
var change = 0.00000001;
|
||||
var amount = 1 - fee - change;
|
||||
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0);
|
||||
server.createTx(txOpts, function(err, tx) {
|
||||
should.exist(err);
|
||||
err.code.should.equal('DUSTAMOUNT');
|
||||
err.message.should.equal('Amount below dust threshold');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail with different error for insufficient funds and locked funds', function(done) {
|
||||
helpers.stubUtxos(server, wallet, [10, 10], function() {
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 11, null, TestData.copayers[0].privKey_1H_0);
|
||||
|
@ -977,20 +993,18 @@ describe('Copay server', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should fail with insufficient funds if fee is too large', function(done) {
|
||||
helpers.stubUtxos(server, wallet, 10, function() {
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 9, null, TestData.copayers[0].privKey_1H_0);
|
||||
|
||||
var txpStub = sinon.stub(TxProposal.prototype, 'getBitcoreTx').throws({
|
||||
name: 'bitcore.ErrorTransactionFeeError'
|
||||
});
|
||||
it('should create tx with 0 change output', function(done) {
|
||||
helpers.stubUtxos(server, wallet, [1], function() {
|
||||
var fee = Bitcore.Transaction.FEE_PER_KB / 1e8;
|
||||
var amount = 1 - fee;
|
||||
|
||||
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', amount, null, TestData.copayers[0].privKey_1H_0);
|
||||
server.createTx(txOpts, function(err, tx) {
|
||||
should.exist(err);
|
||||
err.code.should.equal('INSUFFICIENTFUNDS');
|
||||
err.message.should.equal('Insufficient funds for fee');
|
||||
|
||||
txpStub.restore();
|
||||
should.not.exist(err);
|
||||
should.exist(tx);
|
||||
var bitcoreTx = tx.getBitcoreTx();
|
||||
bitcoreTx.outputs.length.should.equal(1);
|
||||
bitcoreTx.outputs[0].satoshis.should.equal(tx.amount);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue