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

265 lines
No EOL
6.1 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 {
var level = Math.floor((blockHeight - 55001) / 32);
var 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;
if(Math.floor((reduction * reduction + reduction) / 2) <= level) {
return false;
}
return true;
}
function getAverageBlockTime(blocks) {
var numBlocks = blocks.length;
var windowSize = 100;
var sum = 0;
for(i = numBlocks - windowSize; i < numBlocks; i++) {
sum += blocks[i].block_time - blocks[i-1].block_time;
}
return sum / windowSize;
}
function buildChartData(blockData) {
var chartData = [];
var supply = 0;
var reward = 0;
var averageBlockTime = getAverageBlockTime(blockData);
var blockTime = 0;
var lastBlock = 4071017; // Last block with reward
var skip = 100;
var blocksPerYear = Math.floor((3600*24*365) / averageBlockTime);
var historicalSupply = {};
var lastYearSupply = 0;
var lastYearBlock = 0;
var inflationRate = 0;
for(var i = 0; i < lastBlock; i++) {
reward = getReward(i);
supply += reward;
historicalSupply[i + 1] = supply;
if(i == 0) { // Reward for 1st block set to 0 for scale
reward = 0;
}
if(i < blockData.length) {
// Historical Data
var b = blockData[i];
blockTime = b.block_time;
}
else {
// Future blocks
skip = 1000;
blockTime += averageBlockTime;
}
// Inflation Rate
if(i + 1 - blocksPerYear <= 0) {
lastYearBlock = 1;
}
else {
lastYearBlock = i + 1 - blocksPerYear;
}
lastYearSupply = historicalSupply[lastYearBlock];
inflationRate = ((supply - lastYearSupply) / lastYearSupply) * 100;
if(i % skip == 0) { // Only push 1/<skip> of all blocks to optimize data loading
chartData.push({
date: new Date(blockTime * 1000),
date: new Date(blockTime * 1000),
AvailableSupply: supply,
RewardLBC: reward,
InflationRate: inflationRate,
BlockId: i + 1
});
}
}
return chartData;
}
function loadChartData() {
var api_url = "https://chainquery.lbry.io/api/sql?query=";
var query = "SELECT id, block_time FROM block";
var url = api_url + query;
var loadProgress = $('.mining-inflation-chart-container .load-progress');
$.ajax({
url: url,
type: 'get',
dataType: 'json',
beforeSend: function() {
chartLoadInProgress = true;
loadProgress.css({ display: 'block' });
},
success: function(response) {
if(response.success) {
chartData = buildChartData(response.data);
if(chart) {
chart.dataProvider = chartData;
chart.validateNow();
chart.validateData();
}
}
else {
console.log("Could not fetch block data.");
}
},
complete: function() {
chartLoadInProgress = false;
loadProgress.css({ display: 'none' });
}
});
}
var chart;
var chartData = [];
var chartLoadInProgress = false;
AmCharts.ready(function() {
chart = AmCharts.makeChart('mining-inflation-chart', {
type: 'serial',
theme: 'light',
mouseWheelZoomEnabled: true,
height: '100%',
categoryField: 'date',
synchronizeGrid: true,
dataProvider: chartData,
responsive: {
enabled: true,
},
valueAxes: [
{
id: 'v-supply',
axisColor: '#1e88e5',
axisThickness: 2,
position: 'left',
labelFunction: function(value) {
return (Math.round((value / 1000000) * 1000000)/1000000).toFixed(2);
}
},
{
id: 'v-reward',
axisColor: '#0b7a06',
axisThickness: 2,
position: 'left',
offset: 75,
},
{
id: 'v-inflation-rate',
axisColor: '#ff9900',
axisThickness: 2,
position: 'right',
labelFunction: function(value) {
return value.toFixed(2);
}
},
],
categoryAxis: {
parseDates: true,
autoGridCount: false,
minorGridEnabled: true,
minorGridAlpha: 0.04,
axisColor: '#dadada',
twoLineMode: true
},
graphs: [
{
id: 'g-supply',
valueAxis: 'v-supply', // we have to indicate which value axis should be used
title: 'Available supply (millions LBC)',
valueField: 'AvailableSupply',
bullet: 'round',
bulletBorderThickness: 1,
bulletBorderAlpha: 1,
bulletColor: '#ffffff',
bulletSize: 5,
useLineColorForBulletBorder: true,
lineColor: '#1e88e5',
hideBulletsCount: 101,
balloonText: '[[AvailableSupply]]',
balloonFunction: function(item, graph) {
var result = graph.balloonText;
return result.replace('[[AvailableSupply]]', (Math.round((item.dataContext.AvailableSupply / 1000000) * 1000000)/1000000).toFixed(2));
}
},
{
id: 'g-reward',
valueAxis: 'v-reward',
title: 'Block Reward (LBC)',
valueField: 'RewardLBC',
bullet: 'round',
bulletBorderThickness: 1,
bulletBorderAlpha: 1,
bulletColor: '#ffffff',
bulletSize: 5,
useLineColorForBulletBorder: true,
lineColor: '#0b7a06',
balloonText: '[[RewardLBC]] LBC<br>Block [[BlockId]]',
hideBulletsCount: 101
},
{
id: 'g-inflation-rate',
valueAxis: 'v-inflation-rate',
title: 'Annualized Inflation Rate',
valueField: 'InflationRate',
bullet: 'round',
bulletBorderThickness: 1,
bulletBorderAlpha: 1,
bulletColor: '#ffffff',
bulletSize: 5,
useLineColorForBulletBorder: true,
lineColor: '#ff9900',
balloonText: '[[InflationRate]]%',
hideBulletsCount: 101,
balloonFunction: function(item, graph) {
var result = graph.balloonText;
return result.replace('[[InflationRate]]', item.dataContext.InflationRate.toFixed(2));
}
}
],
chartCursor: {
cursorAlpha: 0.1,
fullWidth: true,
valueLineBalloonEnabled: true,
categoryBalloonColor: '#333333',
cursorColor: '#1e88e5'
},
chartScrollbar: {
scrollbarHeight: 36,
color: '#888888',
gridColor: '#bbbbbb'
},
legend: {
marginLeft: 110,
useGraphSettings: true,
valueText: "",
spacing: 64,
},
export: {
enabled: true,
fileName: 'lbry-supply-chart',
position: 'bottom-right',
divId: 'chart-export'
}
});
loadChartData();
});