Add new "last updated date" settings

-Added new configurable settings to allow displaying a "last updated date" timestamp for: index, reward, masternode, movement, network, richlist and market pages
-Affected pages are now configured to be completely hidden and disabled when their display settings are set to false
This commit is contained in:
joeuhren
2020-12-31 15:19:48 -07:00
parent 9488e7e588
commit 2fd39d76ce
14 changed files with 357 additions and 89 deletions
+6
View File
@@ -437,6 +437,12 @@ app.set('website', settings.website);
app.set('genesis_block', settings.genesis_block);
app.set('index', settings.index);
app.set('reward_page', settings.reward_page);
app.set('masternodes_page', settings.masternodes_page);
app.set('movement_page', settings.movement_page);
app.set('network_page', settings.network_page);
app.set('richlist_page', settings.richlist_page);
app.set('markets_page', settings.markets_page);
app.set('use_rpc', settings.use_rpc);
app.set('heavy', settings.heavy);
app.set('save_stats_after_sync_blocks', settings.save_stats_after_sync_blocks);
+47 -8
View File
@@ -759,10 +759,12 @@ module.exports = {
return cb(distribution);
});
},
// updates heavy stats for coin
// height: current block height, count: amount of votes to store
update_heavy: function(coin, height, count, cb) {
var newVotes = [];
lib.get_maxmoney( function (maxmoney) {
lib.get_maxvote( function (maxvote) {
lib.get_vote( function (vote) {
@@ -773,14 +775,13 @@ module.exports = {
lib.get_nextin( function (nextin) {
lib.syncLoop(count, function (loop) {
var i = loop.iteration();
lib.get_blockhash(height-i, function (hash) {
lib.get_blockhash(height - i, function (hash) {
lib.get_block(hash, function (block) {
newVotes.push({count:height-i,reward:block.reward,vote:(block && block.vote ? block.vote : 0)});
newVotes.push({ count: height - i, reward: block.reward, vote: (block && block.vote ? block.vote : 0) });
loop.next();
});
});
}, function(){
console.log(newVotes);
}, function() {
Heavy.updateOne({coin: coin}, {
lvote: (vote ? vote : 0),
reward: (reward ? reward : 0),
@@ -790,10 +791,13 @@ module.exports = {
phase: (phase ? phase : 'N/A'),
maxvote: (maxvote ? maxvote : 0),
nextin: (nextin ? nextin : 'N/A'),
votes: newVotes,
votes: newVotes
}, function() {
//console.log('address updated: %s', hash);
return cb();
// update reward_last_updated value
module.exports.update_last_updated_stats(settings.coin, { reward_last_updated: Math.floor(new Date() / 1000) }, function (new_cb) {
console.log('heavy update complete');
return cb();
});
});
});
});
@@ -1195,13 +1199,48 @@ module.exports = {
// updates last_updated stats; called by sync.js
update_last_updated_stats: function (coin, param, cb) {
if (param.masternodes_last_updated) {
if (param.blockchain_last_updated) {
// update blockchain last updated date
Stats.updateOne({ coin: coin }, {
blockchain_last_updated: param.blockchain_last_updated
}, function () {
return cb(true);
});
} else if (param.reward_last_updated) {
// update reward last updated date
Stats.updateOne({ coin: coin }, {
reward_last_updated: param.reward_last_updated
}, function () {
return cb(true);
});
} else if (param.masternodes_last_updated) {
// update masternode last updated date
Stats.updateOne({ coin: coin }, {
masternodes_last_updated: param.masternodes_last_updated
}, function () {
return cb(true);
});
} else if (param.network_last_updated) {
// update network last updated date
Stats.updateOne({ coin: coin }, {
network_last_updated: param.network_last_updated
}, function () {
return cb(true);
});
} else if (param.richlist_last_updated) {
// update richlist last updated date
Stats.updateOne({ coin: coin }, {
richlist_last_updated: param.richlist_last_updated
}, function () {
return cb(true);
});
} else if (param.markets_last_updated) {
// update markets last updated date
Stats.updateOne({ coin: coin }, {
markets_last_updated: param.markets_last_updated
}, function () {
return cb(true);
});
} else {
// invalid option
return cb(false);
+38
View File
@@ -140,12 +140,50 @@ exports.movement = {
//index
exports.index = {
// show_last_updated: determine whether to show a label above the transaction data with the last updated date
"show_last_updated": true,
"show_hashrate": false,
"difficulty": "POS",
"last_txs": 100,
"txs_per_page": 10
};
// reward page
exports.reward_page = {
// show_last_updated: determine whether to show a label above the reward data with the last updated date
"show_last_updated": true
};
// masternodes page
exports.masternodes_page = {
// show_last_updated: determine whether to show a label above the masternode data with the last updated date
"show_last_updated": true
};
// movement page
exports.movement_page = {
// show_last_updated: determine whether to show a label above the movement data with the last updated date
"show_last_updated": true
};
// network page
exports.network_page = {
// show_last_updated: determine whether to show a label above the network data with the last updated date
"show_last_updated": true
};
// richlist page
exports.richlist_page = {
// show_last_updated: determine whether to show a label above the richlist data with the last updated date
"show_last_updated": true
};
// markets page
exports.markets_page = {
// show_last_updated: determine whether to show a label above the market data with the last updated date
"show_last_updated": true
};
// twitter, facebook, googleplus, bitcointalk, github, slack, discord, telegram, reddit, youtube, website
exports.twitter = "your-twitter-username";
exports.facebook = "your-facebook-username";
+6 -1
View File
@@ -10,7 +10,12 @@ var StatsSchema = new Schema({
connections: { type: Number, default: 0 },
last_price: { type: Number, default: 0 },
last_usd_price: { type: Number, default: 0 },
masternodes_last_updated: { type: Number, default: 0 }
blockchain_last_updated: { type: Number, default: 0 },
reward_last_updated: { type: Number, default: 0 },
masternodes_last_updated: { type: Number, default: 0 },
network_last_updated: { type: Number, default: 0 },
richlist_last_updated: { type: Number, default: 0 },
markets_last_updated: { type: Number, default: 0 }
});
module.exports = mongoose.model('coinstats', StatsSchema);
+122 -36
View File
@@ -150,7 +150,16 @@ function route_get_tx(res, txid) {
}
function route_get_index(res, error) {
res.render('index', { active: 'home', error: error, showSync: db.check_show_sync_message()});
// check if index page should show last updated date
if (settings.index.show_last_updated == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('index', { active: 'home', error: error, last_updated: stats.blockchain_last_updated, showSync: db.check_show_sync_message()});
});
} else {
// skip lookup up the last updated date and display the page now
res.render('index', { active: 'home', error: error, last_updated: null, showSync: db.check_show_sync_message()});
}
}
function route_get_address(res, hash, count) {
@@ -191,36 +200,67 @@ router.get('/info', function(req, res) {
});
router.get('/markets/:market', function(req, res) {
var market = req.params['market'];
if (settings.markets.enabled.indexOf(market) != -1) {
db.get_market(market, function(data) {
var exMarket = require('../lib/markets/' + market);
res.render('./market', {
active: 'markets',
marketdata: {
market_name: (exMarket.market_name == null ? '' : exMarket.market_name),
market_logo: (exMarket.market_logo == null ? '' : exMarket.market_logo),
coin: settings.markets.coin,
exchange: settings.markets.exchange,
data: data,
},
market: market,
showSync: db.check_show_sync_message()
// ensure markets page is enabled
if (settings.display.markets == true) {
var market_id = req.params['market'];
if (settings.markets.enabled.indexOf(market_id) != -1) {
// lookup market data
db.get_market(market_id, function(data) {
// load market data
var market_data = require('../lib/markets/' + market_id);
// check if markets page should show last updated date
if (settings.markets_page.show_last_updated == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('./market', {
active: 'markets',
marketdata: {
market_name: (market_data.market_name == null ? '' : market_data.market_name),
market_logo: (market_data.market_logo == null ? '' : market_data.market_logo),
coin: settings.markets.coin,
exchange: settings.markets.exchange,
data: data,
},
market: market_id,
last_updated: stats.markets_last_updated,
showSync: db.check_show_sync_message()
});
});
} else {
// skip lookup up the last updated date and display the page now
res.render('./market', {
active: 'markets',
marketdata: {
market_name: (market_data.market_name == null ? '' : market_data.market_name),
market_logo: (market_data.market_logo == null ? '' : market_data.market_logo),
coin: settings.markets.coin,
exchange: settings.markets.exchange,
data: data,
},
market: market_id,
last_updated: null,
showSync: db.check_show_sync_message()
});
}
});
});
} else {
// selected market is not enabled so default to the index page
route_get_index(res, null);
}
} else {
// markets page is not enabled so default to the index page
route_get_index(res, null);
}
});
router.get('/richlist', function(req, res) {
if (settings.display.richlist == true ) {
// ensure richlist page is enabled
if (settings.display.richlist == true) {
db.get_stats(settings.coin, function (stats) {
db.get_richlist(settings.coin, function(richlist){
//console.log(richlist);
db.get_richlist(settings.coin, function(richlist) {
if (richlist) {
db.get_distribution(richlist, stats, function(distribution) {
//console.log(distribution);
res.render('richlist', {
active: 'richlist',
balance: richlist.balance,
@@ -234,35 +274,74 @@ router.get('/richlist', function(req, res) {
show_dist: settings.richlist.distribution,
show_received: settings.richlist.received,
show_balance: settings.richlist.balance,
showSync: db.check_show_sync_message()
last_updated: (settings.richlist_page.show_last_updated == true ? stats.richlist_last_updated : null),
showSync: db.check_show_sync_message()
});
});
} else {
// richlist data not found so default to the index page
route_get_index(res, null);
}
});
});
} else {
// richlist page is not enabled so default to the index page
route_get_index(res, null);
}
});
router.get('/movement', function(req, res) {
res.render('movement', {active: 'movement', flaga: settings.movement.low_flag, flagb: settings.movement.high_flag, min_amount:settings.movement.min_amount, showSync: db.check_show_sync_message()});
// ensure movement page is enabled
if (settings.display.movement == true) {
// check if movement page should show last updated date
if (settings.movement_page.show_last_updated == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('movement', {active: 'movement', flaga: settings.movement.low_flag, flagb: settings.movement.high_flag, min_amount:settings.movement.min_amount, last_updated: stats.blockchain_last_updated, showSync: db.check_show_sync_message()});
});
} else {
// skip lookup up the last updated date and display the page now
res.render('movement', {active: 'movement', flaga: settings.movement.low_flag, flagb: settings.movement.high_flag, min_amount:settings.movement.min_amount, last_updated: null, showSync: db.check_show_sync_message()});
}
} else {
// movement page is not enabled so default to the index page
route_get_index(res, null);
}
});
router.get('/network', function(req, res) {
res.render('network', {active: 'network', showSync: db.check_show_sync_message()});
// ensure network page is enabled
if (settings.display.network == true) {
// check if network page should show last updated date
if (settings.network_page.show_last_updated == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('network', {active: 'network', last_updated: stats.network_last_updated, showSync: db.check_show_sync_message()});
});
} else {
// skip lookup up the last updated date and display the page now
res.render('network', {active: 'network', last_updated: null, showSync: db.check_show_sync_message()});
}
} else {
// network page is not enabled so default to the index page
route_get_index(res, null);
}
});
// masternode list page
router.get('/masternodes', function(req, res) {
// ensure masternode page is enabled
if (settings.display.masternodes == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('masternodes', {active: 'masternodes', last_updated: stats.masternodes_last_updated, showSync: db.check_show_sync_message()});
});
// check if masternodes page should show last updated date
if (settings.masternodes_page.show_last_updated == true) {
// lookup last updated date
db.get_stats(settings.coin, function (stats) {
res.render('masternodes', {active: 'masternodes', last_updated: stats.masternodes_last_updated, showSync: db.check_show_sync_message()});
});
} else {
// skip lookup up the last updated date and display the page now
res.render('masternodes', {active: 'masternodes', last_updated: null, showSync: db.check_show_sync_message()});
}
} else {
// masternode page is not enabled so default to the index page
route_get_index(res, null);
@@ -270,29 +349,36 @@ router.get('/masternodes', function(req, res) {
});
router.get('/reward', function(req, res) {
if (settings.heavy) {
// ensure reward page is enabled
if (settings.heavy == true) {
db.get_stats(settings.coin, function (stats) {
console.log(stats);
db.get_heavy(settings.coin, function (heavy) {
if (!heavy)
heavy = { coin: settings.coin, lvote: 0, reward: 0, supply: 0, cap: 0, estnext: 0, phase: 'N/A', maxvote: 0, nextin: 'N/A', votes: [] };
var votes = heavy.votes;
votes.sort(function (a,b) {
if (a.count < b.count) {
votes.sort(function (a, b) {
if (a.count < b.count)
return -1;
} else if (a.count > b.count) {
else if (a.count > b.count)
return 1;
} else {
else
return 0;
}
});
res.render('reward', { active: 'reward', stats: stats, heavy: heavy, votes: votes, showSync: db.check_show_sync_message() });
res.render('reward', {
active: 'reward',
stats: stats,
heavy: heavy,
votes: votes,
last_updated: (settings.reward_page.show_last_updated == true ? stats.reward_last_updated : null),
showSync: db.check_show_sync_message()
});
});
});
} else {
// reward page is not enabled so default to the index page
route_get_index(res, null);
}
});
+76 -42
View File
@@ -229,8 +229,11 @@ if (database == 'peers') {
}
});
}, function() {
console.log('peer sync complete');
exit();
// update network_last_updated value
db.update_last_updated_stats(settings.coin, { network_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
console.log('peer sync complete');
exit();
});
});
} else {
console.log('no peers found');
@@ -296,43 +299,47 @@ if (database == 'peers') {
exit();
} else {
db.update_db(settings.coin, function(stats){
if (settings.heavy == true) {
db.update_heavy(settings.coin, 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}, {
received: [],
balance: [],
}, function(err3) {
Stats.updateOne({coin: settings.coin}, {
last: 0,
count: 0,
supply: 0
}, function() {
console.log('index cleared (reindex)');
});
if (settings.heavy == true)
db.update_heavy(settings.coin, 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}, {
received: [],
balance: [],
}, function(err3) {
Stats.updateOne({coin: settings.coin}, {
last: 0,
count: 0,
supply: 0
}, function() {
console.log('index cleared (reindex)');
});
// Check if there are more than 1000 blocks to index
var showSync = check_show_sync_message(stats.count);
// Check if there are more than 1000 blocks to index
var showSync = check_show_sync_message(stats.count);
db.update_tx_db(settings.coin, 1, stats.count, stats.txes, settings.update_timeout, function(){
db.update_richlist('received', function(){
db.update_richlist('balance', function(){
db.get_stats(settings.coin, function(nstats){
// Check if the sync msg was showing
if (showSync) {
// Remove the sync msg
remove_sync_message();
}
console.log('reindex complete (block: %s)', nstats.last);
exit();
db.update_tx_db(settings.coin, 1, stats.count, stats.txes, settings.update_timeout, function() {
db.update_richlist('received', function() {
db.update_richlist('balance', function() {
db.get_stats(settings.coin, function(nstats) {
// Check if the sync msg was showing
if (showSync) {
// Remove the sync msg
remove_sync_message();
}
// update richlist_last_updated value
db.update_last_updated_stats(settings.coin, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
// update blockchain_last_updated value
db.update_last_updated_stats(settings.coin, { blockchain_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
console.log('reindex complete (block: %s)', nstats.last);
exit();
});
});
});
});
});
@@ -366,8 +373,14 @@ if (database == 'peers') {
// Remove the sync msg
remove_sync_message();
}
console.log('update complete (block: %s)', nstats.last);
exit();
// update richlist_last_updated value
db.update_last_updated_stats(settings.coin, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
// update blockchain_last_updated value
db.update_last_updated_stats(settings.coin, { blockchain_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
console.log('update complete (block: %s)', nstats.last);
exit();
});
});
});
});
});
@@ -383,8 +396,11 @@ if (database == 'peers') {
db.update_richlist('received', function() {
console.log('richlist updated received.');
db.update_richlist('balance', function() {
console.log('richlist update complete');
exit();
// update richlist_last_updated value
db.update_last_updated_stats(settings.coin, { richlist_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
console.log('richlist update complete');
exit();
});
});
});
});
@@ -402,6 +418,18 @@ if (database == 'peers') {
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}, {
txes: count
}, function() {
console.log('tx count update complete');
exit();
});
});
}
});
}
@@ -482,5 +510,11 @@ function remove_sync_message() {
function get_last_usd_price() {
// Get the last usd price for coinstats
db.get_last_usd_price(function(retVal) { exit(); });
db.get_last_usd_price(function(retVal) {
// update markets_last_updated value
db.update_last_updated_stats(settings.coin, { markets_last_updated: Math.floor(new Date() / 1000) }, function (cb) {
console.log('market sync complete');
exit();
});
});
}
+38
View File
@@ -144,12 +144,50 @@
// index page (valid options for difficulty are POW, POS or Hybrid)
"index": {
// show_last_updated: determine whether to show a label above the transaction data with the last updated date
"show_last_updated": true,
"show_hashrate": true,
"difficulty": "POS",
"last_txs": 100,
"txs_per_page": 10
},
// reward page
"reward_page": {
// show_last_updated: determine whether to show a label above the reward data with the last updated date
"show_last_updated": true
},
// masternodes page
"masternodes_page": {
// show_last_updated: determine whether to show a label above the masternode data with the last updated date
"show_last_updated": true
},
// movement page
"movement_page": {
// show_last_updated: determine whether to show a label above the movement data with the last updated date
"show_last_updated": true
},
// network page
"network_page": {
// show_last_updated: determine whether to show a label above the network data with the last updated date
"show_last_updated": true
},
// richlist page
"richlist_page": {
// show_last_updated: determine whether to show a label above the richlist data with the last updated date
"show_last_updated": true
},
// markets page
"markets_page": {
// show_last_updated: determine whether to show a label above the market data with the last updated date
"show_last_updated": true
},
// ensure links on API page are valid
"api": {
"blockindex": 6415,
+3
View File
@@ -77,6 +77,9 @@ block content
strong #{settings.locale.ex_error}
div #{error}
.col-md-12.cardSpacer
if settings.index.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Blockchain data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
.card.card-default.border-0.cardSpacer
.card-header
strong #{settings.locale.ex_latest_transactions}
+3
View File
@@ -50,6 +50,9 @@ block content
});
});
.col-xs-12.col-md-12
if settings.markets_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Market data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
if settings.markets.market_select_visible == true && settings.market_data.length > 1
.row
.col-md-12.cardSpacer
+3 -2
View File
@@ -93,8 +93,9 @@ block content
.col-md-12.cardSpacer
.text-center(style='margin-bottom:15px;')
i The current listing of all masternodes known to be active on the network.
div.font-weight-bold(style='margin-bottom:15px;') Last updated:
span.font-weight-normal=(last_updated == null ? ' N/A' : ' ' + format_unixtime(last_updated))
if settings.masternodes_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Masternode list last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
.card.card-default
.card-header
strong Masternodes
+3
View File
@@ -75,6 +75,9 @@ block content
}, 45000);
});
.col-md-12
if settings.movement_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Blockchain data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
.card.card-default.border-0.cardSpacer
.card-header
strong="Latest Movement"
+4
View File
@@ -1,10 +1,14 @@
extends layout
block content
include ./includes/common.pug
.col-md-12.cardSpacer
.text-center(style='margin-bottom:15px;')
i #{settings.locale.net_warning}
.container
if settings.network_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Network data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
ul.nav.nav-tabs(role='tablist')
li.nav-item(role='presentation')
a.nav-link.active(href='#connections', aria-controls='connections', role='tab', data-toggle='tab') #{settings.locale.net_connections}
+4
View File
@@ -1,6 +1,7 @@
extends layout
block content
include ./includes/common.pug
script.
$(document).ready(function() {
$('.summary-table').dataTable({
@@ -17,6 +18,9 @@ block content
});
.row(style='margin-left:0;margin-right:0;')
.col-xs-12.col-md-12
if settings.reward_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Reward data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
.card.card-default.border-0.card-address-summary
.card-header(style='position:relative;')
strong #{settings.locale.heavy_title}
+4
View File
@@ -1,6 +1,7 @@
extends layout
block content
include ./includes/common.pug
if show_dist == true
script.
$(document).ready(function() {
@@ -34,6 +35,9 @@ block content
.row(style='margin-left:0;margin-right:0;')
div(class=(show_dist == true ? 'col-xs-12 col-lg-8' : 'col-12'))
.container
if settings.richlist_page.show_last_updated == true
div.font-weight-bold(style='margin-bottom:15px;') Top 100 data last updated:
span.font-weight-normal=(last_updated == null || last_updated == '0' ? ' N/A' : ' ' + format_unixtime(last_updated))
ul.nav.nav-tabs(role='tablist')
li.nav-item(role='presentation')
a.nav-link.active(href='#balance', aria-controls='balance', role='tab', data-toggle='tab') #{settings.locale.rl_current_balance}