2019-05-27 10:33:22 -07:00
var mongoose = require ( 'mongoose' )
, Stats = require ( '../models/stats' )
, Markets = require ( '../models/markets' )
, Address = require ( '../models/address' )
2020-11-19 21:37:42 -07:00
, AddressTx = require ( '../models/addresstx' )
2019-05-27 10:33:22 -07:00
, Tx = require ( '../models/tx' )
, Richlist = require ( '../models/richlist' )
, Peers = require ( '../models/peers' )
, Heavy = require ( '../models/heavy' )
, lib = require ( './explorer' )
, settings = require ( './settings' )
2020-11-20 16:28:28 -07:00
, fs = require ( 'fs' )
2020-11-20 11:13:13 -07:00
, coindesk = require ( './apis/coindesk' )
2020-11-23 17:19:42 -07:00
, async = require ( 'async' ) ;
2019-05-27 10:33:22 -07:00
2019-10-17 21:51:13 -06:00
function find _address ( hash , caseSensitive , cb ) {
if ( caseSensitive ) {
// faster search but only matches exact string including case
Address . findOne ( { a _id : hash } , function ( err , address ) {
if ( address )
return cb ( address ) ;
else
return cb ( ) ;
} ) ;
} else {
// slower search but matches exact string ignoring case
Address . findOne ( { a _id : { $regex : '^' + hash + '$' , $options : 'i' } } , function ( err , address ) {
if ( address )
return cb ( address ) ;
else
return cb ( ) ;
} ) ;
}
2019-05-27 10:33:22 -07:00
}
2020-11-20 16:28:28 -07:00
function find _address _tx ( address , hash , cb ) {
AddressTx . findOne ( { a _id : address , txid : hash } , function ( err , address _tx ) {
if ( address _tx ) {
return cb ( address _tx ) ;
} else {
return cb ( ) ;
}
} ) ;
}
2019-05-27 10:33:22 -07:00
function find _richlist ( coin , cb ) {
Richlist . findOne ( { coin : coin } , function ( err , richlist ) {
if ( richlist ) {
return cb ( richlist ) ;
} else {
return cb ( ) ;
}
} ) ;
}
2020-11-22 15:00:47 -07:00
function update _address ( hash , blockheight , txid , amount , type , cb ) {
var to _sent = false ;
var to _received = false ;
var addr _inc = { }
if ( hash == 'coinbase' ) {
addr _inc . sent = amount ;
} else {
if ( type == 'vin' ) {
addr _inc . sent = amount ;
addr _inc . balance = - amount ;
2019-05-27 10:33:22 -07:00
} else {
2020-11-22 15:00:47 -07:00
addr _inc . received = amount ;
addr _inc . balance = amount ;
}
}
Address . findOneAndUpdate ( { a _id : hash } , {
$inc : addr _inc
} , {
new : true ,
upsert : true
} , function ( err , address ) {
if ( err ) {
return cb ( err ) ;
} else {
2020-11-22 17:35:57 -07:00
if ( hash != 'coinbase' ) {
AddressTx . findOneAndUpdate ( { a _id : hash , txid : txid } , {
2020-11-22 18:27:04 -07:00
$inc : {
amount : addr _inc . balance
} ,
2020-11-22 17:35:57 -07:00
$set : {
a _id : hash ,
blockindex : blockheight ,
2020-11-22 18:27:04 -07:00
txid : txid
2020-11-22 17:35:57 -07:00
}
} , {
new : true ,
upsert : true
} , function ( err , addresstx ) {
if ( err ) {
return cb ( err ) ;
} else {
return cb ( ) ;
}
} ) ;
} else {
return cb ( ) ;
}
2019-05-27 10:33:22 -07:00
}
} ) ;
}
function find _tx ( txid , cb ) {
Tx . findOne ( { txid : txid } , function ( err , tx ) {
if ( tx ) {
return cb ( tx ) ;
} else {
return cb ( null ) ;
}
} ) ;
}
2020-11-20 18:56:25 -07:00
function save _tx ( txid , blockheight , cb ) {
2019-05-27 10:33:22 -07:00
lib . get _rawtransaction ( txid , function ( tx ) {
2020-12-07 21:32:43 -07:00
if ( tx && tx != 'There was an error. Check your console.' ) {
2020-11-20 18:56:25 -07:00
lib . prepare _vin ( tx , function ( vin ) {
lib . prepare _vout ( tx . vout , txid , vin , ( ( typeof tx . vjoinsplit === 'undefined' || tx . vjoinsplit == null ) ? [ ] : tx . vjoinsplit ) , function ( vout , nvin ) {
lib . syncLoop ( vin . length , function ( loop ) {
var i = loop . iteration ( ) ;
2020-11-22 15:00:47 -07:00
update _address ( nvin [ i ] . addresses , blockheight , txid , nvin [ i ] . amount , 'vin' , function ( ) {
2020-11-20 18:56:25 -07:00
loop . next ( ) ;
} ) ;
} , function ( ) {
lib . syncLoop ( vout . length , function ( subloop ) {
var t = subloop . iteration ( ) ;
if ( vout [ t ] . addresses ) {
2020-11-22 15:00:47 -07:00
update _address ( vout [ t ] . addresses , blockheight , txid , vout [ t ] . amount , 'vout' , function ( ) {
2020-11-20 18:56:25 -07:00
subloop . next ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2020-11-20 18:56:25 -07:00
} else {
subloop . next ( ) ;
}
} , function ( ) {
lib . calculate _total ( vout , function ( total ) {
var newTx = new Tx ( {
txid : tx . txid ,
vin : nvin ,
vout : vout ,
total : total . toFixed ( 8 ) ,
timestamp : tx . time ,
blockhash : tx . blockhash ,
blockindex : blockheight ,
} ) ;
newTx . save ( function ( err ) {
if ( err ) {
2020-12-03 14:16:34 -07:00
return cb ( err , false ) ;
2019-05-27 10:33:22 -07:00
} else {
2020-12-03 14:16:34 -07:00
return cb ( null , vout . length > 0 ) ;
2019-05-27 10:33:22 -07:00
}
} ) ;
} ) ;
} ) ;
} ) ;
2020-11-20 18:56:25 -07:00
} ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} else {
2020-12-03 14:16:34 -07:00
return cb ( 'tx not found: ' + txid , false ) ;
2019-05-27 10:33:22 -07:00
}
} ) ;
}
function get _market _data ( market , cb ) {
2020-11-27 20:34:15 -07:00
if ( fs . existsSync ( './lib/markets/' + market + '.js' ) ) {
2020-11-23 17:19:42 -07:00
exMarket = require ( './markets/' + market ) ;
2020-11-27 20:34:15 -07:00
exMarket . get _data ( settings . markets , function ( err , obj ) {
2020-11-23 17:19:42 -07:00
return cb ( err , obj ) ;
} ) ;
2020-11-27 20:34:15 -07:00
} else {
2020-11-23 17:19:42 -07:00
return cb ( null ) ;
2019-05-27 10:33:22 -07:00
}
}
2020-11-20 16:28:28 -07:00
function create _lock ( lockfile , cb ) {
if ( settings . lock _during _index == true ) {
var fname = './tmp/' + lockfile + '.pid' ;
2020-12-03 16:21:06 -07:00
fs . appendFile ( fname , process . pid . toString ( ) , function ( err ) {
2020-11-20 16:28:28 -07:00
if ( err ) {
console . log ( "Error: unable to create %s" , fname ) ;
process . exit ( 1 ) ;
} else {
return cb ( ) ;
}
} ) ;
} else {
return cb ( ) ;
}
}
function remove _lock ( lockfile , cb ) {
if ( settings . lock _during _index == true ) {
var fname = './tmp/' + lockfile + '.pid' ;
fs . unlink ( fname , function ( err ) {
if ( err ) {
console . log ( "unable to remove lock: %s" , fname ) ;
process . exit ( 1 ) ;
} else {
return cb ( ) ;
}
} ) ;
} else {
return cb ( ) ;
}
}
function is _locked ( lockfile , cb ) {
if ( settings . lock _during _index == true ) {
var fname = './tmp/' + lockfile + '.pid' ;
fs . exists ( fname , function ( exists ) {
if ( exists ) {
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} else {
return cb ( false ) ;
}
}
2019-05-27 10:33:22 -07:00
module . exports = {
// initialize DB
connect : function ( database , cb ) {
2020-11-22 17:39:46 -07:00
mongoose . connect ( database , { useNewUrlParser : true , useCreateIndex : true , useUnifiedTopology : true , useFindAndModify : false } , function ( err ) {
2019-05-27 10:33:22 -07:00
if ( err ) {
console . log ( 'Unable to connect to database: %s' , database ) ;
console . log ( 'Aborting' ) ;
process . exit ( 1 ) ;
}
//console.log('Successfully connected to MongoDB');
return cb ( ) ;
} ) ;
} ,
2020-11-20 16:28:28 -07:00
is _locked : function ( cb ) {
is _locked ( "db_index" , function ( exists ) {
if ( exists ) {
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} ,
2020-12-05 12:39:36 -07:00
check _show _sync _message : function ( ) {
2020-12-05 18:21:21 -07:00
return fs . existsSync ( './tmp/show_sync_message.tmp' ) ;
2020-12-05 12:39:36 -07:00
} ,
2020-12-23 18:40:10 -07:00
update _label : function ( hash , message , cb ) {
find _address ( hash , false , function ( address ) {
if ( address ) {
Address . updateOne ( { a _id : hash } , {
name : message
} , function ( ) {
// ensure that if this address exists in the richlist that it displays the new alias
module . exports . get _richlist ( settings . coin , function ( richlist ) {
var updated = false ;
// loop through received addresses
for ( r = 0 ; r < richlist . received . length ; r ++ ) {
// check if this is the correct address
if ( richlist . received [ r ] . a _id == hash ) {
// update the claim name
richlist . received [ r ] [ 'name' ] = message ;
// mark as updated
updated = true ;
}
}
// loop through balance addresses
for ( b = 0 ; b < richlist . balance . length ; b ++ ) {
// check if this is the correct address
if ( richlist . balance [ b ] . a _id == hash ) {
// update the claim name
richlist . balance [ b ] [ 'name' ] = message ;
// mark as updated
updated = true ;
}
}
// check if the address was updated in the richlist
if ( updated ) {
// save the richlist back to collection
Richlist . updateOne ( { coin : settings . coin } , {
received : richlist . received ,
balance : richlist . balance
} , function ( ) {
// finished updating the claim label
2020-12-26 22:01:36 -07:00
return cb ( '' ) ;
2020-12-23 18:40:10 -07:00
} ) ;
} else {
// finished updating the claim label
2020-12-26 22:01:36 -07:00
return cb ( '' ) ;
2020-12-23 18:40:10 -07:00
}
} ) ;
2020-11-22 14:39:10 -07:00
} ) ;
2020-12-26 22:01:36 -07:00
} else {
// address is not valid or does not have any transactions
return cb ( 'no_address' ) ;
2020-11-22 14:39:10 -07:00
}
} ) ;
} ,
2019-05-27 10:33:22 -07:00
check _stats : function ( coin , cb ) {
Stats . findOne ( { coin : coin } , function ( err , stats ) {
if ( stats ) {
// collection exists, now check if it is missing the last_usd_price column
Stats . findOne ( { last _usd _price : { $exists : false } } , function ( err , stats ) {
if ( stats ) {
// the last_usd_price needs to be added to the collection
2019-06-07 20:05:28 -06:00
Stats . updateOne ( { coin : coin } , {
2019-05-27 10:33:22 -07:00
last _usd _price : 0 ,
} , function ( ) { return cb ( null ) ; } ) ;
}
} ) ;
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} ,
get _stats : function ( coin , cb ) {
Stats . findOne ( { coin : coin } , function ( err , stats ) {
if ( stats ) {
return cb ( stats ) ;
} else {
return cb ( null ) ;
}
} ) ;
} ,
create _stats : function ( coin , cb ) {
var newStats = new Stats ( {
coin : coin ,
2020-11-22 20:40:15 -07:00
last : 0
2019-05-27 10:33:22 -07:00
} ) ;
newStats . save ( function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
console . log ( "initial stats entry created for %s" , coin ) ;
//console.log(newStats);
return cb ( ) ;
}
} ) ;
} ,
2019-10-17 21:51:13 -06:00
get _address : function ( hash , caseSensitive , cb ) {
find _address ( hash , caseSensitive , function ( address ) {
2019-05-27 10:33:22 -07:00
return cb ( address ) ;
} ) ;
} ,
get _richlist : function ( coin , cb ) {
find _richlist ( coin , function ( richlist ) {
return cb ( richlist ) ;
} ) ;
} ,
2020-12-23 18:40:10 -07:00
// 'list' variable can be either 'received' or 'balance'
2019-05-27 10:33:22 -07:00
update _richlist : function ( list , cb ) {
2019-06-24 19:52:15 -06:00
// Create the burn address array so that we omit burned coins from the rich list
var oBurnAddresses = [ ] ;
for ( var x = 0 ; x < settings . burned _coins . length ; x ++ ) {
oBurnAddresses . push ( settings . burned _coins [ x ] . address ) ;
}
2019-10-18 22:31:07 -06:00
// always omit the private address from the richlist
oBurnAddresses . push ( "private_tx" ) ;
2020-12-23 18:40:10 -07:00
if ( list == 'received' ) {
// Update 'received' richlist data
Address . find ( { a _id : { $nin : oBurnAddresses } } , 'a_id name balance received' ) . sort ( { received : 'desc' } ) . limit ( 100 ) . exec ( function ( err , addresses ) {
2019-06-07 20:05:28 -06:00
Richlist . updateOne ( { coin : settings . coin } , {
2020-12-23 18:40:10 -07:00
received : addresses
2019-05-27 10:33:22 -07:00
} , function ( ) {
return cb ( ) ;
} ) ;
} ) ;
2020-12-23 18:40:10 -07:00
} else {
// Update 'balance' richlist data
Address . find ( { a _id : { $nin : oBurnAddresses } } , 'a_id name balance received' ) . sort ( { balance : 'desc' } ) . limit ( 100 ) . exec ( function ( err , addresses ) {
2019-06-07 20:05:28 -06:00
Richlist . updateOne ( { coin : settings . coin } , {
2020-12-23 18:40:10 -07:00
balance : addresses
2019-05-27 10:33:22 -07:00
} , function ( ) {
return cb ( ) ;
} ) ;
} ) ;
}
} ,
get _tx : function ( txid , cb ) {
find _tx ( txid , function ( tx ) {
return cb ( tx ) ;
} ) ;
} ,
get _txs : function ( block , cb ) {
var txs = [ ] ;
lib . syncLoop ( block . tx . length , function ( loop ) {
var i = loop . iteration ( ) ;
find _tx ( block . tx [ i ] , function ( tx ) {
if ( tx ) {
txs . push ( tx ) ;
loop . next ( ) ;
} else {
loop . next ( ) ;
}
} )
} , function ( ) {
return cb ( txs ) ;
} ) ;
} ,
create _txs : function ( block , cb ) {
2020-11-20 16:28:28 -07:00
is _locked ( "db_index" , function ( exists ) {
if ( exists ) {
console . log ( "db_index lock file exists..." ) ;
return cb ( ) ;
} else {
lib . syncLoop ( block . tx . length , function ( loop ) {
var i = loop . iteration ( ) ;
2020-12-03 14:16:34 -07:00
save _tx ( block . tx [ i ] , block . height , function ( err , tx _has _vout ) {
2020-11-20 16:28:28 -07:00
if ( err ) {
loop . next ( ) ;
} else {
//console.log('tx stored: %s', block.tx[i]);
loop . next ( ) ;
}
} ) ;
} , function ( ) {
return cb ( ) ;
} ) ;
}
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2020-12-18 14:55:30 -07:00
get _last _txs : function ( start , length , min , cb ) {
this . get _last _txs _ajax ( start , length , min , function ( txs , count ) {
2020-11-28 20:40:37 -07:00
var data = [ ] ;
for ( i = 0 ; i < txs . length ; i ++ ) {
var row = [ ] ;
row . push ( txs [ i ] . blockindex ) ;
row . push ( txs [ i ] . blockhash ) ;
row . push ( txs [ i ] . txid ) ;
row . push ( txs [ i ] . vout . length ) ;
row . push ( ( txs [ i ] . total ) ) ;
row . push ( new Date ( ( txs [ i ] . timestamp ) * 1000 ) . toUTCString ( ) ) ;
data . push ( row ) ;
}
2020-12-17 23:55:57 -07:00
return cb ( data , count ) ;
2020-11-28 20:40:37 -07:00
} ) ;
} ,
2020-11-20 18:12:49 -07:00
get _last _txs _ajax : function ( start , length , min , cb ) {
2020-12-10 17:51:46 -07:00
// check if min is greater than zero
if ( min > 0 ) {
// min is greater than zero which means we must pull record count from the txes collection
Tx . find ( { 'total' : { $gte : min } } ) . countDocuments ( function ( err , count ) {
// Get last transactions where there is at least 1 vout
Tx . find ( { 'total' : { $gte : min } , 'vout' : { $gte : { $size : 1 } } } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( function ( err , txs ) {
if ( err ) {
return cb ( err ) ;
} else {
return cb ( txs , count ) ;
}
} ) ;
2020-11-23 15:35:14 -07:00
} ) ;
2020-12-10 17:51:46 -07:00
} else {
// min is zero (shouldn't ever be negative) which means we must pull record count from the coinstats collection (pulling from txes could potentially take a long time because it would include coinbase txes)
Stats . findOne ( { coin : settings . coin } , function ( err , stats ) {
// Get last transactions where there is at least 1 vout
Tx . find ( { 'total' : { $gte : min } , 'vout' : { $gte : { $size : 1 } } } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( function ( err , txs ) {
if ( err ) {
return cb ( err ) ;
} else {
return cb ( txs , stats . txes ) ;
}
} ) ;
} ) ;
}
2020-11-20 17:32:06 -07:00
} ,
2020-11-19 21:37:42 -07:00
get _address _txs _ajax : function ( hash , start , length , cb ) {
var totalCount = 0 ;
2020-11-28 14:44:42 -07:00
AddressTx . find ( { a _id : hash } ) . countDocuments ( function ( err , count ) {
2020-11-19 21:37:42 -07:00
if ( err ) {
return cb ( err ) ;
} else {
2020-11-22 18:27:04 -07:00
totalCount = count ;
AddressTx . aggregate ( [
2020-11-23 20:58:34 -07:00
{ $match : { a _id : hash } } ,
2020-11-22 18:27:04 -07:00
{ $sort : { blockindex : - 1 } } ,
2020-11-23 20:58:34 -07:00
{ $skip : Number ( start ) } ,
2020-11-22 18:27:04 -07:00
{
$group : {
_id : '' ,
balance : { $sum : '$amount' }
}
} ,
{
$project : {
_id : 0 ,
balance : '$balance'
}
} ,
{ $sort : { blockindex : - 1 } }
] , function ( err , balance _sum ) {
if ( err ) {
2020-11-19 21:37:42 -07:00
return cb ( err ) ;
} else {
2020-11-23 15:35:14 -07:00
AddressTx . find ( { a _id : hash } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( function ( err , address _tx ) {
2020-11-19 21:37:42 -07:00
if ( err ) {
return cb ( err ) ;
} else {
var txs = [ ] ;
2020-11-22 18:27:04 -07:00
var count = address _tx . length ;
2020-11-23 20:58:34 -07:00
var running _balance = balance _sum . length > 0 ? balance _sum [ 0 ] . balance : 0 ;
2020-11-19 21:37:42 -07:00
var txs = [ ] ;
lib . syncLoop ( count , function ( loop ) {
var i = loop . iteration ( ) ;
2020-11-23 20:58:34 -07:00
find _tx ( address _tx [ i ] . txid , function ( tx ) {
2020-11-20 16:28:28 -07:00
if ( tx && ! txs . includes ( tx ) ) {
2020-11-22 18:27:04 -07:00
tx . balance = running _balance ;
2020-11-19 21:37:42 -07:00
txs . push ( tx ) ;
loop . next ( ) ;
2020-11-20 16:28:28 -07:00
} else if ( ! txs . includes ( tx ) ) {
2020-11-19 21:37:42 -07:00
txs . push ( "1. Not found" ) ;
loop . next ( ) ;
2020-11-20 16:28:28 -07:00
} else {
loop . next ( ) ;
2020-11-19 21:37:42 -07:00
}
2020-11-22 18:27:04 -07:00
running _balance = running _balance - address _tx [ i ] . amount ;
2020-11-19 21:37:42 -07:00
} )
} , function ( ) {
return cb ( txs , totalCount ) ;
} ) ;
}
} ) ;
}
} ) ;
}
} ) ;
} ,
2019-05-27 10:33:22 -07:00
create _market : function ( coin , exchange , market , cb ) {
var newMarkets = new Markets ( {
market : market ,
coin : coin ,
exchange : exchange ,
} ) ;
newMarkets . save ( function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
console . log ( "initial markets entry created for %s" , market ) ;
//console.log(newMarkets);
return cb ( ) ;
}
} ) ;
} ,
// checks market data exists for given market
check _market : function ( market , cb ) {
Markets . findOne ( { market : market } , function ( err , exists ) {
if ( exists ) {
return cb ( market , true ) ;
} else {
return cb ( market , false ) ;
}
} ) ;
} ,
// gets market data for given market
get _market : function ( market , cb ) {
Markets . findOne ( { market : market } , function ( err , data ) {
if ( data ) {
return cb ( data ) ;
} else {
return cb ( null ) ;
}
} ) ;
} ,
// creates initial richlist entry in database; called on first launch of explorer
create _richlist : function ( coin , cb ) {
var newRichlist = new Richlist ( {
coin : coin ,
} ) ;
newRichlist . save ( function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
console . log ( "initial richlist entry created for %s" , coin ) ;
//console.log(newRichlist);
return cb ( ) ;
}
} ) ;
} ,
2020-11-20 14:06:53 -07:00
// drops richlist data for given coin
delete _richlist : function ( coin , cb ) {
Richlist . findOneAndRemove ( { coin : coin } , function ( err , exists ) {
if ( exists ) {
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} ,
2019-05-27 10:33:22 -07:00
// checks richlist data exists for given coin
check _richlist : function ( coin , cb ) {
Richlist . findOne ( { coin : coin } , function ( err , exists ) {
if ( exists ) {
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} ,
create _heavy : function ( coin , cb ) {
var newHeavy = new Heavy ( {
coin : coin ,
} ) ;
newHeavy . save ( function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
console . log ( "initial heavy entry created for %s" , coin ) ;
console . log ( newHeavy ) ;
return cb ( ) ;
}
} ) ;
} ,
check _heavy : function ( coin , cb ) {
Heavy . findOne ( { coin : coin } , function ( err , exists ) {
if ( exists ) {
return cb ( true ) ;
} else {
return cb ( false ) ;
}
} ) ;
} ,
get _heavy : function ( coin , cb ) {
Heavy . findOne ( { coin : coin } , function ( err , heavy ) {
if ( heavy ) {
return cb ( heavy ) ;
} else {
return cb ( null ) ;
}
} ) ;
} ,
get _distribution : function ( richlist , stats , cb ) {
var distribution = {
supply : stats . supply ,
t _1 _25 : { percent : 0 , total : 0 } ,
t _26 _50 : { percent : 0 , total : 0 } ,
t _51 _75 : { percent : 0 , total : 0 } ,
t _76 _100 : { percent : 0 , total : 0 } ,
t _101plus : { percent : 0 , total : 0 }
} ;
lib . syncLoop ( richlist . balance . length , function ( loop ) {
var i = loop . iteration ( ) ;
var count = i + 1 ;
var percentage = ( ( richlist . balance [ i ] . balance / 100000000 ) / stats . supply ) * 100 ;
if ( count <= 25 ) {
distribution . t _1 _25 . percent = distribution . t _1 _25 . percent + percentage ;
distribution . t _1 _25 . total = distribution . t _1 _25 . total + ( richlist . balance [ i ] . balance / 100000000 ) ;
}
if ( count <= 50 && count > 25 ) {
distribution . t _26 _50 . percent = distribution . t _26 _50 . percent + percentage ;
distribution . t _26 _50 . total = distribution . t _26 _50 . total + ( richlist . balance [ i ] . balance / 100000000 ) ;
}
if ( count <= 75 && count > 50 ) {
distribution . t _51 _75 . percent = distribution . t _51 _75 . percent + percentage ;
distribution . t _51 _75 . total = distribution . t _51 _75 . total + ( richlist . balance [ i ] . balance / 100000000 ) ;
}
if ( count <= 100 && count > 75 ) {
distribution . t _76 _100 . percent = distribution . t _76 _100 . percent + percentage ;
distribution . t _76 _100 . total = distribution . t _76 _100 . total + ( richlist . balance [ i ] . balance / 100000000 ) ;
}
loop . next ( ) ;
} , function ( ) {
distribution . t _101plus . percent = parseFloat ( 100 - distribution . t _76 _100 . percent - distribution . t _51 _75 . percent - distribution . t _26 _50 . percent - distribution . t _1 _25 . percent ) . toFixed ( 2 ) ;
distribution . t _101plus . total = parseFloat ( distribution . supply - distribution . t _76 _100 . total - distribution . t _51 _75 . total - distribution . t _26 _50 . total - distribution . t _1 _25 . total ) . toFixed ( 8 ) ;
distribution . t _1 _25 . percent = parseFloat ( distribution . t _1 _25 . percent ) . toFixed ( 2 ) ;
distribution . t _1 _25 . total = parseFloat ( distribution . t _1 _25 . total ) . toFixed ( 8 ) ;
distribution . t _26 _50 . percent = parseFloat ( distribution . t _26 _50 . percent ) . toFixed ( 2 ) ;
distribution . t _26 _50 . total = parseFloat ( distribution . t _26 _50 . total ) . toFixed ( 8 ) ;
distribution . t _51 _75 . percent = parseFloat ( distribution . t _51 _75 . percent ) . toFixed ( 2 ) ;
distribution . t _51 _75 . total = parseFloat ( distribution . t _51 _75 . total ) . toFixed ( 8 ) ;
distribution . t _76 _100 . percent = parseFloat ( distribution . t _76 _100 . percent ) . toFixed ( 2 ) ;
distribution . t _76 _100 . total = parseFloat ( distribution . t _76 _100 . total ) . toFixed ( 8 ) ;
return cb ( distribution ) ;
} ) ;
} ,
// updates heavy stats for coin
// height: current block height, count: amount of votes to store
update _heavy : function ( coin , height , count , cb ) {
var newVotes = [ ] ;
lib . get _maxmoney ( function ( maxmoney ) {
lib . get _maxvote ( function ( maxvote ) {
lib . get _vote ( function ( vote ) {
lib . get _phase ( function ( phase ) {
lib . get _reward ( function ( reward ) {
lib . get _supply ( function ( supply ) {
lib . get _estnext ( function ( estnext ) {
lib . get _nextin ( function ( nextin ) {
lib . syncLoop ( count , function ( loop ) {
var i = loop . iteration ( ) ;
lib . get _blockhash ( height - i , function ( hash ) {
lib . get _block ( hash , function ( block ) {
2020-12-17 20:01:50 -07:00
newVotes . push ( { count : height - i , reward : block . reward , vote : ( block && block . vote ? block . vote : 0 ) } ) ;
2019-05-27 10:33:22 -07:00
loop . next ( ) ;
} ) ;
} ) ;
} , function ( ) {
console . log ( newVotes ) ;
2019-06-07 20:05:28 -06:00
Heavy . updateOne ( { coin : coin } , {
2020-12-07 21:32:43 -07:00
lvote : ( vote ? vote : 0 ) ,
reward : ( reward ? reward : 0 ) ,
supply : ( supply ? supply : 0 ) ,
cap : ( maxmoney ? maxmoney : 0 ) ,
estnext : ( estnext ? estnext : 0 ) ,
phase : ( phase ? phase : 'N/A' ) ,
maxvote : ( maxvote ? maxvote : 0 ) ,
nextin : ( nextin ? nextin : 'N/A' ) ,
2019-05-27 10:33:22 -07:00
votes : newVotes ,
} , function ( ) {
//console.log('address updated: %s', hash);
return cb ( ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ,
// updates market data for given market; called by sync.js
update _markets _db : function ( market , cb ) {
2020-12-08 22:52:15 -07:00
// check if market exists
if ( fs . existsSync ( './lib/markets/' + market + '.js' ) ) {
get _market _data ( market , function ( err , obj ) {
if ( err == null ) {
Markets . updateOne ( { market : market } , {
chartdata : JSON . stringify ( obj . chartdata ) ,
buys : obj . buys ,
sells : obj . sells ,
history : obj . trades ,
summary : obj . stats
} , function ( ) {
if ( market == settings . markets . default ) {
Stats . updateOne ( { coin : settings . coin } , {
last _price : obj . stats . last ,
} , function ( ) {
return cb ( null ) ;
} ) ;
} else {
2019-05-27 10:33:22 -07:00
return cb ( null ) ;
2020-12-08 22:52:15 -07:00
}
} ) ;
} else {
return cb ( err ) ;
}
} ) ;
} else {
// market does not exist
return cb ( 'market is not installed' ) ;
}
2019-05-27 10:33:22 -07:00
} ,
get _last _usd _price : function ( cb ) {
// Check if the market price is being recorded in BTC
if ( settings . markets . enabled . length > 0 && settings . markets . exchange . toLowerCase ( ) == "btc" ) {
// Convert btc to usd via coindesk api
coindesk . get _data ( function ( err , last _usd ) {
// Get current stats
Stats . findOne ( { coin : settings . coin } , function ( err , stats ) {
// Update the last usd price
2019-06-07 20:05:28 -06:00
Stats . updateOne ( { coin : settings . coin } , {
2019-05-27 10:33:22 -07:00
last _usd _price : ( last _usd * stats . last _price ) ,
} , function ( ) {
return cb ( null ) ;
} ) ;
} ) ;
} ) ;
} else {
return cb ( null ) ;
}
} ,
// updates stats data for given coin; called by sync.js
update _db : function ( coin , cb ) {
lib . get _blockcount ( function ( count ) {
2020-12-03 14:16:34 -07:00
if ( ! count ) {
2019-05-27 10:33:22 -07:00
console . log ( 'Unable to connect to explorer API' ) ;
return cb ( false ) ;
}
2020-12-03 14:16:34 -07:00
lib . get _supply ( function ( supply ) {
2019-05-27 10:33:22 -07:00
lib . get _connectioncount ( function ( connections ) {
2020-12-03 14:16:34 -07:00
Stats . findOne ( { coin : coin } , function ( err , stats ) {
if ( stats ) {
Stats . updateOne ( { coin : coin } , {
coin : coin ,
count : count ,
2020-12-07 21:32:43 -07:00
supply : ( supply ? supply : 0 ) ,
connections : ( connections ? connections : 0 )
2020-12-03 14:16:34 -07:00
} , function ( err ) {
if ( err ) {
console . log ( "Error during Stats Update: " , err ) ;
}
return cb ( {
coin : coin ,
count : count ,
2020-12-07 21:32:43 -07:00
supply : ( supply ? supply : 0 ) ,
connections : ( connections ? connections : 0 ) ,
2020-12-03 14:16:34 -07:00
last : ( stats . last ? stats . last : 0 ) ,
txes : ( stats . txes ? stats . txes : 0 )
} ) ;
} ) ;
} else {
console . log ( "Error during Stats Update: " , ( err ? err : 'cannot find stats collection' ) ) ;
return cb ( false ) ;
2020-11-22 20:40:15 -07:00
}
2019-05-27 10:33:22 -07:00
} ) ;
} ) ;
} ) ;
} ) ;
} ,
// updates tx, address & richlist db's; called by sync.js
2020-12-03 14:16:34 -07:00
update _tx _db : function ( coin , start , end , txes , timeout , cb ) {
2020-11-20 16:28:28 -07:00
is _locked ( "db_index" , function ( exists ) {
if ( exists ) {
console . log ( "db_index lock file exists..." ) ;
return cb ( ) ;
} else {
create _lock ( "db_index" , function ( ) {
var complete = false ;
2020-11-22 15:00:47 -07:00
var blocks _to _scan = [ ] ;
var task _limit _blocks = settings . block _parallel _tasks ;
2020-11-22 17:24:57 -07:00
if ( typeof start === 'undefined' || start < 1 ) start = 1 ; // fix for invalid block height (skip genesis block as it should not have valid txs)
2020-11-22 15:00:47 -07:00
if ( task _limit _blocks < 1 ) { task _limit _blocks = 1 ; }
2020-11-22 18:27:04 -07:00
var task _limit _txs = 1 ;
2020-11-22 15:00:47 -07:00
for ( i = start ; i < ( end + 1 ) ; i ++ ) {
blocks _to _scan . push ( i ) ;
}
async . eachLimit ( blocks _to _scan , task _limit _blocks , function ( block _height , next _block ) {
2020-12-08 20:49:06 -07:00
if ( block _height % settings . save _stats _after _sync _blocks === 0 ) {
2020-11-22 15:00:47 -07:00
Stats . updateOne ( { coin : coin } , {
last : block _height - 1 ,
2020-12-03 14:16:34 -07:00
txes : txes ,
2020-11-22 15:00:47 -07:00
last _txs : '' //not used anymore left to clear out existing objects
} , function ( ) { } ) ;
2020-11-20 16:28:28 -07:00
}
2020-11-22 15:00:47 -07:00
lib . get _blockhash ( block _height , function ( blockhash ) {
2020-11-20 16:28:28 -07:00
if ( blockhash ) {
lib . get _block ( blockhash , function ( block ) {
if ( block ) {
2020-11-22 15:00:47 -07:00
async . eachLimit ( block . tx , task _limit _txs , function ( txid , next _tx ) {
Tx . findOne ( { txid : txid } , function ( err , tx ) {
2020-11-20 16:28:28 -07:00
if ( tx ) {
2020-11-22 15:00:47 -07:00
setTimeout ( function ( ) {
tx = null ;
next _tx ( ) ;
} , timeout ) ;
2020-11-20 16:28:28 -07:00
} else {
2020-12-03 14:16:34 -07:00
save _tx ( txid , block _height , function ( err , tx _has _vout ) {
2020-11-20 16:28:28 -07:00
if ( err ) {
console . log ( err ) ;
} else {
2020-11-22 15:00:47 -07:00
console . log ( '%s: %s' , block _height , txid ) ;
2020-11-20 16:28:28 -07:00
}
2020-12-03 14:16:34 -07:00
if ( tx _has _vout )
txes ++ ;
2020-11-20 16:28:28 -07:00
setTimeout ( function ( ) {
tx = null ;
2020-11-22 15:00:47 -07:00
next _tx ( ) ;
2020-11-20 16:28:28 -07:00
} , timeout ) ;
} ) ;
}
} ) ;
} , function ( ) {
2020-11-22 15:00:47 -07:00
setTimeout ( function ( ) {
blockhash = null ;
block = null ;
next _block ( ) ;
} , timeout ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2020-11-20 16:28:28 -07:00
} else {
console . log ( 'block not found: %s' , blockhash ) ;
2020-11-22 15:00:47 -07:00
setTimeout ( function ( ) {
next _block ( ) ;
} , timeout ) ;
2019-05-27 10:33:22 -07:00
}
} ) ;
2020-11-20 16:28:28 -07:00
} else {
2020-11-22 15:00:47 -07:00
setTimeout ( function ( ) {
next _block ( ) ;
} , timeout ) ;
2020-11-20 16:28:28 -07:00
}
} ) ;
} , function ( ) {
Tx . find ( { } ) . sort ( { timestamp : 'desc' } ) . limit ( settings . index . last _txs ) . exec ( function ( err , txs ) {
2020-11-20 18:45:01 -07:00
Stats . updateOne ( { coin : coin } , {
2020-11-20 16:28:28 -07:00
last : end ,
2020-12-03 14:16:34 -07:00
txes : txes ,
2020-11-20 16:28:28 -07:00
last _txs : '' //not used anymore left to clear out existing objects
} , function ( ) {
remove _lock ( "db_index" , function ( ) {
return cb ( ) ;
} ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2020-11-20 16:28:28 -07:00
} ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ) ;
2020-11-20 16:28:28 -07:00
}
2019-05-27 10:33:22 -07:00
} ) ;
} ,
create _peer : function ( params , cb ) {
var newPeer = new Peers ( params ) ;
newPeer . save ( function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
return cb ( ) ;
}
} ) ;
} ,
find _peer : function ( address , cb ) {
Peers . findOne ( { address : address } , function ( err , peer ) {
if ( err ) {
return cb ( null ) ;
} else {
if ( peer ) {
return cb ( peer ) ;
} else {
return cb ( null )
}
}
} )
} ,
2020-11-20 14:49:14 -07:00
drop _peer : function ( address , cb ) {
Peers . deleteOne ( { address : address } , function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
return cb ( )
}
} )
} ,
drop _peers : function ( cb ) {
Peers . deleteMany ( { } , function ( err ) {
if ( err ) {
console . log ( err ) ;
return cb ( ) ;
} else {
return cb ( )
}
} )
} ,
2019-05-27 10:33:22 -07:00
get _peers : function ( cb ) {
Peers . find ( { } , function ( err , peers ) {
if ( err ) {
return cb ( [ ] ) ;
} else {
return cb ( peers ) ;
}
} ) ;
2020-12-08 22:52:15 -07:00
} ,
2020-12-23 18:40:10 -07:00
populate _claim _address _names : function ( tx , cb ) {
var addresses = [ ] ;
// loop through vin addresses
tx . vin . forEach ( function ( vin ) {
// check if this address already exists
if ( addresses . indexOf ( vin . addresses ) == - 1 ) {
// add address to array
addresses . push ( vin . addresses ) ;
}
} ) ;
// loop through vout addresses
tx . vout . forEach ( function ( vout ) {
// check if this address already exists
if ( addresses . indexOf ( vout . addresses ) == - 1 ) {
// add address to array
addresses . push ( vout . addresses ) ;
}
} ) ;
// loop through address array
lib . syncLoop ( addresses . length , function ( loop ) {
var a = loop . iteration ( ) ;
module . exports . get _address ( addresses [ a ] , false , function ( address ) {
if ( address && address . name != null && address . name != '' ) {
// look for address in vin
for ( v = 0 ; v < tx . vin . length ; v ++ ) {
// check if this is the correct address
if ( tx . vin [ v ] . addresses == address . a _id ) {
// add claim name to array
tx . vin [ v ] [ 'claim_name' ] = address . name ;
}
}
// look for address in vout
for ( v = 0 ; v < tx . vout . length ; v ++ ) {
// check if this is the correct address
if ( tx . vout [ v ] . addresses == address . a _id ) {
// add claim name to array
tx . vout [ v ] [ 'claim_name' ] = address . name ;
}
}
}
loop . next ( ) ;
} ) ;
} , function ( ) {
// return modified tx object
return cb ( tx ) ;
} ) ;
} ,
2020-12-08 22:52:15 -07:00
fs : fs
2020-11-20 14:06:53 -07:00
} ;