|
|
@@ -18,15 +18,15 @@ function doApiReq(endpoint, cb) { |
|
|
|
xhr.timeout = 5000; |
|
|
|
|
|
|
|
xhr.onreadystatechange = function() { |
|
|
|
if (xhr.readyState == 4) { |
|
|
|
if (xhr.status == 200) { |
|
|
|
let json = JSON.parse(xhr.responseText); |
|
|
|
cb(json); |
|
|
|
} else { |
|
|
|
// TODO Make this better? |
|
|
|
cb(null); |
|
|
|
} |
|
|
|
} |
|
|
|
if (xhr.readyState == 4) { |
|
|
|
if (xhr.status == 200) { |
|
|
|
let json = JSON.parse(xhr.responseText); |
|
|
|
cb(json); |
|
|
|
} else { |
|
|
|
// TODO Make this better? |
|
|
|
cb(null); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
xhr.open("GET", API_PREFIX + endpoint); |
|
|
@@ -39,11 +39,11 @@ function doGetRecentBlocks(cb) { |
|
|
|
|
|
|
|
function doGetBlockCoinBaseTx(blockhash, cb) { |
|
|
|
doApiReq("/block/" + blockhash + "/txs", function(resp) { |
|
|
|
if (resp != null) { |
|
|
|
cb(resp[0]); |
|
|
|
} else { |
|
|
|
cb(null); |
|
|
|
} |
|
|
|
if (resp != null) { |
|
|
|
cb(resp[0]); |
|
|
|
} else { |
|
|
|
cb(null); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
@@ -56,9 +56,9 @@ function calcRenderedSatQty(sats, decimals) { |
|
|
|
let decimal = (subBtc - subDecimalRem) / maskModulus; |
|
|
|
|
|
|
|
if (decimal != 0) { |
|
|
|
return btc.toString() + "." + decimal.toString(); |
|
|
|
return btc.toString() + "." + decimal.toString(); |
|
|
|
} else { |
|
|
|
return btc.toString(); |
|
|
|
return btc.toString(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -80,9 +80,9 @@ function calcRewardBreakdown(height, sats) { |
|
|
|
|
|
|
|
function toggleElemSelected(elem) { |
|
|
|
if (elem.classList.contains("blbselected")) { |
|
|
|
elem.classList.remove("blbselected"); |
|
|
|
elem.classList.remove("blbselected"); |
|
|
|
} else { |
|
|
|
elem.classList.add("blbselected"); |
|
|
|
elem.classList.add("blbselected"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -108,9 +108,9 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
entry.appendChild(innerElem); |
|
|
|
|
|
|
|
if (block.height % 2 == 0) { |
|
|
|
innerElem.classList.add("blocklisteven"); |
|
|
|
innerElem.classList.add("blocklisteven"); |
|
|
|
} else { |
|
|
|
innerElem.classList.add("blocklistodd"); |
|
|
|
innerElem.classList.add("blocklistodd"); |
|
|
|
} |
|
|
|
|
|
|
|
/* ===== Top row data ===== */ |
|
|
@@ -127,9 +127,9 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
iconElem.classList.add("blbicon"); |
|
|
|
iconCtr.appendChild(iconElem); |
|
|
|
if (block.height % HALVING_PERIOD == 0) { |
|
|
|
iconElem.src = GOLD_BLOCK; |
|
|
|
iconElem.src = GOLD_BLOCK; |
|
|
|
} else { |
|
|
|
iconElem.src = IRON_BLOCK; |
|
|
|
iconElem.src = IRON_BLOCK; |
|
|
|
} |
|
|
|
|
|
|
|
// Element for all the data. |
|
|
@@ -160,9 +160,9 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
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; |
|
|
|
let reward = resp.vout[0].value; |
|
|
|
let rewardStr = calcRewardBreakdown(block.height, reward); |
|
|
|
rewardElem.innerHTML = rewardStr; |
|
|
|
}); |
|
|
|
|
|
|
|
/* ==== Detail row data ===== */ |
|
|
@@ -191,17 +191,17 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
|
|
|
|
// Make the duration element. |
|
|
|
if (prevBlock != null) { |
|
|
|
let timeElem = document.createElement("div"); |
|
|
|
let blocktime = block.timestamp - prevBlock.timestamp; |
|
|
|
if (blocktime < 0) { |
|
|
|
blocktime = 0; // ehhhhhhhh |
|
|
|
} |
|
|
|
timeElem.innerHTML = "Since last block: " + blocktime.toString() + " sec"; |
|
|
|
detailElem.appendChild(timeElem); |
|
|
|
let timeElem = document.createElement("div"); |
|
|
|
let blocktime = block.timestamp - prevBlock.timestamp; |
|
|
|
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); |
|
|
|
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); |
|
|
|
} |
|
|
|
|
|
|
|
let linksElem = document.createElement("div"); |
|
|
@@ -224,14 +224,14 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
//closeElem.classList.add("closebtn"); |
|
|
|
//closeElem.innerHTML = "close"; |
|
|
|
linksElem.onclick = function() { |
|
|
|
console.log("foobar"); |
|
|
|
// This is such a hack but it works. We have to do this because the |
|
|
|
// onclick for the entry we're removing it from here *still gets run* |
|
|
|
// when we pick up the click here. This just defers removing it until |
|
|
|
// we're about to render the next frame, so we're sure we remove it. |
|
|
|
window.requestAnimationFrame(function() { |
|
|
|
entry.classList.add("blbselected"); |
|
|
|
}); |
|
|
|
console.log("foobar"); |
|
|
|
// This is such a hack but it works. We have to do this because the |
|
|
|
// onclick for the entry we're removing it from here *still gets run* |
|
|
|
// when we pick up the click here. This just defers removing it until |
|
|
|
// we're about to render the next frame, so we're sure we remove it. |
|
|
|
window.requestAnimationFrame(function() { |
|
|
|
entry.classList.add("blbselected"); |
|
|
|
}); |
|
|
|
}; |
|
|
|
//detailElem.appendChild(closeElem); |
|
|
|
|
|
|
@@ -242,7 +242,7 @@ function makeBlockElem(block, prevBlock) { |
|
|
|
entry.appendChild(innerElem); |
|
|
|
entry.classList.add("blocklistentry"); |
|
|
|
entry.onclick = function() { |
|
|
|
toggleElemSelected(entry); |
|
|
|
toggleElemSelected(entry); |
|
|
|
}; |
|
|
|
|
|
|
|
return entry; |
|
|
@@ -253,38 +253,38 @@ var timeLeftElem = null; |
|
|
|
|
|
|
|
function updateRemainingCount(block) { |
|
|
|
if (blocksLeftElem == null) { |
|
|
|
blocksLeftElem = document.getElementById("blocksleft"); |
|
|
|
blocksLeftElem = document.getElementById("blocksleft"); |
|
|
|
} |
|
|
|
|
|
|
|
if (timeLeftElem == null) { |
|
|
|
timeLeftElem = document.getElementById("timeleft"); |
|
|
|
timeLeftElem = document.getElementById("timeleft"); |
|
|
|
} |
|
|
|
|
|
|
|
let blocksLeft = nextHalvingHeight - curTipBlock.height; |
|
|
|
blocksLeftElem.innerHTML = blocksLeft.toString() |
|
|
|
|
|
|
|
if (blocksLeft < 1) { |
|
|
|
timeLeftElem.innerHTML = "Halving imminent!"; |
|
|
|
timeLeftElem.innerHTML = "Halving imminent!"; |
|
|
|
} else { |
|
|
|
let nowUnix = Date.now() / 1000; // wtf??? |
|
|
|
let nowUnix = Date.now() / 1000; // wtf??? |
|
|
|
|
|
|
|
let sinceLastBlock = nowUnix - block.timestamp; |
|
|
|
let secsLeft = ((blocksLeft * 10 * 60) - sinceLastBlock)|0; |
|
|
|
let sinceLastBlock = nowUnix - block.timestamp; |
|
|
|
let secsLeft = ((blocksLeft * 10 * 60) - sinceLastBlock)|0; |
|
|
|
|
|
|
|
let secsPart = secsLeft % 60; |
|
|
|
let minLeft = (secsLeft - secsPart) / 60; |
|
|
|
let minPart = minLeft % 60; |
|
|
|
let hrsLeft = (minLeft - minPart) / 60; |
|
|
|
let secsPart = secsLeft % 60; |
|
|
|
let minLeft = (secsLeft - secsPart) / 60; |
|
|
|
let minPart = minLeft % 60; |
|
|
|
let hrsLeft = (minLeft - minPart) / 60; |
|
|
|
|
|
|
|
let acc = secsPart + "s"; |
|
|
|
if (minLeft > 0) { |
|
|
|
acc = (minPart + "m ") + acc; |
|
|
|
} |
|
|
|
if (hrsLeft > 0) { |
|
|
|
acc = (hrsLeft + "h ") + acc; |
|
|
|
} |
|
|
|
let acc = secsPart + "s"; |
|
|
|
if (minLeft > 0) { |
|
|
|
acc = (minPart + "m ") + acc; |
|
|
|
} |
|
|
|
if (hrsLeft > 0) { |
|
|
|
acc = (hrsLeft + "h ") + acc; |
|
|
|
} |
|
|
|
|
|
|
|
timeLeftElem.innerHTML = "roughly " + acc + " remaining"; |
|
|
|
timeLeftElem.innerHTML = "roughly " + acc + " remaining"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -296,7 +296,7 @@ function addNewBlock(block) { |
|
|
|
|
|
|
|
elem.classList.add("newblock"); |
|
|
|
setTimeout(function() { |
|
|
|
elem.classList.remove("newblock"); |
|
|
|
elem.classList.remove("newblock"); |
|
|
|
}, 2000); |
|
|
|
|
|
|
|
let blocklist = document.getElementById("blocklist"); |
|
|
@@ -313,24 +313,24 @@ function populateRecentBlocks(blocks) { |
|
|
|
updateRemainingCount(curTipBlock.height); |
|
|
|
|
|
|
|
for (let i = 0; i < blocks.length; i++) { |
|
|
|
let block = blocks[i]; |
|
|
|
let prevBlock = null; |
|
|
|
if (i < blocks.length - 1) { |
|
|
|
prevBlock = blocks[i + 1]; |
|
|
|
} |
|
|
|
let block = blocks[i]; |
|
|
|
let prevBlock = null; |
|
|
|
if (i < blocks.length - 1) { |
|
|
|
prevBlock = blocks[i + 1]; |
|
|
|
} |
|
|
|
|
|
|
|
let elem = makeBlockElem(block, prevBlock); |
|
|
|
let elem = makeBlockElem(block, prevBlock); |
|
|
|
|
|
|
|
if (i == 0) { |
|
|
|
// Adding the new block so we give it the class to make it colored, |
|
|
|
// but set a timer so it goes away eventually. |
|
|
|
elem.classList.add("newblock"); |
|
|
|
setTimeout(function() { |
|
|
|
elem.classList.remove("newblock"); |
|
|
|
}, 2000); |
|
|
|
} |
|
|
|
if (i == 0) { |
|
|
|
// Adding the new block so we give it the class to make it colored, |
|
|
|
// but set a timer so it goes away eventually. |
|
|
|
elem.classList.add("newblock"); |
|
|
|
setTimeout(function() { |
|
|
|
elem.classList.remove("newblock"); |
|
|
|
}, 2000); |
|
|
|
} |
|
|
|
|
|
|
|
blocklist.appendChild(elem); |
|
|
|
blocklist.appendChild(elem); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
@@ -341,48 +341,48 @@ function populateRecentBlocks(blocks) { |
|
|
|
function getPollDelayAtHeight(height) { |
|
|
|
let blocksUntilHalving = HALVING_PERIOD - (height % HALVING_PERIOD); |
|
|
|
if (blocksUntilHalving == 1) { |
|
|
|
return 1000; |
|
|
|
return 1000; |
|
|
|
} else if (blocksUntilHalving == 2) { |
|
|
|
return 2500; |
|
|
|
return 2500; |
|
|
|
} else { |
|
|
|
return 10000; |
|
|
|
return 10000; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function checkNewBlocks() { |
|
|
|
console.log("Polling for new blocks..."); |
|
|
|
doGetRecentBlocks(function(blocks) { |
|
|
|
if (blocks == null) { |
|
|
|
alert("Error polling for new bocks, please refresh the page."); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Find the index of the newest known block. |
|
|
|
let knownHeight = recentBlocks[0].height; |
|
|
|
let newestKnownIndex = -1; |
|
|
|
for (let i = 0; i < blocks.length; i++) { |
|
|
|
if (blocks[i].height == knownHeight) { |
|
|
|
newestKnownIndex = i; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// If there's no new blocks, exit. |
|
|
|
if (newestKnownIndex == 0) { |
|
|
|
console.log("No new blocks found."); |
|
|
|
} else if (newestKnownIndex == -1) { |
|
|
|
console.log("wtf"); |
|
|
|
} |
|
|
|
|
|
|
|
// If there are new blocks, add them. |
|
|
|
for (let i = newestKnownIndex - 1; i >= 0; i--) { |
|
|
|
let newBlock = blocks[i]; |
|
|
|
console.log("Adding new block at height " + newBlock.height + " (" + newBlock.id + ")"); |
|
|
|
addNewBlock(newBlock); |
|
|
|
} |
|
|
|
|
|
|
|
// Set up to call this again. |
|
|
|
setTimeout(checkNewBlocks, getPollDelayAtHeight(recentBlocks[0].height)); |
|
|
|
if (blocks == null) { |
|
|
|
alert("Error polling for new bocks, please refresh the page."); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Find the index of the newest known block. |
|
|
|
let knownHeight = recentBlocks[0].height; |
|
|
|
let newestKnownIndex = -1; |
|
|
|
for (let i = 0; i < blocks.length; i++) { |
|
|
|
if (blocks[i].height == knownHeight) { |
|
|
|
newestKnownIndex = i; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// If there's no new blocks, exit. |
|
|
|
if (newestKnownIndex == 0) { |
|
|
|
console.log("No new blocks found."); |
|
|
|
} else if (newestKnownIndex == -1) { |
|
|
|
console.log("wtf"); |
|
|
|
} |
|
|
|
|
|
|
|
// If there are new blocks, add them. |
|
|
|
for (let i = newestKnownIndex - 1; i >= 0; i--) { |
|
|
|
let newBlock = blocks[i]; |
|
|
|
console.log("Adding new block at height " + newBlock.height + " (" + newBlock.id + ")"); |
|
|
|
addNewBlock(newBlock); |
|
|
|
} |
|
|
|
|
|
|
|
// Set up to call this again. |
|
|
|
setTimeout(checkNewBlocks, getPollDelayAtHeight(recentBlocks[0].height)); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
@@ -390,17 +390,17 @@ function init() { |
|
|
|
console.log("Hello!"); |
|
|
|
|
|
|
|
doGetRecentBlocks(function(blocks) { |
|
|
|
if (blocks == null) { |
|
|
|
alert("Error loading blocks, please refresh the page."); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
recentBlocks = blocks; |
|
|
|
|
|
|
|
populateRecentBlocks(blocks); |
|
|
|
setTimeout(checkNewBlocks, 5000); |
|
|
|
setInterval(function() { |
|
|
|
updateRemainingCount(recentBlocks[0]); |
|
|
|
}, 1000); |
|
|
|
if (blocks == null) { |
|
|
|
alert("Error loading blocks, please refresh the page."); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
recentBlocks = blocks; |
|
|
|
|
|
|
|
populateRecentBlocks(blocks); |
|
|
|
setTimeout(checkNewBlocks, 5000); |
|
|
|
setInterval(function() { |
|
|
|
updateRemainingCount(recentBlocks[0]); |
|
|
|
}, 1000); |
|
|
|
}); |
|
|
|
} |