4790764e2c
-Restructured the settings.json.template and settings.js files with better groupings -Added better comments for improved explanations of all settings -Better handling of page length options on all datatables; Page length options are now configurable and also only display options based on limits set by certain items_per_page and max_items_per_query settings -Markets have been extended to support unlimited trading pairs for each exchange -Added coin_symbol and pair_symbol to the markets schema to support multiple trading pairs -Added a burned field to the richlist schema for tracking burned coin addresses -Added a locale string for the new richlist wealth distribution "Top 1-100 Total" table row -Updated a couple locale strings that were incomplete or needed fixing (api_getblockhash and api_getnextrewardwhenstr) -Added a new css class to remove some redundant inline styles for the richlist wealth distribution color boxes -Richlist page now allows better separation of the top list(s) and the wealth distribution table and chart (you can now hide or show sections as desired) -Richlist page now allows for better burned coin support (Hide burned coin addresses from lists and totals even when the burned coin amounts are still included in the total coin supply value) -Block page now only displays the raw block link if the api_page.public_apis.rpc.getblock.enabled settings is set to true -Transaction page now only displays the raw tx link if the api_page.public_apis.rpc.getrawtransaction.enabled setting is set to true -Rate limiting class has been made global and is now used to limit market requests -getnetworkhashps rpc call now returns a '-' if shared_pages.show_hashrate is not set to true -Searching for unsycned blocks/txs no longer saves the data locally but instead still shows the data on screen. This helps prevent syncing data out-of-order (This eliminates the need for db_index.pid which has been removed) -Coin supply is now always taken from the stats collection database instead of from the wallet via rpc command in all cases except when syncing -Lots of misc fixes and code cleanup changes -List of changed settings: -title -> shared_pages.page_title -coin -> coin.name -symbol -> coin.symbol -logo -> shared_pages.logo -headerlogo -> shared_pages.page_header.home_link_logo -favicon -> shared_pages.favicon -homelink -> shared_pages.page_header.home_link -logoheight -> shared_pages.page_header.home_link_logo_height -sticky_header -> shared_pages.page_header.sticky_header -sticky_footer -> shared_pages.page_footer.sticky_footer -footer_height_desktop -> shared_pages.page_footer.footer_height_desktop -footer_height_tablet -> shared_pages.page_footer.footer_height_tablet -footer_height_mobile -> shared_pages.page_footer.footer_height_mobile -social_link_percent_height_desktop -> shared_pages.page_footer.social_link_percent_height_desktop -social_link_percent_height_tablet -> shared_pages.page_footer.social_link_percent_height_tablet -social_link_percent_height_mobile -> shared_pages.page_footer.social_link_percent_height_mobile -theme -> shared_pages.theme -port -> webserver.port -update_timeout -> sync.update_timeout -check_timeout -> sync.check_timeout -block_parallel_tasks -> sync.block_parallel_tasks -use_rpc -> api_cmds.use_rpc -confirmations -> shared_pages.confirmations -display.api -> api_page.enabled -display.markets -> markets_page.enabled -display.richlist -> richlist_page.enabled -display.search -> shared_pages.page_header.show_search -display.movement -> movement_page.enabled -display.network -> network_page.enabled -display.masternodes -> masternodes_page.enabled -display.claim_address -> claim_address_page.enabled -display.claim_address_header_menu -> claim_address_page.show_header_menu -display.page_header_bgcolor -> shared_pages.page_header.bgcolor -display.page_footer_bgcolor -> shared_pages.page_footer.bgcolor -display.table_header_bgcolor -> shared_pages.table_header_bgcolor -display.networkpnl -> shared_pages.page_header.panels.network_panel.display_order -display.difficultypnl -> shared_pages.page_header.panels.difficulty_panel.display_order -display.masternodespnl -> shared_pages.page_header.panels.masternodes_panel.display_order -display.coinsupplypnl -> shared_pages.page_header.panels.coin_supply_panel.display_order -display.pricepnl -> shared_pages.page_header.panels.price_panel.display_order -display.marketcappnl -> shared_pages.page_header.panels.market_cap_panel.display_order -display.logopnl -> shared_pages.page_header.panels.logo_panel.display_order -index.show_last_updated -> index_page.show_last_updated -index.show_hashrate -> shared_pages.show_hashrate -index.difficulty -> shared_pages.difficulty -index.last_txs -> api_page.public_apis.ext.getlasttxs.max_items_per_query -index.txs_per_page -> index_page.transaction_table.items_per_page (for index page) AND movement_page.movement_table.items_per_page (for movement page) -reward_page.show_last_updated -> blockchain_specific.heavycoin.reward_page.show_last_updated -api.blockindex -> api_page.sample_data.blockindex -api.blockhash -> api_page.sample_data.blockhash -api.txhash -> api_page.sample_data.txhash -api.address -> api_page.sample_data.address -markets.exchange -> markets_page.default_exchange.trading_pair -markets.default -> markets_page.default_exchange.exchange_name -markets.market_dropdown_menu -> markets_page.show_market_dropdown_menu -markets.market_select_visible -> markets_page.show_market_select -richlist.distribution -> richlist_page.wealth_distribution.show_distribution_chart -richlist.received -> richlist_page.show_received_coins -richlist.balance -> richlist_page.show_current_balance -movement.min_amount -> movement_page.movement_table.min_amount -movement.low_flag -> movement_page.movement_table.low_warning_flag -movement.high_flag -> movement_page.movement_table.high_warning_flag -social_links -> shared_pages.page_footer.social_links -social_links[x].image_url -> shared_pages.page_footer.social_links[x].image_path -genesis_tx -> transaction_page.genesis_tx -genesis_block -> block_page.genesis_block -heavy -> blockchain_specific.heavycoin.enabled -save_stats_after_sync_blocks -> sync.save_stats_after_sync_blocks -txcount -> api_page.public_apis.ext.getaddresstxs.max_items_per_query -txcount_per_page -> address_page.history_table.items_per_page -show_sent_received -> address_page.show_sent_received -supply -> sync.supply -nethash -> shared_pages.page_header.panels.network_panel.nethash -nethash_units -> shared_pages.page_header.panels.network_panel.nethash_units -usecors -> webserver.cors.enabled -corsorigin -> webserver.cors.corsorigin -burned_coins -> richlist_page.burned_coins.addresses -public_api.rpc.getdifficulty -> api_page.public_apis.rpc.getdifficulty.enabled -public_api.rpc.getconnectioncount -> api_page.public_apis.rpc.getconnectioncount.enabled -public_api.rpc.getblockcount -> api_page.public_apis.rpc.getblockcount.enabled -public_api.rpc.getblockhash -> api_page.public_apis.rpc.getblockhash.enabled -public_api.rpc.getblock -> api_page.public_apis.rpc.getblock.enabled -public_api.rpc.getrawtransaction -> api_page.public_apis.rpc.getrawtransaction.enabled -public_api.rpc.getnetworkhashps -> api_page.public_apis.rpc.getnetworkhashps.enabled -public_api.rpc.getvotelist -> api_page.public_apis.rpc.getvotelist.enabled -public_api.rpc.getmasternodecount -> api_page.public_apis.rpc.getmasternodecount.enabled -public_api.rpc.getmaxmoney -> blockchain_specific.heavycoin.public_apis.getmaxmoney.enabled -public_api.rpc.getmaxvote -> blockchain_specific.heavycoin.public_apis.getmaxvote.enabled -public_api.rpc.getvote -> blockchain_specific.heavycoin.public_apis.getvote.enabled -public_api.rpc.getphase -> blockchain_specific.heavycoin.public_apis.getphase.enabled -public_api.rpc.getreward -> blockchain_specific.heavycoin.public_apis.getreward.enabled -public_api.rpc.getsupply -> blockchain_specific.heavycoin.public_apis.getsupply.enabled -public_api.rpc.getnextrewardestimate -> blockchain_specific.heavycoin.public_apis.getnextrewardestimate.enabled -public_api.rpc.getnextrewardwhenstr -> blockchain_specific.heavycoin.public_apis.getnextrewardwhenstr.enabled -public_api.ext.getmoneysupply -> api_page.public_apis.ext.getmoneysupply.enabled -public_api.ext.getdistribution -> api_page.public_apis.ext.getdistribution.enabled -public_api.ext.getaddress -> api_page.public_apis.ext.getaddress.enabled -public_api.ext.getaddresstxs -> api_page.public_apis.ext.getaddresstxs.enabled -public_api.ext.gettx -> api_page.public_apis.ext.gettx.enabled -public_api.ext.getbalance -> api_page.public_apis.ext.getbalance.enabled -public_api.ext.getlasttxs -> api_page.public_apis.ext.getlasttxs.enabled -public_api.ext.getcurrentprice -> api_page.public_apis.ext.getcurrentprice.enabled -public_api.ext.getbasicstats -> api_page.public_apis.ext.getbasicstats.enabled -public_api.ext.getsummary -> api_page.public_apis.ext.getsummary.enabled -public_api.ext.getnetworkpeers -> api_page.public_apis.ext.getnetworkpeers.enabled -public_api.ext.getmasternodelist -> api_page.public_apis.ext.getmasternodelist.enabled -public_api.ext.getmasternoderewards -> api_page.public_apis.ext.getmasternoderewards.enabled -public_api.ext.getmasternoderewardstotal -> api_page.public_apis.ext.getmasternoderewardstotal.enabled -api_cmds.heavies.getmaxmoney -> blockchain_specific.heavycoin.api_cmds.getmaxmoney -api_cmds.heavies.getmaxvote -> blockchain_specific.heavycoin.api_cmds.getmaxvote -api_cmds.heavies.getvote -> blockchain_specific.heavycoin.api_cmds.getvote -api_cmds.heavies.getphase -> blockchain_specific.heavycoin.api_cmds.getphase -api_cmds.heavies.getreward -> blockchain_specific.heavycoin.api_cmds.getreward -api_cmds.heavies.getnextrewardestimate -> blockchain_specific.heavycoin.api_cmds.getnextrewardestimate -api_cmds.heavies.getnextrewardwhenstr -> blockchain_specific.heavycoin.api_cmds.getnextrewardwhenstr -api_cmds.heavies.getsupply -> blockchain_specific.heavycoin.api_cmds.getsupply -List of new settings: -shared_pages.page_header.panels.network_panel.enabled: allow enabling/disabling of the network panel -shared_pages.page_header.panels.difficulty_panel.enabled: allow enabling/disabling of the difficulty panel -shared_pages.page_header.panels.masternodes_panel.enabled: allow enabling/disabling of the masternodes panel -shared_pages.page_header.panels.coin_supply_panel.enabled: allow enabling/disabling of the coin supply panel -shared_pages.page_header.panels.price_panel.enabled: allow enabling/disabling of the price panel -shared_pages.page_header.panels.market_cap_panel.enabled: allow enabling/disabling of the market cap panel -shared_pages.page_header.panels.logo_panel.enabled: allow enabling/disabling of the logo panel -index_page.transaction_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -index_page.transaction_table.reload_table_seconds: the time in seconds to automatically reload the table data from the server -address_page.history_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -masternodes_page.masternode_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -masternodes_page.masternode_table.items_per_page: the default amount of items/records to display in the table at any given time -movement_page.movement_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -movement_page.movement_table.reload_table_seconds: the time in seconds to automatically reload the table data from the server -network_page.connections_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -network_page.connections_table.items_per_page: the default amount of items/records to display in the table at any given time -network_page.addnodes_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -network_page.addnodes_table.items_per_page: the default amount of items/records to display in the table at any given time -network_page.onetry_table.page_length_options: specify the page length options that determine how many items/records to display in the table at any given time -network_page.onetry_table.items_per_page: the default amount of items/records to display in the table at any given time -richlist_page.wealth_distribution.show_distribution_table: show/hide the wealth distribution summary table -richlist_page.wealth_distribution.colors: a list of html color codes to represent the top 100 groupings in the wealth distribution table and pie chart -richlist_page.burned_coins.include_burned_coins_in_distribution: determine whether to include burned coins in the wealth distribution section or not -markets_page.exchanges.altmarkets.enabled: enable/disable the altmarkets exchange -markets_page.exchanges.altmarkets.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.bittrex.enabled: enable/disable the bittrex exchange -markets_page.exchanges.bittrex.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.bleutrade.enabled: enable/disable the bleutrade exchange -markets_page.exchanges.bleutrade.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.crex.enabled: enable/disable the crex exchange -markets_page.exchanges.crex.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.poloniex.enabled: enable/disable the poloniex exchange -markets_page.exchanges.poloniex.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.stex.enabled: enable/disable the stex exchange -markets_page.exchanges.stex.trading_pairs: a list of market trading pair symbols -markets_page.exchanges.yobit.enabled: enable/disable the yobit exchange -markets_page.exchanges.yobit.trading_pairs: a list of market trading pair symbols -claim_address_page.enable_bad_word_filter: enable/disable the "bad word" filter for claimed addresses, so that trying to claim an address with a bad word will fail -sync.show_sync_msg_when_syncing_more_than_blocks: show the sync msg at the top of all pages during index syncronization if there are more than this many blocks to process -labels[x].enabled: allow enabling/disabling of specific wallet address labels -blockchain_specific.heavycoin.reward_page.enabled: enable/disable the reward page -blockchain_specific.zksnarks.enabled: enable/disable Zcash zk-SNARKs private transaction support (WIP - 90% complete) -List of deleted settings -address: unnecessary setting has been replaced by dynamic values via http request -markets.coin: replaced by a richer set of settings that allow choosing the coin for each market -markets.enabled -> replaced by a richer set of settings that allow enabling/disabling each market specifically -lock_during_index: no longer possible to save unsynced blocks/txs via search so this settings is now obsolete/unused
523 lines
22 KiB
JavaScript
523 lines
22 KiB
JavaScript
var mongoose = require('mongoose')
|
|
, lib = require('../lib/explorer')
|
|
, db = require('../lib/database')
|
|
, Tx = require('../models/tx')
|
|
, Address = require('../models/address')
|
|
, AddressTx = require('../models/addresstx')
|
|
, Richlist = require('../models/richlist')
|
|
, Stats = require('../models/stats')
|
|
, settings = require('../lib/settings');
|
|
|
|
var mode = 'update';
|
|
var database = 'index';
|
|
|
|
// displays usage and exits
|
|
function usage() {
|
|
console.log('Usage: scripts/sync.sh /path/to/nodejs [mode]');
|
|
console.log('');
|
|
console.log('Mode: (required)');
|
|
console.log('update Updates index from last sync to current block');
|
|
console.log('check Checks index for (and adds) any missing transactions/addresses');
|
|
console.log('reindex Clears index then resyncs from genesis to current block');
|
|
console.log('reindex-rich Clears and recreates the richlist data');
|
|
console.log('reindex-txcount Rescan and flatten the tx count value for faster access');
|
|
console.log('market Updates market summaries, orderbooks, trade history + charts');
|
|
console.log('peers Updates peer info based on local wallet connections');
|
|
console.log('masternodes Updates the list of active masternodes on the network');
|
|
console.log('');
|
|
console.log('Notes:');
|
|
console.log('- \'current block\' is the latest created block when script is executed.');
|
|
console.log('- The market + peers databases only support (& defaults to) reindex mode.');
|
|
console.log('- If check mode finds missing data (ignoring new data since last sync),');
|
|
console.log(' index_timeout in settings.json is set too low.')
|
|
console.log('');
|
|
process.exit(0);
|
|
}
|
|
|
|
// check options
|
|
if (process.argv[2] == 'index') {
|
|
if (process.argv.length <3) {
|
|
usage();
|
|
} else {
|
|
switch(process.argv[3])
|
|
{
|
|
case 'update':
|
|
mode = 'update';
|
|
break;
|
|
case 'check':
|
|
mode = 'check';
|
|
break;
|
|
case 'reindex':
|
|
mode = 'reindex';
|
|
break;
|
|
case 'reindex-rich':
|
|
mode = 'reindex-rich';
|
|
break;
|
|
case 'reindex-txcount':
|
|
mode = 'reindex-txcount';
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
} else if (process.argv[2] == 'market') {
|
|
database = 'market';
|
|
} else if (process.argv[2] == 'peers') {
|
|
database = 'peers';
|
|
} else if (process.argv[2] == 'masternodes') {
|
|
database = 'masternodes';
|
|
} else {
|
|
usage();
|
|
}
|
|
|
|
function create_lock(cb) {
|
|
if ( database == 'index' ) {
|
|
var fname = './tmp/' + database + '.pid';
|
|
db.fs.appendFile(fname, process.pid.toString(), function (err) {
|
|
if (err) {
|
|
console.log("Error: unable to create %s", fname);
|
|
process.exit(1);
|
|
} else {
|
|
return cb();
|
|
}
|
|
});
|
|
} else {
|
|
return cb();
|
|
}
|
|
}
|
|
|
|
function remove_lock(cb) {
|
|
if ( database == 'index' ) {
|
|
var fname = './tmp/' + database + '.pid';
|
|
db.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(cb) {
|
|
if ( database == 'index' ) {
|
|
var fname = './tmp/' + database + '.pid';
|
|
db.fs.exists(fname, function (exists) {
|
|
if(exists) {
|
|
return cb(true);
|
|
} else {
|
|
return cb(false);
|
|
}
|
|
});
|
|
} else {
|
|
return cb();
|
|
}
|
|
}
|
|
|
|
function exit() {
|
|
remove_lock(function(){
|
|
mongoose.disconnect();
|
|
process.exit(0);
|
|
});
|
|
}
|
|
|
|
var dbString = 'mongodb://' + settings.dbsettings.user;
|
|
dbString = dbString + ':' + settings.dbsettings.password;
|
|
dbString = dbString + '@' + settings.dbsettings.address;
|
|
dbString = dbString + ':' + settings.dbsettings.port;
|
|
dbString = dbString + '/' + settings.dbsettings.database;
|
|
|
|
if (database == 'peers') {
|
|
var rateLimitLib = require('../lib/ratelimit');
|
|
console.log('syncing peers.. please wait..');
|
|
// syncing peers does not require a lock
|
|
mongoose.connect(dbString, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false }, function(err) {
|
|
if (err) {
|
|
console.log('Unable to connect to database: %s', dbString);
|
|
console.log('Aborting');
|
|
exit();
|
|
} else {
|
|
lib.get_peerinfo(function (body) {
|
|
if (body != null) {
|
|
lib.syncLoop(body.length, function (loop) {
|
|
var i = loop.iteration();
|
|
var address = body[i].addr.substring(0, body[i].addr.lastIndexOf(":")).replace("[","").replace("]","");
|
|
var port = body[i].addr.substring(body[i].addr.lastIndexOf(":") + 1);
|
|
var rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
|
|
db.find_peer(address, function(peer) {
|
|
if (peer) {
|
|
if (isNaN(peer['port']) || peer['port'].length < 2 || peer['country'].length < 1 || peer['country_code'].length < 1) {
|
|
db.drop_peers(function() {
|
|
console.log('Saved peers missing ports or country, dropping peers. Re-run this script afterwards.');
|
|
exit();
|
|
});
|
|
}
|
|
console.log('Updated peer %s [%s/%s]', address, (i + 1).toString(), body.length.toString());
|
|
// peer already exists
|
|
loop.next();
|
|
} else {
|
|
rateLimit.schedule(function() {
|
|
lib.get_geo_location(address, function (error, geo) {
|
|
// check if an error was returned
|
|
if (error) {
|
|
console.log(error);
|
|
exit();
|
|
} else {
|
|
// add peer to collection
|
|
db.create_peer({
|
|
address: address,
|
|
port: port,
|
|
protocol: body[i].version,
|
|
version: body[i].subver.replace('/', '').replace('/', ''),
|
|
country: geo.country_name,
|
|
country_code: geo.country_code
|
|
}, function() {
|
|
console.log('Added new peer %s [%s/%s]', address, (i + 1).toString(), body.length.toString());
|
|
loop.next();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}, function() {
|
|
// update network_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { network_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('peer sync complete');
|
|
exit();
|
|
});
|
|
});
|
|
} else {
|
|
console.log('no peers found');
|
|
exit();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else if (database == 'masternodes') {
|
|
console.log('syncing masternodes.. please wait..');
|
|
// syncing masternodes does not require a lock
|
|
mongoose.connect(dbString, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false }, function(err) {
|
|
if (err) {
|
|
console.log('Unable to connect to database: %s', dbString);
|
|
console.log('Aborting');
|
|
exit();
|
|
} else {
|
|
lib.get_masternodelist(function (body) {
|
|
if (body != null) {
|
|
lib.syncLoop(body.length, function (loop) {
|
|
var i = loop.iteration();
|
|
db.save_masternode(body[i], function (success) {
|
|
if (success)
|
|
loop.next();
|
|
else {
|
|
console.log('error: cannot save masternode %s.', (body[i].addr ? body[i].addr : 'UNKNOWN'));
|
|
exit();
|
|
}
|
|
});
|
|
}, function () {
|
|
db.remove_old_masternodes(function (cb) {
|
|
db.update_last_updated_stats(settings.coin.name, { masternodes_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('masternode sync complete');
|
|
exit();
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
console.log('no masternodes found');
|
|
exit();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// index and market sync requires locking
|
|
is_locked(function (exists) {
|
|
if (exists) {
|
|
console.log("Script already running..");
|
|
process.exit(0);
|
|
} else {
|
|
create_lock(function (){
|
|
console.log("script launched with pid: " + process.pid);
|
|
mongoose.connect(dbString, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false }, function(err) {
|
|
if (err) {
|
|
console.log('Unable to connect to database: %s', dbString);
|
|
console.log('Aborting');
|
|
exit();
|
|
} else if (database == 'index') {
|
|
db.check_stats(settings.coin.name, function(exists) {
|
|
if (exists == false) {
|
|
console.log('Run \'npm start\' to create database structures before running this script.');
|
|
exit();
|
|
} else {
|
|
db.update_db(settings.coin.name, function(stats){
|
|
if (settings.blockchain_specific.heavycoin.enabled == true)
|
|
db.update_heavy(settings.coin.name, stats.count, 20, function() {});
|
|
if (mode == 'reindex') {
|
|
Tx.deleteMany({}, function(err) {
|
|
console.log('TXs cleared.');
|
|
Address.deleteMany({}, function(err2) {
|
|
console.log('Addresses cleared.');
|
|
AddressTx.deleteMany({}, function(err3) {
|
|
console.log('Address TXs cleared.');
|
|
Richlist.updateOne({coin: settings.coin.name}, {
|
|
received: [],
|
|
balance: [],
|
|
}, function(err3) {
|
|
Stats.updateOne({coin: settings.coin.name}, {
|
|
last: 0,
|
|
count: 0,
|
|
supply: 0
|
|
}, function() {
|
|
console.log('index cleared (reindex)');
|
|
});
|
|
|
|
// Check if the sync msg should be shown
|
|
check_show_sync_message(stats.count);
|
|
|
|
db.update_tx_db(settings.coin.name, 1, stats.count, stats.txes, settings.sync.update_timeout, function() {
|
|
db.update_richlist('received', function() {
|
|
db.update_richlist('balance', function() {
|
|
db.get_stats(settings.coin.name, function(nstats) {
|
|
// always check for and remove the sync msg if exists
|
|
remove_sync_message();
|
|
// update richlist_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
// update blockchain_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { blockchain_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('reindex complete (block: %s)', nstats.last);
|
|
exit();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
} else if (mode == 'check') {
|
|
console.log('starting check.. please wait..');
|
|
db.update_tx_db(settings.coin.name, 1, stats.count, stats.txes, settings.sync.check_timeout, function(){
|
|
db.get_stats(settings.coin.name, function(nstats){
|
|
console.log('check complete (block: %s)', nstats.last);
|
|
exit();
|
|
});
|
|
});
|
|
} else if (mode == 'update') {
|
|
// Get the last synced block index value
|
|
var last = (stats.last ? stats.last : 0);
|
|
// Get the total number of blocks
|
|
var count = (stats.count ? stats.count : 0);
|
|
// Check if the sync msg should be shown
|
|
check_show_sync_message(count - last);
|
|
|
|
db.update_tx_db(settings.coin.name, last, count, stats.txes, settings.sync.update_timeout, function(){
|
|
db.update_richlist('received', function(){
|
|
db.update_richlist('balance', function(){
|
|
db.get_stats(settings.coin.name, function(nstats){
|
|
// always check for and remove the sync msg if exists
|
|
remove_sync_message();
|
|
// update richlist_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
// update blockchain_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { blockchain_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('update complete (block: %s)', nstats.last);
|
|
exit();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
} else if (mode == 'reindex-rich') {
|
|
console.log('check richlist');
|
|
db.check_richlist(settings.coin.name, function(exists) {
|
|
if (exists) console.log('richlist entry found, deleting now..');
|
|
db.delete_richlist(settings.coin.name, function(deleted) {
|
|
if (deleted) console.log('richlist entry deleted');
|
|
db.create_richlist(settings.coin.name, function() {
|
|
console.log('richlist created.');
|
|
db.update_richlist('received', function() {
|
|
console.log('richlist updated received.');
|
|
db.update_richlist('balance', function() {
|
|
// update richlist_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('richlist update complete');
|
|
exit();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
} else if (mode == 'reindex-txcount') {
|
|
console.log('calculating tx count.. please wait..');
|
|
// Resetting the transaction counter requires a single lookup on the txes collection to find all txes that have a positive or zero total and 1 or more vout
|
|
Tx.find({'total': {$gte: 0}, 'vout': { $gte: { $size: 1 }}}).countDocuments(function(err, count) {
|
|
console.log('found tx count: ' + count.toString());
|
|
Stats.updateOne({coin: settings.coin.name}, {
|
|
txes: count
|
|
}, function() {
|
|
console.log('tx count update complete');
|
|
exit();
|
|
});
|
|
});
|
|
} else if (mode == 'reindex-last') {
|
|
console.log('calculating last tx.. please wait..');
|
|
// Resetting the last counter requires a single lookup on the txes collection to find all txes that have a positive or zero total and 1 or more vout
|
|
Tx.find({'total': {$gte: 0}, 'vout': { $gte: { $size: 1 }}}).countDocuments(function(err, count) {
|
|
console.log('found tx count: ' + count.toString());
|
|
Stats.updateOne({coin: settings.coin.name}, {
|
|
txes: count
|
|
}, function() {
|
|
console.log('tx count update complete');
|
|
exit();
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// check if market feature is enabled
|
|
if (settings.markets_page.enabled == true) {
|
|
var complete = 0;
|
|
var total_pairs = 0;
|
|
var exchanges = Object.keys(settings.markets_page.exchanges);
|
|
|
|
// loop through all exchanges to determine how many trading pairs must be updated
|
|
exchanges.forEach(function (key, index, map) {
|
|
// check if market is enabled via settings
|
|
if (settings.markets_page.exchanges[key].enabled == true) {
|
|
// check if market is installed/supported
|
|
if (db.fs.existsSync('./lib/markets/' + key + '.js')) {
|
|
// add trading pairs to total
|
|
total_pairs += settings.markets_page.exchanges[key].trading_pairs.length;
|
|
|
|
// loop through all trading pairs for this market
|
|
for (var i = 0; i < settings.markets_page.exchanges[key].trading_pairs.length; i++) {
|
|
// ensure trading pair setting is always uppercase
|
|
settings.markets_page.exchanges[key].trading_pairs[i] = settings.markets_page.exchanges[key].trading_pairs[i].toUpperCase();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// check if there are any trading pairs to update
|
|
if (total_pairs > 0) {
|
|
// initialize the rate limiter to wait 2 seconds between requests to prevent abusing external apis
|
|
var rateLimitLib = require('../lib/ratelimit');
|
|
var rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
|
|
// loop through and test all exchanges defined in the settings.json file
|
|
exchanges.forEach(function (key, index, map) {
|
|
// check if market is enabled via settings
|
|
if (settings.markets_page.exchanges[key].enabled == true) {
|
|
// check if market is installed/supported
|
|
if (db.fs.existsSync('./lib/markets/' + key + '.js')) {
|
|
// loop through all trading pairs
|
|
settings.markets_page.exchanges[key].trading_pairs.forEach(function (pair_key, pair_index, pair_map) {
|
|
// split the pair data
|
|
var split_pair = pair_key.split('/');
|
|
// check if this is a valid trading pair
|
|
if (split_pair.length == 2) {
|
|
// lookup the exchange in the market collection
|
|
db.check_market(key, split_pair[0], split_pair[1], function(mkt, exists) {
|
|
// check if exchange trading pair exists in the market collection
|
|
if (exists) {
|
|
// automatically pause for 2 seconds in between requests
|
|
rateLimit.schedule(function() {
|
|
// update market data
|
|
db.update_markets_db(key, split_pair[0], split_pair[1], function(err) {
|
|
if (!err) {
|
|
console.log('%s: %s market data updated successfully.', key, pair_key);
|
|
complete++;
|
|
if (complete == total_pairs)
|
|
get_last_usd_price();
|
|
} else {
|
|
console.log('%s: %s: %s', key, pair_key, err);
|
|
complete++;
|
|
if (complete == total_pairs)
|
|
get_last_usd_price();
|
|
}
|
|
});
|
|
});
|
|
} else {
|
|
console.log('error: entry for %s does not exist in markets database.', key);
|
|
complete++;
|
|
if (complete == total_pairs)
|
|
get_last_usd_price();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
// market not installed
|
|
console.log('%s market not installed', key);
|
|
complete++;
|
|
if (complete == total_pairs)
|
|
get_last_usd_price();
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
// no market trading pairs are enabled
|
|
console.log('error: no market trading pairs are enabled in settings');
|
|
exit();
|
|
}
|
|
} else {
|
|
// market page is not enabled
|
|
console.log('error: market feature is disabled in settings');
|
|
exit();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function check_show_sync_message(blocks_to_sync) {
|
|
var retVal = false;
|
|
var filePath = './tmp/show_sync_message.tmp';
|
|
// Check if the sync msg should be shown
|
|
if (blocks_to_sync > settings.sync.show_sync_msg_when_syncing_more_than_blocks) {
|
|
// Check if the show sync stub file already exists
|
|
if (!db.fs.existsSync(filePath)) {
|
|
// File doesn't exist, so create it now
|
|
db.fs.writeFileSync(filePath, '');
|
|
}
|
|
|
|
retVal = true;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
function remove_sync_message() {
|
|
var filePath = './tmp/show_sync_message.tmp';
|
|
// Check if the show sync stub file exists
|
|
if (db.fs.existsSync(filePath)) {
|
|
// File exists, so delete it now
|
|
try {
|
|
db.fs.unlinkSync(filePath);
|
|
} catch (err) {
|
|
console.log(err);
|
|
}
|
|
}
|
|
}
|
|
|
|
function get_last_usd_price() {
|
|
// Get the last usd price for coinstats
|
|
db.get_last_usd_price(function(retVal) {
|
|
// update markets_last_updated value
|
|
db.update_last_updated_stats(settings.coin.name, { markets_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
|
|
console.log('market sync complete');
|
|
exit();
|
|
});
|
|
});
|
|
} |