Browse Source

reorg tests + test feeLevel arg

activeAddress
Ivan Socolsky 9 years ago
parent
commit
ee18f7d236
No known key found for this signature in database GPG Key ID: FAECE6A05FAA4F56
  1. 823
      test/integration/server.js

823
test/integration/server.js

@ -2294,91 +2294,184 @@ describe('Wallet service', function() {
});
});
});
it('should fail to create a tx without outputs', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [],
feePerKb: 123e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
should.not.exist(tx);
err.message.should.equal('No outputs were specified');
done();
describe('Validations', function() {
it('should fail to create a tx without outputs', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [],
feePerKb: 123e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
should.not.exist(tx);
err.message.should.equal('No outputs were specified');
done();
});
});
});
});
it('should create a tx with foreign ID', function(done) {
helpers.stubUtxos(server, wallet, 2, function() {
it('should fail to create tx for invalid address', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = {
outputs: [{
toAddress: 'invalid address',
amount: 0.5e8
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
should.not.exist(tx);
// may fail due to Non-base58 character, or Checksum mismatch, or other
done();
});
});
});
it('should fail to create tx for address of different network', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = {
outputs: [{
toAddress: 'myE38JHdxmQcTJGP1ZiX4BiGhDxMJDvLJD',
amount: 0.5e8
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(tx);
should.exist(err);
err.code.should.equal('INCORRECT_ADDRESS_NETWORK');
err.message.should.equal('Incorrect address network');
done();
});
});
});
it('should fail to create tx for invalid amount', function(done) {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
amount: 0,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
should.not.exist(tx);
should.exist(err);
err.message.should.equal('Invalid amount');
done();
});
});
});
it('should return already created tx if same foreign ID is specified and tx still unpublished', function(done) {
helpers.stubUtxos(server, wallet, 2, function() {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
server.createTx(txOpts, function(err, tx) {
it.skip('should fail to specify both feeLevel & feePerKb', function(done) {
});
it('should be able to create tx with inputs argument', function(done) {
helpers.stubUtxos(server, wallet, [1, 3, 2], function(utxos) {
server.getUtxos({}, function(err, utxos) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
server.storage.fetchTxs(wallet.id, {}, function(err, txs) {
var inputs = [utxos[0], utxos[2]];
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 2.5e8,
}],
feePerKb: 100e2,
inputs: inputs,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(txs);
txs.length.should.equal(1);
should.exist(tx);
tx.inputs.length.should.equal(2);
var txids = _.pluck(tx.inputs, 'txid');
txids.should.contain(utxos[0].txid);
txids.should.contain(utxos[2].txid);
done();
});
});
});
});
it('should be able to specify change address', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function(utxos) {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8e8,
}],
feePerKb: 100e2,
changeAddress: utxos[0].address,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
var t = tx.getBitcoreTx();
t.getChangeOutput().script.toAddress().toString().should.equal(txOpts.changeAddress);
done();
});
});
});
it('should be able to specify inputs & absolute fee', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function(utxos) {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8e8,
}],
inputs: utxos,
fee: 1000e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.amount.should.equal(helpers.toSatoshi(0.8));
should.not.exist(tx.feePerKb);
tx.fee.should.equal(1000e2);
var t = tx.getBitcoreTx();
t.getFee().should.equal(1000e2);
t.getChangeOutput().satoshis.should.equal(3e8 - 0.8e8 - 1000e2);
done();
});
});
});
});
it('should return already published tx if same foreign ID is specified and tx already published', function(done) {
helpers.stubUtxos(server, wallet, [2, 2, 2], function() {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
var publishOpts = helpers.getProposalSignatureOpts(tx, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err, tx) {
describe('Foreign ID', function() {
it('should create a tx with foreign ID', function(done) {
helpers.stubUtxos(server, wallet, 2, function() {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
done();
});
});
});
it('should return already created tx if same foreign ID is specified and tx still unpublished', function(done) {
helpers.stubUtxos(server, wallet, 2, function() {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
tx.status.should.equal('pending');
server.storage.fetchTxs(wallet.id, {}, function(err, txs) {
should.not.exist(err);
should.exist(txs);
txs.length.should.equal(1);
done();
});
@ -2386,59 +2479,285 @@ describe('Wallet service', function() {
});
});
});
it('should return already published tx if same foreign ID is specified and tx already published', function(done) {
helpers.stubUtxos(server, wallet, [2, 2, 2], function() {
var txOpts = {
txProposalId: '123',
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 1e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
var publishOpts = helpers.getProposalSignatureOpts(tx, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.id.should.equal('123');
tx.status.should.equal('pending');
server.storage.fetchTxs(wallet.id, {}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(1);
done();
});
});
});
});
});
});
});
it('should be able to publish a temporary tx proposal', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
customData: 'some custom data',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
describe('Publishing', function() {
it('should be able to publish a temporary tx proposal', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
customData: 'some custom data',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
server.getPendingTxs({}, function(err, txs) {
should.exist(txp);
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.not.exist(err);
txs.length.should.equal(1);
should.exist(txs[0].proposalSignature);
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(1);
should.exist(txs[0].proposalSignature);
done();
});
});
});
});
});
it('should not be able to publish a temporary tx proposal created in a dry run', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
dryRun: true,
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.code.should.equal('TX_NOT_FOUND');
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(0);
done();
});
});
});
});
});
it('should delay NewTxProposal notification until published', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
_.pluck(notifications, 'type').should.not.contain('NewTxProposal');
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.not.exist(err);
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
_.pluck(notifications, 'type').should.contain('NewTxProposal');
done();
});
});
});
});
});
});
it('should fail to publish non-existent tx proposal', function(done) {
server.publishTx({
txProposalId: 'wrong-id',
proposalSignature: 'dummy',
}, function(err) {
should.exist(err);
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.should.be.empty;
done();
});
});
});
it('should fail to publish tx proposal with wrong signature', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
server.publishTx({
txProposalId: txp.id,
proposalSignature: 'dummy'
}, function(err) {
should.exist(err);
err.message.should.contain('Invalid proposal signature');
done();
});
});
});
});
});
it('should not be able to publish a temporary tx proposal created in a dry run', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
it('should fail to publish tx proposal not signed by the creator', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
var publishOpts = {
txProposalId: txp.id,
proposalSignature: helpers.signMessage(txp.getRawTx(), TestData.copayers[1].privKey_1H_0),
}
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.message.should.contain('Invalid proposal signature');
done();
});
});
});
});
it('should fail to publish a temporary tx proposal if utxos are unavailable', function(done) {
var txp1, txp2;
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
message: 'some message',
feePerKb: 100e2,
dryRun: true,
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.code.should.equal('TX_NOT_FOUND');
async.waterfall([
function(next) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
next();
});
},
function(next) {
server.createTx(txOpts, next);
},
function(txp, next) {
txp1 = txp;
server.createTx(txOpts, next);
},
function(txp, next) {
txp2 = txp;
should.exist(txp1);
should.exist(txp2);
var publishOpts = helpers.getProposalSignatureOpts(txp1, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, next);
},
function(txp, next) {
var publishOpts = helpers.getProposalSignatureOpts(txp2, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.code.should.equal('UNAVAILABLE_UTXOS');
next();
});
},
function(next) {
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(0);
done();
txs.length.should.equal(1);
next();
});
},
function(next) {
// A new tx proposal should use the next available UTXO
server.createTx(txOpts, next);
},
function(txp3, next) {
should.exist(txp3);
var publishOpts = helpers.getProposalSignatureOpts(txp3, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, next);
},
function(txp, next) {
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(2);
next();
});
},
], function(err) {
should.not.exist(err);
done();
});
});
});
describe.only('Fee levels', function() {
it('should create a tx specifying feeLevel', function(done) {
helpers.stubFeeLevels({
1: 40000,
2: 20000,
6: 18000,
24: 9000,
});
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feeLevel: 'economy',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
txp.amount.should.equal(helpers.toSatoshi(0.8));
txp.feePerKb.should.equal(180e2);
done();
});
});
});
it.skip('should fail if the specified fee level does not exist', function(done) {});
it.skip('should assume "normal" fee level if no feeLevel and no feePerKb/fee is specified', function(done) {});
});
it('should generate new change address for each created tx', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
@ -2499,56 +2818,28 @@ describe('Wallet service', function() {
});
});
});
it('should fail to create tx for invalid address', function(done) {
it('should fail gracefully when bitcore throws exception on raw tx creation', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = {
outputs: [{
toAddress: 'invalid address',
amount: 0.5e8
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
should.not.exist(tx);
// may fail due to Non-base58 character, or Checksum mismatch, or other
done();
var bitcoreStub = sinon.stub(Bitcore, 'Transaction');
bitcoreStub.throws({
name: 'dummy',
message: 'dummy exception'
});
});
});
it('should fail to create tx for address of different network', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = {
outputs: [{
toAddress: 'myE38JHdxmQcTJGP1ZiX4BiGhDxMJDvLJD',
amount: 0.5e8
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.5e8,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(tx);
should.exist(err);
err.code.should.equal('INCORRECT_ADDRESS_NETWORK');
err.message.should.equal('Incorrect address network');
err.message.should.equal('dummy exception');
bitcoreStub.restore();
done();
});
});
});
it('should fail to create tx for invalid amount', function(done) {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(tx);
should.exist(err);
err.message.should.equal('Invalid amount');
done();
});
});
it('should fail to create a tx exceeding max size in kb', function(done) {
var _oldDefault = Defaults.MAX_TX_SIZE_IN_KB;
Defaults.MAX_TX_SIZE_IN_KB = 1;
@ -2593,46 +2884,41 @@ describe('Wallet service', function() {
});
});
});
it('should create tx with 0 change output', function(done) {
it('should fail to create tx for dust amount in outputs', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var fee = 4100; // The exact fee of the resulting tx
var amount = 1e8 - fee;
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: amount,
amount: 20e2,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
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);
should.exist(err);
err.code.should.equal('DUST_AMOUNT');
err.message.should.equal('Amount below dust threshold');
done();
});
});
});
it('should fail gracefully when bitcore throws exception on raw tx creation', function(done) {
it('should create tx with 0 change output', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var bitcoreStub = sinon.stub(Bitcore, 'Transaction');
bitcoreStub.throws({
name: 'dummy',
message: 'dummy exception'
});
var fee = 4100; // The exact fee of the resulting tx
var amount = 1e8 - fee;
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.5e8,
amount: amount,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
err.message.should.equal('dummy exception');
bitcoreStub.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();
});
});
@ -2697,124 +2983,6 @@ describe('Wallet service', function() {
});
});
});
it('should be able to create tx with inputs argument', function(done) {
helpers.stubUtxos(server, wallet, [1, 3, 2], function(utxos) {
server.getUtxos({}, function(err, utxos) {
should.not.exist(err);
var inputs = [utxos[0], utxos[2]];
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 2.5e8,
}],
feePerKb: 100e2,
inputs: inputs,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.inputs.length.should.equal(2);
var txids = _.pluck(tx.inputs, 'txid');
txids.should.contain(utxos[0].txid);
txids.should.contain(utxos[2].txid);
done();
});
});
});
});
it('should delay NewTxProposal notification until published', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
_.pluck(notifications, 'type').should.not.contain('NewTxProposal');
var publishOpts = helpers.getProposalSignatureOpts(txp, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.not.exist(err);
server.getNotifications({}, function(err, notifications) {
should.not.exist(err);
_.pluck(notifications, 'type').should.contain('NewTxProposal');
done();
});
});
});
});
});
});
it('should fail to publish non-existent tx proposal', function(done) {
server.publishTx({
txProposalId: 'wrong-id',
proposalSignature: 'dummy',
}, function(err) {
should.exist(err);
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.should.be.empty;
done();
});
});
});
it('should fail to publish tx proposal with wrong signature', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
server.publishTx({
txProposalId: txp.id,
proposalSignature: 'dummy'
}, function(err) {
should.exist(err);
err.message.should.contain('Invalid proposal signature');
done();
});
});
});
});
it('should fail to publish tx proposal not signed by the creator', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
feePerKb: 100e2,
message: 'some message',
};
server.createTx(txOpts, function(err, txp) {
should.not.exist(err);
should.exist(txp);
var publishOpts = {
txProposalId: txp.id,
proposalSignature: helpers.signMessage(txp.getRawTx(), TestData.copayers[1].privKey_1H_0),
}
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.message.should.contain('Invalid proposal signature');
done();
});
});
});
});
it('should accept a tx proposal signed with a custom key', function(done) {
var reqPrivKey = new Bitcore.PrivateKey();
var reqPubKey = reqPrivKey.toPublicKey().toString();
@ -2864,116 +3032,6 @@ describe('Wallet service', function() {
});
});
});
it('should fail to publish a temporary tx proposal if utxos are unavailable', function(done) {
var txp1, txp2;
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8 * 1e8,
}],
message: 'some message',
feePerKb: 100e2,
};
async.waterfall([
function(next) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
next();
});
},
function(next) {
server.createTx(txOpts, next);
},
function(txp, next) {
txp1 = txp;
server.createTx(txOpts, next);
},
function(txp, next) {
txp2 = txp;
should.exist(txp1);
should.exist(txp2);
var publishOpts = helpers.getProposalSignatureOpts(txp1, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, next);
},
function(txp, next) {
var publishOpts = helpers.getProposalSignatureOpts(txp2, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, function(err) {
should.exist(err);
err.code.should.equal('UNAVAILABLE_UTXOS');
next();
});
},
function(next) {
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(1);
next();
});
},
function(next) {
// A new tx proposal should use the next available UTXO
server.createTx(txOpts, next);
},
function(txp3, next) {
should.exist(txp3);
var publishOpts = helpers.getProposalSignatureOpts(txp3, TestData.copayers[0].privKey_1H_0);
server.publishTx(publishOpts, next);
},
function(txp, next) {
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs.length.should.equal(2);
next();
});
},
], function(err) {
should.not.exist(err);
done();
});
});
it('should be able to specify change address', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function(utxos) {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8e8,
}],
feePerKb: 100e2,
changeAddress: utxos[0].address,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
var t = tx.getBitcoreTx();
t.getChangeOutput().script.toAddress().toString().should.equal(txOpts.changeAddress);
done();
});
});
});
it('should be able to specify inputs & absolute fee', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function(utxos) {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 0.8e8,
}],
inputs: utxos,
fee: 1000e2,
};
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
should.exist(tx);
tx.amount.should.equal(helpers.toSatoshi(0.8));
should.not.exist(tx.feePerKb);
tx.fee.should.equal(1000e2);
var t = tx.getBitcoreTx();
t.getFee().should.equal(1000e2);
t.getChangeOutput().satoshis.should.equal(3e8 - 0.8e8 - 1000e2);
done();
});
});
});
it('should be able to send max funds', function(done) {
helpers.stubUtxos(server, wallet, [1, 2], function() {
var txOpts = {
@ -3033,23 +3091,6 @@ describe('Wallet service', function() {
});
});
});
it('should fail to create tx for dust amount in outputs', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = {
outputs: [{
toAddress: '18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7',
amount: 20e2,
}],
feePerKb: 100e2,
};
server.createTx(txOpts, function(err, tx) {
should.exist(err);
err.code.should.equal('DUST_AMOUNT');
err.message.should.equal('Amount below dust threshold');
done();
});
});
});
});
describe('Backoff time', function(done) {

Loading…
Cancel
Save