block-explorer/public/js/mining-inflation-chart.js

165 lines
5.5 KiB
JavaScript
Raw Normal View History

2021-01-17 21:50:21 +01:00
function getReward(blockHeight) {
if (blockHeight === 0) {
return 400000000;
}
else if (blockHeight <= 5100) {
return 1;
}
else if (blockHeight <= 55000) {
return 1 + Math.floor((blockHeight - 5001) / 100);
}
else {
const level = Math.floor((blockHeight - 55001) / 32);
let reduction = Math.floor((Math.floor(Math.sqrt((8 * level) + 1)) - 1) / 2);
while(!(withinLevelBounds(reduction, level))) {
if(Math.floor((reduction * reduction + reduction) / 2) > level) {
reduction--;
}
else {
reduction++;
}
}
return Math.max(0, 500 - reduction);
}
}
function withinLevelBounds(reduction, level) {
if(Math.floor((reduction * reduction + reduction) / 2) > level) {
return false;
}
reduction += 1;
return Math.floor((reduction * reduction + reduction) / 2) > level;
}
function getAverageBlockTime(blocks) {
const windowSize = 100;
let sum = 0;
let height = 0;
for(let i = blocks.length - windowSize; i < blocks.length; i++) {
sum += blocks[i].block_time - blocks[i-1].block_time;
height += blocks[i].height - blocks[i-1].height + 1;
}
return sum / height;
}
function getBlockTime(currentHeight, blocks, averageBlockTime) {
if(currentHeight < blocks.length) {
return blocks[currentHeight].block_time;
} else {
return (blocks[blocks.length - 1].block_time + ((blocks.length - currentHeight + 1) * averageBlockTime));
}
}
function buildChartData(blockData) {
let chartData = [];
let supply = 0;
let averageBlockTime = getAverageBlockTime(blockData);
let blocksPerYear = Math.floor((3600*24*365) / averageBlockTime);
let lastBlockHeight = 4071017; // Last block with reward
let blockTime = 0;
// Getting historical data
for(let i = 0; i < blockData.length; i++) {
let newReward = getReward(blockData[i].height);
if(i === 0) {
supply += newReward;
newReward = 0; // Reward for 1st block set to 0 for scale
} else if(i === 1) {
supply += blockData[i].height - blockData[i - 1].height - 1;
} else {
let oldReward = getReward(blockData[i - 1].height);
supply += (blockData[i].height - blockData[i-1].height) * ((newReward + oldReward) / 2);
}
// Get blockTime from data or from prediction
blockTime = getBlockTime(i, blockData, averageBlockTime);
// Inflation Rate
let inflationRate = 0;
if(i !== 0) {
inflationRate = (newReward * blocksPerYear * 100) / supply;
}
chartData.push({
date: new Date(blockTime * 1000),
AvailableSupply: supply / 1000000,
RewardLBC: newReward,
InflationRate: inflationRate,
BlockId: blockData[i].height
});
}
// Getting historical data
for(let j = blockData[blockData.length - 1].height; j < lastBlockHeight; j++) {
let skip = 1000;
let reward = getReward(j);
supply += reward;
// Get blockTime from data or from prediction
blockTime += averageBlockTime;
// Inflation Rate
let newInflationRate = (reward * blocksPerYear * 100) / supply;
if(j % skip === 0) {
chartData.push({
date: new Date(blockTime * 1000),
AvailableSupply: supply / 1000000,
RewardLBC: reward,
InflationRate: newInflationRate,
BlockId: j
});
}
}
return chartData;
}
am4core.ready(function() {
let chart = am4core.create("mining-inflation-chart", am4charts.XYChart);
chart.colors.step = 3;
// Create axes
let dateAxis = chart.xAxes.push(new am4charts.DateAxis());
let supplyValueAxis = chart.yAxes.push(new am4charts.ValueAxis());
let supplySeries = chart.series.push(new am4charts.LineSeries());
supplySeries.dataFields.valueY = "AvailableSupply";
supplySeries.dataFields.dateX = "date";
supplySeries.strokeWidth = 2;
supplySeries.yAxis = supplyValueAxis;
supplySeries.name = "Available Supply (millions LBC)";
supplySeries.tooltipText = "{valueY} LBC";
let rewardSeries = chart.series.push(new am4charts.LineSeries());
rewardSeries.dataFields.valueY = "RewardLBC";
rewardSeries.dataFields.dateX = "date";
rewardSeries.strokeWidth = 2;
rewardSeries.yAxis = supplyValueAxis;
rewardSeries.name = "Block Reward (LBC)";
rewardSeries.tooltipText = "{valueY} LBC";
let inflationValueAxis = chart.yAxes.push(new am4charts.ValueAxis());
let inflationSeries = chart.series.push(new am4charts.LineSeries());
inflationSeries.dataFields.valueY = "InflationRate";
inflationSeries.dataFields.dateX = "date";
inflationSeries.strokeWidth = 2;
inflationSeries.yAxis = inflationValueAxis;
inflationSeries.name = "Annualized Inflation Rate";
inflationSeries.tooltipText = "{valueY}%";
inflationValueAxis.renderer.opposite = true;
chart.legend = new am4charts.Legend();
chart.cursor = new am4charts.XYCursor();
chart.exporting.menu = new am4core.ExportMenu();
chart.dataSource.url = "/api/stats/mining";
chart.events.on("beforedatavalidated", function(ev) {
if(ev.target.data.length > 0 && ev.target.data[0].data !== undefined) {
chart.data = buildChartData(ev.target.data[0].data);
$(".mining-inflation-chart-box .load-progress").hide();
}
});
});