diff --git a/lib/server.js b/lib/server.js index e01e039..706b48b 100644 --- a/lib/server.js +++ b/lib/server.js @@ -606,6 +606,7 @@ WalletService._getCopayerHash = function(name, xPubKey, requestPubKey) { * @param {string} opts.requestPubKey - Public Key used to check requests from this copayer. * @param {string} opts.copayerSignature - S(name|xPubKey|requestPubKey). Used by other copayers to verify that the copayer joining knows the wallet secret. * @param {string} opts.customData - (optional) Custom data for this copayer. + * @param {string} opts.dryRun[=false] - (optional) Simulate the action but do not change server state. * @param {string} [opts.supportBIP44AndP2PKH = true] - Client supports BIP44 & P2PKH for joining wallets. */ WalletService.prototype.joinWallet = function(opts, cb) { @@ -1854,6 +1855,7 @@ WalletService.prototype._validateAndSanitizeTxOpts = function(wallet, opts, cb) * @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. * @returns {TxProposal} Transaction proposal. */ WalletService.prototype.createTx = function(opts, cb) { @@ -1911,10 +1913,11 @@ WalletService.prototype.createTx = function(opts, cb) { self._selectTxInputs(txp, opts.utxosToExclude, next); }, function(next) { - if (!changeAddress) return next(); + if (!changeAddress || opts.dryRun) return next(); self.storage.storeAddressAndWallet(wallet, txp.changeAddress, next); }, function(next) { + if (opts.dryRun) return next(); self.storage.storeTx(wallet.id, txp, next); }, ], function(err) { diff --git a/test/integration/server.js b/test/integration/server.js index f6f1497..371c124 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -2841,6 +2841,33 @@ describe('Wallet service', function() { }); }); + 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, + }], + message: 'some message', + customData: 'some custom data', + 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 = {