From 65bda681d52016749b3bb420736136e7001acfac Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Fri, 20 May 2016 12:27:45 -0300 Subject: [PATCH] allow a specific change address --- lib/errors/errordefinitions.js | 1 + lib/server.js | 23 +++++++++++++++++------ test/integration/server.js | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/errors/errordefinitions.js b/lib/errors/errordefinitions.js index 62f0081..f5c8c2f 100644 --- a/lib/errors/errordefinitions.js +++ b/lib/errors/errordefinitions.js @@ -15,6 +15,7 @@ var errors = { INSUFFICIENT_FUNDS: 'Insufficient funds', INSUFFICIENT_FUNDS_FOR_FEE: 'Insufficient funds for fee', INVALID_ADDRESS: 'Invalid address', + INVALID_CHANGE_ADDRESS: 'Invalid change address', KEY_IN_COPAYER: 'Key already registered', LOCKED_FUNDS: 'Funds are locked by pending transaction proposals', HISTORY_LIMIT_EXCEEDED: 'Requested page limit is above allowed maximum', diff --git a/lib/server.js b/lib/server.js index 7c64ad3..185c963 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1871,12 +1871,13 @@ WalletService.prototype._validateAndSanitizeTxOpts = function(wallet, opts, cb) * @param {number} opts.outputs[].amount - Amount to transfer in satoshi. * @param {string} opts.outputs[].message - A message to attach to this output. * @param {string} opts.message - A message to attach to this transaction. - * @param {string} opts.feePerKb - Use an alternative fee per KB for this TX. - * @param {string} opts.sendMax - Optional. Send maximum amount of funds that make sense under the specified fee/feePerKb conditions. (defaults to false). + * @param {number} opts.feePerKb - Use an alternative fee per KB for this TX. + * @param {string} opts.changeAddress - Optional. Use this address as the change address for the tx. The address should belong to the wallet. + * @param {Boolean} opts.sendMax - Optional. Send maximum amount of funds that make sense under the specified fee/feePerKb conditions. (defaults to false). * @param {string} opts.payProUrl - Optional. Paypro URL for peers to verify TX - * @param {string} opts.excludeUnconfirmedUtxos[=false] - Optional. Do not use UTXOs of unconfirmed transactions as inputs - * @param {string} opts.validateOutputs[=true] - Optional. Perform validation on outputs. - * @param {string} opts.dryRun[=false] - Optional. Simulate the action but do not change server state. + * @param {Boolean} opts.excludeUnconfirmedUtxos[=false] - Optional. Do not use UTXOs of unconfirmed transactions as inputs + * @param {Boolean} opts.validateOutputs[=true] - Optional. Perform validation on outputs. + * @param {Boolean} opts.dryRun[=false] - Optional. Simulate the action but do not change server state. * @param {Array} opts.inputs - Optional. Inputs for this TX * @param {number} opts.fee - Optional. Use an fixed fee for this TX (only when opts.inputs is specified) * @param {Boolean} opts.noShuffleOutputs - Optional. If set, TX outputs won't be shuffled. Defaults to false @@ -1909,9 +1910,19 @@ WalletService.prototype.createTx = function(opts, cb) { }); }, function(next) { - if (!opts.sendMax) { + if (opts.sendMax) return next(); + if (opts.changeAddress) { + self.storage.fetchAddress(opts.changeAddress, function(err, address) { + if (err) return next(Errors.INVALID_CHANGE_ADDRESS); + changeAddress = address; + return next(); + }); + } else { changeAddress = wallet.createAddress(true); + return next(); } + }, + function(next) { var txOpts = { walletId: self.walletId, creatorId: self.copayerId, diff --git a/test/integration/server.js b/test/integration/server.js index 2e12885..c47b2b6 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -3138,6 +3138,25 @@ describe('Wallet service', function() { }); }); }); + 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 = {