2021-03-17 17:54:09 -06:00
var mongoose = require ( 'mongoose' ) ,
Stats = require ( '../models/stats' ) ,
Markets = require ( '../models/markets' ) ,
Masternode = require ( '../models/masternode' ) ,
Address = require ( '../models/address' ) ,
AddressTx = require ( '../models/addresstx' ) ,
Tx = require ( '../models/tx' ) ,
2023-05-06 12:36:35 -06:00
Orphans = require ( '../models/orphans' ) ,
2021-03-17 17:54:09 -06:00
Richlist = require ( '../models/richlist' ) ,
Peers = require ( '../models/peers' ) ,
Heavy = require ( '../models/heavy' ) ,
2022-04-11 01:37:27 -06:00
NetworkHistory = require ( '../models/networkhistory' ) ,
2023-09-26 18:22:28 -06:00
ClaimAddress = require ( '../models/claimaddress' ) ,
2021-03-17 17:54:09 -06:00
lib = require ( './explorer' ) ,
settings = require ( './settings' ) ,
2024-01-05 00:47:22 -07:00
fs = require ( 'fs' ) ;
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
2023-05-07 20:55:29 -06:00
Address . findOne ( { a _id : hash } ) . then ( ( address ) => {
2019-10-17 21:51:13 -06:00
if ( address )
return cb ( address ) ;
else
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-10-17 21:51:13 -06:00
} ) ;
} else {
// slower search but matches exact string ignoring case
2023-05-07 20:55:29 -06:00
Address . findOne ( { a _id : { $regex : '^' + hash + '$' , $options : 'i' } } ) . then ( ( address ) => {
2019-10-17 21:51:13 -06:00
if ( address )
return cb ( address ) ;
else
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-10-17 21:51:13 -06:00
} ) ;
}
2019-05-27 10:33:22 -07:00
}
2023-09-26 18:22:28 -06:00
function find _claim _name ( hash , cb ) {
ClaimAddress . findOne ( { a _id : hash } ) . then ( ( claim _address ) => {
if ( claim _address )
return cb ( claim _address . claim _name ) ;
else
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
} ) ;
}
2019-05-27 10:33:22 -07:00
function find _richlist ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Richlist . findOne ( { coin : coin } ) . then ( ( richlist ) => {
2021-03-17 17:54:09 -06:00
if ( richlist )
2019-05-27 10:33:22 -07:00
return cb ( richlist ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
}
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 = { }
2021-03-17 17:54:09 -06:00
if ( hash == 'coinbase' )
2020-11-22 15:00:47 -07:00
addr _inc . sent = amount ;
2021-03-17 17:54:09 -06:00
else {
2020-11-22 15:00:47 -07:00
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 ;
}
}
2021-03-17 17:54:09 -06:00
2020-11-22 15:00:47 -07:00
Address . findOneAndUpdate ( { a _id : hash } , {
$inc : addr _inc
} , {
new : true ,
upsert : true
2023-05-07 20:55:29 -06:00
} ) . then ( ( address ) => {
if ( hash != 'coinbase' ) {
AddressTx . findOneAndUpdate ( { a _id : hash , txid : txid } , {
$inc : {
amount : addr _inc . balance
} ,
$set : {
a _id : hash ,
blockindex : blockheight ,
txid : txid
}
} , {
new : true ,
upsert : true
} ) . then ( ( addresstx ) => {
2020-11-22 17:35:57 -07:00
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
return cb ( err ) ;
} ) ;
} else
return cb ( ) ;
} ) . catch ( ( err ) => {
return cb ( err ) ;
2019-05-27 10:33:22 -07:00
} ) ;
}
function find _tx ( txid , cb ) {
2023-05-07 20:55:29 -06:00
Tx . findOne ( { txid : txid } ) . then ( ( tx ) => {
2021-03-17 17:54:09 -06:00
if ( tx )
2019-05-27 10:33:22 -07:00
return cb ( tx ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( null ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2019-05-27 10:33:22 -07:00
} ) ;
}
2021-01-22 15:04:32 -07:00
function get _market _data ( market , coin _symbol , pair _symbol , 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 ) ;
2021-03-17 17:54:09 -06:00
2024-06-16 18:58:12 -06:00
exMarket . get _data ( { coin : coin _symbol , exchange : pair _symbol , api _error _msg : settings . localization . mkt _unexpected _api _data } , function ( err , obj ) {
2020-11-23 17:19:42 -07:00
return cb ( err , obj ) ;
} ) ;
2021-01-22 15:04:32 -07:00
} else
2020-11-23 17:19:42 -07:00
return cb ( null ) ;
2020-11-20 16:28:28 -07:00
}
2021-03-20 01:34:13 -06:00
function check _add _db _field ( model _obj , field _name , default _value , cb ) {
// determine if a particular field exists in a db collection
2023-05-07 20:55:29 -06:00
model _obj . findOne ( { [ field _name ] : { $exists : false } } ) . then ( ( model _data ) => {
2021-03-20 01:34:13 -06:00
// check if field exists
if ( model _data ) {
// add field to all documents in the collection
model _obj . updateMany ( { } , {
$set : { [ field _name ] : default _value }
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2021-03-20 01:34:13 -06:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2021-03-20 01:34:13 -06:00
} ) ;
} else
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2021-03-20 01:34:13 -06:00
} ) ;
}
2022-06-24 19:43:02 -06:00
function check _rename _db _field ( model _obj , old _field _name , new _field _name , cb ) {
// determine if a particular field exists in a db collection
2023-05-07 20:55:29 -06:00
model _obj . findOne ( { [ old _field _name ] : { $exists : false } } ) . then ( ( model _data ) => {
2022-06-24 19:43:02 -06:00
// check if old field exists
if ( model _data ) {
// rename field
model _obj . updateMany ( { } , {
$rename : { [ old _field _name ] : new _field _name }
2023-05-07 20:55:29 -06:00
} , { multi : true , strict : false } ) . then ( ( ) => {
2022-06-24 19:43:02 -06:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2022-06-24 19:43:02 -06:00
} ) ;
} else
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2022-06-24 19:43:02 -06:00
} ) ;
}
2023-09-26 18:22:28 -06:00
function check _remove _db _field ( model _obj , field _name , cb ) {
// determine if a particular field exists in a db collection
model _obj . findOne ( { [ field _name ] : { $exists : true } } ) . then ( ( model _data ) => {
// check if field exists
if ( model _data ) {
// remove field
model _obj . updateMany ( { } , {
$unset : { [ field _name ] : 1 }
} , { multi : true , strict : false } ) . then ( ( ) => {
return cb ( true ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
} ) ;
} else
return cb ( false ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
} ) ;
}
2021-07-09 20:39:02 -06:00
function hex _to _ascii ( hex ) {
2023-05-07 20:55:29 -06:00
var str = '' ;
for ( var i = 0 ; i < hex . length ; i += 2 )
str += String . fromCharCode ( parseInt ( hex . substr ( i , 2 ) , 16 ) ) ;
return str ;
2021-07-09 20:39:02 -06:00
}
2022-04-30 20:53:10 -06:00
function init _markets ( cb ) {
2023-10-27 18:33:52 -06:00
let installed _markets = [ ] ;
2022-04-30 20:53:10 -06:00
// check if markets/exchanges feature is enabled
if ( settings . markets _page . enabled == true ) {
2023-10-27 18:33:52 -06:00
let marketCounter = 0 ;
2022-04-30 20:53:10 -06:00
// loop through and test all exchanges defined in the settings.json file
Object . keys ( settings . markets _page . exchanges ) . forEach ( function ( key , index , map ) {
// check if market is enabled via settings
if ( settings . markets _page . exchanges [ key ] . enabled == true ) {
// check if exchange is installed/supported
if ( module . exports . fs . existsSync ( './lib/markets/' + key + '.js' ) ) {
2024-01-05 00:47:22 -07:00
// check if there are any trading pairs
if ( settings . markets _page . exchanges [ key ] . trading _pairs . length > 0 ) {
let pairCounter = 0 ;
// loop through all trading pairs
settings . markets _page . exchanges [ key ] . trading _pairs . forEach ( function ( pair _key , pair _index , pair _map ) {
// split the pair data
let split _pair = pair _key . toUpperCase ( ) . split ( '/' ) ;
// check if this is a valid trading pair
if ( split _pair . length == 2 ) {
// add this pair to the list of installed markets
installed _markets . push ( {
market : key ,
coin _symbol : split _pair [ 0 ] ,
pair _symbol : split _pair [ 1 ]
} ) ;
2023-10-27 18:33:52 -06:00
2024-01-05 00:47:22 -07:00
// lookup the exchange in the market collection
module . exports . check _market ( key , split _pair [ 0 ] , split _pair [ 1 ] , function ( market , exists ) {
// check if exchange trading pair exists in the market collection
if ( ! exists ) {
// exchange doesn't exist in the market collection so add a default definition now
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . creating _initial _entry . replace ( '{1}' , ` ${ market } [ ${ split _pair [ 0 ] } / ${ split _pair [ 1 ] } ] ` ) } .. ${ settings . localization . please _wait } .. ` ) ;
2024-01-05 00:47:22 -07:00
module . exports . create _market ( split _pair [ 0 ] , split _pair [ 1 ] , market , function ( ) {
pairCounter ++ ;
// check if all pairs have been tested
if ( pairCounter == settings . markets _page . exchanges [ key ] . trading _pairs . length )
marketCounter ++ ;
// check if all exchanges have been tested
if ( marketCounter == Object . keys ( settings . markets _page . exchanges ) . length ) {
// finished initializing markets
return cb ( installed _markets ) ;
}
} ) ;
} else {
2022-04-30 20:53:10 -06:00
pairCounter ++ ;
// check if all pairs have been tested
if ( pairCounter == settings . markets _page . exchanges [ key ] . trading _pairs . length )
marketCounter ++ ;
2024-01-05 00:47:22 -07:00
}
2022-04-30 20:53:10 -06:00
2024-01-05 00:47:22 -07:00
// check if all exchanges have been tested
if ( marketCounter == Object . keys ( settings . markets _page . exchanges ) . length ) {
// finished initializing markets
return cb ( installed _markets ) ;
}
} ) ;
} else {
pairCounter ++ ;
2022-04-30 20:53:10 -06:00
2024-01-05 00:47:22 -07:00
// check if all pairs have been tested
if ( pairCounter == settings . markets _page . exchanges [ key ] . trading _pairs . length )
marketCounter ++ ;
}
} ) ;
} else
marketCounter ++ ;
2022-04-30 20:53:10 -06:00
} else
marketCounter ++ ;
} else
marketCounter ++ ;
} ) ;
// check if all exchanges have been tested
if ( marketCounter == Object . keys ( settings . markets _page . exchanges ) . length ) {
// finished initializing markets
2023-10-27 18:33:52 -06:00
return cb ( installed _markets ) ;
2022-04-30 20:53:10 -06:00
}
} else
2023-10-27 18:33:52 -06:00
return cb ( installed _markets ) ;
}
function remove _inactive _markets ( installed _markets , cb ) {
// lookup the list of markets in the database collection
Markets . find ( { } ) . then ( ( db _markets ) => {
// check if the database has any markets installed
if ( db _markets != null && db _markets . length > 0 ) {
// loop through the list of markets in the database
lib . syncLoop ( db _markets . length , function ( market _loop ) {
let m = market _loop . iteration ( ) ;
// check if this market is installed
if ( installed _markets . findIndex ( x => x . market . toUpperCase ( ) == db _markets [ m ] . market . toUpperCase ( ) && x . coin _symbol . toUpperCase ( ) == db _markets [ m ] . coin _symbol . toUpperCase ( ) && x . pair _symbol . toUpperCase ( ) == db _markets [ m ] . pair _symbol . toUpperCase ( ) ) == - 1 ) {
// remove this market from the database because it is not installed or active
Markets . deleteOne ( { market : db _markets [ m ] . market , coin _symbol : db _markets [ m ] . coin _symbol , pair _symbol : db _markets [ m ] . pair _symbol } ) . then ( ( ) => {
// move to the next market record
market _loop . next ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
// move to the next market record
market _loop . next ( ) ;
} ) ;
} else {
// move to the next market record
market _loop . next ( ) ;
}
} , function ( ) {
// finished removing inactive markets
return cb ( ) ;
} ) ;
} else
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
2022-04-30 20:53:10 -06:00
return cb ( ) ;
2023-10-27 18:33:52 -06:00
} ) ;
2022-04-30 20:53:10 -06:00
}
function init _heavy ( cb ) {
if ( settings . blockchain _specific . heavycoin . enabled == true ) {
module . exports . check _heavy ( settings . coin . name , function ( exists ) {
if ( exists == false ) {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . creating _initial _entry . replace ( '{1}' , 'heavycoin' ) } .. ${ settings . localization . please _wait } .. ` ) ;
2022-04-30 20:53:10 -06:00
module . exports . create _heavy ( settings . coin . name , function ( ) {
return cb ( ) ;
} ) ;
} else
return cb ( ) ;
} ) ;
} else
return cb ( ) ;
}
2023-09-26 18:22:28 -06:00
function init _claimaddress ( coin , cb ) {
// first, get the stats data
Stats . findOne ( { coin : coin } ) . then ( ( stats ) => {
var newer _claim _address = false ;
// check if stats were found
if ( stats ) {
// check if the claim address data was already moved to the new collection
if ( stats . newer _claim _address != null && stats . newer _claim _address == true )
newer _claim _address = true ;
}
// check if the claim address data should be moved to a new collection
if ( ! newer _claim _address ) {
// find all addresses with a custom claim address name
Address . find ( { $and : [ { "name" : { $ne : "" } } , { "name" : { $ne : null } } ] } ) . exec ( ) . then ( ( addresses ) => {
// loop through the claimed addresses
lib . syncLoop ( addresses . length , function ( address _loop ) {
var a = address _loop . iteration ( ) ;
// create a new claimaddress record
var claim _address = new ClaimAddress ( {
a _id : addresses [ a ] . a _id ,
claim _name : addresses [ a ] . name
} ) ;
// add new claim address to collection
claim _address . save ( ) . then ( ( ) => {
address _loop . next ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
address _loop . next ( ) ;
} ) ;
} , function ( ) {
// finished moving all claimed address data to the new collection
// remove the name field from the address collection to reclaim disk space
check _remove _db _field ( Address , 'name' , function ( removed ) {
// update the stats data to prevent this one-time process from happening again in the future
Stats . updateOne ( { coin : coin } , { newer _claim _address : true } ) . then ( ( ) => {
return cb ( true ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
} ) ;
} ) ;
} ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
} ) ;
} else
return cb ( true ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
} ) ;
}
2024-06-16 18:58:12 -06:00
function init _plugins ( coin , cb ) {
// check if there are any defined plugins in the settings
if ( settings . plugins . allowed _plugins != null && settings . plugins . allowed _plugins . length > 0 ) {
let checkedPlugins = 0 ;
// loop through all plugins defined in the settings
settings . plugins . allowed _plugins . forEach ( function ( plugin ) {
// check if this plugin is enabled
if ( ! plugin . enabled ) {
checkedPlugins ++ ;
if ( checkedPlugins == settings . plugins . allowed _plugins . length )
return cb ( ) ;
} else {
const pluginName = ( plugin . plugin _name == null ? '' : plugin . plugin _name ) ;
// check if the plugin exists in the plugins directory
if ( ! fs . existsSync ( ` ./plugins/ ${ pluginName } ` ) ) {
console . log ( ` WARNING: Plugin ' ${ pluginName } ' is not installed in the plugins directory ` ) ;
checkedPlugins ++ ;
if ( checkedPlugins == settings . plugins . allowed _plugins . length )
return cb ( ) ;
} else {
// check if the plugin's server_functions file exists
if ( ! fs . existsSync ( ` ./plugins/ ${ pluginName } /lib/server_functions.js ` ) ) {
console . log ( ` WARNING: Plugin ' ${ pluginName } ' is missing the /lib/server_functions.js file ` ) ;
checkedPlugins ++ ;
if ( checkedPlugins == settings . plugins . allowed _plugins . length )
return cb ( ) ;
} else {
// load the server_functions.js file from the plugin
const serverFunctions = require ( ` ../plugins/ ${ pluginName } /lib/server_functions ` ) ;
// check if the plugin_load function exists
if ( typeof serverFunctions . plugin _load !== 'function' ) {
console . log ( ` WARNING: Plugin ' ${ pluginName } ' is missing the plugin_load function ` ) ;
checkedPlugins ++ ;
if ( checkedPlugins == settings . plugins . allowed _plugins . length )
return cb ( ) ;
} else {
// call the plugin_load function to initialize the plugin
serverFunctions . plugin _load ( coin , function ( ) {
checkedPlugins ++ ;
if ( checkedPlugins == settings . plugins . allowed _plugins . length )
return cb ( ) ;
} ) ;
}
}
}
}
} ) ;
} else
return cb ( ) ;
}
2023-05-11 20:12:17 -06:00
// find masternode by txid and
function find _masternode ( txhash , addr , cb ) {
Masternode . findOne ( { txhash : txhash , addr : addr } ) . then ( ( masternode ) => {
if ( masternode )
return cb ( masternode ) ;
else
return cb ( null ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
} ) ;
}
2023-09-26 18:22:28 -06:00
function after _update _claim _name ( hash , claim _name , cb ) {
// update claim name in richlist
module . exports . update _richlist _claim _name ( hash , claim _name , function ( ) {
// update claim name in masternode list
module . exports . update _masternode _claim _name ( hash , claim _name , function ( ) {
return cb ( ) ;
} ) ;
} ) ;
}
2019-05-27 10:33:22 -07:00
module . exports = {
// initialize DB
connect : function ( database , cb ) {
2022-12-16 19:17:37 -07:00
mongoose . set ( 'strictQuery' , true ) ;
2023-08-20 20:41:41 -06:00
if ( database == null )
database = 'mongodb://' + encodeURIComponent ( settings . dbsettings . user ) +
':' + encodeURIComponent ( settings . dbsettings . password ) +
'@' + settings . dbsettings . address +
':' + settings . dbsettings . port +
'/' + settings . dbsettings . database ;
2023-05-07 20:55:29 -06:00
mongoose . connect ( database ) . then ( ( ) => {
2021-01-22 15:04:32 -07:00
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( 'Error: Unable to connect to database: %s' , err ) ;
process . exit ( 999 ) ;
2020-11-20 16:28:28 -07:00
} ) ;
} ,
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
} ,
2023-09-26 18:22:28 -06:00
update _claim _name : function ( hash , claim _name , cb ) {
2024-03-20 19:36:16 -06:00
// check if the address has received coins before by looking up the address in the local database
module . exports . get _address ( hash , false , function ( address ) {
// check if the address was found in the local database
if ( address ) {
// check if the claim name is being removed
if ( claim _name == null || claim _name == '' ) {
// remove the claim name
ClaimAddress . findOneAndDelete ( { a _id : hash } ) . then ( ( ) => {
// run processes after the claim name has been updated
after _update _claim _name ( hash , claim _name , function ( ) {
return cb ( '' ) ;
} ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( err ) ;
} ) ;
} else {
// add or update the claim name
ClaimAddress . updateOne ( { a _id : hash } , {
a _id : hash ,
claim _name : claim _name
} , {
upsert : true
} ) . then ( ( ) => {
// run processes after the claim name has been updated
after _update _claim _name ( hash , claim _name , function ( ) {
return cb ( '' ) ;
} ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( err ) ;
} ) ;
}
} else
return cb ( 'no_address' ) ;
} ) ;
2020-11-22 14:39:10 -07:00
} ,
2020-12-30 18:22:02 -07:00
update _richlist _claim _name : function ( hash , claim _name , cb ) {
// check if the richlist is enabled
2021-01-22 15:04:32 -07:00
if ( settings . richlist _page . enabled == true ) {
2020-12-30 18:22:02 -07:00
// ensure that if this address exists in the richlist that it displays the new alias
2021-01-22 15:04:32 -07:00
module . exports . get _richlist ( settings . coin . name , function ( richlist ) {
2020-12-30 18:22:02 -07:00
var updated = false ;
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// 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' ] = claim _name ;
// mark as updated
updated = true ;
}
}
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// 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' ] = claim _name ;
// mark as updated
2021-03-17 17:54:09 -06:00
updated = true ;
2020-12-30 18:22:02 -07:00
}
}
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// check if the address was updated in the richlist
if ( updated ) {
// save the richlist back to collection
2021-01-22 15:04:32 -07:00
Richlist . updateOne ( { coin : settings . coin . name } , {
2020-12-30 18:22:02 -07:00
received : richlist . received ,
balance : richlist . balance
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-30 18:22:02 -07:00
// finished updating the claim label
return cb ( '' ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( '' ) ;
2020-12-30 18:22:02 -07:00
} ) ;
} else {
// finished updating the claim label
return cb ( '' ) ;
}
} ) ;
} else {
// richlist is not enabled so nothing to update
return cb ( '' ) ;
}
} ,
update _masternode _claim _name : function ( hash , claim _name , cb ) {
// check if the masternode list is enabled
2021-01-22 15:04:32 -07:00
if ( settings . masternodes _page . enabled == true ) {
2020-12-30 18:22:02 -07:00
// ensure that if this address exists in the masternode that it displays the new alias
module . exports . get _masternodes ( function ( masternodes ) {
var updated = false ;
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// loop through masternode addresses
for ( m = 0 ; m < masternodes . length ; m ++ ) {
// check if this is the correct address
2024-02-02 15:21:45 -07:00
if ( masternodes [ m ] . addr == hash ) {
2020-12-30 18:22:02 -07:00
// update the claim name
masternodes [ m ] [ 'claim_name' ] = claim _name ;
// mark as updated
updated = true ;
}
}
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// check if the address was updated in the masternode list
if ( updated ) {
// save the updated masternode back to collection
Masternode . updateOne ( { addr : hash } , {
claim _name : claim _name
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-30 18:22:02 -07:00
// finished updating the claim label
return cb ( '' ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( '' ) ;
2020-12-30 18:22:02 -07:00
} ) ;
} else {
// finished updating the claim label
return cb ( '' ) ;
}
} ) ;
} else {
// masternode list is not enabled so nothing to update
return cb ( '' ) ;
}
} ,
2021-03-20 01:34:13 -06:00
check _txes : function ( cb ) {
2023-05-07 20:55:29 -06:00
Tx . findOne ( { } ) . then ( ( tx ) => {
2021-03-20 01:34:13 -06:00
if ( tx ) {
// collection has data
// determine if tx_type field exists
2024-02-06 19:44:11 -07:00
check _add _db _field ( Tx , 'tx_type' , null , function ( ) {
2021-07-09 20:39:02 -06:00
// determine if op_return field exists
2024-02-06 19:44:11 -07:00
check _add _db _field ( Tx , 'op_return' , null , function ( ) {
// determine if algo field exists
check _add _db _field ( Tx , 'algo' , null , function ( ) {
return cb ( true ) ;
} ) ;
2021-07-09 20:39:02 -06:00
} ) ;
2021-03-20 01:34:13 -06:00
} ) ;
} else
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2021-03-20 01:34:13 -06:00
} ) ;
} ,
2019-05-27 10:33:22 -07:00
check _stats : function ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Stats . findOne ( { coin : coin } ) . then ( ( stats ) => {
2021-03-17 17:54:09 -06:00
if ( stats ) {
2021-03-20 01:34:13 -06:00
// collection has data
// determine if last_usd_price field exists
check _add _db _field ( Stats , 'last_usd_price' , 0 , function ( exists ) {
2023-05-06 12:36:35 -06:00
// determine if orphan_index field exists
check _add _db _field ( Stats , 'orphan_index' , 0 , function ( exists ) {
// determine if orphan_current field exists
check _add _db _field ( Stats , 'orphan_current' , 0 , function ( exists ) {
return cb ( true ) ;
} ) ;
} ) ;
2021-03-17 17:54:09 -06:00
} ) ;
} else
2019-05-27 10:33:22 -07:00
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
get _stats : function ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Stats . findOne ( { coin : coin } ) . then ( ( stats ) => {
2021-03-17 17:54:09 -06:00
if ( stats )
2019-05-27 10:33:22 -07:00
return cb ( stats ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( null ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2022-04-30 20:53:10 -06:00
create _stats : function ( coin , skip , cb ) {
// check if stats need to be created
if ( ! skip ) {
var newStats = new Stats ( {
coin : coin ,
2023-05-06 12:36:35 -06:00
last : 0 ,
orphan _index : 0 ,
2023-09-26 18:22:28 -06:00
orphan _current : 0 ,
newer _claim _address : true
2022-04-30 20:53:10 -06:00
} ) ;
2019-05-27 10:33:22 -07:00
2023-05-07 20:55:29 -06:00
newStats . save ( ) . then ( ( ) => {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . entry _created _successfully . replace ( '{1}' , 'stats' ) . replace ( '{2}' , coin ) } ` ) ;
2023-05-07 20:55:29 -06:00
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2022-04-30 20:53:10 -06:00
} ) ;
} else
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ,
2019-10-17 21:51:13 -06:00
get _address : function ( hash , caseSensitive , cb ) {
2021-03-17 17:54:09 -06:00
find _address ( hash , caseSensitive , function ( address ) {
2019-05-27 10:33:22 -07:00
return cb ( address ) ;
} ) ;
} ,
2023-09-26 18:22:28 -06:00
get _claim _name : function ( hash , cb ) {
find _claim _name ( hash , function ( claim _name ) {
return cb ( claim _name ) ;
} ) ;
} ,
2019-05-27 10:33:22 -07:00
get _richlist : function ( coin , cb ) {
2021-03-17 17:54:09 -06:00
find _richlist ( coin , function ( richlist ) {
2019-05-27 10:33:22 -07:00
return cb ( richlist ) ;
} ) ;
} ,
2020-12-23 18:40:10 -07:00
// 'list' variable can be either 'received' or 'balance'
2021-01-22 15:04:32 -07:00
update _richlist : function ( list , cb ) {
// number of addresses to lookup
var total _addresses = 100 ;
// create the burn address array so that we omit burned coins from the rich list
var burn _addresses = settings . richlist _page . burned _coins . addresses ;
2021-03-17 17:54:09 -06:00
2021-03-20 15:02:42 -06:00
// always omit special addresses used by the explorer from the richlist (coinbase, hidden address and unknown address)
burn _addresses . push ( 'coinbase' ) ;
2021-03-20 01:34:13 -06:00
burn _addresses . push ( 'hidden_address' ) ;
2021-03-20 15:02:42 -06:00
burn _addresses . push ( 'unknown_address' ) ;
2019-10-18 22:31:07 -06:00
2020-12-23 18:40:10 -07:00
if ( list == 'received' ) {
2021-01-22 15:04:32 -07:00
// update 'received' richlist data
2023-09-26 18:22:28 -06:00
Address . aggregate ( [
{ $match : {
a _id : { $nin : burn _addresses }
} } ,
{ $sort : { received : - 1 } } ,
{ $limit : total _addresses } ,
{ $lookup :
{
from : "claimaddresses" ,
localField : "a_id" ,
foreignField : "a_id" ,
as : "claim_name"
}
} ,
{ $unwind : { path : "$claim_name" , preserveNullAndEmptyArrays : true } } ,
{
$addFields :
{
'claim_name' : '$claim_name.claim_name'
}
} ,
{
$project :
{
"_id" : 0 ,
"__v" : 0 ,
"sent" : 0
}
}
] ) . then ( ( addresses ) => {
2021-01-22 15:04:32 -07:00
Richlist . updateOne ( { coin : settings . coin . name } , {
2020-12-23 18:40:10 -07:00
received : addresses
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
2019-05-27 10:33:22 -07:00
return cb ( ) ;
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2020-12-23 18:40:10 -07:00
} else {
2021-01-22 15:04:32 -07:00
// update 'balance' richlist data
// check if burned addresses are in use and if it is necessary to track burned balances
if ( settings . richlist _page . burned _coins . addresses == null || settings . richlist _page . burned _coins . addresses . length == 0 || ! settings . richlist _page . burned _coins . include _burned _coins _in _distribution ) {
// update 'balance' richlist data by filtering burned coin addresses immidiately
2023-09-26 18:22:28 -06:00
Address . aggregate ( [
{ $match : {
a _id : { $nin : burn _addresses }
} } ,
{ $sort : { balance : - 1 } } ,
{ $limit : total _addresses } ,
{ $lookup :
{
from : "claimaddresses" ,
localField : "a_id" ,
foreignField : "a_id" ,
as : "claim_name"
}
} ,
{ $unwind : { path : "$claim_name" , preserveNullAndEmptyArrays : true } } ,
{
$addFields :
{
'claim_name' : '$claim_name.claim_name'
}
} ,
{
$project :
{
"_id" : 0 ,
"__v" : 0 ,
"sent" : 0
}
}
] ) . then ( ( addresses ) => {
2021-01-22 15:04:32 -07:00
Richlist . updateOne ( { coin : settings . coin . name } , {
balance : addresses
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
2021-01-22 15:04:32 -07:00
return cb ( ) ;
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2021-01-22 15:04:32 -07:00
} else {
// do not omit burned addresses from database query. instead, increase the limit of returned addresses and manually remove each burned address that made it into the rich list after recording the burned balance
2023-09-26 18:22:28 -06:00
Address . aggregate ( [
{ $sort : { balance : - 1 } } ,
{ $limit : total _addresses + burn _addresses . length } ,
{ $lookup :
{
from : "claimaddresses" ,
localField : "a_id" ,
foreignField : "a_id" ,
as : "claim_name"
}
} ,
{ $unwind : { path : "$claim_name" , preserveNullAndEmptyArrays : true } } ,
{
$addFields :
{
'claim_name' : '$claim_name.claim_name'
}
} ,
{
$project :
{
"_id" : 0 ,
"__v" : 0 ,
"sent" : 0
}
}
] ) . then ( ( addresses ) => {
2021-01-22 15:04:32 -07:00
var return _addresses = [ ] ;
var burned _balance = 0.0 ;
2021-03-17 17:54:09 -06:00
2021-01-22 15:04:32 -07:00
// loop through all richlist addresses
addresses . forEach ( function ( address ) {
// check if this is a burned coin address
if ( burn _addresses . findIndex ( p => p . toLowerCase ( ) == address . a _id . toLowerCase ( ) ) > - 1 ) {
// this is a burned coin address so save the balance, not the address
burned _balance += address . balance ;
} else if ( return _addresses . length < total _addresses ) {
// this is not a burned address so add it to the return list
return _addresses . push ( address ) ;
}
} ) ;
2021-03-17 17:54:09 -06:00
2021-01-22 15:04:32 -07:00
// update the rich list collection
Richlist . updateOne ( { coin : settings . coin . name } , {
balance : return _addresses ,
burned : burned _balance
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
2021-01-22 15:04:32 -07:00
return cb ( ) ;
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2021-01-22 15:04:32 -07:00
} ) ;
}
2019-05-27 10:33:22 -07:00
}
} ,
get _tx : function ( txid , cb ) {
2021-03-17 17:54:09 -06:00
find _tx ( txid , function ( tx ) {
2019-05-27 10:33:22 -07:00
return cb ( tx ) ;
} ) ;
} ,
get _txs : function ( block , cb ) {
var txs = [ ] ;
2021-03-17 17:54:09 -06:00
2019-05-27 10:33:22 -07:00
lib . syncLoop ( block . tx . length , function ( loop ) {
var i = loop . iteration ( ) ;
2021-03-17 17:54:09 -06:00
find _tx ( block . tx [ i ] , function ( tx ) {
2019-05-27 10:33:22 -07:00
if ( tx ) {
txs . push ( tx ) ;
loop . next ( ) ;
2021-03-17 17:54:09 -06:00
} else
2019-05-27 10:33:22 -07:00
loop . next ( ) ;
2021-03-17 17:54:09 -06:00
} ) ;
} , function ( ) {
2019-05-27 10:33:22 -07:00
return cb ( txs ) ;
} ) ;
} ,
2021-01-01 18:24:39 -07:00
get _last _txs : function ( start , length , min , internal , cb ) {
2020-12-18 14:55:30 -07:00
this . get _last _txs _ajax ( start , length , min , function ( txs , count ) {
2020-11-28 20:40:37 -07:00
var data = [ ] ;
2021-01-01 18:24:39 -07:00
for ( i = 0 ; i < txs . length ; i ++ ) {
if ( internal ) {
var row = [ ] ;
2021-03-17 17:54:09 -06:00
2021-01-01 18:24:39 -07:00
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 / 100000000 ) ) ;
row . push ( txs [ i ] . timestamp ) ;
2021-03-17 17:54:09 -06:00
2024-02-06 19:44:11 -07:00
if ( settings . block _page . multi _algorithm . show _algo == true )
row . push ( 'algo:' + ( txs [ i ] . algo == null ? '' : txs [ i ] . algo ) ) ;
2021-01-01 18:24:39 -07:00
data . push ( row ) ;
} else {
2024-02-06 19:44:11 -07:00
let data _entry = {
2021-01-01 18:24:39 -07:00
blockindex : txs [ i ] . blockindex ,
blockhash : txs [ i ] . blockhash ,
txid : txs [ i ] . txid ,
recipients : txs [ i ] . vout . length ,
amount : ( txs [ i ] . total / 100000000 ) ,
timestamp : txs [ i ] . timestamp
2024-02-06 19:44:11 -07:00
} ;
if ( settings . block _page . multi _algorithm . show _algo == true )
data _entry . algo = ( txs [ i ] . algo == null ? '' : txs [ i ] . algo ) ;
data . push ( data _entry ) ;
2021-01-01 18:24:39 -07:00
}
2020-11-28 20:40:37 -07:00
}
2021-03-17 17:54:09 -06:00
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
2023-05-07 20:55:29 -06:00
Tx . find ( { 'total' : { $gte : min } } ) . countDocuments ( ) . then ( ( count ) => {
2021-03-17 17:54:09 -06:00
// get last transactions where there is at least 1 vout
2023-05-07 20:55:29 -06:00
Tx . find ( { 'total' : { $gte : min } , 'vout' : { $gte : { $size : 1 } } } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( ) . then ( ( txs ) => {
return cb ( txs , count ) ;
} ) . catch ( ( err ) => {
return cb ( err ) ;
2020-12-10 17:51:46 -07:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
return cb ( err ) ;
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)
2023-05-07 20:55:29 -06:00
Stats . findOne ( { coin : settings . coin . name } ) . then ( ( stats ) => {
2020-12-10 17:51:46 -07:00
// Get last transactions where there is at least 1 vout
2023-05-07 20:55:29 -06:00
Tx . find ( { 'total' : { $gte : min } , 'vout' : { $gte : { $size : 1 } } } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( ) . then ( ( txs ) => {
return cb ( txs , stats . txes ) ;
} ) . catch ( ( err ) => {
return cb ( err ) ;
2020-12-10 17:51:46 -07:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
return cb ( err ) ;
2020-12-10 17:51:46 -07:00
} ) ;
}
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 ;
2021-03-17 17:54:09 -06:00
2023-05-07 20:55:29 -06:00
AddressTx . find ( { a _id : hash } ) . countDocuments ( ) . then ( ( count ) => {
totalCount = count ;
AddressTx . aggregate ( [
{ $match : { a _id : hash } } ,
{ $sort : { blockindex : - 1 } } ,
{ $skip : Number ( start ) } ,
{
$group : {
_id : '' ,
balance : { $sum : '$amount' }
}
} ,
{
$project : {
_id : 0 ,
balance : '$balance'
2020-11-19 21:37:42 -07:00
}
2023-05-07 20:55:29 -06:00
} ,
{ $sort : { blockindex : - 1 } }
] ) . then ( ( balance _sum ) => {
AddressTx . find ( { a _id : hash } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( ) . then ( ( address _tx ) => {
var txs = [ ] ;
var count = address _tx . length ;
var running _balance = balance _sum . length > 0 ? balance _sum [ 0 ] . balance : 0 ;
var txs = [ ] ;
lib . syncLoop ( count , function ( loop ) {
var i = loop . iteration ( ) ;
find _tx ( address _tx [ i ] . txid , function ( tx ) {
if ( tx && ! txs . includes ( tx ) ) {
tx . balance = running _balance ;
txs . push ( tx ) ;
loop . next ( ) ;
} else if ( ! txs . includes ( tx ) ) {
txs . push ( "1. Not found" ) ;
loop . next ( ) ;
} else
loop . next ( ) ;
running _balance = running _balance - address _tx [ i ] . amount ;
} ) ;
} , function ( ) {
return cb ( txs , totalCount ) ;
} ) ;
} ) . catch ( ( err ) => {
return cb ( err ) ;
2020-11-19 21:37:42 -07:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
return cb ( err ) ;
} ) ;
} ) . catch ( ( err ) => {
return cb ( err ) ;
2020-11-19 21:37:42 -07:00
} ) ;
} ,
2021-01-22 15:04:32 -07:00
create _market : function ( coin _symbol , pair _symbol , market , cb ) {
2019-05-27 10:33:22 -07:00
var newMarkets = new Markets ( {
market : market ,
2021-01-22 15:04:32 -07:00
coin _symbol : coin _symbol ,
2021-03-17 17:54:09 -06:00
pair _symbol : pair _symbol
2019-05-27 10:33:22 -07:00
} ) ;
2023-05-07 20:55:29 -06:00
newMarkets . save ( ) . then ( ( ) => {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . entry _created _successfully . replace ( '{1}' , 'market' ) . replace ( '{2}' , ` ${ market } [ ${ coin _symbol } / ${ pair _symbol } ] ` ) } ` ) ;
2023-05-07 20:55:29 -06:00
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2021-01-22 15:04:32 -07:00
// check if market data exists for a given market and trading pair
check _market : function ( market , coin _symbol , pair _symbol , cb ) {
2023-05-07 20:55:29 -06:00
Markets . findOne ( { market : market , coin _symbol : coin _symbol , pair _symbol : pair _symbol } ) . then ( ( exists ) => {
2021-01-22 15:04:32 -07:00
return cb ( market , exists ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( market , false ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2021-01-22 15:04:32 -07:00
// gets market data for given market and trading pair
get _market : function ( market , coin _symbol , pair _symbol , cb ) {
2023-05-07 20:55:29 -06:00
Markets . findOne ( { market : market , coin _symbol : coin _symbol , pair _symbol : pair _symbol } ) . then ( ( data ) => {
2021-01-22 15:04:32 -07:00
if ( data )
2019-05-27 10:33:22 -07:00
return cb ( data ) ;
2021-01-22 15:04:32 -07:00
else
2019-05-27 10:33:22 -07:00
return cb ( null ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2022-04-30 20:53:10 -06:00
// creates initial richlist entry in database; called on first launch of explorer + after restore or delete database
create _richlist : function ( coin , skip , cb ) {
// check if stats need to be created
if ( ! skip ) {
var newRichlist = new Richlist ( {
coin : coin
} ) ;
2021-03-17 17:54:09 -06:00
2023-05-07 20:55:29 -06:00
newRichlist . save ( ) . then ( ( ) => {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . entry _created _successfully . replace ( '{1}' , 'richlist' ) . replace ( '{2}' , coin ) } ` ) ;
2023-05-07 20:55:29 -06:00
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2022-04-30 20:53:10 -06:00
} ) ;
} else
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ,
2020-11-20 14:06:53 -07:00
// drops richlist data for given coin
delete _richlist : function ( coin , cb ) {
2023-12-27 17:08:24 -07:00
Richlist . findOneAndDelete ( { coin : coin } ) . then ( ( exists ) => {
2021-03-17 17:54:09 -06:00
if ( exists )
2020-11-20 14:06:53 -07:00
return cb ( true ) ;
2021-03-17 17:54:09 -06:00
else
2020-11-20 14:06:53 -07:00
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-11-20 14:06:53 -07:00
} ) ;
} ,
2021-03-17 17:54:09 -06:00
2019-05-27 10:33:22 -07:00
// checks richlist data exists for given coin
check _richlist : function ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Richlist . findOne ( { coin : coin } ) . then ( ( exists ) => {
2021-03-17 17:54:09 -06:00
if ( exists )
2019-05-27 10:33:22 -07:00
return cb ( true ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
create _heavy : function ( coin , cb ) {
var newHeavy = new Heavy ( {
2021-03-17 17:54:09 -06:00
coin : coin
2019-05-27 10:33:22 -07:00
} ) ;
2021-03-17 17:54:09 -06:00
2023-05-07 20:55:29 -06:00
newHeavy . save ( ) . then ( ( ) => {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . entry _created _successfully . replace ( '{1}' , 'heavycoin' ) . replace ( '{2}' , coin ) } ` ) ;
2023-05-07 20:55:29 -06:00
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
check _heavy : function ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Heavy . findOne ( { coin : coin } ) . then ( ( exists ) => {
2021-03-17 17:54:09 -06:00
if ( exists )
2019-05-27 10:33:22 -07:00
return cb ( true ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
get _heavy : function ( coin , cb ) {
2023-05-07 20:55:29 -06:00
Heavy . findOne ( { coin : coin } ) . then ( ( heavy ) => {
2021-03-17 17:54:09 -06:00
if ( heavy )
2019-05-27 10:33:22 -07:00
return cb ( heavy ) ;
2021-03-17 17:54:09 -06:00
else
2019-05-27 10:33:22 -07:00
return cb ( null ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2021-01-22 15:04:32 -07:00
get _distribution : function ( richlist , stats , cb ) {
2019-05-27 10:33:22 -07:00
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 }
} ;
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
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 ;
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
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 ) ;
}
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
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 ) ;
}
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
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 ) ;
}
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
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 ) ;
}
2021-01-22 15:04:32 -07:00
2019-05-27 10:33:22 -07:00
loop . next ( ) ;
2021-01-22 15:04:32 -07:00
} , 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 - ( settings . richlist _page . burned _coins . include _burned _coins _in _distribution == true && richlist . burned > 0 ? ( ( richlist . burned / 100000000 ) / stats . supply ) * 100 : 0 ) ) . 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 - ( settings . richlist _page . burned _coins . include _burned _coins _in _distribution == true && richlist . burned > 0 ? ( richlist . burned / 100000000 ) : 0 ) ) . toFixed ( 8 ) ;
2019-05-27 10:33:22 -07:00
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 ) ;
2021-03-17 17:54:09 -06:00
2019-05-27 10:33:22 -07:00
return cb ( distribution ) ;
} ) ;
} ,
2020-12-31 15:19:48 -07:00
2021-01-22 15:04:32 -07:00
// updates heavycoin stats
2019-05-27 10:33:22 -07:00
// height: current block height, count: amount of votes to store
update _heavy : function ( coin , height , count , cb ) {
var newVotes = [ ] ;
2020-12-31 15:19:48 -07:00
2019-05-27 10:33:22 -07:00
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 ) {
2021-01-22 15:04:32 -07:00
module . exports . get _stats ( settings . coin . name , function ( stats ) {
2019-05-27 10:33:22 -07:00
lib . get _estnext ( function ( estnext ) {
lib . get _nextin ( function ( nextin ) {
lib . syncLoop ( count , function ( loop ) {
var i = loop . iteration ( ) ;
2021-03-17 17:54:09 -06:00
2020-12-31 15:19:48 -07:00
lib . get _blockhash ( height - i , function ( hash ) {
2019-05-27 10:33:22 -07:00
lib . get _block ( hash , function ( block ) {
2020-12-31 15:19:48 -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 ( ) ;
} ) ;
} ) ;
2020-12-31 15:19:48 -07:00
} , function ( ) {
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 ) ,
2021-01-22 15:04:32 -07:00
supply : ( stats && stats . supply ? stats . supply : 0 ) ,
2020-12-07 21:32:43 -07:00
cap : ( maxmoney ? maxmoney : 0 ) ,
estnext : ( estnext ? estnext : 0 ) ,
phase : ( phase ? phase : 'N/A' ) ,
maxvote : ( maxvote ? maxvote : 0 ) ,
nextin : ( nextin ? nextin : 'N/A' ) ,
2020-12-31 15:19:48 -07:00
votes : newVotes
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
// update reward_last_updated value
2021-01-22 15:04:32 -07:00
module . exports . update _last _updated _stats ( settings . coin . name , { reward _last _updated : Math . floor ( new Date ( ) / 1000 ) } , function ( new _cb ) {
2022-04-30 20:53:10 -06:00
console . log ( 'Heavycoin update complete' ) ;
2020-12-31 15:19:48 -07:00
return cb ( ) ;
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ,
2022-04-11 01:37:27 -06:00
// updates network history (nethash and difficulty) data
// height: current block height
update _network _history : function ( height , cb ) {
// lookup network history data for this block height
2023-05-07 20:55:29 -06:00
NetworkHistory . findOne ( { blockindex : height } ) . then ( ( network _hist ) => {
2022-04-11 01:37:27 -06:00
// check if there is already network history data for this block height
if ( ! network _hist ) {
// lookup network hashrate
lib . get _hashrate ( function ( hashrate ) {
// lookup network difficulty
lib . get _difficulty ( function ( difficulty ) {
2022-06-24 19:43:02 -06:00
var difficultyPOW = 0 ;
var difficultyPOS = 0 ;
if ( difficulty && difficulty [ 'proof-of-work' ] ) {
if ( settings . shared _pages . difficulty == 'Hybrid' ) {
difficultyPOS = difficulty [ 'proof-of-stake' ] ;
difficultyPOW = difficulty [ 'proof-of-work' ] ;
} else if ( settings . shared _pages . difficulty == 'POW' )
difficultyPOW = difficulty [ 'proof-of-work' ] ;
else
difficultyPOS = difficulty [ 'proof-of-stake' ] ;
} else if ( settings . shared _pages . difficulty == 'POW' )
difficultyPOW = difficulty ;
else
difficultyPOS = difficulty ;
2022-04-11 01:37:27 -06:00
// create a new network history record
var newNetworkHistory = new NetworkHistory ( {
blockindex : height ,
nethash : ( hashrate == null || hashrate == '-' ? 0 : hashrate ) ,
2022-06-24 19:43:02 -06:00
difficulty _pow : difficultyPOW ,
difficulty _pos : difficultyPOS ,
2022-04-11 01:37:27 -06:00
} ) ;
// save the new network history record
2023-05-07 20:55:29 -06:00
newNetworkHistory . save ( ) . then ( ( ) => {
// get the count of network history records
NetworkHistory . find ( { } ) . countDocuments ( ) . then ( ( count ) => {
// read maximum allowed records from settings
let max _records = settings . network _history . max _saved _records ;
// check if the current count of records is greater than the maximum allowed
if ( count > max _records ) {
// prune network history records to keep collection small and quick to access
NetworkHistory . find ( ) . select ( 'blockindex' ) . sort ( { blockindex : 1 } ) . limit ( count - max _records ) . exec ( ) . then ( ( records ) => {
// create a list of the oldest network history ids that will be deleted
const ids = records . map ( ( doc ) => doc . blockindex ) ;
// delete old network history records
NetworkHistory . deleteMany ( { blockindex : { $in : ids } } ) . then ( ( ) => {
console . log ( 'Network history update complete' ) ;
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2022-04-11 01:37:27 -06:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
2022-04-11 01:37:27 -06:00
return cb ( ) ;
2023-05-07 20:55:29 -06:00
} ) ;
} else {
console . log ( 'Network history update complete' ) ;
return cb ( ) ;
}
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
} ) ;
} ) . catch ( ( err ) => {
console . log ( 'Error updating network history: ' + err ) ;
return cb ( ) ;
2022-04-11 01:37:27 -06:00
} ) ;
} ) ;
} ) ;
} else {
// skip saving network history data when the block hasn't moved since saving last time
return cb ( ) ;
}
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2022-04-11 01:37:27 -06:00
} ) ;
} ,
2019-05-27 10:33:22 -07:00
// updates market data for given market; called by sync.js
2021-01-22 15:04:32 -07:00
update _markets _db : function ( market , coin _symbol , pair _symbol , cb ) {
2020-12-08 22:52:15 -07:00
// check if market exists
if ( fs . existsSync ( './lib/markets/' + market + '.js' ) ) {
2024-01-05 00:47:22 -07:00
get _market _data ( market , coin _symbol , pair _symbol , function ( market _err , obj ) {
2021-01-22 15:04:32 -07:00
// check if there was an error with getting market data
2024-01-05 00:47:22 -07:00
if ( market _err == null ) {
2021-01-22 15:04:32 -07:00
// update the market collection for the current market and trading pair combination
Markets . updateOne ( { market : market , coin _symbol : coin _symbol , pair _symbol : pair _symbol } , {
2020-12-08 22:52:15 -07:00
chartdata : JSON . stringify ( obj . chartdata ) ,
buys : obj . buys ,
sells : obj . sells ,
history : obj . trades ,
summary : obj . stats
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2024-01-05 00:47:22 -07:00
// finished updating market data
return cb ( null , obj . stats . last ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
2024-01-05 00:47:22 -07:00
return cb ( err , null ) ;
2020-12-08 22:52:15 -07:00
} ) ;
} else {
2021-01-22 15:04:32 -07:00
// an error occurred with getting market data so return the error msg
2024-01-05 00:47:22 -07:00
return cb ( market _err , null ) ;
2020-12-08 22:52:15 -07:00
}
} ) ;
} else {
// market does not exist
2024-01-05 00:47:22 -07:00
return cb ( 'market is not installed' , null ) ;
2021-01-22 15:04:32 -07:00
}
2019-05-27 10:33:22 -07:00
} ,
// updates stats data for given coin; called by sync.js
update _db : function ( coin , cb ) {
lib . get _blockcount ( function ( count ) {
2021-02-03 20:54:15 -07:00
// check to ensure count is a positive number
if ( ! count || ( count != null && typeof count === 'number' && count < 0 ) ) {
2022-04-30 20:53:10 -06:00
console . log ( 'Error: Unable to connect to explorer API' ) ;
2021-03-17 17:54:09 -06:00
2019-05-27 10:33:22 -07:00
return cb ( false ) ;
}
2021-03-17 17:54:09 -06:00
2021-01-22 15:04:32 -07:00
lib . get _supply ( function ( supply ) {
2019-05-27 10:33:22 -07:00
lib . get _connectioncount ( function ( connections ) {
2023-05-07 20:55:29 -06:00
Stats . findOne ( { coin : coin } ) . then ( ( stats ) => {
2020-12-03 14:16:34 -07:00
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 )
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-03 14:16:34 -07:00
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 ) ,
2023-05-06 12:36:35 -06:00
txes : ( stats . txes ? stats . txes : 0 ) ,
orphan _index : ( stats . orphan _index ? stats . orphan _index : 0 ) ,
orphan _current : ( stats . orphan _current ? stats . orphan _current : 0 )
2020-12-03 14:16:34 -07:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( "Error during stats update: %s" , err ) ;
return cb ( false ) ;
2020-12-03 14:16:34 -07:00
} ) ;
} else {
2022-04-30 20:53:10 -06:00
console . log ( "Error during stats update: %s" , ( err ? err : 'Cannot find stats collection' ) ) ;
2020-12-03 14:16:34 -07:00
return cb ( false ) ;
2020-11-22 20:40:15 -07:00
}
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ) ;
} ) ;
} ) ;
} ,
create _peer : function ( params , cb ) {
var newPeer = new Peers ( params ) ;
2021-03-17 17:54:09 -06:00
2023-05-07 20:55:29 -06:00
newPeer . save ( ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2019-05-27 10:33:22 -07:00
} ) ;
} ,
2022-07-01 21:11:57 -06:00
find _peer : function ( address , port , cb ) {
2023-05-07 20:55:29 -06:00
Peers . findOne ( { address : address , port : port } ) . then ( ( peer ) => {
if ( peer )
return cb ( peer ) ;
else
return cb ( null )
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2021-03-17 17:54:09 -06:00
} ) ;
2019-05-27 10:33:22 -07:00
} ,
2022-07-01 21:11:57 -06:00
drop _peer : function ( address , port , cb ) {
2023-05-07 20:55:29 -06:00
Peers . deleteOne ( { address : address , port : port } ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2021-03-17 17:54:09 -06:00
} ) ;
2020-11-20 14:49:14 -07:00
} ,
drop _peers : function ( cb ) {
2023-05-07 20:55:29 -06:00
Peers . deleteMany ( { } ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2021-03-17 17:54:09 -06:00
} ) ;
2020-11-20 14:49:14 -07:00
} ,
2019-05-27 10:33:22 -07:00
get _peers : function ( cb ) {
2023-05-07 20:55:29 -06:00
Peers . find ( ) . sort ( { address : 1 , protocol : - 1 , port : 1 } ) . exec ( ) . then ( ( peers ) => {
return cb ( peers ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( [ ] ) ;
2019-05-27 10:33:22 -07:00
} ) ;
2020-12-08 22:52:15 -07:00
} ,
2021-05-03 12:28:08 -06:00
check _masternodes : function ( cb ) {
2023-05-07 20:55:29 -06:00
Masternode . findOne ( { } ) . then ( ( masternode ) => {
2021-05-03 12:28:08 -06:00
if ( masternode ) {
// collection has data
// determine if ip_address field exists
check _add _db _field ( Masternode , 'ip_address' , null , function ( exists ) {
// determine if last_paid_block field exists
check _add _db _field ( Masternode , 'last_paid_block' , null , function ( exists ) {
return cb ( true ) ;
} ) ;
} ) ;
} else
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2021-05-03 12:28:08 -06:00
} ) ;
} ,
2020-12-30 18:22:02 -07:00
// determine if masternode exists and save masternode to collection
2024-02-02 15:21:45 -07:00
save _masternode : function ( raw _masternode , object _key , cb ) {
let txhash = raw _masternode . txhash ;
let addr = raw _masternode . addr ;
if ( txhash == null ) {
// try to use a different field for the txhash
txhash = raw _masternode . proTxHash ;
}
if ( addr == null ) {
// try to use a different field for the addr
addr = raw _masternode . payee ;
}
// check if the txhash and addr values were found
if ( txhash == null && addr == null ) {
try {
// attempt to parse out data separated by spaces
// supported formats:
// 1) status protocol pubkey lastseen activetime lastpaid lastpaidblock vin
// 2) status protocol pubkey vin lastseen activetime lastpaid
const parts = raw _masternode . trim ( ) . split ( /\s+/ ) ;
const result = { } ;
parts . forEach ( ( value , index ) => {
if ( index == 0 ) {
// always save the 1st value as the status
result [ 'status' ] = value ;
} else if ( index == 1 ) {
// always save the 2nd value as the version
result [ 'version' ] = parseInt ( value ) ;
} else if ( index == 2 ) {
// always save the 3rd value as the addr
result [ 'addr' ] = value ;
} else if ( index == 3 ) {
// determine if this is an ip address or lastseen time
if ( value . indexOf ( ':' ) > - 1 || value . indexOf ( '.' ) > - 1 ) {
// this is an ip address
result [ 'address' ] = value ;
} else if ( Number . isInteger ( Number ( value ) ) ) {
// this is a lastseen time value
result [ 'lastseen' ] = parseInt ( value ) ;
}
} else if ( index == 4 ) {
// check if this is a number value
if ( Number . isInteger ( Number ( value ) ) ) {
// determine if this is the lastseen or activetime
if ( result [ 'lastseen' ] == null ) {
// this must be lastseen since it has not yet been found
result [ 'lastseen' ] = parseInt ( value ) ;
} else {
// lastseen was already found so this much be the activetime
result [ 'activetime' ] = parseInt ( value ) ;
}
}
} else if ( index == 5 ) {
// check if this is a number value
if ( Number . isInteger ( Number ( value ) ) ) {
// determine if this is the activetime or lastpaid time
if ( result [ 'activetime' ] == null ) {
// this must be activetime since it has not yet been found
result [ 'activetime' ] = parseInt ( value ) ;
} else {
// activetime was already found so this much be the lastpaid time
result [ 'lastpaid' ] = parseInt ( value ) ;
}
}
} else if ( index == 6 ) {
// check if this is a number value
if ( Number . isInteger ( Number ( value ) ) ) {
// determine if this is the lastpaid time or lastpaidblock
if ( result [ 'lastpaid' ] == null ) {
// this must be lastpaid since it has not yet been found
result [ 'lastpaid' ] = parseInt ( value ) ;
} else {
// lastpaid was already found so this much be the lastpaidblock
result [ 'lastpaidblock' ] = parseInt ( value ) ;
}
}
} else {
// determine if this is an ip address
if ( value . indexOf ( ':' ) > - 1 || value . indexOf ( '.' ) > - 1 ) {
// this is an ip address
result [ 'address' ] = value ;
}
}
} ) ;
// check if the object_key is set
if ( object _key != null ) {
// try to separate the txhash from the outidx
const splitHash = object _key . split ( '-' ) ;
result [ 'txhash' ] = splitHash [ 0 ] ;
result [ 'outidx' ] = ( splitHash . length > 1 ? parseInt ( splitHash [ 1 ] ) : - 1 ) ;
} else {
result [ 'txhash' ] = "" ;
result [ 'outidx' ] = - 1 ;
}
// set the txhash and addr values
txhash = result [ 'txhash' ] ;
addr = result [ 'addr' ] ;
// update the raw_masternode object
raw _masternode = result ;
} catch {
// do nothing as the masternode will already fail to be saved below
}
} else {
// try to convert as many alternately named fields as possible so that there is only one set of fields to deal with
if ( raw _masternode . proTxHash != null ) {
raw _masternode . txhash = raw _masternode . proTxHash ;
delete raw _masternode . proTxHash ;
}
if ( raw _masternode . payee != null ) {
raw _masternode . addr = raw _masternode . payee ;
delete raw _masternode . payee ;
}
if ( raw _masternode . lastpaidtime != null ) {
raw _masternode . lastpaid = raw _masternode . lastpaidtime ;
delete raw _masternode . lastpaidtime ;
}
if ( raw _masternode . lastpaidtime != null ) {
raw _masternode . lastpaid = raw _masternode . lastpaidtime ;
delete raw _masternode . lastpaidtime ;
}
}
2023-05-11 20:12:17 -06:00
2020-12-30 18:22:02 -07:00
// lookup masternode in local collection
2023-05-11 20:12:17 -06:00
find _masternode ( txhash , addr , function ( masternode ) {
2020-12-30 18:22:02 -07:00
// determine if the claim address feature is enabled
2021-01-22 15:04:32 -07:00
if ( settings . claim _address _page . enabled == true ) {
2020-12-30 18:22:02 -07:00
// claim address is enabled so lookup the address claim name
2023-09-26 18:22:28 -06:00
find _claim _name ( addr , function ( claim _name ) {
if ( claim _name != null && claim _name != '' ) {
2020-12-30 18:22:02 -07:00
// save claim name to masternode obejct
2023-09-26 18:22:28 -06:00
raw _masternode . claim _name = claim _name ;
2020-12-30 18:22:02 -07:00
} else {
// save blank claim name to masternode obejct
raw _masternode . claim _name = '' ;
}
2021-03-17 17:54:09 -06:00
2020-12-30 18:22:02 -07:00
// add/update the masternode
module . exports . add _update _masternode ( raw _masternode , ( masternode == null ) , function ( success ) {
return cb ( success ) ;
} ) ;
} ) ;
} else {
// claim address is disabled so add/update the masternode
module . exports . add _update _masternode ( raw _masternode , ( masternode == null ) , function ( success ) {
return cb ( success ) ;
} ) ;
}
} ) ;
} ,
// add or update a single masternode
add _update _masternode ( masternode , add , cb ) {
2024-02-02 15:21:45 -07:00
if ( masternode . txhash == null ) {
2022-07-09 16:23:57 -06:00
console . log ( 'Masternode update error: Tx Hash is missing' ) ;
2020-12-30 18:22:02 -07:00
return cb ( false ) ;
} else {
2024-02-02 15:21:45 -07:00
var mn = new Masternode ( {
rank : masternode . rank ,
network : masternode . network ,
txhash : masternode . txhash ,
outidx : masternode . outidx ,
status : masternode . status ,
addr : masternode . addr ,
version : masternode . version ,
lastseen : ( masternode . lastseen == null ? Math . floor ( Date . now ( ) / 1000 ) : masternode . lastseen ) , // lastseen must have a value since masternodes are deleted based on the lastseen date being too old
activetime : masternode . activetime ,
lastpaid : masternode . lastpaid ,
last _paid _block : masternode . lastpaidblock ,
ip _address : masternode . address ,
claim _name : ( masternode . claim _name == null ? '' : masternode . claim _name )
} ) ;
2020-12-30 18:22:02 -07:00
if ( add ) {
// add new masternode to collection
2023-05-07 20:55:29 -06:00
mn . save ( ) . then ( ( ) => {
return cb ( true ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-30 18:22:02 -07:00
} ) ;
} else {
// update existing masternode in local collection
2024-02-02 15:21:45 -07:00
Masternode . updateOne ( { txhash : masternode . txhash } , masternode ) . then ( ( ) => {
2023-05-07 20:55:29 -06:00
return cb ( true ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-30 18:22:02 -07:00
} ) ;
}
}
} ,
// remove masternodes older than 24 hours
remove _old _masternodes : function ( cb ) {
2023-05-07 20:55:29 -06:00
Masternode . deleteMany ( { lastseen : { $lte : ( Math . floor ( Date . now ( ) / 1000 ) - 86400 ) } } ) . then ( ( ) => {
return cb ( ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( ) ;
2020-12-30 18:22:02 -07:00
} ) ;
} ,
// get the list of masternodes from local collection
get _masternodes : function ( cb ) {
2023-05-07 20:55:29 -06:00
Masternode . find ( { } ) . then ( ( masternodes ) => {
return cb ( masternodes ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( [ ] ) ;
2020-12-30 18:22:02 -07:00
} ) ;
} ,
2020-12-30 20:27:42 -07:00
get _masternode _rewards : function ( mnPayees , since , cb ) {
Tx . aggregate ( [
{ $match : {
"blockindex" : { $gt : Number ( since ) } ,
"vin" : [ ]
} } ,
{ "$unwind" : "$vout" } ,
{ $match : {
"vout.addresses" : { $in : [ mnPayees ] }
} }
2023-05-07 20:55:29 -06:00
] ) . then ( ( data ) => {
return cb ( data ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2020-12-30 20:27:42 -07:00
} ) ;
} ,
get _masternode _rewards _totals : function ( mnPayees , since , cb ) {
Tx . aggregate ( [
{ $match : {
"blockindex" : { $gt : Number ( since ) } ,
"vin" : [ ]
} } ,
{ "$unwind" : "$vout" } ,
{ $match : {
"vout.addresses" : { $in : [ mnPayees ] }
} } ,
{ $group : { _id : null , total : { $sum : "$vout.amount" } } }
2023-05-07 20:55:29 -06:00
] ) . then ( ( data ) => {
return cb ( ( data . length > 0 ? data [ 0 ] . total / 100000000 : 0 ) ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2020-12-30 20:27:42 -07:00
} ) ;
} ,
2020-12-30 18:22:02 -07:00
// updates last_updated stats; called by sync.js
update _last _updated _stats : function ( coin , param , cb ) {
2020-12-31 15:19:48 -07:00
if ( param . blockchain _last _updated ) {
// update blockchain last updated date
Stats . updateOne ( { coin : coin } , {
blockchain _last _updated : param . blockchain _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-31 15:19:48 -07:00
} ) ;
} else if ( param . reward _last _updated ) {
// update reward last updated date
Stats . updateOne ( { coin : coin } , {
reward _last _updated : param . reward _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-31 15:19:48 -07:00
} ) ;
} else if ( param . masternodes _last _updated ) {
2020-12-30 18:22:02 -07:00
// update masternode last updated date
Stats . updateOne ( { coin : coin } , {
masternodes _last _updated : param . masternodes _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-30 18:22:02 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-30 18:22:02 -07:00
} ) ;
2020-12-31 15:19:48 -07:00
} else if ( param . network _last _updated ) {
// update network last updated date
Stats . updateOne ( { coin : coin } , {
network _last _updated : param . network _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-31 15:19:48 -07:00
} ) ;
} else if ( param . richlist _last _updated ) {
// update richlist last updated date
Stats . updateOne ( { coin : coin } , {
richlist _last _updated : param . richlist _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-31 15:19:48 -07:00
} ) ;
} else if ( param . markets _last _updated ) {
// update markets last updated date
Stats . updateOne ( { coin : coin } , {
markets _last _updated : param . markets _last _updated
2023-05-07 20:55:29 -06:00
} ) . then ( ( ) => {
2020-12-31 15:19:48 -07:00
return cb ( true ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2020-12-31 15:19:48 -07:00
} ) ;
2020-12-30 18:22:02 -07:00
} else {
// invalid option
return cb ( false ) ;
}
} ,
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
2023-09-26 18:22:28 -06:00
lib . syncLoop ( addresses . length , function ( loop ) {
2020-12-23 18:40:10 -07:00
var a = loop . iteration ( ) ;
2023-09-26 18:22:28 -06:00
module . exports . get _claim _name ( addresses [ a ] , function ( claim _name ) {
if ( claim _name != null && claim _name != '' ) {
2020-12-23 18:40:10 -07:00
// look for address in vin
for ( v = 0 ; v < tx . vin . length ; v ++ ) {
// check if this is the correct address
2023-09-26 18:22:28 -06:00
if ( tx . vin [ v ] . addresses == addresses [ a ] ) {
2020-12-23 18:40:10 -07:00
// add claim name to array
2023-09-26 18:22:28 -06:00
tx . vin [ v ] [ 'claim_name' ] = claim _name ;
2020-12-23 18:40:10 -07:00
}
}
// look for address in vout
for ( v = 0 ; v < tx . vout . length ; v ++ ) {
// check if this is the correct address
2023-09-26 18:22:28 -06:00
if ( tx . vout [ v ] . addresses == addresses [ a ] ) {
2020-12-23 18:40:10 -07:00
// add claim name to array
2023-09-26 18:22:28 -06:00
tx . vout [ v ] [ 'claim_name' ] = claim _name ;
2020-12-23 18:40:10 -07:00
}
}
}
loop . next ( ) ;
} ) ;
} , function ( ) {
// return modified tx object
return cb ( tx ) ;
} ) ;
} ,
2022-04-11 01:37:27 -06:00
get _network _chart _data : function ( cb ) {
// lookup all network history data for populating network charts
2023-05-07 20:55:29 -06:00
NetworkHistory . find ( ) . sort ( { blockindex : 1 } ) . exec ( ) . then ( ( data ) => {
2022-04-11 01:37:27 -06:00
return cb ( data ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( null ) ;
2022-04-11 01:37:27 -06:00
} ) ;
} ,
2022-06-24 19:43:02 -06:00
check _networkhistory : function ( cb ) {
2023-05-07 20:55:29 -06:00
NetworkHistory . findOne ( { } ) . then ( ( networkhistory ) => {
2022-06-24 19:43:02 -06:00
if ( networkhistory ) {
// collection has data
// determine if the difficulty field exists
check _rename _db _field ( NetworkHistory , 'difficulty' , 'difficulty_pow' , function ( renamed ) {
// determine if difficulty_pos field exists
check _add _db _field ( NetworkHistory , 'difficulty_pos' , 0 , function ( exists ) {
return cb ( true ) ;
} ) ;
} ) ;
} else
return cb ( false ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( false ) ;
2022-06-24 19:43:02 -06:00
} ) ;
} ,
2022-04-30 20:53:10 -06:00
initialize _data _startup : function ( cb ) {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . initializing _database } .. ${ settings . localization . please _wait } .. ` ) ;
2022-04-30 20:53:10 -06:00
// check if stats collection is initialized
module . exports . check _stats ( settings . coin . name , function ( stats _exists ) {
var skip = true ;
// determine if stats collection already exists
if ( stats _exists == false ) {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . creating _initial _entry . replace ( '{1}' , 'stats' ) } .. ${ settings . localization . please _wait } .. ` ) ;
2022-04-30 20:53:10 -06:00
skip = false ;
}
// initialize the stats collection
module . exports . create _stats ( settings . coin . name , skip , function ( ) {
// check and initialize the markets collection
2023-10-27 18:33:52 -06:00
init _markets ( function ( installed _markets ) {
// remove inactive markets from the database collection
remove _inactive _markets ( installed _markets , function ( ) {
// add new field(s) to tx collection if missing
module . exports . check _txes ( function ( txes _exists ) {
// add new field(s) to masternode collection if missing
module . exports . check _masternodes ( function ( masternodes _exists ) {
// add new field(s) and/or rename old field(s) in networkhistory collection if applicable
module . exports . check _networkhistory ( function ( networkhistory _exists ) {
// check if richlist collection is initialized
module . exports . check _richlist ( settings . coin . name , function ( richlist _exists ) {
skip = true ;
// determine if richlist collection already exists
if ( richlist _exists == false ) {
2024-06-16 18:58:12 -06:00
console . log ( ` ${ settings . localization . creating _initial _entry . replace ( '{1}' , 'richlist' ) } .. ${ settings . localization . please _wait } .. ` ) ;
2023-10-27 18:33:52 -06:00
skip = false ;
}
// initialize the richlist collection
module . exports . create _richlist ( settings . coin . name , skip , function ( ) {
// check and initialize the heavycoin collection
init _heavy ( function ( ) {
// check and initialize the claimaddress collection
init _claimaddress ( settings . coin . name , function ( ) {
2024-06-16 18:58:12 -06:00
// initialize all enabled plugins
init _plugins ( settings . coin . name , function ( ) {
// finished initializing startup data
console . log ( 'Database initialization complete' ) ;
return cb ( ) ;
} ) ;
2023-10-27 18:33:52 -06:00
} ) ;
2023-09-26 18:22:28 -06:00
} ) ;
2022-06-24 19:43:02 -06:00
} ) ;
2022-04-30 20:53:10 -06:00
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ,
remove _sync _message : function ( ) {
var filePath = './tmp/show_sync_message.tmp' ;
// Check if the show sync stub file exists
if ( fs . existsSync ( filePath ) ) {
// File exists, so delete it now
try {
fs . unlinkSync ( filePath ) ;
} catch ( err ) {
console . log ( err ) ;
}
}
} ,
2024-02-06 19:44:11 -07:00
save _tx : function ( txid , blockheight , block , cb ) {
2022-07-17 16:49:02 -06:00
lib . get _rawtransaction ( txid , function ( tx ) {
2024-06-16 18:58:12 -06:00
if ( tx && tx != ` ${ settings . localization . ex _error } : ${ settings . localization . check _console } ` ) {
2022-07-17 16:49:02 -06:00
lib . prepare _vin ( tx , function ( vin , tx _type _vin ) {
lib . prepare _vout ( tx . vout , txid , vin , ( ( ! settings . blockchain _specific . zksnarks . enabled || typeof tx . vjoinsplit === 'undefined' || tx . vjoinsplit == null ) ? [ ] : tx . vjoinsplit ) , function ( vout , nvin , tx _type _vout ) {
2023-05-06 12:36:35 -06:00
lib . syncLoop ( nvin . length , function ( loop ) {
2022-07-17 16:49:02 -06:00
var i = loop . iteration ( ) ;
// check if address is inside an array
if ( Array . isArray ( nvin [ i ] . addresses ) ) {
// extract the address
nvin [ i ] . addresses = nvin [ i ] . addresses [ 0 ] ;
}
update _address ( nvin [ i ] . addresses , blockheight , txid , nvin [ i ] . amount , 'vin' , function ( ) {
loop . next ( ) ;
} ) ;
} , function ( ) {
lib . syncLoop ( vout . length , function ( subloop ) {
var t = subloop . iteration ( ) ;
// check if address is inside an array
if ( Array . isArray ( vout [ t ] . addresses ) ) {
// extract the address
vout [ t ] . addresses = vout [ t ] . addresses [ 0 ] ;
}
if ( vout [ t ] . addresses ) {
update _address ( vout [ t ] . addresses , blockheight , txid , vout [ t ] . amount , 'vout' , function ( ) {
subloop . next ( ) ;
} ) ;
} else
subloop . next ( ) ;
} , function ( ) {
lib . calculate _total ( vout , function ( total ) {
var op _return = null ;
2024-02-06 19:44:11 -07:00
var algo = null ;
2022-07-17 16:49:02 -06:00
// check if the op_return value should be decoded and saved
if ( settings . transaction _page . show _op _return ) {
// loop through vout to find the op_return value
tx . vout . forEach ( function ( vout _data ) {
// check if the op_return value exists
if ( vout _data . scriptPubKey != null && vout _data . scriptPubKey . asm != null && vout _data . scriptPubKey . asm . indexOf ( 'OP_RETURN' ) > - 1 ) {
// decode the op_return value
op _return = hex _to _ascii ( vout _data . scriptPubKey . asm . replace ( 'OP_RETURN' , '' ) . trim ( ) ) ;
}
} ) ;
}
2024-02-06 19:44:11 -07:00
// check if the algo value should be saved
if ( settings . block _page . multi _algorithm . show _algo ) {
// get the algo value
algo = block [ settings . block _page . multi _algorithm . key _name ] ;
}
2022-07-17 16:49:02 -06:00
var newTx = new Tx ( {
txid : tx . txid ,
2023-05-06 12:36:35 -06:00
vin : ( vin == null || vin . length == 0 ? [ ] : nvin ) ,
2022-07-17 16:49:02 -06:00
vout : vout ,
total : total . toFixed ( 8 ) ,
timestamp : tx . time ,
blockhash : tx . blockhash ,
blockindex : blockheight ,
tx _type : ( tx _type _vout == null ? tx _type _vin : tx _type _vout ) ,
2024-02-06 19:44:11 -07:00
op _return : op _return ,
algo : algo
2022-07-17 16:49:02 -06:00
} ) ;
2023-05-07 20:55:29 -06:00
newTx . save ( ) . then ( ( ) => {
return cb ( null , vout . length > 0 ) ;
} ) . catch ( ( err ) => {
return cb ( err , false ) ;
2022-07-17 16:49:02 -06:00
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
} else
return cb ( 'tx not found: ' + txid , false ) ;
} ) ;
} ,
2023-05-06 12:36:35 -06:00
// get the list of orphans from local collection
get _orphans : function ( start , length , cb ) {
// get the count of orphaned blocks
2023-05-07 20:55:29 -06:00
Orphans . find ( { } ) . countDocuments ( ) . then ( ( count ) => {
2023-05-06 12:36:35 -06:00
// get the actual orphaned block data
2023-05-07 20:55:29 -06:00
Orphans . find ( { } ) . sort ( { blockindex : - 1 } ) . skip ( Number ( start ) ) . limit ( Number ( length ) ) . exec ( ) . then ( ( orphans ) => {
return cb ( orphans , count ) ;
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( [ ] , count ) ;
2023-05-06 12:36:35 -06:00
} ) ;
2023-05-07 20:55:29 -06:00
} ) . catch ( ( err ) => {
console . log ( err ) ;
return cb ( [ ] , 0 ) ;
2023-05-06 12:36:35 -06:00
} ) ;
} ,
2020-12-08 22:52:15 -07:00
fs : fs
2020-11-20 14:06:53 -07:00
} ;