allow for external use of getSendMaxInfo + refactor createTx
This commit is contained in:
parent
b2fc191f54
commit
d23788100e
138
lib/server.js
138
lib/server.js
|
@ -1153,6 +1153,7 @@ WalletService.prototype.getBalance = function(opts, cb) {
|
|||
* @param {Object} opts
|
||||
* @param {string} opts.feePerKb - The fee per KB used to compute the TX.
|
||||
* @param {string} opts.excludeUnconfirmedUtxos[=false] - Optional. Do not use UTXOs of unconfirmed transactions as inputs
|
||||
* @param {string} opts.returnInputs[=false] - Optional. Return the list of UTXOs that would be included in the tx.
|
||||
* @returns {Object} sendMaxInfo
|
||||
*/
|
||||
WalletService.prototype.getSendMaxInfo = function(opts, cb) {
|
||||
|
@ -1209,7 +1210,7 @@ WalletService.prototype.getSendMaxInfo = function(opts, cb) {
|
|||
info.size = txp.getEstimatedSize();
|
||||
info.fee = txp.getEstimatedFee();
|
||||
info.amount = _.sum(txp.inputs, 'satoshis') - info.fee;
|
||||
info.inputs = txp.inputs;
|
||||
if (opts.returnInputs) info.inputs = txp.inputs;
|
||||
|
||||
return cb(null, info);
|
||||
});
|
||||
|
@ -1785,20 +1786,78 @@ WalletService.prototype.createTxLegacy = function(opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
WalletService.prototype._doCreateTx = function(opts, cb) {
|
||||
WalletService.prototype._validateAndSanitizeTxOpts = function(wallet, opts, cb) {
|
||||
var self = this;
|
||||
|
||||
if (!Utils.checkRequired(opts, ['outputs']))
|
||||
return cb(new ClientError('Required argument missing'));
|
||||
async.series([
|
||||
|
||||
// feePerKb is required unless inputs & fee are specified
|
||||
if (!_.isNumber(opts.feePerKb) && !(opts.inputs && _.isNumber(opts.fee)))
|
||||
return cb(new ClientError('Required argument missing'));
|
||||
function(next) {
|
||||
if (!Utils.checkRequired(opts, ['outputs']))
|
||||
return next(new ClientError('Required argument missing'));
|
||||
next();
|
||||
},
|
||||
function(next) {
|
||||
// feePerKb is required unless inputs & fee are specified
|
||||
if (!_.isNumber(opts.feePerKb) && !(opts.inputs && _.isNumber(opts.fee)))
|
||||
return next(new ClientError('Required argument missing'));
|
||||
|
||||
if (_.isNumber(opts.feePerKb)) {
|
||||
if (opts.feePerKb < Defaults.MIN_FEE_PER_KB || opts.feePerKb > Defaults.MAX_FEE_PER_KB)
|
||||
return cb(new ClientError('Invalid fee per KB'));
|
||||
}
|
||||
if (_.isNumber(opts.feePerKb)) {
|
||||
if (opts.feePerKb < Defaults.MIN_FEE_PER_KB || opts.feePerKb > Defaults.MAX_FEE_PER_KB)
|
||||
return next(new ClientError('Invalid fee per KB'));
|
||||
}
|
||||
next();
|
||||
},
|
||||
function(next) {
|
||||
if (!opts.sendMax) return next();
|
||||
if (!_.isArray(opts.outputs) || opts.outputs.length > 1) {
|
||||
return next(new ClientError('Only one output allowed when sendMax is specified'));
|
||||
}
|
||||
if (_.isNumber(opts.outputs[0].amount))
|
||||
return next(new ClientError('Amount is not allowed when sendMax is specified'));
|
||||
if (_.isNumber(opts.fee))
|
||||
return next(new ClientError('Fee is not allowed when sendMax is specified (use feePerKb instead)'));
|
||||
|
||||
self.getSendMaxInfo({
|
||||
feePerKb: opts.feePerKb || Defaults.DEFAULT_FEE_PER_KB,
|
||||
excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
if (err) return next(err);
|
||||
opts.outputs[0].amount = info.amount;
|
||||
opts.inputs = info.inputs;
|
||||
return next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
if (opts.validateOutputs === false) return next();
|
||||
var validationError = self._validateOutputs(opts, wallet);
|
||||
if (validationError) {
|
||||
return next(validationError);
|
||||
}
|
||||
next();
|
||||
},
|
||||
], cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new transaction proposal.
|
||||
* @param {Object} opts
|
||||
* @param {Array} opts.outputs - List of outputs.
|
||||
* @param {string} opts.outputs[].toAddress - Destination address.
|
||||
* @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 {Array} opts.inputs - Optional. Inputs for this TX
|
||||
* @param {string} opts.fee - Optional. Use an alternative fee for this TX (mutually exclusive with feePerKb)
|
||||
* @param {string} opts.feePerKb - Optional. Use an alternative fee per KB for this TX (mutually exclusive with fee)
|
||||
* @param {string} 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.
|
||||
* @returns {TxProposal} Transaction proposal.
|
||||
*/
|
||||
WalletService.prototype.createTx = function(opts, cb) {
|
||||
var self = this;
|
||||
|
||||
self._runLocked(cb, function(cb) {
|
||||
|
||||
|
@ -1813,17 +1872,13 @@ WalletService.prototype._doCreateTx = function(opts, cb) {
|
|||
next();
|
||||
});
|
||||
},
|
||||
function(next) {
|
||||
self._validateAndSanitizeTxOpts(wallet, opts, next);
|
||||
},
|
||||
function(next) {
|
||||
self._canCreateTx(function(err, canCreate) {
|
||||
if (err) return next(err);
|
||||
if (!canCreate) return next(Errors.TX_CANNOT_CREATE);
|
||||
|
||||
if (opts.validateOutputs !== false) {
|
||||
var validationError = self._validateOutputs(opts, wallet);
|
||||
if (validationError) {
|
||||
return next(validationError);
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
@ -1869,53 +1924,6 @@ WalletService.prototype._doCreateTx = function(opts, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new transaction proposal.
|
||||
* @param {Object} opts
|
||||
* @param {Array} opts.outputs - List of outputs.
|
||||
* @param {string} opts.outputs[].toAddress - Destination address.
|
||||
* @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 {Array} opts.inputs - Optional. Inputs for this TX
|
||||
* @param {string} opts.fee - Optional. Use an alternative fee for this TX (mutually exclusive with feePerKb)
|
||||
* @param {string} opts.feePerKb - Optional. Use an alternative fee per KB for this TX (mutually exclusive with fee)
|
||||
* @param {string} 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.
|
||||
* @returns {TxProposal} Transaction proposal.
|
||||
*/
|
||||
WalletService.prototype.createTx = function(opts, cb) {
|
||||
var self = this;
|
||||
|
||||
opts = opts || [];
|
||||
async.series([
|
||||
|
||||
function(next) {
|
||||
if (!opts.sendMax) return next();
|
||||
if (!_.isArray(opts.outputs) || opts.outputs.length > 1) {
|
||||
return next(new ClientError('Only one output allowed when sendMax is specified'));
|
||||
}
|
||||
if (_.isNumber(opts.outputs[0].amount))
|
||||
return next(new ClientError('Amount is not allowed when sendMax is specified'));
|
||||
if (_.isNumber(opts.fee))
|
||||
return next(new ClientError('Fee is not allowed when sendMax is specified (use feePerKb instead)'));
|
||||
|
||||
self.getSendMaxInfo(opts, function(err, info) {
|
||||
if (err) return next(err);
|
||||
opts.outputs[0].amount = info.amount;
|
||||
opts.inputs = info.inputs;
|
||||
return next();
|
||||
});
|
||||
},
|
||||
], function(err) {
|
||||
if (err) return cb(err);
|
||||
self._doCreateTx(opts, cb);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
WalletService.prototype._verifyRequestPubKey = function(requestPubKey, signature, xPubKey) {
|
||||
var pub = (new Bitcore.HDPublicKey(xPubKey)).derive(Constants.PATHS.REQUEST_KEY_AUTH).publicKey;
|
||||
return Utils.verifyMessage(requestPubKey, signature, pub.toString());
|
||||
|
|
|
@ -3653,6 +3653,7 @@ describe('Wallet service', function() {
|
|||
it('should be able to get send max info on empty wallet', function(done) {
|
||||
server.getSendMaxInfo({
|
||||
feePerKb: 10000,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3667,6 +3668,7 @@ describe('Wallet service', function() {
|
|||
helpers.stubUtxos(server, wallet, [0.1, 0.2, 0.3, 0.4], function() {
|
||||
server.getSendMaxInfo({
|
||||
feePerKb: 10000,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3683,6 +3685,7 @@ describe('Wallet service', function() {
|
|||
server.getSendMaxInfo({
|
||||
feePerKb: 10000,
|
||||
excludeUnconfirmedUtxos: true,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3707,6 +3710,7 @@ describe('Wallet service', function() {
|
|||
server.getSendMaxInfo({
|
||||
feePerKb: 10000,
|
||||
excludeUnconfirmedUtxos: true,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3723,6 +3727,7 @@ describe('Wallet service', function() {
|
|||
helpers.stubUtxos(server, wallet, ['u0.1', 0.2, 0.3, 0.4, 0.000001, 0.0002, 0.0003], function() {
|
||||
server.getSendMaxInfo({
|
||||
feePerKb: 0.001e8,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3732,6 +3737,7 @@ describe('Wallet service', function() {
|
|||
info.amount.should.equal(1e8 - info.fee);
|
||||
server.getSendMaxInfo({
|
||||
feePerKb: 0.0001e8,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
@ -3750,6 +3756,7 @@ describe('Wallet service', function() {
|
|||
helpers.stubUtxos(server, wallet, _.range(1, 10, 0), function() {
|
||||
server.getSendMaxInfo({
|
||||
feePerKb: 10000,
|
||||
returnInputs: true,
|
||||
}, function(err, info) {
|
||||
should.not.exist(err);
|
||||
should.exist(info);
|
||||
|
|
Loading…
Reference in New Issue