|
@ -53,20 +53,35 @@ function WalletService() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Time after which a Tx proposal can be erased by any copayer. in seconds
|
|
|
// Time after which a Tx proposal can be erased by any copayer. in seconds
|
|
|
WalletService.deleteLockTime = 24 * 3600; |
|
|
WalletService.DELETE_LOCKTIME = 24 * 3600; |
|
|
|
|
|
|
|
|
// Allowed consecutive txp rejections before backoff is applied.
|
|
|
// Allowed consecutive txp rejections before backoff is applied.
|
|
|
WalletService.backoffOffset = 3; |
|
|
WalletService.BACKOFF_OFFSET = 3; |
|
|
|
|
|
|
|
|
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
|
|
|
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
|
|
|
WalletService.backoffTimeMinutes = 2; |
|
|
WalletService.BACKOFF_TIME = 2; |
|
|
|
|
|
|
|
|
// Fund scanning parameters
|
|
|
// Fund scanning parameters
|
|
|
WalletService.scanConfig = { |
|
|
WalletService.SCAN_CONFIG = { |
|
|
SCAN_WINDOW: 20, |
|
|
scanWindow: 20, |
|
|
DERIVATION_DELAY: 10, // in milliseconds
|
|
|
derivationDelay: 10, // in milliseconds
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
WalletService.FEE_LEVELS = [{ |
|
|
|
|
|
name: 'priority', |
|
|
|
|
|
nbBlocks: 1, |
|
|
|
|
|
defaultValue: 50000 |
|
|
|
|
|
}, { |
|
|
|
|
|
name: 'normal', |
|
|
|
|
|
nbBlocks: 4, |
|
|
|
|
|
defaultValue: 20000 |
|
|
|
|
|
}, { |
|
|
|
|
|
name: 'economy', |
|
|
|
|
|
nbBlocks: 12, |
|
|
|
|
|
defaultValue: 10000 |
|
|
|
|
|
}]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Initializes global settings for all instances. |
|
|
* Initializes global settings for all instances. |
|
|
* @param {Object} opts |
|
|
* @param {Object} opts |
|
@ -810,7 +825,7 @@ WalletService.prototype.getFeeLevels = function(opts, cb) { |
|
|
if (network != 'livenet' && network != 'testnet') |
|
|
if (network != 'livenet' && network != 'testnet') |
|
|
return cb(new ClientError('Invalid network')); |
|
|
return cb(new ClientError('Invalid network')); |
|
|
|
|
|
|
|
|
var levels = WalletUtils.FEE_LEVELS; |
|
|
var levels = WalletService.FEE_LEVELS; |
|
|
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks')); |
|
|
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks')); |
|
|
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) { |
|
|
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) { |
|
|
var values = _.map(levels, function(level) { |
|
|
var values = _.map(levels, function(level) { |
|
@ -924,7 +939,7 @@ WalletService.prototype._selectTxInputs = function(txp, cb) { |
|
|
|
|
|
|
|
|
WalletService.prototype._canCreateTx = function(copayerId, cb) { |
|
|
WalletService.prototype._canCreateTx = function(copayerId, cb) { |
|
|
var self = this; |
|
|
var self = this; |
|
|
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.backoffOffset, function(err, txs) { |
|
|
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.BACKOFF_OFFSET, function(err, txs) { |
|
|
if (err) return cb(err); |
|
|
if (err) return cb(err); |
|
|
|
|
|
|
|
|
if (!txs.length) |
|
|
if (!txs.length) |
|
@ -934,7 +949,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) { |
|
|
status: 'rejected' |
|
|
status: 'rejected' |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
var exceededRejections = lastRejections.length - WalletService.backoffOffset; |
|
|
var exceededRejections = lastRejections.length - WalletService.BACKOFF_OFFSET; |
|
|
if (exceededRejections <= 0) |
|
|
if (exceededRejections <= 0) |
|
|
return cb(null, true); |
|
|
return cb(null, true); |
|
|
|
|
|
|
|
@ -942,7 +957,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) { |
|
|
var lastTxTs = txs[0].createdOn; |
|
|
var lastTxTs = txs[0].createdOn; |
|
|
var now = Math.floor(Date.now() / 1000); |
|
|
var now = Math.floor(Date.now() / 1000); |
|
|
var timeSinceLastRejection = now - lastTxTs; |
|
|
var timeSinceLastRejection = now - lastTxTs; |
|
|
var backoffTime = 60 * Math.pow(WalletService.backoffTimeMinutes, exceededRejections); |
|
|
var backoffTime = 60 * Math.pow(WalletService.BACKOFF_TIME, exceededRejections); |
|
|
|
|
|
|
|
|
if (timeSinceLastRejection <= backoffTime) |
|
|
if (timeSinceLastRejection <= backoffTime) |
|
|
log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime); |
|
|
log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime); |
|
@ -1132,7 +1147,7 @@ WalletService.prototype.removeWallet = function(opts, cb) { |
|
|
WalletService.prototype.getRemainingDeleteLockTime = function(txp) { |
|
|
WalletService.prototype.getRemainingDeleteLockTime = function(txp) { |
|
|
var now = Math.floor(Date.now() / 1000); |
|
|
var now = Math.floor(Date.now() / 1000); |
|
|
|
|
|
|
|
|
var lockTimeRemaining = txp.createdOn + WalletService.deleteLockTime - now; |
|
|
var lockTimeRemaining = txp.createdOn + WalletService.DELETE_LOCKTIME - now; |
|
|
if (lockTimeRemaining < 0) |
|
|
if (lockTimeRemaining < 0) |
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
|
|
@ -1644,7 +1659,7 @@ WalletService.prototype.scan = function(opts, cb) { |
|
|
async.mapSeries(_.range(size), function(i, next) { |
|
|
async.mapSeries(_.range(size), function(i, next) { |
|
|
setTimeout(function() { |
|
|
setTimeout(function() { |
|
|
next(null, derivator.derive()); |
|
|
next(null, derivator.derive()); |
|
|
}, WalletService.scanConfig.DERIVATION_DELAY) |
|
|
}, WalletService.SCAN_CONFIG.derivationDelay) |
|
|
}, cb); |
|
|
}, cb); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -1660,7 +1675,7 @@ WalletService.prototype.scan = function(opts, cb) { |
|
|
async.whilst(function() { |
|
|
async.whilst(function() { |
|
|
return activity; |
|
|
return activity; |
|
|
}, function(next) { |
|
|
}, function(next) { |
|
|
deriveAddresses(WalletService.scanConfig.SCAN_WINDOW, derivator, function(err, addresses) { |
|
|
deriveAddresses(WalletService.SCAN_CONFIG.scanWindow, derivator, function(err, addresses) { |
|
|
if (err) return next(err); |
|
|
if (err) return next(err); |
|
|
networkName = networkName || Bitcore.Address(addresses[0].address).toObject().network; |
|
|
networkName = networkName || Bitcore.Address(addresses[0].address).toObject().network; |
|
|
checkActivity(_.pluck(addresses, 'address'), networkName, function(err, thereIsActivity) { |
|
|
checkActivity(_.pluck(addresses, 'address'), networkName, function(err, thereIsActivity) { |
|
@ -1670,7 +1685,7 @@ WalletService.prototype.scan = function(opts, cb) { |
|
|
if (thereIsActivity) { |
|
|
if (thereIsActivity) { |
|
|
allAddresses.push(addresses); |
|
|
allAddresses.push(addresses); |
|
|
} else { |
|
|
} else { |
|
|
derivator.rewind(WalletService.scanConfig.SCAN_WINDOW); |
|
|
derivator.rewind(WalletService.SCAN_CONFIG.scanWindow); |
|
|
} |
|
|
} |
|
|
next(); |
|
|
next(); |
|
|
}); |
|
|
}); |
|
|