diff --git a/lib/server.js b/lib/server.js index 96153dc..6a7c4fe 100644 --- a/lib/server.js +++ b/lib/server.js @@ -614,8 +614,8 @@ WalletService.prototype.joinWallet = function(opts, cb) { } if (_.find(wallet.copayers, { - xPubKey: opts.xPubKey - })) return cb(Errors.COPAYER_IN_WALLET); + xPubKey: opts.xPubKey + })) return cb(Errors.COPAYER_IN_WALLET); if (wallet.copayers.length == wallet.n) return cb(Errors.WALLET_FULL); @@ -708,8 +708,8 @@ WalletService.prototype._canCreateAddress = function(ignoreMaxGap, cb) { isChange: true }), Defaults.MAX_MAIN_ADDRESS_GAP); if (latestAddresses.length < Defaults.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, { - hasActivity: true - })) return cb(null, true); + hasActivity: true + })) return cb(null, true); var bc = self._getBlockchainExplorer(latestAddresses[0].network); var activityFound = false; @@ -945,8 +945,13 @@ WalletService.prototype._totalizeUtxos = function(utxos) { WalletService.prototype._computeBytesToSendMax = function(utxos, cb) { var self = this; + var size = { + all: 0, + confirmed: 0 + }; + var unlockedUtxos = _.reject(utxos, 'locked'); - if (_.isEmpty(unlockedUtxos)) return cb(null, 0); + if (_.isEmpty(unlockedUtxos)) return cb(null, size); self.getWallet({}, function(err, wallet) { if (err) return cb(err); @@ -956,9 +961,13 @@ WalletService.prototype._computeBytesToSendMax = function(utxos, cb) { requiredSignatures: wallet.m, walletN: wallet.n, }); + + txp.inputs = unlockedUtxos; + size.all = txp.getEstimatedSize(); - var size = txp.getEstimatedSize(); + txp.inputs = _.filter(unlockedUtxos, 'confirmations'); + size.confirmed = txp.getEstimatedSize(); return cb(null, size); }); @@ -992,7 +1001,8 @@ WalletService.prototype._getBalanceFromAddresses = function(addresses, cb) { if (err) { log.error('Could not compute size of send max transaction', err); } - balance.totalBytesToSendMax = _.isNumber(size) ? size : null; + balance.totalBytesToSendMax = _.isNumber(size.all) ? size.all : null; + balance.totalBytesToSendConfirmedMax = _.isNumber(size.confirmed) ? size.confirmed : null; return cb(null, balance); }); }); diff --git a/test/integration/server.js b/test/integration/server.js index 524cd09..29c6b52 100644 --- a/test/integration/server.js +++ b/test/integration/server.js @@ -1417,6 +1417,7 @@ describe('Wallet service', function() { balance.lockedAmount.should.equal(0); balance.availableAmount.should.equal(helpers.toSatoshi(6)); balance.totalBytesToSendMax.should.equal(578); + balance.totalBytesToSendConfirmedMax.should.equal(418); balance.totalConfirmedAmount.should.equal(helpers.toSatoshi(4)); balance.lockedConfirmedAmount.should.equal(0); @@ -2563,6 +2564,7 @@ describe('Wallet service', function() { balance.lockedAmount.should.equal(0); balance.availableAmount.should.equal(helpers.toSatoshi(9)); balance.totalBytesToSendMax.should.equal(2896); + balance.totalBytesToSendConfirmedMax.should.equal(2896); var fee = parseInt((balance.totalBytesToSendMax * 10000 / 1000).toFixed(0)); var max = balance.availableAmount - fee; var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', max / 1e8, TestData.copayers[0].privKey_1H_0); @@ -2594,6 +2596,7 @@ describe('Wallet service', function() { balance.lockedAmount.should.equal(helpers.toSatoshi(4)); balance.availableAmount.should.equal(helpers.toSatoshi(5)); balance.totalBytesToSendMax.should.equal(1653); + balance.totalBytesToSendConfirmedMax.should.equal(1653); var fee = parseInt((balance.totalBytesToSendMax * 2000 / 1000).toFixed(0)); var max = balance.availableAmount - fee; var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', max / 1e8, TestData.copayers[0].privKey_1H_0, { @@ -2616,6 +2619,38 @@ describe('Wallet service', function() { }); }); + it('should be able to send max confirmed', function(done) { + helpers.stubUtxos(server, wallet, [1, 1, 'u1', 'u1'], function() { + server.getBalance({}, function(err, balance) { + should.not.exist(err); + balance.totalAmount.should.equal(helpers.toSatoshi(4)); + balance.totalConfirmedAmount.should.equal(helpers.toSatoshi(2)); + balance.lockedAmount.should.equal(0); + balance.availableAmount.should.equal(helpers.toSatoshi(4)); + balance.availableConfirmedAmount.should.equal(helpers.toSatoshi(2)); + balance.totalBytesToSendMax.should.equal(1342); + balance.totalBytesToSendConfirmedMax.should.equal(720); + var fee = parseInt((balance.totalBytesToSendConfirmedMax * 10000 / 1000).toFixed(0)); + var max = balance.availableConfirmedAmount - fee; + var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', max / 1e8, TestData.copayers[0].privKey_1H_0); + server.createTxLegacy(txOpts, function(err, tx) { + should.not.exist(err); + should.exist(tx); + tx.amount.should.equal(max); + var estimatedFee = 720 * 10000 / 1000; + tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee); + server.getBalance({}, function(err, balance) { + should.not.exist(err); + balance.lockedAmount.should.equal(helpers.toSatoshi(2)); + balance.availableConfirmedAmount.should.equal(0); + balance.availableAmount.should.equal(helpers.toSatoshi(2)); + done(); + }); + }); + }); + }); + }); + it('should not use UTXO provided in utxosToExclude option', function(done) { helpers.stubUtxos(server, wallet, [1, 2, 3], function(utxos) { var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 4.5, TestData.copayers[0].privKey_1H_0);