165 lines
5.5 KiB
JavaScript
165 lines
5.5 KiB
JavaScript
|
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();
|
||
|
}
|
||
|
});
|
||
|
});
|