Tons of network chart improvements and changes

-Chart.js has been updated to v4.4.7
-The chartjs-plugin-crosshair chart plugin has been updated to v2.0.5 via a forked version that has a working sync feature which is now available as a new setting option for use with the network charts
-Added a new max_hours setting to display chart data for a certain number of hours instead of a fixed set of records which can help reveal holes in the sync process for the explorer and/or blockchain
-Added a new timestamp field to the network history collection for use with the max_hours setting chart data
-Added a number of new network chart settings to control display of the chart title, legend, a new vertical block line option, chart height, an option to force 2 charts to appear on their own row or beside each other, and an option to force a chart to take up all available space in the chart box without extra padding
-Added a new dependency chartjs-plugin-annotation v3.1.0 to display block lines in new hourly charts
This commit is contained in:
Joe Uhren
2024-12-28 19:22:38 -07:00
parent 8730b94629
commit 45a929b254
19 changed files with 849 additions and 235 deletions
+7 -4
View File
@@ -86,10 +86,13 @@ Table of Contents
- DataTables v1.13.6
- Font Awesome v6.4.2
- Luxon v3.4.3
- Chart.js v4.4.0
- chartjs-plugin-crosshair v2.0.0 ([https://github.com/abelheinsbroek/chartjs-plugin-crosshair](https://github.com/abelheinsbroek/chartjs-plugin-crosshair))
- Chart.js v4.4.7
- chartjs-plugin-crosshair v2.0.5
- Forked version with working sync feature: ([https://github.com/joeuhren/chartjs-plugin-crosshair](https://github.com/joeuhren/chartjs-plugin-crosshair))
- Original version: ([https://github.com/abelheinsbroek/chartjs-plugin-crosshair](https://github.com/abelheinsbroek/chartjs-plugin-crosshair))
- chartjs-chart-financial v0.1.1 ([https://github.com/chartjs/chartjs-chart-financial](https://github.com/chartjs/chartjs-chart-financial))
- chartjs-adapter-luxon v1.3.1 ([https://github.com/chartjs/chartjs-adapter-luxon](https://github.com/chartjs/chartjs-adapter-luxon))
- chartjs-plugin-annotation v3.1.0 ([https://github.com/chartjs/chartjs-plugin-annotation](https://github.com/chartjs/chartjs-plugin-annotation))
- OverlayScrollbars v2.3.2
- flag-icons v6.11.1 ([https://github.com/lipis/flag-icons](https://github.com/lipis/flag-icons))
- Intl.js (uses the v4.8.0 polyfill service to only download if using a browser that doesn't already support the ECMAScript Internationalization API)
@@ -179,8 +182,8 @@ Table of Contents
- **USD Market Cap:** Displays the current market cap value (value measured in USD)
- **Logo:** Display an image of your coin logo
- Configurable network charts that can be independently displayed in the header of any page
- **Hashrate chart:** Line graph listing of the estimated network hashes per second over the last number of blocks *\*Requires a full sync before network data will start being collected*
- **Difficulty chart:** Line graph listing of the block difficulty over the last number of blocks *\*Requires a full sync before network data will start being collected*
- **Hashrate chart:** Line graph listing of the estimated network hashes per second over the last number of blocks or hours *\*Requires a full sync before network data will start being collected*
- **Difficulty chart:** Line graph listing of the block difficulty over the last number of blocks or hours *\*Requires a full sync before network data will start being collected*
- Add as many custom social links to the explorer footer as desired. Useful for linking to github, twitter, coinmarketcap or any other social media or external links as necessary.
- Custom rpc/api command support which increases blockchain compatibility. Supported cmds:
- **getnetworkhashps:** Returns the estimated network hashes per second
+85 -52
View File
@@ -1306,67 +1306,97 @@ module.exports = {
lib.get_hashrate(function(hashrate) {
// lookup network difficulty
lib.get_difficulty(function(difficulty) {
var difficultyPOW = 0;
var difficultyPOS = 0;
// lookup the block hash
lib.get_blockhash(height, function(blockhash) {
if (blockhash) {
// lookup block data
lib.get_block(blockhash, function(block) {
if (block) {
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;
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;
// create a new network history record
var newNetworkHistory = new NetworkHistory({
blockindex: height,
nethash: (hashrate == null || hashrate == '-' ? 0 : hashrate),
difficulty_pow: difficultyPOW,
difficulty_pos: difficultyPOS,
});
// create a new network history record
var newNetworkHistory = new NetworkHistory({
blockindex: height,
nethash: (hashrate == null || hashrate == '-' ? 0 : hashrate),
difficulty_pow: difficultyPOW,
difficulty_pos: difficultyPOS,
timestamp: block.time
});
// save the new network history record
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;
// save the new network history record
newNetworkHistory.save().then(() => {
// read maximum allowed records from settings
const 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);
// check if the max allowed records is set
if (max_records == 0) {
// read maximum hours from settings
const max_hours = settings.network_history.max_hours;
// delete old network history records
NetworkHistory.deleteMany({blockindex: {$in: ids}}).then(() => {
console.log('Network history update complete');
return cb();
// calculate the cutoff timestamp value
const timestampThreshold = Math.floor(Date.now() / 1000) - max_hours * 60 * 60;
// delete all network history records that are older than the max hours setting
NetworkHistory.deleteMany({ timestamp: { $lt: timestampThreshold } }).then(delete_result => {
console.log('Network history update complete');
return cb();
}).catch(err => {
console.log(err);
return cb();
});
} else {
// prune network history records to keep collection small and quick to access
NetworkHistory.find().sort({ blockindex: -1 }).skip(max_records).select('blockindex').exec().then((records) => {
// check if any records need to be deleted
if (records.length > 0) {
// 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();
});
} else {
// no records need to be deleted
console.log('Network history update complete');
return cb();
}
}).catch((err) => {
console.log(err);
return cb();
});
}
}).catch((err) => {
console.log(err);
console.log('Error updating network history: ' + err);
return cb();
});
}).catch((err) => {
console.log(err);
} else {
console.log(`Error updating network history: Cannot find block with hash ${blockhash}`);
return cb();
});
} else {
console.log('Network history update complete');
return cb();
}
}).catch((err) => {
console.log(err);
}
});
} else {
console.log(`Error updating network history: Cannot find block hash with height ${height}`);
return cb();
});
}).catch((err) => {
console.log('Error updating network history: ' + err);
return cb();
}
});
});
});
@@ -1928,7 +1958,10 @@ module.exports = {
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);
// determine if timestamp field exists
check_add_db_field(NetworkHistory, 'timestamp', 0, function(timestamp_exists) {
return cb(true);
});
});
});
} else
+147 -4
View File
@@ -86,7 +86,9 @@ exports.network_history = {
// If set to false, historical data such as network hashrate and difficulty values will not be saved or available for network charts
"enabled": true,
// max_saved_records: The maximum # of blocks to save historical data for
"max_saved_records": 120
"max_saved_records": 120,
// max_hours: The maximum # of hours to save historical data for. The max_saved_records value will supercede this value so be sure to set max_saved_records to 0 if wanting to display data for a certain number of hours
"max_hours": 24
};
/* Shared page settings */
@@ -343,6 +345,51 @@ exports.shared_pages = {
// If set to false, the network hashrate chart will be completely inaccessible
// NOTE: The `shared_pages.show_hashrate` option must be set to true or else the network hashrate chart will be completely inaccessible
"enabled": true,
// chart_title: A collection of settings that pertain to the chart title
"chart_title": {
// enabled: Enable/disable the chart title (true/false)
// If set to false, the chart title will be completely absent from the chart
"enabled": false,
// title_text: The text to display in the chart title
// NOTE: You can add a "/n" character for a carriage return
// The following keywords can be used in the chart title:
// {coin_name}: Display the name of the coin from the `coin.name` setting
// {max_saved_records}: Display the number of records the chart is showing data for from the `network_history.max_saved_records` setting
// {max_hours}: Display the number of hours the chart is showing data for from the `network_history.max_hours` setting
// {current_nethash}: Display the most recent nethash value from the network chart data
// {highest_nethash}: Display the highest nethash value from the network chart data
// {lowest_nethash}: Display the lowest nethash value from the network chart data
// {highest_block}: Display the highest block height value from the network chart data
// {lowest_block}: Display the lowest block height value from the network chart data
"title_text": "{coin_name} Network Hashrate History for the last {max_hours} hours\nHigh: {highest_nethash}\nCurrent: {current_nethash}\nLow: {lowest_nethash}\nBlock: {highest_block}",
// alignment: Determine how to align the chart title text horizontally
// Valid options are left, center and right
"alignment": "center",
// color: Change the chart title text color
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"color": "#666666",
// font: A collection of settings that pertain to the chart title font
"font": {
// family: The font to use for the chart title
// Valid options are: Arial, Verdana, Times New Roman, Georgia, Courier New, Tahoma
"family": "Arial",
// size: Determine the size of the font text in pixels
"size": 20,
// weight: Determine the thickness of the font text
// Valid options are: normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900
"weight": "bold"
}
},
// legend: A collection of settings that pertain to the chart legend
"legend": {
// enabled: Enable/disable the chart legend (true/false)
// If set to false, the legend will be completely absent from the chart
"enabled": true,
// position: Determine where to position the chart legend
// Valid options are top, left, bottom and right
"position": "bottom"
},
// bgcolor: Change the background color of the network hashrate chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
@@ -359,15 +406,85 @@ exports.shared_pages = {
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"crosshair_color": "#000000",
// block_line: A collection of settings that pertain to the vertical block line on the network hashrate chart
"block_line": {
// enabled: Enable/disable the vertical block line (true/false)
// If set to false, the vertical block line will be completely hidden from the chart
// NOTE: The `network_history.max_saved_records` option must also be set to 0 or else the vertical block line will be completely hidden from the chart
"enabled": true,
// block_line_color: Change the line color of the block data for the network hashrate chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"block_line_color": "rgba(0, 128, 0, 0.2)"
},
// round_decimals: Set how many decimal places the hash rates are rounded to (Max 20)
// NOTE: Set to a value of -1 to output the raw value without rounding
"round_decimals": 3
"round_decimals": 3,
// chart_height: Height of chart in px
"chart_height": 300,
// full_row: Determine whether the chart will appear in its own row or can have another chart beside it in the same row
// If set to true, the chart will take up the full width of the page
// If set to false, and another chart is configured to display, the 2nd chart will appear beside this chart, both taking up 50% of the width of the screen
// NOTE: On smaller screens such as mobile phones and some tablets, each chart will take up it's own row regardless of what the full_row setting is set to due to limited screen real estate
"full_row": false,
// stretch_to_fit: Determine if the chart should be fit inside the surrounding chart box with or without padding
// If set to true, the chart will take up the full available space inside the chart box
// If set to false, there will be some padding on all 4 sides of the chart box
"stretch_to_fit": false
},
// difficulty_chart: A collection of settings that pertain to the network difficulty chart
"difficulty_chart": {
// enabled: Enable/disable the network difficulty chart (true/false)
// If set to false, the network difficulty chart will be completely inaccessible
"enabled": true,
// chart_title: A collection of settings that pertain to the chart title
"chart_title": {
// enabled: Enable/disable the chart title (true/false)
// If set to false, the chart title will be completely absent from the chart
"enabled": false,
// title_text: The text to display in the chart title
// NOTE: You can add a "/n" character for a carriage return
// The following keywords can be used in the chart title:
// {coin_name}: Display the name of the coin from the `coin.name` setting
// {max_saved_records}: Display the number of records the chart is showing data for from the `network_history.max_saved_records` setting
// {max_hours}: Display the number of hours the chart is showing data for from the `network_history.max_hours` setting
// {current_pow_difficulty}: Display the most recent POW difficulty value from the network chart data
// {highest_pow_difficulty}: Display the highest POW difficulty value from the network chart data
// {lowest_pow_difficulty}: Display the lowest POW difficulty value from the network chart data
// {current_pos_difficulty}: Display the most recent POS difficulty value from the network chart data
// {highest_pos_difficulty}: Display the highest POS difficulty value from the network chart data
// {lowest_pos_difficulty}: Display the lowest POS difficulty value from the network chart data
// {highest_block}: Display the highest block height value from the network chart data
// {lowest_block}: Display the lowest block height value from the network chart data
"title_text": "{coin_name} Difficulty Rate History for the last {max_hours} hours\nHigh: {highest_pos_difficulty}\nCurrent: {current_pos_difficulty}\nLow: {lowest_pos_difficulty}\nBlock: {highest_block}",
// alignment: Determine how to align the chart title text horizontally
// Valid options are left, center and right
"alignment": "center",
// color: Change the chart title text color
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"color": "#666666",
// font: A collection of settings that pertain to the chart title font
"font": {
// family: The font to use for the chart title
// Valid options are: Arial, Verdana, Times New Roman, Georgia, Courier New, Tahoma
"family": "Arial",
// size: Determine the size of the font text in pixels
"size": 20,
// weight: Determine the thickness of the font text
// Valid options are: normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900
"weight": "bold"
}
},
// legend: A collection of settings that pertain to the chart legend
"legend": {
// enabled: Enable/disable the chart legend (true/false)
// If set to false, the legend will be completely absent from the chart
"enabled": true,
// position: Determine where to position the chart legend
// Valid options are top, left, bottom and right
"position": "bottom"
},
// bgcolor: Change the background color of the network difficulty chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
@@ -392,13 +509,39 @@ exports.shared_pages = {
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"crosshair_color": "#000000",
// block_line: A collection of settings that pertain to the vertical block line on the network difficulty chart
"block_line": {
// enabled: Enable/disable the vertical block line (true/false)
// If set to false, the vertical block line will be completely hidden from the chart
// NOTE: The `network_history.max_saved_records` option must also be set to 0 or else the vertical block line will be completely hidden from the chart
"enabled": true,
// block_line_color: Change the line color of the block data for the network difficulty chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"block_line_color": "rgba(0, 128, 0, 0.2)"
},
// round_decimals: Set how many decimal places the difficulty values are rounded to (Max 20)
// NOTE: Set to a value of -1 to output the raw value without rounding
"round_decimals": 3
"round_decimals": 3,
// chart_height: Height of chart in px
"chart_height": 300,
// full_row: Determine whether the chart will appear in its own row or can have another chart beside it in the same row
// If set to true, the chart will take up the full width of the page
// If set to false, and another chart is configured to display, the 2nd chart will appear beside this chart, both taking up 50% of the width of the screen
// NOTE: On smaller screens such as mobile phones and some tablets, each chart will take up it's own row regardless of what the full_row setting is set to due to limited screen real estate
"full_row": false,
// stretch_to_fit: Determine if the chart should be fit inside the surrounding chart box with or without padding
// If set to true, the chart will take up the full available space inside the chart box
// If set to false, there will be some padding on all 4 sides of the chart box
"stretch_to_fit": false
},
// reload_chart_seconds: The time in seconds to automatically reload the network chart data from the server
// Set to 0 to disable automatic reloading of chart data
"reload_chart_seconds": 60
"reload_chart_seconds": 60,
// sync_charts: Determine if multiple network charts should be synced while cycling through different data points
// If set to true, all network charts will be synced so that when clicking on or moving the mouse cursor over a particular chart, all other network charts will also have their crosshairs set to the same data point for easy comparison
// If set to false, only the chart that is currently being manipulated will display a crosshair for the data point being viewed
"sync_charts": false
}
},
// page_footer: A collection of settings that pertain to the page footer that is displayed at the bottom of all pages
+2 -1
View File
@@ -5,7 +5,8 @@ var NetworkHistorySchema = new Schema({
blockindex: {type: Number, default: 0, index: true},
nethash: { type: Number, default: 0 },
difficulty_pow: { type: Number, default: 0 },
difficulty_pos: { type: Number, default: 0 }
difficulty_pos: { type: Number, default: 0 },
timestamp: { type: Number, default: 0 }
}, {id: false});
module.exports = mongoose.model('NetworkHistory', NetworkHistorySchema);
+148 -5
View File
@@ -87,8 +87,10 @@
// enabled: Enable/disable the saving of additional network history data (true/false)
// If set to false, historical data such as network hashrate and difficulty values will not be saved or available for network charts
"enabled": true,
// max_saved_records: The maximum # of blocks to save historical data for
"max_saved_records": 120
// max_saved_records: The maximum # of blocks to save historical data for. Set this value to 0 if using the max_hours option
"max_saved_records": 120,
// max_hours: The maximum # of hours to save historical data for. The max_saved_records value will supercede this value so be sure to set max_saved_records to 0 if wanting to display data for a certain number of hours
"max_hours": 24
},
/* Shared page settings */
@@ -345,6 +347,51 @@
// If set to false, the network hashrate chart will be completely inaccessible
// NOTE: The `shared_pages.show_hashrate` option must be set to true or else the network hashrate chart will be completely inaccessible
"enabled": true,
// chart_title: A collection of settings that pertain to the chart title
"chart_title": {
// enabled: Enable/disable the chart title (true/false)
// If set to false, the chart title will be completely absent from the chart
"enabled": false,
// title_text: The text to display in the chart title
// NOTE: You can add a "/n" character for a carriage return
// The following keywords can be used in the chart title:
// {coin_name}: Display the name of the coin from the `coin.name` setting
// {max_saved_records}: Display the number of records the chart is showing data for from the `network_history.max_saved_records` setting
// {max_hours}: Display the number of hours the chart is showing data for from the `network_history.max_hours` setting
// {current_nethash}: Display the most recent nethash value from the network chart data
// {highest_nethash}: Display the highest nethash value from the network chart data
// {lowest_nethash}: Display the lowest nethash value from the network chart data
// {highest_block}: Display the highest block height value from the network chart data
// {lowest_block}: Display the lowest block height value from the network chart data
"title_text": "{coin_name} Network Hashrate History for the last {max_hours} hours\nHigh: {highest_nethash}\nCurrent: {current_nethash}\nLow: {lowest_nethash}\nBlock: {highest_block}",
// alignment: Determine how to align the chart title text horizontally
// Valid options are left, center and right
"alignment": "center",
// color: Change the chart title text color
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"color": "#666666",
// font: A collection of settings that pertain to the chart title font
"font": {
// family: The font to use for the chart title
// Valid options are: Arial, Verdana, Times New Roman, Georgia, Courier New, Tahoma
"family": "Arial",
// size: Determine the size of the font text in pixels
"size": 20,
// weight: Determine the thickness of the font text
// Valid options are: normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900
"weight": "bold"
}
},
// legend: A collection of settings that pertain to the chart legend
"legend": {
// enabled: Enable/disable the chart legend (true/false)
// If set to false, the legend will be completely absent from the chart
"enabled": true,
// position: Determine where to position the chart legend
// Valid options are top, left, bottom and right
"position": "bottom"
},
// bgcolor: Change the background color of the network hashrate chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
@@ -361,15 +408,85 @@
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"crosshair_color": "#000000",
// block_line: A collection of settings that pertain to the vertical block line on the network hashrate chart
"block_line": {
// enabled: Enable/disable the vertical block line (true/false)
// If set to false, the vertical block line will be completely hidden from the chart
// NOTE: The `network_history.max_saved_records` option must also be set to 0 or else the vertical block line will be completely hidden from the chart
"enabled": true,
// block_line_color: Change the line color of the block data for the network hashrate chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"block_line_color": "rgba(0, 128, 0, 0.2)"
},
// round_decimals: Set how many decimal places the hash rates are rounded to (Max 20)
// NOTE: Set to a value of -1 to output the raw value without rounding
"round_decimals": 3
"round_decimals": 3,
// chart_height: Height of chart in px
"chart_height": 300,
// full_row: Determine whether the chart will appear in its own row or can have another chart beside it in the same row
// If set to true, the chart will take up the full width of the page
// If set to false, and another chart is configured to display, the 2nd chart will appear beside this chart, both taking up 50% of the width of the screen
// NOTE: On smaller screens such as mobile phones and some tablets, each chart will take up it's own row regardless of what the full_row setting is set to due to limited screen real estate
"full_row": false,
// stretch_to_fit: Determine if the chart should be fit inside the surrounding chart box with or without padding
// If set to true, the chart will take up the full available space inside the chart box
// If set to false, there will be some padding on all 4 sides of the chart box
"stretch_to_fit": false
},
// difficulty_chart: A collection of settings that pertain to the network difficulty chart
"difficulty_chart": {
// enabled: Enable/disable the network difficulty chart (true/false)
// If set to false, the network difficulty chart will be completely inaccessible
"enabled": true,
// chart_title: A collection of settings that pertain to the chart title
"chart_title": {
// enabled: Enable/disable the chart title (true/false)
// If set to false, the chart title will be completely absent from the chart
"enabled": false,
// title_text: The text to display in the chart title
// NOTE: You can add a "/n" character for a carriage return
// The following keywords can be used in the chart title:
// {coin_name}: Display the name of the coin from the `coin.name` setting
// {max_saved_records}: Display the number of records the chart is showing data for from the `network_history.max_saved_records` setting
// {max_hours}: Display the number of hours the chart is showing data for from the `network_history.max_hours` setting
// {current_pow_difficulty}: Display the most recent POW difficulty value from the network chart data
// {highest_pow_difficulty}: Display the highest POW difficulty value from the network chart data
// {lowest_pow_difficulty}: Display the lowest POW difficulty value from the network chart data
// {current_pos_difficulty}: Display the most recent POS difficulty value from the network chart data
// {highest_pos_difficulty}: Display the highest POS difficulty value from the network chart data
// {lowest_pos_difficulty}: Display the lowest POS difficulty value from the network chart data
// {highest_block}: Display the highest block height value from the network chart data
// {lowest_block}: Display the lowest block height value from the network chart data
"title_text": "{coin_name} Difficulty Rate History for the last {max_hours} hours\nHigh: {highest_pos_difficulty}\nCurrent: {current_pos_difficulty}\nLow: {lowest_pos_difficulty}\nBlock: {highest_block}",
// alignment: Determine how to align the chart title text horizontally
// Valid options are left, center and right
"alignment": "center",
// color: Change the chart title text color
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"color": "#666666",
// font: A collection of settings that pertain to the chart title font
"font": {
// family: The font to use for the chart title
// Valid options are: Arial, Verdana, Times New Roman, Georgia, Courier New, Tahoma
"family": "Arial",
// size: Determine the size of the font text in pixels
"size": 20,
// weight: Determine the thickness of the font text
// Valid options are: normal, bold, bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900
"weight": "bold"
}
},
// legend: A collection of settings that pertain to the chart legend
"legend": {
// enabled: Enable/disable the chart legend (true/false)
// If set to false, the legend will be completely absent from the chart
"enabled": true,
// position: Determine where to position the chart legend
// Valid options are top, left, bottom and right
"position": "bottom"
},
// bgcolor: Change the background color of the network difficulty chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
@@ -394,13 +511,39 @@
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"crosshair_color": "#000000",
// block_line: A collection of settings that pertain to the vertical block line on the network difficulty chart
"block_line": {
// enabled: Enable/disable the vertical block line (true/false)
// If set to false, the vertical block line will be completely hidden from the chart
// NOTE: The `network_history.max_saved_records` option must also be set to 0 or else the vertical block line will be completely hidden from the chart
"enabled": true,
// block_line_color: Change the line color of the block data for the network difficulty chart
// Set this to any valid html color
// Ex: "#ffffff" or "rgba(255, 255, 255, 1)" or "white"
"block_line_color": "rgba(0, 128, 0, 0.2)"
},
// round_decimals: Set how many decimal places the difficulty values are rounded to (Max 20)
// NOTE: Set to a value of -1 to output the raw value without rounding
"round_decimals": 3
"round_decimals": 3,
// chart_height: Height of chart in px
"chart_height": 300,
// full_row: Determine whether the chart will appear in its own row or can have another chart beside it in the same row
// If set to true, the chart will take up the full width of the page
// If set to false, and another chart is configured to display, the 2nd chart will appear beside this chart, both taking up 50% of the width of the screen
// NOTE: On smaller screens such as mobile phones and some tablets, each chart will take up it's own row regardless of what the full_row setting is set to due to limited screen real estate
"full_row": false,
// stretch_to_fit: Determine if the chart should be fit inside the surrounding chart box with or without padding
// If set to true, the chart will take up the full available space inside the chart box
// If set to false, there will be some padding on all 4 sides of the chart box
"stretch_to_fit": false
},
// reload_chart_seconds: The time in seconds to automatically reload the network chart data from the server
// Set to 0 to disable automatic reloading of chart data
"reload_chart_seconds": 60
"reload_chart_seconds": 60,
// sync_charts: Determine if multiple network charts should be synced while cycling through different data points
// If set to true, all network charts will be synced so that when clicking on or moving the mouse cursor over a particular chart, all other network charts will also have their crosshairs set to the same data point for easy comparison
// If set to false, only the chart that is currently being manipulated will display a crosshair for the data point being viewed
"sync_charts": true
}
},
// page_footer: A collection of settings that pertain to the page footer that is displayed at the bottom of all pages
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
var hashAddress = "#{address.a_id}";
var setting_maxTxCount = parseInt("#{settings.api_page.public_apis.ext.getaddresstxs.max_items_per_query}");
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
- var block_difficulty = parseFloat(block.difficulty).toFixed(4);
- var theadClasses = [];
if settings.shared_pages.table_header_bgcolor != null && settings.shared_pages.table_header_bgcolor != ''
+6
View File
@@ -0,0 +1,6 @@
div#difficultyChartParent(class=chartColumnClass, style='display:none;margin:10px 0;')
.card.card-default.border-0
.card-header
strong Network Difficulty
.card-body(style=(settings.shared_pages.page_header.network_charts.difficulty_chart.stretch_to_fit == true ? 'padding:0!important;' : ''))
canvas#difficultyChart(style='min-height:'+settings.shared_pages.page_header.network_charts.difficulty_chart.chart_height+'px;max-height:'+settings.shared_pages.page_header.network_charts.difficulty_chart.chart_height+'px;background-color:'+settings.shared_pages.page_header.network_charts.difficulty_chart.bgcolor+';')
+6
View File
@@ -0,0 +1,6 @@
div#nethashChartParent(class=chartColumnClass, style='display:none;margin:10px 0;')
.card.card-default.border-0
.card-header
strong Network Hashrate
.card-body(style=(settings.shared_pages.page_header.network_charts.nethash_chart.stretch_to_fit == true ? 'padding:0!important;' : ''))
canvas#nethashChart(style='min-height:'+settings.shared_pages.page_header.network_charts.nethash_chart.chart_height+'px;max-height:'+settings.shared_pages.page_header.network_charts.nethash_chart.chart_height+'px;background-color:'+settings.shared_pages.page_header.network_charts.nethash_chart.bgcolor+';')
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
var setting_maxTxCount = parseInt("#{settings.api_page.public_apis.ext.getlasttxs.max_items_per_query}");
var setting_txPerPage = parseInt("#{settings.index_page.transaction_table.items_per_page}");
+448 -157
View File
@@ -157,12 +157,25 @@ html(lang='en')
- showNethashChart = true
if settings.error_page.show_difficulty_chart == true
- showDifficultyChart = true
if active == 'markets' || active == 'richlist' || active == 'reward' || (settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true)))
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js')
if settings.network_history.enabled == true
if !(showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true)
- showNethashChart = false
if !(showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true)
- showDifficultyChart = false
else
- showNethashChart = false
- showDifficultyChart = false
if active == 'home' || active == 'address' || active == 'block' || active == 'markets' || active == 'masternodes' || active == 'movement' || active == 'network' || active == 'orphans' || active == 'reward' || active == 'richlist' || active == 'tx'
include ./includes/common.pug
if active == 'markets' || active == 'richlist' || active == 'reward' || showNethashChart == true || showDifficultyChart == true
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js')
if active == 'markets'
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chartjs-chart-financial@0.1.1/dist/chartjs-chart-financial.min.js')
if active == 'markets' || (settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true)))
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair@2.0.0')
if active == 'markets' || showNethashChart == true || showDifficultyChart == true
script(type='text/javascript', src='https://cdn.jsdelivr.net/gh/joeuhren/chartjs-plugin-crosshair@v2.0.5/build/chartjs-plugin-crosshair.min.js')
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.3.1')
if showNethashChart == true || showDifficultyChart == true
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@3.1.0/dist/chartjs-plugin-annotation.min.js')
- var sideBarClasses = [];
if settings.shared_pages.page_header.bgcolor != null && settings.shared_pages.page_header.bgcolor != ''
- sideBarClasses.push('bg-' + settings.shared_pages.page_header.bgcolor);
@@ -497,8 +510,9 @@ html(lang='en')
update_stats();
});
if settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true))
if showNethashChart == true || showDifficultyChart == true
script.
const maxSavedRecords = #{settings.network_history.max_saved_records};
const countDecimals = function(value) {
const text = value.toString();
@@ -521,6 +535,223 @@ html(lang='en')
}
});
}
function roundToNearestMinute(timestamp) {
return Math.floor(timestamp * 1000 / (60 * 1000)) * (60 * 1000);
}
function formatNetworkChartValue(val, roundDecimals, lbl, returnNum) {
let max = 20;
if (roundDecimals != -1)
max = roundDecimals;
else {
const decimalCount = countDecimals(val || 0);
if (decimalCount < max)
max = decimalCount;
}
if (returnNum)
return (val || 0);
else
return Number((val || 0)).toLocaleString('en',{'minimumFractionDigits':0,'maximumFractionDigits':max,'useGrouping':true}) + (lbl == 'Hashrate' ? ' ' + getNetHashUnits() : '');
}
function populateHourChartData(result) {
const roundedDataMap = new Map();
result.forEach((entry) => {
const roundedTimestamp = roundToNearestMinute(entry.timestamp);
if (roundedTimestamp != 0 && !roundedDataMap.has(roundedTimestamp))
roundedDataMap.set(roundedTimestamp, { ...entry, tick: roundedTimestamp });
});
let normalizedData = Array.from(roundedDataMap.values()).sort((a, b) => a.tick - b.tick);
let lastKnownValue = { blockindex: 0, difficulty_pow: 0, difficulty_pos: 0, nethash: 0 };
let maxTimestamp = new Date().getTime();
let hourData = [];
if (normalizedData.length > 0)
maxTimestamp = normalizedData[normalizedData.length - 1].tick;
const minTimestamp = maxTimestamp - ((#{settings.network_history.max_hours} * 60 * 60 * 1000) - (60 * 1000)); // x hours before maxTimestamp minus 1 minute to encompass the full timeframe
if (normalizedData.length > 0 && normalizedData[0].tick > minTimestamp) {
// use the first real data point values but set blockindex to 0
lastKnownValue = { ...normalizedData[0], blockindex: 0 };
// backfill from minTimestamp up to the first real data point
for (let ts = minTimestamp; ts < normalizedData[0].tick; ts += 60 * 1000)
hourData.push({ ...lastKnownValue, tick: ts });
}
let currentTimestamp = Math.max(minTimestamp, normalizedData[0]?.tick || minTimestamp);
for (let i = 0; i < normalizedData.length; i++) {
const dataPoint = normalizedData[i];
// fill any gap between currentTimestamp and the current dataPoint.tick
while (currentTimestamp < dataPoint.tick) {
hourData.push({ ...lastKnownValue, tick: currentTimestamp, blockindex: 0 });
currentTimestamp += 60 * 1000; // move to the next minute
}
// add the real data point to hourData
lastKnownValue = dataPoint;
hourData.push({ ...dataPoint, tick: dataPoint.tick });
// move currentTimestamp to the next minute after the current data point
currentTimestamp = dataPoint.tick + 60 * 1000;
}
// fill remaining range up to maxTimestamp with last known values
while (currentTimestamp < maxTimestamp) {
hourData.push({ ...lastKnownValue, tick: currentTimestamp, blockindex: 0 });
currentTimestamp += 60 * 1000;
}
xScale = {
type: 'time',
time: {
unit: 'minute',
stepSize: 60,
displayFormats: {
minute: '#{settings.shared_pages.date_time.display_format}'
}
},
min: minTimestamp, // Set x-axis to start at the first data point
max: maxTimestamp, // Set x-axis to end at the last data point
ticks: {
maxTicksLimit: #{settings.network_history.max_hours},
callback: function(value) {
return format_unixtime(Math.floor(value / 1000));
}
}
};
return {
hourData: hourData,
minTimestamp: minTimestamp,
maxTimestamp: maxTimestamp,
xScale: xScale
};
}
function populatePluginDataTitle(chartData, chartTitleSettings, roundDecimals, netHashOnly, difficultyOnly) {
let showPOW = false;
let showPOS = false;
let highestNethash = 0;
let lowestNethash = -1;
let highestPowDifficulty = 0;
let lowestPowDifficulty = -1;
let highestPosDifficulty = 0;
let lowestPosDifficulty = -1;
let highestBlock = 0;
let lowestBlock = -1;
let pluginTitle = {};
const currentNethash = formatNetworkChartValue((chartData.length > 0 && chartData[0].nethash != null ? chartData[chartData.length - 1].nethash : 0), roundDecimals, 'Hashrate', true);
const currentPowDifficulty = formatNetworkChartValue((chartData.length > 0 && chartData[0].difficulty_pow != null ? chartData[chartData.length - 1].difficulty_pow : 0), roundDecimals, 'Difficulty', true);
const currentPosDifficulty = formatNetworkChartValue((chartData.length > 0 && chartData[0].difficulty_pos != null ? chartData[chartData.length - 1].difficulty_pos : 0), roundDecimals, 'Difficulty', true);
for (let i = 0; i < chartData.length; i++) {
if (chartData[i].difficulty_pow != null && chartData[i].difficulty_pow != 0)
showPOW = true;
if (chartData[i].difficulty_pos != null && chartData[i].difficulty_pos != 0)
showPOS = true;
if (chartData[i].nethash != null && chartData[i].nethash > highestNethash)
highestNethash = formatNetworkChartValue(chartData[i].nethash, roundDecimals, 'Hashrate', true);
if (chartData[i].nethash != null && (lowestNethash == -1 || chartData[i].nethash < lowestNethash))
lowestNethash = formatNetworkChartValue(chartData[i].nethash, roundDecimals, 'Hashrate', true);
if (chartData[i].difficulty_pow != null && chartData[i].difficulty_pow > highestPowDifficulty)
highestPowDifficulty = formatNetworkChartValue(chartData[i].difficulty_pow, roundDecimals, 'Difficulty', true);
if (chartData[i].difficulty_pow != null && (lowestPowDifficulty == -1 || chartData[i].difficulty_pow < lowestPowDifficulty))
lowestPowDifficulty = formatNetworkChartValue(chartData[i].difficulty_pow, roundDecimals, 'Difficulty', true);
if (chartData[i].difficulty_pos != null && chartData[i].difficulty_pos > highestPosDifficulty)
highestPosDifficulty = formatNetworkChartValue(chartData[i].difficulty_pos, roundDecimals, 'Difficulty', true);
if (chartData[i].difficulty_pos != null && (lowestPosDifficulty == -1 || chartData[i].difficulty_pos < lowestPosDifficulty))
lowestPosDifficulty = formatNetworkChartValue(chartData[i].difficulty_pos, roundDecimals, 'Difficulty', true);
if (chartData[i].blockindex > highestBlock)
highestBlock = chartData[i].blockindex;
if (chartData[i].blockindex > 0 && (lowestBlock == -1 || chartData[i].blockindex < lowestBlock))
lowestBlock = chartData[i].blockindex;
}
if (chartTitleSettings.enabled == true) {
let chart_title = chartTitleSettings.title_text.replace(/\n/g, '\\n')
.replace(/{coin_name}/g, '#{settings.coin.name}')
.replace(/{max_saved_records}/g, maxSavedRecords)
.replace(/{max_hours}/g, '#{settings.network_history.max_hours}')
.replace(/{highest_block}/g, highestBlock)
.replace(/{lowest_block}/g, lowestBlock);
if (netHashOnly || (!netHashOnly && !difficultyOnly)) {
chart_title = chart_title
.replace(/{current_nethash}/g, formatNetworkChartValue(currentNethash, roundDecimals, 'Hashrate', false))
.replace(/{highest_nethash}/g, formatNetworkChartValue(highestNethash, roundDecimals, 'Hashrate', false))
.replace(/{lowest_nethash}/g, formatNetworkChartValue(lowestNethash, roundDecimals, 'Hashrate', false));
}
if (difficultyOnly || (!netHashOnly && !difficultyOnly)) {
chart_title = chart_title
.replace(/{current_pow_difficulty}/g, formatNetworkChartValue(currentPowDifficulty, roundDecimals, 'Difficulty', false))
.replace(/{highest_pow_difficulty}/g, formatNetworkChartValue(highestPowDifficulty, roundDecimals, 'Difficulty', false))
.replace(/{lowest_pow_difficulty}/g, formatNetworkChartValue(lowestPowDifficulty, roundDecimals, 'Difficulty', false))
.replace(/{current_pos_difficulty}/g, formatNetworkChartValue(currentPosDifficulty, roundDecimals, 'Difficulty', false))
.replace(/{highest_pos_difficulty}/g, formatNetworkChartValue(highestPosDifficulty, roundDecimals, 'Difficulty', false))
.replace(/{lowest_pos_difficulty}/g, formatNetworkChartValue(lowestPosDifficulty, roundDecimals, 'Difficulty', false))
}
pluginTitle = {
display: true,
text: chart_title.split('\\n'),
position: 'top',
align: chartTitleSettings.alignment.replace('left', 'start').replace('right', 'end'),
color: chartTitleSettings.color,
font: {
family: chartTitleSettings.font.family,
size: chartTitleSettings.font.size,
weight: chartTitleSettings.font.weight
},
padding: {
top: 10,
bottom: 10
}
};
} else {
pluginTitle = {
display: false
};
}
return {
showPOW: showPOW,
showPOS: showPOS,
pluginTitle: pluginTitle
};
}
function populateBlockIndexAnnotations(hourData, blockLineSettings) {
let blockIndexAnnotations = null;
if (blockLineSettings.enabled && maxSavedRecords == 0) {
blockIndexAnnotations = {
annotations: (
hourData
.filter(d => d.blockindex)
.map(d => ({
type: 'line',
mode: 'vertical',
scaleID: 'x',
value: d.tick,
borderColor: blockLineSettings.block_line_color,
borderWidth: 1,
label: {
enabled: false
}
}))
)
};
}
return blockIndexAnnotations;
}
$(document).ready(function() {
const setting_reload_chart_seconds = #{settings.shared_pages.page_header.network_charts.reload_chart_seconds};
@@ -532,27 +763,101 @@ html(lang='en')
update_network_charts();
});
if settings.network_history.enabled == true && showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true
if showNethashChart == true
script.
let nethashChart;
function populateNethashChart(result) {
const ctxNethash = document.getElementById('nethashChart').getContext('2d');
let timeData = {};
if (maxSavedRecords == 0)
timeData = populateHourChartData(result);
const extraData = populatePluginDataTitle((maxSavedRecords == 0 ? timeData.hourData : result), !{JSON.stringify(settings.shared_pages.page_header.network_charts.nethash_chart.chart_title)}, #{settings.shared_pages.page_header.network_charts.nethash_chart.round_decimals}, true, false);
const netHashDataSet = [
{
label: 'Hashrate',
data: (maxSavedRecords == 0 ?
timeData.hourData.map(a => ({
x: a.tick,
y: a.nethash,
blockindex: a.blockindex
})) :
result.map(function(a) {return a.nethash;})
),
backgroundColor: ['#{settings.shared_pages.page_header.network_charts.nethash_chart.fill_color}'],
borderColor: ['#{settings.shared_pages.page_header.network_charts.nethash_chart.line_color}'],
fill: 'start'
}
];
const pluginData = {
title: extraData.pluginTitle,
legend: {
display: #{settings.shared_pages.page_header.network_charts.nethash_chart.legend.enabled},
position: '#{settings.shared_pages.page_header.network_charts.nethash_chart.legend.position}'
},
tooltip: {
mode: 'index',
intersect: false,
displayColors: true,
callbacks: {
title: function(context) {
if (maxSavedRecords == 0)
return format_unixtime(Math.floor(context[0].parsed.x / 1000));
else
return 'Block ' + context[0].label + ' Hashrate';
},
label: function(context) {
if (maxSavedRecords == 0)
return formatNetworkChartValue(context.raw.y, #{settings.shared_pages.page_header.network_charts.nethash_chart.round_decimals}, context.dataset.label, false);
else
return formatNetworkChartValue(context.raw, #{settings.shared_pages.page_header.network_charts.nethash_chart.round_decimals}, context.dataset.label, false);
},
afterLabel: function(context) {
if (maxSavedRecords == 0) {
const tooltipItems = context.chart.tooltip.dataPoints;
const isLastVisibleItem = tooltipItems[tooltipItems.length - 1] === context;
// only display blockindex if this is the last visible tooltip item
if (isLastVisibleItem) {
const blockindex = context.raw.blockindex;
if (blockindex && blockindex !== 0)
return `Block: ${blockindex}`;
}
}
return '';
}
}
},
crosshair: {
line: {
color: '#{settings.shared_pages.page_header.network_charts.nethash_chart.crosshair_color}',
width: 1
},
sync: {
enabled: #{settings.shared_pages.page_header.network_charts.sync_charts},
group: 1,
suppressTooltips: false,
axis: 'x'
},
zoom: {
enabled: false
}
},
annotation: populateBlockIndexAnnotations(timeData.hourData, !{JSON.stringify(settings.shared_pages.page_header.network_charts.nethash_chart.block_line)})
};
if (nethashChart == null) {
nethashChart = new Chart(ctxNethash, {
type: 'line',
data: {
labels: result.map(function(a) {return a.blockindex;}),
datasets: [
{
label: 'Hashrate',
data: result.map(function(a) {return a.nethash;}),
backgroundColor: ['#{settings.shared_pages.page_header.network_charts.nethash_chart.fill_color}'],
borderColor: ['#{settings.shared_pages.page_header.network_charts.nethash_chart.line_color}'],
fill: 'start'
}
]
labels: (maxSavedRecords == 0 ? timeData.hourData.map(function(a) {return a.tick;}) : result.map(function(a) {return a.blockindex;})),
datasets: netHashDataSet
},
options: {
maintainAspectRatio: false,
@@ -568,79 +873,50 @@ html(lang='en')
y: {
title: {
display: true,
text: 'Network ' + getNetHashUnits(),
text: 'Hashrate ' + getNetHashUnits(),
font: {
weight: 'bold'
}
}
}
},
plugins: {
legend: {
display: true,
position: 'bottom'
},
title: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
displayColors: true,
callbacks: {
title: function(context) {
return 'Block ' + context[0].label + ' Hashrate';
},
label: function(context) {
const val = #{settings.shared_pages.page_header.network_charts.nethash_chart.round_decimals};
let max = 20;
if (val != -1)
max = val;
else {
const decimalCount = countDecimals(context.raw || 0);
if (decimalCount < max)
max = decimalCount;
}
return Number((context.raw || 0)).toLocaleString('en',{'minimumFractionDigits':0,'maximumFractionDigits':max,'useGrouping':true}) + ' ' + getNetHashUnits();
}
}
},
crosshair: {
line: {
color: '#{settings.shared_pages.page_header.network_charts.nethash_chart.crosshair_color}',
width: 1
},
sync: {
enabled: false
},
zoom: {
enabled: false
}
}
}
plugins: pluginData
}
});
if (maxSavedRecords == 0)
nethashChart.options.scales.x = timeData.xScale;
$('#nethashChartParent').fadeIn();
} else {
nethashChart.data.labels = result.map(function(a) {return a.blockindex;});
nethashChart.data.datasets[0].data = result.map(function(a) {return a.nethash;});
nethashChart.update();
nethashChart.data.labels = (maxSavedRecords == 0 ? timeData.hourData.map(function(a) {return a.tick;}) : result.map(function(a) {return a.blockindex;}));
nethashChart.data.datasets = netHashDataSet;
nethashChart.options.plugins = pluginData;
if (maxSavedRecords == 0) {
nethashChart.options.scales.x.min = timeData.minTimestamp;
nethashChart.options.scales.x.max = timeData.maxTimestamp;
}
nethashChart.update('none');
}
}
if settings.network_history.enabled == true && showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true
if showDifficultyChart == true
script.
let difficultyChart;
function populateDifficultyChart(result) {
const ctxDifficulty = document.getElementById('difficultyChart').getContext('2d');
let timeData = {};
let diffDataSets = [];
let showPOW = false;
let showPOS = false;
if (maxSavedRecords == 0)
timeData = populateHourChartData(result);
const extraData = populatePluginDataTitle((maxSavedRecords == 0 ? timeData.hourData : result), !{JSON.stringify(settings.shared_pages.page_header.network_charts.difficulty_chart.chart_title)}, #{settings.shared_pages.page_header.network_charts.difficulty_chart.round_decimals}, false, true);
for (let i = 0; i < result.length; i++) {
if (result[i].difficulty_pow != 0)
showPOW = true;
@@ -651,7 +927,14 @@ html(lang='en')
if (showPOS) {
diffDataSets.push({
label: 'POS Difficulty',
data: result.map(function(a) {return a.difficulty_pos;}),
data: (maxSavedRecords == 0 ?
timeData.hourData.map(a => ({
x: a.tick,
y: a.difficulty_pos,
blockindex: a.blockindex
})) :
result.map(function(a) {return a.difficulty_pos;})
),
backgroundColor: ['#{settings.shared_pages.page_header.network_charts.difficulty_chart.pos_fill_color}'],
borderColor: ['#{settings.shared_pages.page_header.network_charts.difficulty_chart.pos_line_color}'],
fill: 'start'
@@ -661,18 +944,84 @@ html(lang='en')
if (showPOW || !showPOS) {
diffDataSets.push({
label: 'POW Difficulty',
data: result.map(function(a) {return a.difficulty_pow;}),
data: (maxSavedRecords == 0 ?
timeData.hourData.map(a => ({
x: a.tick,
y: a.difficulty_pow,
blockindex: a.blockindex
})) :
result.map(function(a) {return a.difficulty_pow;})
),
backgroundColor: ['#{settings.shared_pages.page_header.network_charts.difficulty_chart.pow_fill_color}'],
borderColor: ['#{settings.shared_pages.page_header.network_charts.difficulty_chart.pow_line_color}'],
fill: 'start'
});
}
const pluginData = {
title: extraData.pluginTitle,
legend: {
display: #{settings.shared_pages.page_header.network_charts.difficulty_chart.legend.enabled},
position: '#{settings.shared_pages.page_header.network_charts.difficulty_chart.legend.position}'
},
tooltip: {
mode: 'index',
intersect: false,
displayColors: true,
callbacks: {
title: function(context) {
if (maxSavedRecords == 0)
return format_unixtime(Math.floor(context[0].parsed.x / 1000));
else
return 'Block ' + context[0].label + ' Difficulty';
},
label: function(context) {
if (maxSavedRecords == 0)
return formatNetworkChartValue(context.raw.y, #{settings.shared_pages.page_header.network_charts.difficulty_chart.round_decimals}, context.dataset.label, false);
else
return formatNetworkChartValue(context.raw, #{settings.shared_pages.page_header.network_charts.difficulty_chart.round_decimals}, context.dataset.label, false);
},
afterLabel: function(context) {
if (maxSavedRecords == 0) {
const tooltipItems = context.chart.tooltip.dataPoints;
const isLastVisibleItem = tooltipItems[tooltipItems.length - 1] === context;
// only display blockindex if this is the last visible tooltip item
if (isLastVisibleItem) {
const blockindex = context.raw.blockindex;
if (blockindex && blockindex !== 0)
return `Block: ${blockindex}`;
}
}
return '';
}
}
},
crosshair: {
line: {
color: '#{settings.shared_pages.page_header.network_charts.difficulty_chart.crosshair_color}',
width: 1
},
sync: {
enabled: #{settings.shared_pages.page_header.network_charts.sync_charts},
group: 1,
suppressTooltips: false,
axis: 'x'
},
zoom: {
enabled: false
}
},
annotation: populateBlockIndexAnnotations(timeData.hourData, !{JSON.stringify(settings.shared_pages.page_header.network_charts.difficulty_chart.block_line)})
};
if (difficultyChart == null) {
difficultyChart = new Chart(ctxDifficulty, {
type: 'line',
data: {
labels: result.map(function(a) {return a.blockindex;}),
labels: (maxSavedRecords == 0 ? timeData.hourData.map(function(a) {return a.tick;}) : result.map(function(a) {return a.blockindex;})),
datasets: diffDataSets
},
options: {
@@ -696,82 +1045,28 @@ html(lang='en')
}
}
},
plugins: {
legend: {
display: true,
position: 'bottom'
},
title: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
displayColors: true,
callbacks: {
title: function(context) {
return 'Block ' + context[0].label + ' Difficulty';
},
label: function(context) {
const val = #{settings.shared_pages.page_header.network_charts.difficulty_chart.round_decimals};
let max = 20;
if (val != -1)
max = val;
else {
const decimalCount = countDecimals(context.raw || 0);
if (decimalCount < max)
max = decimalCount;
}
return Number((context.raw || 0)).toLocaleString('en',{'minimumFractionDigits':0,'maximumFractionDigits':max,'useGrouping':true});
}
}
},
crosshair: {
line: {
color: '#{settings.shared_pages.page_header.network_charts.difficulty_chart.crosshair_color}',
width: 1
},
sync: {
enabled: false
},
zoom: {
enabled: false
}
}
}
plugins: pluginData
}
});
if (maxSavedRecords == 0)
difficultyChart.options.scales.x = timeData.xScale;
$('#difficultyChartParent').fadeIn();
} else {
difficultyChart.data.labels = result.map(function(a) {return a.blockindex;});
difficultyChart.data.labels = (maxSavedRecords == 0 ? timeData.hourData.map(function(a) {return a.tick;}) : result.map(function(a) {return a.blockindex;}));
difficultyChart.data.datasets = diffDataSets;
difficultyChart.options.plugins = pluginData;
if (difficultyChart.data.datasets.length != diffDataSets.length)
difficultyChart.data.datasets = diffDataSets;
else if (
(
difficultyChart.data.datasets[0].label.indexOf('POW') > -1 &&
diffDataSets[0].label.indexOf('POW') > -1
)
||
(
difficultyChart.data.datasets[0].label.indexOf('POS') > -1 &&
diffDataSets[0].label.indexOf('POS') > -1
)
) {
difficultyChart.data.datasets[0].data = diffDataSets[0].data;
if (maxSavedRecords == 0) {
difficultyChart.options.scales.x.min = timeData.minTimestamp;
difficultyChart.options.scales.x.max = timeData.maxTimestamp;
}
if (difficultyChart.data.datasets.length == 2)
difficultyChart.data.datasets[1].data = diffDataSets[1].data;
} else
difficultyChart.data.datasets = diffDataSets;
difficultyChart.update();
difficultyChart.update('none');
}
}
if (showPanels == true && showNetworkPanel == true) || (settings.network_history.enabled == true && showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true)
if (showPanels == true && showNetworkPanel == true) || showNethashChart == true || showDifficultyChart == true
script.
function getNetHashUnits() {
let networkSuffix = '';
@@ -1409,26 +1704,22 @@ html(lang='en')
#index-search.form-group.d-flex.justify-content-center
input.form-control(type='text', name='search', placeholder=settings.localization.ex_search_message, style='min-width:80%;margin-right:5px;')
button.btn.btn-success(type='submit') #{settings.localization.ex_search_button}
if settings.network_history.enabled == true && ((showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true) || (showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true))
.container
if showNethashChart == true || showDifficultyChart == true
- var chartColumnClass = 'col-lg-12';
.container(style='padding-left:0;padding-right:0;')
.row.align-items-start
- var chartColumnClass = 'col-lg-12';
if showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true && showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true
if showNethashChart == true && showDifficultyChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.full_row == false && settings.shared_pages.page_header.network_charts.difficulty_chart.full_row == false
- chartColumnClass = 'col-lg-6';
if showNethashChart == true && settings.shared_pages.page_header.network_charts.nethash_chart.enabled == true && settings.shared_pages.show_hashrate == true
div#nethashChartParent(class=chartColumnClass, style='display:none;margin:10px 0;')
.card.card-default.border-0
.card-header
strong Network Hashrate
.card-body
canvas#nethashChart(style='max-height:300px;background-color:'+settings.shared_pages.page_header.network_charts.nethash_chart.bgcolor+';')
if showDifficultyChart == true && settings.shared_pages.page_header.network_charts.difficulty_chart.enabled == true
div#difficultyChartParent(class=chartColumnClass, style='display:none;margin:10px 0;')
.card.card-default.border-0
.card-header
strong Network Difficulty
.card-body
canvas#difficultyChart(style='max-height:300px;background-color:'+settings.shared_pages.page_header.network_charts.difficulty_chart.bgcolor+';')
include ./includes/nethash_chart.pug
include ./includes/difficulty_chart.pug
else if showNethashChart == true
include ./includes/nethash_chart.pug
else if showDifficultyChart == true
include ./includes/difficulty_chart.pug
if showNethashChart == true && showDifficultyChart == true && (settings.shared_pages.page_header.network_charts.nethash_chart.full_row == true || settings.shared_pages.page_header.network_charts.difficulty_chart.full_row == true)
.container(style='padding-left:0;padding-right:0;')
.row.align-items-start
include ./includes/difficulty_chart.pug
block content
div#footer-container(class=footerClasses, role='navigation')
.col-4.navbar-nav
-2
View File
@@ -1,8 +1,6 @@
extends layout
block content
include ./includes/common.pug
script(type='text/javascript', src='https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.3.1')
script.
$(document).ready(function() {
if ('#{settings.markets_page.page_header.show_last_updated}' == 'true') {
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
var setting_txPerPage = parseInt("#{settings.masternodes_page.masternode_table.items_per_page}");
var lengthMenuOpts = !{JSON.stringify(settings.masternodes_page.masternode_table.page_length_options)};
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
var setting_maxTxCount = parseInt("#{settings.api_page.public_apis.ext.getlasttxs.max_items_per_query}");
var setting_txPerPage = parseInt("#{settings.movement_page.movement_table.items_per_page}");
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
function generateLengthMenu(setting_txPerPage, lengthMenuOpts) {
var addedLength = false;
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
var setting_txPerPage = parseInt("#{settings.orphans_page.orphans_table.items_per_page}");
var lengthMenuOpts = !{JSON.stringify(settings.orphans_page.orphans_table.page_length_options)};
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
$(document).ready(function() {
$('.summary-table').dataTable({
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
script.
$(document).ready(function() {
if ('#{settings.richlist_page.page_header.show_last_updated}' == 'true') {
-1
View File
@@ -1,7 +1,6 @@
extends layout
block content
include ./includes/common.pug
- var theadClasses = [];
if settings.shared_pages.table_header_bgcolor != null && settings.shared_pages.table_header_bgcolor != ''
- theadClasses.push('table-' + settings.shared_pages.table_header_bgcolor);