@ -8,6 +8,7 @@ var config = require('../config');
log . debug = log . verbose ;
log . disableColor ( ) ;
var EmailValidator = require ( 'email-validator' ) ;
var Stringify = require ( 'json-stable-stringify' ) ;
@ -272,6 +273,28 @@ WalletService.prototype._runLocked = function(cb, task) {
this . lock . runLocked ( this . walletId , cb , task ) ;
} ;
WalletService . prototype . logi = function ( ) {
if ( ! this ) return log . info . apply ( this , arguments ) ;
if ( ! this . walletId ) return log . info . apply ( this , arguments ) ;
var args = [ ] . slice . call ( arguments ) ;
args . unshift ( '<' + this . walletId + '>' ) ;
log . info . apply ( this , args ) ;
} ;
WalletService . prototype . logw = function ( ) {
if ( ! this ) return log . info . apply ( this , arguments ) ;
if ( ! this . walletId ) return log . info . apply ( this , arguments ) ;
var args = [ ] . slice . call ( arguments ) ;
args . unshift ( '<' + this . walletId + '>' ) ;
log . info . apply ( this , args ) ;
} ;
WalletService . prototype . login = function ( opts , cb ) {
var self = this ;
@ -381,7 +404,7 @@ WalletService.prototype.createWallet = function(opts, cb) {
addressType : addressType ,
} ) ;
self . storage . storeWallet ( wallet , function ( err ) {
log . debug ( 'Wallet created' , wallet . id , opts . network ) ;
self . logi ( 'Wallet created' , wallet . id , opts . network ) ;
newWallet = wallet ;
return acb ( err ) ;
} ) ;
@ -597,7 +620,7 @@ WalletService.prototype._notify = function(type, data, opts, cb) {
}
opts = opts || { } ;
log . debug ( 'Notification' , type , data ) ;
//self.logi('Notification', type);
cb = cb || function ( ) { } ;
@ -1068,7 +1091,7 @@ WalletService.prototype._getBlockchainExplorer = function(coin, network) {
try {
bc = new BlockchainExplorer ( opts ) ;
} catch ( ex ) {
log . warn ( 'Could not instantiate blockchain explorer' , ex ) ;
this . logw ( 'Could not instantiate blockchain explorer' , ex ) ;
}
return bc ;
} ;
@ -1082,6 +1105,9 @@ WalletService.prototype._getUtxos = function(coin, addresses, cb) {
var bc = self . _ getBlockchainExplorer ( coin , networkName ) ;
if ( ! bc ) return cb ( new Error ( 'Could not get blockchain explorer instance' ) ) ;
self . logi ( '' , 'Querying utxos: %s addrs' , addresses . length ) ;
bc . getUtxos ( addresses , function ( err , utxos ) {
if ( err ) return cb ( err ) ;
@ -1260,7 +1286,7 @@ WalletService.prototype._getBalanceFromAddresses = function(opts, cb, i) {
self . storage . storeBalanceCache ( self . walletId , opts . addresses , balance , function ( err ) {
if ( err )
log . warn ( 'Could not save cache:' , err ) ;
self . logw ( 'Could not save cache:' , err ) ;
return cb ( null , balance ) ;
} ) ;
@ -1272,7 +1298,7 @@ WalletService.prototype._getBalanceFromAddresses = function(opts, cb, i) {
if ( err ) return cb ( err ) ;
if ( cache ) {
log . info ( 'Using UTXO Cache' ) ;
self . logi ( 'Using UTXO Cache' ) ;
return cb ( null , cache , true ) ;
}
@ -1313,7 +1339,7 @@ WalletService.prototype._getBalanceOneStep = function(opts, cb) {
if ( err ) return cb ( err ) ;
if ( addresses . length == opts . alreadyQueriedLength ) {
log . info ( 'Query Skipped, all active addresses' ) ;
self . logi ( 'Query Skipped, all active addresses' ) ;
return cb ( null , null , true ) ;
}
@ -1328,7 +1354,7 @@ WalletService.prototype._getBalanceOneStep = function(opts, cb) {
var withBalance = _ . map ( balance . byAddress , 'address' )
self . storage . storeAddressesWithBalance ( self . walletId , withBalance , function ( err ) {
if ( err ) {
log . warn ( 'Could not update wallet cache' , err ) ;
self . logw ( 'Could not update wallet cache' , err ) ;
}
return cb ( null , balance , cacheUsed ) ;
} ) ;
@ -1342,7 +1368,7 @@ WalletService.prototype._getActiveAddresses = function(cb) {
self . storage . fetchAddressesWithBalance ( self . walletId , function ( err , addressesWB ) {
if ( err ) {
log . warn ( 'Could not fetch active addresses from cache' , err ) ;
self . logw ( 'Could not fetch active addresses from cache' , err ) ;
return cb ( ) ;
}
if ( ! _ . isArray ( addressesWB ) )
@ -1364,7 +1390,7 @@ WalletService.prototype._checkAndUpdateAddressCount = function(twoStepCache, cb)
var self = this ;
if ( twoStepCache . addressCount > Defaults . TWO_STEP_BALANCE_THRESHOLD ) {
log . info ( 'Not counting addresses for ' + self . walletId ) ;
self . logi ( 'Not counting addresses' ) ;
return cb ( null , true ) ;
}
@ -1424,7 +1450,7 @@ WalletService.prototype.getBalance = function(opts, cb, i) {
if ( ! _ . isArray ( activeAddresses ) ) {
return self . _ getBalanceOneStep ( opts , cb ) ;
} else {
log . debug ( 'Requesting partial balance for ' + activeAddresses . length + ' addresses' ) ;
self . logi ( 'Requesting partial balance for ' + activeAddresses . length + ' addresses' ) ;
self . _ getBalanceFromAddresses ( {
coin : opts . coin ,
@ -1436,13 +1462,13 @@ WalletService.prototype.getBalance = function(opts, cb, i) {
var now = Math . floor ( Date . now ( ) / 1000 ) ;
if ( twoStepCache . lastEmpty > now - Defaults . TWO_STEP_INACTIVE_CLEAN_DURATION_MIN * 60 ) {
log . debug ( 'Not running the FULL balance query due to TWO_STEP_INACTIVE_CLEAN_DURATION_MIN ' ) ;
self . logi ( 'Not running the FULL balance query due to TWO_STEP_INACTIVE_CLEAN_DURATION_MIN ' ) ;
return ;
}
setTimeout ( function ( ) {
log . debug ( 'Running full balance query' ) ;
self . logi ( 'Running full balance query' ) ;
opts . alreadyQueriedLength = activeAddresses . length ;
opts . fastCache = Defaults . BALANCE_CACHE_DURATION ;
@ -1450,7 +1476,7 @@ WalletService.prototype.getBalance = function(opts, cb, i) {
self . _ getBalanceOneStep ( opts , function ( err , fullBalance , skipped ) {
if ( err ) return ;
if ( ! skipped && ! _ . isEqual ( partialBalance , fullBalance ) ) {
log . info ( 'Balance in active addresses differs from final balance' ) ;
self . logi ( 'Balance in active addresses differs from final balance' ) ;
self . _ notify ( 'BalanceUpdated' , fullBalance , {
isGlobal : true
} ) ;
@ -1499,7 +1525,6 @@ WalletService.prototype.getSendMaxInfo = function(opts, cb) {
return cb ( new ClientError ( 'Only one of feeLevel/feePerKb can be specified' ) ) ;
if ( feeArgs == 0 ) {
log . debug ( 'No fee provided, using "normal" fee level' ) ;
opts . feeLevel = 'normal' ;
}
@ -1606,7 +1631,7 @@ WalletService.prototype._sampleFeeLevels = function(coin, network, points, cb) {
if ( ! bc ) return cb ( new Error ( 'Could not get blockchain explorer instance' ) ) ;
bc . estimateFee ( points , function ( err , result ) {
if ( err ) {
log . error ( 'Error estimating fee' , err ) ;
self . logw ( 'Error estimating fee' , err ) ;
return cb ( err ) ;
}
@ -1620,7 +1645,7 @@ WalletService.prototype._sampleFeeLevels = function(coin, network, points, cb) {
} ) ) ;
if ( failed . length ) {
var logger = network == 'livenet' ? log . warn : log . debug ;
var logger = network == 'livenet' ? self . logw : self . logi ;
logger ( 'Could not compute fee estimation in ' + network + ': ' + failed . join ( ', ' ) + ' blocks.' ) ;
}
@ -1708,6 +1733,7 @@ WalletService.prototype._estimateFee = function(txp) {
} ;
WalletService . prototype . _ checkTx = function ( txp ) {
var self = this ;
var bitcoreError ;
var serializationOpts = {
@ -1726,7 +1752,7 @@ WalletService.prototype._checkTx = function(txp) {
txp . fee = bitcoreTx . getFee ( ) ;
}
} catch ( ex ) {
log . error ( 'Error building Bitcore transaction' , ex ) ;
self . logw ( 'Error building Bitcore transaction' , ex ) ;
return ex ;
}
@ -1782,16 +1808,16 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
var netValueInUtxos = totalValueInUtxos - baseTxpFee - ( utxos . length * feePerInput ) ;
if ( totalValueInUtxos < txpAmount ) {
log . debug ( 'Total value in all utxos (' + Utils . formatAmountInBtc ( totalValueInUtxos ) + ') is insufficient to cover for txp amount (' + Utils . formatAmountInBtc ( txpAmount ) + ')' ) ;
self . logi ( 'Total value in all utxos (' + Utils . formatAmountInBtc ( totalValueInUtxos ) + ') is insufficient to cover for txp amount (' + Utils . formatAmountInBtc ( txpAmount ) + ')' ) ;
return cb ( Errors . INSUFFICIENT_FUNDS ) ;
}
if ( netValueInUtxos < txpAmount ) {
log . debug ( 'Value after fees in all utxos (' + Utils . formatAmountInBtc ( netValueInUtxos ) + ') is insufficient to cover for txp amount (' + Utils . formatAmountInBtc ( txpAmount ) + ')' ) ;
self . logi ( 'Value after fees in all utxos (' + Utils . formatAmountInBtc ( netValueInUtxos ) + ') is insufficient to cover for txp amount (' + Utils . formatAmountInBtc ( txpAmount ) + ')' ) ;
return cb ( Errors . INSUFFICIENT_FUNDS_FOR_FEE ) ;
}
var bigInputThreshold = txpAmount * Defaults . UTXO_SELECTION_MAX_SINGLE_UTXO_FACTOR + ( baseTxpFee + feePerInput ) ;
log . debug ( 'Big input threshold ' + Utils . formatAmountInBtc ( bigInputThreshold ) ) ;
self . logi ( 'Big input threshold ' + Utils . formatAmountInBtc ( bigInputThreshold ) ) ;
var partitions = _ . partition ( utxos , function ( utxo ) {
return utxo . satoshis > bigInputThreshold ;
@ -1802,8 +1828,8 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
return - utxo . satoshis ;
} ) ;
log . debug ( 'Considering ' + bigInputs . length + ' big inputs (' + Utils . formatUtxos ( bigInputs ) + ')' ) ;
log . debug ( 'Considering ' + smallInputs . length + ' small inputs (' + Utils . formatUtxos ( smallInputs ) + ')' ) ;
//log.debug('Considering ' + bigInputs.length + ' big inputs (' + Utils.formatUtxos(bigInputs) + ')');
//log.debug('Considering ' + smallInputs.length + ' small inputs (' + Utils.formatUtxos(smallInputs) + ')');
var total = 0 ;
var netTotal = - baseTxpFee ;
@ -1812,11 +1838,11 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
var error ;
_ . each ( smallInputs , function ( input , i ) {
log . debug ( 'Input #' + i + ': ' + Utils . formatUtxos ( input ) ) ;
//log.debug('Input #' + i + ': ' + Utils.formatUtxos(input));
var netInputAmount = input . satoshis - feePerInput ;
log . debug ( 'The input contributes ' + Utils . formatAmountInBtc ( netInputAmount ) ) ;
//log.debug('The input contributes ' + Utils.formatAmountInBtc(netInputAmount));
selected . push ( input ) ;
@ -1826,45 +1852,45 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
var txpSize = baseTxpSize + selected . length * sizePerInput ;
fee = Math . round ( baseTxpFee + selected . length * feePerInput ) ;
log . debug ( 'Tx size: ' + Utils . formatSize ( txpSize ) + ', Tx fee: ' + Utils . formatAmountInBtc ( fee ) ) ;
//log.debug('Tx size: ' + Utils.formatSize(txpSize) + ', Tx fee: ' + Utils.formatAmountInBtc(fee));
var feeVsAmountRatio = fee / txpAmount ;
var amountVsUtxoRatio = netInputAmount / txpAmount ;
log . debug ( 'Fee/Tx amount: ' + Utils . formatRatio ( feeVsAmountRatio ) + ' (max: ' + Utils . formatRatio ( Defaults . UTXO_SELECTION_MAX_FEE_VS_TX_AMOUNT_FACTOR ) + ')' ) ;
log . debug ( 'Tx amount/Input amount:' + Utils . formatRatio ( amountVsUtxoRatio ) + ' (min: ' + Utils . formatRatio ( Defaults . UTXO_SELECTION_MIN_TX_AMOUNT_VS_UTXO_FACTOR ) + ')' ) ;
//log.debug('Fee/Tx amount: ' + Utils.formatRatio(feeVsAmountRatio) + ' (max: ' + Utils.formatRatio(Defaults.UTXO_SELECTION_MAX_FEE_VS_TX_AMOUNT_FACTOR) + ')');
//log.debug('Tx amount/Input amount:' + Utils.formatRatio(amountVsUtxoRatio) + ' (min: ' + Utils.formatRatio(Defaults.UTXO_SELECTION_MIN_TX_AMOUNT_VS_UTXO_FACTOR) + ')');
if ( txpSize / 1000. > Defaults . MAX_TX_SIZE_IN_KB ) {
log . debug ( 'Breaking because tx size (' + Utils . formatSize ( txpSize ) + ') is too big (max: ' + Utils . formatSize ( Defaults . MAX_TX_SIZE_IN_KB * 1000. ) + ')' ) ;
//log.debug('Breaking because tx size (' + Utils.formatSize(txpSize) + ') is too big (max: ' + Utils.formatSize(Defaults.MAX_TX_SIZE_IN_KB * 1000.) + ')');
error = Errors . TX_MAX_SIZE_EXCEEDED ;
return false ;
}
if ( ! _ . isEmpty ( bigInputs ) ) {
if ( amountVsUtxoRatio < Defaults . UTXO_SELECTION_MIN_TX_AMOUNT_VS_UTXO_FACTOR ) {
log . debug ( 'Breaking because utxo is too small compared to tx amount') ;
//log.debug( 'Breaking because utxo is too small compared to tx amount');
return false ;
}
if ( feeVsAmountRatio > Defaults . UTXO_SELECTION_MAX_FEE_VS_TX_AMOUNT_FACTOR ) {
var feeVsSingleInputFeeRatio = fee / ( baseTxpFee + feePerInput ) ;
log . debug ( 'Fee/Single-input fee: ' + Utils . formatRatio ( feeVsSingleInputFeeRatio ) + ' (max: ' + Utils . formatRatio ( Defaults . UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR ) + ')' + ' loses wrt single-input tx: ' + Utils . formatAmountInBtc ( ( selected . length - 1 ) * feePerInput ) ) ;
//log.debug('Fee/Single-input fee: ' + Utils.formatRatio(feeVsSingleInputFeeRatio) + ' (max: ' + Utils.formatRatio(Defaults.UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR) + ')' + ' loses wrt single-input tx: ' + Utils.formatAmountInBtc((selected.length - 1) * feePerInput));
if ( feeVsSingleInputFeeRatio > Defaults . UTXO_SELECTION_MAX_FEE_VS_SINGLE_UTXO_FEE_FACTOR ) {
log . debug ( 'Breaking because fee is too significant compared to tx amount and it is too expensive compared to using single input') ;
//log.debug( 'Breaking because fee is too significant compared to tx amount and it is too expensive compared to using single input');
return false ;
}
}
}
log . debug ( 'Cumuled total so far: ' + Utils . formatAmountInBtc ( total ) + ', Net total so far: ' + Utils . formatAmountInBtc ( netTotal ) ) ;
//log.debug('Cumuled total so far: ' + Utils.formatAmountInBtc(total) + ', Net total so far: ' + Utils.formatAmountInBtc(netTotal));
if ( netTotal >= txpAmount ) {
var changeAmount = Math . round ( total - txpAmount - fee ) ;
log . debug ( 'Tx change: ' , Utils . formatAmountInBtc ( changeAmount ) ) ;
//log.debug('Tx change: ', Utils.formatAmountInBtc(changeAmount));
var dustThreshold = Math . max ( Defaults . MIN_OUTPUT_AMOUNT , Bitcore_ [ txp . coin ] . Transaction . DUST_AMOUNT ) ;
if ( changeAmount > 0 && changeAmount <= dustThreshold ) {
log . debug ( 'Change below dust threshold (' + Utils . formatAmountInBtc ( dustThreshold ) + '). Incrementing fee to remove change.' ) ;
//log.debug('Change below dust threshold (' + Utils.formatAmountInBtc(dustThreshold) + '). Incrementing fee to remove change.');
// Remove dust change by incrementing fee
fee += changeAmount ;
}
@ -1874,12 +1900,12 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
} ) ;
if ( netTotal < txpAmount ) {
log . debug ( 'Could not reach Txp total (' + Utils . formatAmountInBtc ( txpAmount ) + '), still missing: ' + Utils . formatAmountInBtc ( txpAmount - netTotal ) ) ;
//log.debug('Could not reach Txp total (' + Utils.formatAmountInBtc(txpAmount) + '), still missing: ' + Utils.formatAmountInBtc(txpAmount - netTotal));
selected = [ ] ;
if ( ! _ . isEmpty ( bigInputs ) ) {
var input = _ . first ( bigInputs ) ;
log . debug ( 'Using big input: ' , Utils . formatUtxos ( input ) ) ;
//log.debug('Using big input: ', Utils.formatUtxos(input));
total = input . satoshis ;
fee = Math . round ( baseTxpFee + feePerInput ) ;
netTotal = total - fee ;
@ -1888,14 +1914,14 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
}
if ( _ . isEmpty ( selected ) ) {
log . debug ( 'Could not find enough funds within this utxo subset') ;
//log.debug( 'Could not find enough funds within this utxo subset');
return cb ( error || Errors . INSUFFICIENT_FUNDS_FOR_FEE ) ;
}
return cb ( null , selected , fee ) ;
} ;
log . debug ( 'Selecting inputs for a ' + Utils . formatAmountInBtc ( txp . getTotalAmount ( ) ) + ' txp' ) ;
//log.debug('Selecting inputs for a ' + Utils.formatAmountInBtc(txp.getTotalAmount()) + ' txp');
self . _ getUtxosForCurrentWallet ( { } , function ( err , utxos ) {
if ( err ) return cb ( err ) ;
@ -1917,7 +1943,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
utxos = sanitizeUtxos ( utxos ) ;
log . debug ( 'Considering ' + utxos . length + ' utxos (' + Utils . formatUtxos ( utxos ) + ')' ) ;
//log.debug('Considering ' + utxos.length + ' utxos (' + Utils.formatUtxos(utxos) + ')');
var groups = [ 6 , 1 ] ;
if ( ! txp . excludeUnconfirmedUtxos ) groups . push ( 0 ) ;
@ -1936,21 +1962,21 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
return utxo . confirmations >= group ;
} ) ;
log . debug ( 'Group >= ' + group ) ;
//log.debug('Group >= ' + group);
// If this group does not have any new elements, skip it
if ( lastGroupLength === candidateUtxos . length ) {
log . debug ( 'This group is identical to the one already explored') ;
//log.debug( 'This group is identical to the one already explored');
return next ( ) ;
}
log . debug ( 'Candidate utxos: ' + Utils . formatUtxos ( candidateUtxos ) ) ;
//log.debug('Candidate utxos: ' + Utils.formatUtxos(candidateUtxos));
lastGroupLength = candidateUtxos . length ;
select ( candidateUtxos , function ( err , selectedInputs , selectedFee ) {
if ( err ) {
log . debug ( 'No inputs selected on this group: ' , err ) ;
//log.debug('No inputs selected on this group: ', err);
selectionError = err ;
return next ( ) ;
}
@ -1959,8 +1985,8 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
inputs = selectedInputs ;
fee = selectedFee ;
log . debug ( 'Selected inputs from this group: ' + Utils . formatUtxos ( inputs ) ) ;
log . debug ( 'Fee for this selection: ' + Utils . formatAmountInBtc ( fee ) ) ;
//log.debug('Selected inputs from this group: ' + Utils.formatUtxos(inputs));
//log.debug('Fee for this selection: ' + Utils.formatAmountInBtc(fee));
return next ( ) ;
} ) ;
@ -1975,9 +2001,9 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
if ( ! err ) {
var change = _ . sum ( txp . inputs , 'satoshis' ) - _ . sum ( txp . outputs , 'amount' ) - txp . fee ;
log . debug ( 'Successfully built transaction. Total fees: ' + Utils . formatAmountInBtc ( txp . fee ) + ', total change: ' + Utils . formatAmountInBtc ( change ) ) ;
self . logi ( 'Successfully built transaction. Total fees: ' + Utils . formatAmountInBtc ( txp . fee ) + ', total change: ' + Utils . formatAmountInBtc ( change ) ) ;
} else {
log . warn ( 'Error building transaction' , err ) ;
self . logw ( 'Error building transaction' , err ) ;
}
return cb ( err ) ;
@ -2008,7 +2034,7 @@ WalletService.prototype._canCreateTx = function(cb) {
var backoffTime = Defaults . BACKOFF_TIME ;
if ( timeSinceLastRejection <= backoffTime )
log . debug ( 'Not allowing to create TX: timeSinceLastRejection/backoffTime' , timeSinceLastRejection , backoffTime ) ;
self . logi ( 'Not allowing to create TX: timeSinceLastRejection/backoffTime' , timeSinceLastRejection , backoffTime ) ;
return cb ( null , timeSinceLastRejection > backoffTime ) ;
} ) ;
@ -2061,7 +2087,6 @@ WalletService.prototype._validateAndSanitizeTxOpts = function(wallet, opts, cb)
return next ( new ClientError ( 'Only one of feeLevel/feePerKb/fee can be specified' ) ) ;
if ( feeArgs == 0 ) {
log . debug ( 'No fee provided, using "normal" fee level' ) ;
opts . feeLevel = 'normal' ;
}
@ -2133,7 +2158,7 @@ WalletService.prototype._getFeePerKb = function(wallet, opts, cb) {
} ) ;
if ( ! level ) {
var msg = 'Could not compute fee for "' + opts . feeLevel + '" level' ;
log . error ( msg ) ;
self . logw ( msg ) ;
return cb ( new ClientError ( msg ) ) ;
}
return cb ( null , level . feePerKb ) ;
@ -2369,7 +2394,7 @@ WalletService.prototype.getTx = function(opts, cb) {
self . storage . fetchTxNote ( self . walletId , txp . txid , function ( err , note ) {
if ( err ) {
log . warn ( 'Error fetching tx note for ' + txp . txid ) ;
self . logw ( 'Error fetching tx note for ' + txp . txid ) ;
}
txp . note = note ;
return cb ( null , txp ) ;
@ -2572,18 +2597,16 @@ WalletService.prototype.signTx = function(opts, cb) {
try {
if ( ! txp . sign ( self . copayerId , opts . signatures , copayer . xPubKey ) ) {
log . warn ( 'Error signing transaction (BAD_SIGNATURES)' ) ;
log . warn ( 'Wallet id:' , self . walletId ) ;
log . warn ( 'Copayer id:' , self . copayerId ) ;
log . warn ( 'Client version:' , self . clientVersion ) ;
log . warn ( 'Arguments:' , JSON . stringify ( opts ) ) ;
log . warn ( 'Transaction proposal:' , JSON . stringify ( txp ) ) ;
self . logw ( 'Error signing transaction (BAD_SIGNATURES)' ) ;
self . logw ( 'Client version:' , self . clientVersion ) ;
self . logw ( 'Arguments:' , JSON . stringify ( opts ) ) ;
self . logw ( 'Transaction proposal:' , JSON . stringify ( txp ) ) ;
var raw = txp . getBitcoreTx ( ) . uncheckedSerialize ( ) ;
log . warn ( 'Raw tx:' , raw ) ;
self . logw ( 'Raw tx:' , raw ) ;
return cb ( Errors . BAD_SIGNATURES ) ;
}
} catch ( ex ) {
log . error ( 'Error signing transaction proposal' , ex ) ;
self . logw ( 'Error signing transaction proposal' , ex ) ;
return cb ( ex ) ;
}
@ -3092,6 +3115,9 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
var addressStrs = _ . map ( addresses , 'address' ) ;
var bc = self . _ getBlockchainExplorer ( wallet . coin , wallet . network ) ;
if ( ! bc ) return next ( new Error ( 'Could not get blockchain explorer instance' ) ) ;
self . logi ( '' , 'Querying tx for: %s addrs' , addresses . length ) ;
bc . getTransactions ( addressStrs , from , to , function ( err , rawTxs , total ) {
if ( err ) return next ( err ) ;
@ -3149,13 +3175,13 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
network : wallet . network
} , function ( err , levels ) {
if ( err ) {
log . warn ( 'Could not fetch fee levels' , err ) ;
self . logw ( 'Could not fetch fee levels' , err ) ;
} else {
var level = _ . find ( levels , {
level : 'superEconomy'
} ) ;
if ( ! level || ! level . nbBlocks ) {
log . debug ( 'Cannot compute super economy fee level from blockchain' ) ;
self . logi ( 'Cannot compute super economy fee level from blockchain' ) ;
} else {
var minFeePerKb = level . feePerKb ;
_ . each ( unconfirmed , function ( tx ) {
@ -3217,10 +3243,10 @@ WalletService.prototype.getTxHistory = function(opts, cb) {
tagLowFees ( wallet , finalTxs , function ( err ) {
if ( err )
log . warn ( 'Failed to tag unconfirmed with low fee' ) ;
self . logw ( 'Failed to tag unconfirmed with low fee' ) ;
if ( res . txs . fromCache )
log . debug ( "History from cache for:" , self . walletId , from , to ) ;
self . logi ( "History from cache for:" , self . walletId , from , to ) ;
return cb ( null , finalTxs , ! ! res . txs . fromCache ) ;
} ) ;
@ -3253,7 +3279,7 @@ WalletService.prototype.scan = function(opts, cb) {
var gap = Defaults . SCAN_ADDRESS_GAP ;
async . whilst ( function ( ) {
log . debug ( 'Scanning addr gap:' + inactiveCounter ) ;
self . logi ( 'Scanning addr gap:' + inactiveCounter ) ;
return inactiveCounter < gap ;
} , function ( next ) {
var address = derivator . derive ( ) ;