|
|
@ -605,13 +605,14 @@ WalletService.prototype.verifyMessageSignature = function(opts, cb) { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
WalletService.prototype._getBlockchainExplorer = function(provider, network) { |
|
|
|
WalletService.prototype._getBlockchainExplorer = function(network) { |
|
|
|
if (!this.blockchainExplorer) { |
|
|
|
var opts = {}; |
|
|
|
if (this.blockchainExplorerOpts && this.blockchainExplorerOpts[network]) { |
|
|
|
opts = this.blockchainExplorerOpts[network]; |
|
|
|
} |
|
|
|
opts.provider = provider; |
|
|
|
// TODO: provider should be configurable
|
|
|
|
opts.provider = 'insight'; |
|
|
|
opts.network = network; |
|
|
|
this.blockchainExplorer = new BlockchainExplorer(opts); |
|
|
|
} |
|
|
@ -636,7 +637,7 @@ WalletService.prototype._getUtxos = function(cb) { |
|
|
|
var addressToPath = _.indexBy(addresses, 'address'); // TODO : check performance
|
|
|
|
var networkName = Bitcore.Address(addressStrs[0]).toObject().network; |
|
|
|
|
|
|
|
var bc = self._getBlockchainExplorer('insight', networkName); |
|
|
|
var bc = self._getBlockchainExplorer(networkName); |
|
|
|
bc.getUnspentUtxos(addressStrs, function(err, inutxos) { |
|
|
|
if (err) { |
|
|
|
log.error('Could not fetch unspent outputs', err); |
|
|
@ -765,6 +766,86 @@ WalletService.prototype.getBalance = function(opts, cb) { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
WalletService.prototype._sampleFeeLevels = function(network, points, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
// TODO: cache blockexplorer data
|
|
|
|
var bc = self._getBlockchainExplorer(network); |
|
|
|
async.map(points, function(p, next) { |
|
|
|
bc.estimateFee(p, function(err, result) { |
|
|
|
if (err) { |
|
|
|
log.error('Error estimating fee', err); |
|
|
|
return next(err); |
|
|
|
} |
|
|
|
var feePerKB = _.isObject(result) ? +(result.feePerKB) : -1; |
|
|
|
if (feePerKB < 0) { |
|
|
|
log.warn('Could not compute fee estimation (nbBlocks=' + p + ')'); |
|
|
|
} |
|
|
|
return next(null, [p, feePerKB * 1e8]); |
|
|
|
}); |
|
|
|
}, function(err, results) { |
|
|
|
if (err) return cb(err); |
|
|
|
return cb(null, _.zipObject(results)); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns fee levels for the current state of the network. |
|
|
|
* @param {Object} opts |
|
|
|
* @param {string} [opts.network = 'livenet'] - The Bitcoin network to estimate fee levels from. |
|
|
|
* @returns {Object} feeLevels - A list of fee levels & associated amount per kB in satoshi. |
|
|
|
*/ |
|
|
|
WalletService.prototype.getFeeLevels = function(opts, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
opts = opts || {}; |
|
|
|
|
|
|
|
var network = opts.network || 'livenet'; |
|
|
|
if (network != 'livenet' && network != 'testnet') |
|
|
|
return cb(new ClientError('Invalid network')); |
|
|
|
|
|
|
|
var levels = [{ |
|
|
|
name: 'emergency', |
|
|
|
nbBlocks: 1, |
|
|
|
modifier: 1.5, |
|
|
|
defaultValue: 50000 |
|
|
|
}, { |
|
|
|
name: 'priority', |
|
|
|
nbBlocks: 1, |
|
|
|
modifier: 1, |
|
|
|
defaultValue: 20000 |
|
|
|
}, { |
|
|
|
name: 'normal', |
|
|
|
nbBlocks: 3, |
|
|
|
modifier: 1, |
|
|
|
defaultValue: 10000 |
|
|
|
}, { |
|
|
|
name: 'economy', |
|
|
|
nbBlocks: 10, |
|
|
|
modifier: 1, |
|
|
|
defaultValue: 5000 |
|
|
|
}, ]; |
|
|
|
|
|
|
|
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks')); |
|
|
|
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) { |
|
|
|
var values = _.map(levels, function(level) { |
|
|
|
var feePerKB; |
|
|
|
if (err) { |
|
|
|
feePerKB = level.defaultValue; |
|
|
|
} else { |
|
|
|
var sample = feeSamples[level.nbBlocks]; |
|
|
|
feePerKB = (sample < 0) ? level.defaultValue : sample * level.modifier; |
|
|
|
} |
|
|
|
return { |
|
|
|
level: level.name, |
|
|
|
feePerKB: feePerKB, |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
return cb(null, values); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
WalletService.prototype._selectTxInputs = function(txp, cb) { |
|
|
|
var self = this; |
|
|
|
|
|
|
@ -1107,7 +1188,7 @@ WalletService.prototype._broadcastTx = function(txp, cb) { |
|
|
|
} catch (ex) { |
|
|
|
return cb(ex); |
|
|
|
} |
|
|
|
var bc = this._getBlockchainExplorer('insight', txp.getNetworkName()); |
|
|
|
var bc = this._getBlockchainExplorer(txp.getNetworkName()); |
|
|
|
bc.broadcast(raw, function(err, txid) { |
|
|
|
if (err) { |
|
|
|
log.error('Could not broadcast transaction', err); |
|
|
@ -1119,7 +1200,7 @@ WalletService.prototype._broadcastTx = function(txp, cb) { |
|
|
|
|
|
|
|
WalletService.prototype._checkTxInBlockchain = function(txp, cb) { |
|
|
|
var tx = txp.getBitcoreTx(); |
|
|
|
var bc = this._getBlockchainExplorer('insight', txp.getNetworkName()); |
|
|
|
var bc = this._getBlockchainExplorer(txp.getNetworkName()); |
|
|
|
bc.getTransaction(tx.id, function(err, tx) { |
|
|
|
if (err) { |
|
|
|
log.error('Could not get transaction info', err); |
|
|
@ -1507,7 +1588,7 @@ WalletService.prototype.getTxHistory = function(opts, cb) { |
|
|
|
var addressStrs = _.pluck(addresses, 'address'); |
|
|
|
var networkName = Bitcore.Address(addressStrs[0]).toObject().network; |
|
|
|
|
|
|
|
var bc = self._getBlockchainExplorer('insight', networkName); |
|
|
|
var bc = self._getBlockchainExplorer(networkName); |
|
|
|
async.parallel([ |
|
|
|
|
|
|
|
function(next) { |
|
|
@ -1561,7 +1642,7 @@ WalletService.prototype.scan = function(opts, cb) { |
|
|
|
}; |
|
|
|
|
|
|
|
function checkActivity(addresses, networkName, cb) { |
|
|
|
var bc = self._getBlockchainExplorer('insight', networkName); |
|
|
|
var bc = self._getBlockchainExplorer(networkName); |
|
|
|
bc.getAddressActivity(addresses, cb); |
|
|
|
}; |
|
|
|
|
|
|
|