Browse Source

Added more data to blocks list and tried making the layout nicer.

master
Trey Del Bonis 4 years ago
parent
commit
93f1da32d5
3 changed files with 200 additions and 50 deletions
  1. 1
    1
      www/index.html
  2. 132
    36
      www/main.js
  3. 67
    13
      www/style.css

+ 1
- 1
www/index.html View File

@@ -18,7 +18,7 @@
<h2>Remaining: <span id="blocksleft">...</span></h2>

<div id="blocklist">
<span id="blocklistloading">Loading...</span>
<span id="blocklistloading">Loading blocks...</span>
</div>

</div>

+ 132
- 36
www/main.js View File

@@ -4,13 +4,19 @@

const API_PREFIX = "https://blockstream.info/api";

let nextHalvingHeight = 630000;
const IRON_BLOCK = "https://gamepedia.cursecdn.com/minecraft_gamepedia/7/7e/Block_of_Iron_JE4_BE3.png?version=692673bafa1e94785ab6012d7a3c8dc4";
const GOLD_BLOCK = "https://gamepedia.cursecdn.com/minecraft_gamepedia/7/72/Block_of_Gold_JE6_BE3.png?version=9d1a63c717df80feffa9ec93ebceb014";

var nextHalvingHeight = 630000;

var curTipBlock = null;
var recentBlocks = null;

function doApiReq(endpoint, cb) {
let xhr = new XMLHttpRequest();

xhr.timeout = 5000;

xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
@@ -41,70 +47,153 @@ function doGetBlockCoinBaseTx(blockhash, cb) {
});
}

function calcRenderedSatQty(sats, decimals) {
let subBtc = sats % 100000000;
let btc = (sats - subBtc) / 100000000;

let maskModulus = 10 ** (8 - decimals);
let subDecimalRem = subBtc % maskModulus;
let decimal = (subBtc - subDecimalRem) / maskModulus;

if (decimal != 0) {
return btc.toString() + "." + decimal.toString();
} else {
return btc.toString();
}
}

const HALVING_PERIOD = 210000;

function calcRewardAtHeight(height) {
let epoch = Math.floor(height / HALVING_PERIOD);
return 5000000000 / (2 ** epoch);
}

function calcRewardBreakdown(height, sats) {
let subsidy = calcRewardAtHeight(height);
let fees = sats - subsidy;

let rSubsidy = calcRenderedSatQty(subsidy, 2);
let rFees = calcRenderedSatQty(fees, 3);
return rSubsidy + " subsidy + " + rFees + " fees"
}

function toggleElemSelected(elem) {
if (elem.classList.contains("blbselected")) {
elem.classList.remove("blbselected");
} else {
elem.classList.add("blbselected");
}
}

function makeBlockElem(block, prevBlock) {
let elem = document.createElement("div");
let entry = document.createElement("div");

let innerElem = document.createElement("div");
innerElem.classList.add("entryinner");
entry.appendChild(innerElem);

/* ===== Top row data ===== */

let topElem = document.createElement("div");
topElem.classList.add("entrytop");
innerElem.appendChild(topElem);

// Make the icon.
let iconElem = document.createElement("img");
iconElem.classList.add("blbicon");
topElem.appendChild(iconElem);
if (block.height % HALVING_PERIOD == 0) {
iconElem.src = GOLD_BLOCK;
} else {
iconElem.src = IRON_BLOCK;
}

// Element for all the data.
let dataElem = document.createElement("div");
dataElem.classList.add("blbdata");
topElem.appendChild(dataElem);

// Make the height element.
let heightElem = document.createElement("span");
heightElem.innerHTML = block.height.toString();
heightElem.classList.add("blbheight");
elem.appendChild(heightElem);
heightElem.innerHTML = block.height.toString();
dataElem.appendChild(heightElem);

// Make the reward breakdown element.
let rewardElem = document.createElement("span");
rewardElem.innerHTML = "Reward: ? sat";
dataElem.appendChild(rewardElem);
doGetBlockCoinBaseTx(block.id, function(resp) {
let reward = resp.vout[0].value;
let rewardStr = calcRewardBreakdown(block.height, reward);
rewardElem.innerHTML = rewardStr;
});

// Make the hash element.
let hashElem = document.createElement("span");
hashElem.innerHTML = block.id;
hashElem.classList.add("blbhash");
elem.appendChild(hashElem);
topElem.appendChild(hashElem);

// Make the reward breakdown element.
let rewardElem = document.createElement("span");
rewardElem.innerHTML = "Reward: ? sat";
rewardElem.classList.add("blbreward");
elem.appendChild(rewardElem);
/* ==== Detail row data ===== */

// Invoke the thing to populate the reward.
doGetBlockCoinBaseTx(block.id, function(resp) {
let reward = resp.vout[0].value;
// Details
let detailElem = document.createElement("div");
detailElem.classList.add("entrydetail");

let rewardSubBtc = reward % 100000000;
let rewardBtc = (reward - rewardSubBtc) / 100000000;
let rewardBtcStr = rewardBtc.toString() + "." + rewardSubBtc.toString();
// Weight and height
let sizeElem = document.createElement("div");
detailElem.appendChild(sizeElem);
let blockKB = Math.floor(block.size / 1024);
let blockkWU = Math.floor(block.weight / 1024);
detailElem.innerHTML = "Weight/Size: " + blockKB + " KiB / " + blockkWU + " kSipa";

rewardElem.innerHTML = "Reward: " + rewardBtcStr + " BTC";
});
// Number of transactions
let txsElem = document.createElement("div");
detailElem.appendChild(txsElem);
txsElem.innerHTML = "Tx count: " + block.tx_count;

// Make the duration element.
let timeElem = document.createElement("span");
if (prevBlock != null) {
let timeElem = document.createElement("div");
let blocktime = block.timestamp - prevBlock.timestamp;
timeElem.innerHTML = blocktime.toString() + " sec";
if (blocktime < 0) {
blocktime = 0; // ehhhhhhhh
}
timeElem.innerHTML = "Since last block: " + blocktime.toString() + " sec";
detailElem.appendChild(timeElem);
} else {
let oopsElem = document.createElement("div");
oopsElem.innerHTML = "<br/>(I don't feel like making the request to get the previous block to find the blocktime)";
detailElem.appendChild(oopsElem);
}
timeElem.classList.add("blbtime");
elem.appendChild(timeElem);

// Add the class.
elem.classList.add("blocklistblock");
/* ===== Finalize ===== */

return elem;
// Put it together.
innerElem.appendChild(detailElem);
entry.appendChild(innerElem);
entry.classList.add("blocklistentry");
entry.onclick = function() {
toggleElemSelected(entry);
};

return entry;
}

var blocksleftElem = null;

function updateCurrentTip(block) {

if (blocksleftElem == null) {
blocksleftElem = document.getElementById("blocksleft");
}

curHeight = block.height;
blocksleftElem.innerHTML = (nextHalvingHeight - curTipBlock.height).toString()

}

function populateRecentBlocks(blocks) {

console.log(blocks);

let blocklist = document.getElementById("blocklist");
let loadingElem = document.getElementById("blocklistloading");

@@ -112,7 +201,6 @@ function populateRecentBlocks(blocks) {
updateCurrentTip(curTipBlock.height);

for (let i = 0; i < blocks.length; i++) {

if (i < blocks.length - 1) {
let elem = makeBlockElem(blocks[i], blocks[i + 1]);
blocklist.appendChild(elem);
@@ -120,21 +208,29 @@ function populateRecentBlocks(blocks) {
let elem = makeBlockElem(blocks[i], null);
blocklist.appendChild(elem);
}
}

loadingElem.style.display = "none";

}

function init() {

console.log("Hello!");

let checkHeights = [0, 1, 2, 209999, 210000, 210001, 629999, 630000, 630001];
for (let i = 0; i < checkHeights.length; i++) {
console.log("Reward at " + checkHeights[i] + " is " + calcRewardAtHeight(checkHeights[i]));
}

doGetRecentBlocks(function(blocks) {
if (blocks == null) {
alert("Error loading blocks, please refresh the page.");
return;
}

recentBlocks = blocks;

populateRecentBlocks(blocks);

// TODO Set up more stuff.
})

});
}

+ 67
- 13
www/style.css View File

@@ -6,37 +6,91 @@ body {
margin: 0 auto;
}

.blocklistblock {
.blocklistentry {
width: 100%;
}

.entryinner {
margin: 6pt;
border: 1px solid black;
border-radius: 3px 3px 3px 3px;
padding: 12pt;
}

width: 100%;
.blbselected .entryinner {
background-color: #eee;
}

.blocklistblock:hover {
background-color: lightgrey;
.entryinner:hover {
background-color: lightgray;
}

.blocklistblock > span {
margin: 4pt;
.entrytop {
display: flex;
flex-direction: row;
align-items: stretch;
}

.blbheight {
width: 10%;
.entrytopinner {
display: flex;
flex: auto;
align-items: stretch;
}

.blbicon {
height: 36pt;
/*max-width: 36pt;*/
margin: 0;

vertical-align: middle;

flex: initial;
}

.blbdata {
height: 100%;
width: auto;

margin-top: auto;
margin-bottom: auto;

display: table;

flex: auto;
}

.blbhash {
width: 20%;
max-width: 100%;

font-size: 12pt;
font-family: monospace;

vertical-align: middle;
float: right;
flex: 1;
}

.blbdata span {
margin: 4pt;

display: table-cell;
vertical-align: middle;
}

.blbheight {
width: 96px;
font-weight: bold;
}

.entrydetail {
margin-top: 8pt;
display: none;
}

.blbreward {
width: 15%;
.blbselected .entrydetail {
display: block;
}

.blbtime {
width: 15%;
.entrydetail {
margin: 5px;
}

Loading…
Cancel
Save