diff --git "a/Burstcoin Pool\344\270\255\346\226\207\345\270\256\345\212\251.pdf" "b/Burstcoin Pool\344\270\255\346\226\207\345\270\256\345\212\251.pdf" new file mode 100644 index 00000000..565bd8d2 Binary files /dev/null and "b/Burstcoin Pool\344\270\255\346\226\207\345\270\256\345\212\251.pdf" differ diff --git a/pool.properties b/pool.properties index 038c6983..92e96c2c 100644 --- a/pool.properties +++ b/pool.properties @@ -1,78 +1,78 @@ -# Properties for Burstcoin Pool - -# The port to run the server on -serverPort = 80 - -# The address of the node to connect to. -# Make sure this uses the correct port -# for HTTP / gRPC, depending on which is -# selected. -nodeAddresses = grpc://localhost:6878; http://localhost:6876 - -# The name of the pool -poolName = My Awesome Pool - -# The passphrase of the pool account -passphrase = mysecretpassphrase - -# Database connection settings. Replace "pooldb" with your database name. -dbUrl=jdbc:mariadb://localhost:3306/pooldb -dbUsername=root -dbPassword= - -# Deadlines of the last nAvg blocks will be used to estimate capacity -nAvg = 360 - -# Minimum number of deadlines needed to get a share and be listed as a miner -nMin = 10 - -# Minimum block length in seconds for it to count towards miner estimated capacities -tMin = 30 - -# Maximum deadline accepted by the pool -maxDeadline = 1000000000 - -# The number of blocks behind the latest to process and, if necessary, reward. -# A higher value means more delayed rewards, a lower value means higher likelihood of problems due to -# short lived network forks. -processLag = 10 - -# Recipient of pool fees -feeRecipient=BURST-W5YR-ZZQC-KUBJ-G78KB -# Percentage of each block reward taken by pool (1 = 100%) -poolFeePercentage = 0.01 -# Percentage of each block reward (minus pool fees) taken by forger eg. 0 would be a 0-100 pool, 1 would be a 100-0 pool. -winnerRewardPercentage = 0 - -# Minimum number of Burst to payout by default. -# Changing this will only affect new miners -# This is also the minimum payout for the fee recipient -defaultMinimumPayout = 100 -# Minimum number of Burst a miner can set their minimum payout to -minimumMinimumPayout = 50 -# Minimum number of miners paid per transaction, including fee recipient. -# Pool pays out if every miner has reached minimum payout or if more than -# this many miners have reached minimum payout -minPayoutsPerTransaction = 10 -# Transaction fee for payouts. Will be deducted evenly from miners that are being paid. -transactionFee = 1 -# Number of times to retry making payout transaction if failed -payoutRetryCount = 3 -# Number of times to retry submitting nonce if failed -submitNonceRetryCount = 3 - -# The icon files for the website -site.icon.ico = icon.ico -site.icon.png = icon.png - -# The public node that the site will link to -site.nodeAddress = https://wallet.burst-alliance.org:8125/index.html - -# The software packages URL that the site will link to -site.softwarePackagesAddress = https://github.com/burst-apps-team - -# The discord URL that the site will link to -site.discord = https://discord.gg/ms6eagX - -# The title, as displayed on the site -site.title = Burst Pool +# Properties for Burstcoin Pool + +# The port to run the server on +serverPort = 80 + +# The address of the node to connect to. +# Make sure this uses the correct port +# for HTTP / gRPC, depending on which is +# selected.<--rpc端口设置 默认测试网-api v1 api v2> +nodeAddresses = grpc://localhost:6878; http://localhost:6876 + +# The name of the pool +poolName = My Awesome Pool + +# The passphrase of the pool account <--!矿池账户密码--> +passphrase = mysecretpassphrase + +# Database connection settings. Replace "pooldb" with your database name.<--!池数据库连接账户密码> +dbUrl=jdbc:mariadb://localhost:3306/pooldb +dbUsername=root +dbPassword= + +# Deadlines of the last nAvg blocks will be used to estimate capacity<--!容量确认轮--> +nAvg = 360 + +# Minimum number of deadlines needed to get a share and be listed as a miner<--!矿工确认区块--> +nMin = 1 + +# Minimum block length in seconds for it to count towards miner estimated capacities<--!最小统计秒区块--> +tMin = 30 + +# Maximum deadline accepted by the pool<--!池接收DL上限--> +maxDeadline = 1000000000 + +# The number of blocks behind the latest to process and, if necessary, reward. +# A higher value means more delayed rewards, a lower value means higher likelihood of problems due to +# short lived network forks.<--区块流程滞后--> +processLag = 10 + +# Recipient of pool fees<--池收费账户设置,可用数字ID--> +feeRecipient=BURST-W5YR-ZZQC-KUBJ-G78KB +# Percentage of each block reward taken by pool (1 = 100%)<--池费率--> +poolFeePercentage = 0.01 +# Percentage of each block reward (minus pool fees) taken by forger eg. 0 would be a 0-100 pool, 1 would be a 100-0 pool.<--默认0-100池--> +winnerRewardPercentage = 0 + +# Minimum number of Burst to payout by default. +# Changing this will only affect new miners +# This is also the minimum payout for the fee recipient +defaultMinimumPayout = 100 +# Minimum number of Burst a miner can set their minimum payout to +minimumMinimumPayout = 50 +# Minimum number of miners paid per transaction, including fee recipient. +# Pool pays out if every miner has reached minimum payout or if more than +# this many miners have reached minimum payout +minPayoutsPerTransaction = 10 +# Transaction fee for payouts. Will be deducted evenly from miners that are being paid. +transactionFee = 1 +# Number of times to retry making payout transaction if failed +payoutRetryCount = 3 +# Number of times to retry submitting nonce if failed +submitNonceRetryCount = 3 + +# The icon files for the website +site.icon.ico = icon.ico +site.icon.png = icon.png + +# The public node that the site will link to<--在线钱包地址设置--> +site.nodeAddress = https://wallet.burst-alliance.org:8125/index.html + +# The software packages URL that the site will link to<--默认挖掘开采工具下载地址设置--> +site.softwarePackagesAddress = https://github.com/burst-apps-team + +# The discord URL that the site will link to<--对应矿池绑定页面设置--> +site.discord = https://discord.gg/ms6eagX + +# The title, as displayed on the site<--池名称设置--> +site.title = Burst Pool diff --git a/settings.gradle b/settings.gradle index bee29c3e..709ac343 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -rootProject.name = 'burstcoin-pool' +rootProject.name = 'burstpool-bate-1' diff --git a/src/main/resources/html/img/burst_B_blue.png b/src/main/resources/html/img/burst_B_blue.png new file mode 100644 index 00000000..7ebcbb04 Binary files /dev/null and b/src/main/resources/html/img/burst_B_blue.png differ diff --git a/src/main/resources/html/img/discord.png b/src/main/resources/html/img/discord.png index d6baf07f..6761fa06 100644 Binary files a/src/main/resources/html/img/discord.png and b/src/main/resources/html/img/discord.png differ diff --git a/src/main/resources/html/img/icon.png b/src/main/resources/html/img/icon.png new file mode 100644 index 00000000..708171e9 Binary files /dev/null and b/src/main/resources/html/img/icon.png differ diff --git a/src/main/resources/html/img/logo.png b/src/main/resources/html/img/logo.png new file mode 100644 index 00000000..10cb5984 Binary files /dev/null and b/src/main/resources/html/img/logo.png differ diff --git a/src/main/resources/html/index.html b/src/main/resources/html/index.html index c25d84e3..6a5613f0 100644 --- a/src/main/resources/html/index.html +++ b/src/main/resources/html/index.html @@ -1,352 +1,377 @@ - - - - - {TITLE} - - - - - - - - - - - -
-
-
-
-
-
-

Elapsed

-
-
-

Loading...

-
-
-
-
-

Best Deadline

-
-
-

Loading...

-
-
-
-
-

Best Miner

-
-
-

Loading...

-
-
-
-
-

Best Nonce

-
-
-

Loading...

-
-
-
-
-

Block Height

-
-
-

Loading...

-
-
-
-
-

Network Difficulty

-
-
-

Loading...

-
-
-
-
-

Miners

-
-
-

Loading...

-
-
-
-
-

Pool Capacity

-
-
-

Loading...

-
-
-
-
-
- -
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- - - - - - - - - - - - - -
MinerCurrent DeadlinePending BalanceEffective CapacityConfirmed DeadlinesShareSoftware
Loading...
-

Powered by the Burst Apps Team. Copyright © Harry Phillips 2019

-
- - - - - - - - - + + + + + {TITLE} + + + + + + + + + + + +
+
+
+
+
+
+

计时

+
+
+

加载中...

+
+
+
+
+

当前最佳截止日期

+
+
+

加载中...

+
+
+
+
+

当前最佳矿工

+
+
+

加载中...

+
+
+
+
+

当前最佳 Nonce

+
+
+

加载中...

+
+
+
+
+

当前区块高度

+
+
+

加载中...

+
+
+
+
+

基准目标

+
+
+

加载中...

+
+
+
+
+

矿工数量

+
+
+

加载中...

+
+
+
+
+

矿池预估容量

+
+
+

加载中...

+
+
+
+
+

当前全网容量

+
+
+

加载中...

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + + +
矿工当前DL待平衡有效容量确认DL收益占比软件
加载中...
+

BURST团队技术支持. 版权所有 © Harry Phillips 2019

+
+ + + + + + + + + diff --git a/src/main/resources/html/js/index.js b/src/main/resources/html/js/index.js index 65fc64f3..7d56ca59 100644 --- a/src/main/resources/html/js/index.js +++ b/src/main/resources/html/js/index.js @@ -1,374 +1,375 @@ -const noneFoundYet = "None found yet!"; -const loading = "Loading..."; -const minerNotFound = "Miner not found"; - -const genesisBaseTarget = 4398046511104 / 240; - -let maxSubmissions = "Unknown"; - -let miners = new Array(0); -const colors = [ - "#3366CC", - "#DC3912", - "#FF9900", - "#109618", - "#990099", - "#3B3EAC", - "#0099C6", - "#DD4477", - "#66AA00", - "#B82E2E", - "#316395", - "#994499", - "#22AA99", - "#AAAA11", - "#6633CC", - "#E67300", - "#8B0707", - "#329262", - "#5574A6", - "#3B3EAC" -]; - -const entityMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/', - '`': '`', - '=': '=' -}; - -function escapeHtml(string) { - return typeof string === 'string' ? String(string).replace(/[&<>"'`=\/]/g, function (s) { - return entityMap[s]; - }) : string; -} - -let chart = null; - -function filterTimePart(part, suffix) { - if (part === 0) { - part = null; - } else { - part = part.toString() + suffix; - } - return part; -} - -function formatTime(secs) { - secs = parseInt(secs, 10); - if (secs === null || secs < 0) return ""; - if (secs === 0) return "0s"; - let years = filterTimePart(Math.floor(secs / 3600 / 24 / 365), "y"); - let days = filterTimePart(Math.floor((secs / 3600 / 24) % 365), "d"); - let hours = filterTimePart(Math.floor((secs / 3600) % 24), "h"); - let minutes = filterTimePart(Math.floor(secs / 60) % 60, "m"); - let seconds = filterTimePart(secs % 60, "s"); - - let result = ""; - if (years !== null) result += " " + years; - if (days !== null) result += " " + days; - if (hours !== null) result += " " + hours; - if (minutes !== null) result += " " + minutes; - if (seconds !== null) result += " " + seconds; - return result.substr(1); -} - -function formatBaseTarget(baseTarget) { - return (genesisBaseTarget / baseTarget).toFixed(3) + " TB" -} - -function getPoolInfo() { - fetch("/api/getConfig").then(http => { - return http.json(); - }).then(response => { - maxSubmissions = response.nAvg + response.processLag; - document.getElementById("poolName").innerText = response.poolName; - document.getElementById("poolAccount").innerHTML = formatMinerName(response.poolAccountRS, response.poolAccount, response.poolAccount, true); - document.getElementById("nAvg").innerText = response.nAvg; - document.getElementById("nMin").innerText = response.nMin; - document.getElementById("maxDeadline").innerText = response.maxDeadline; - document.getElementById("processLag").innerText = response.processLag + " Blocks"; - document.getElementById("feeRecipient").innerText = response.feeRecipientRS; - document.getElementById("poolFee").innerText = (parseFloat(response.poolFeePercentage)*100).toFixed(3) + "%"; - document.getElementById("winnerReward").innerText = (parseFloat(response.winnerRewardPercentage)*100).toFixed(3) + "%"; - document.getElementById("minimumPayout").innerText = response.defaultMinimumPayout + " BURST"; - document.getElementById("minPayoutsAtOnce").innerText = response.minPayoutsPerTransaction; - document.getElementById("payoutTxFee").innerText = response.transactionFee + " BURST"; - document.getElementById("poolVersion").innerText = response.version; - }); -} - -let roundStart = 0; - -function updateRoundElapsed() { - document.getElementById("currentRoundElapsed").innerText = formatTime(parseInt((new Date().getTime() / 1000).toFixed()) - roundStart); -} - -function getCurrentRound() { - fetch("/api/getCurrentRound").then(http => { - return http.json(); - }).then(response => { - roundStart = response.roundStart; - document.getElementById("blockHeight").innerText = response.miningInfo.height; - document.getElementById("netDiff").innerText = formatBaseTarget(response.miningInfo.baseTarget); - if (response.bestDeadline != null) { - document.getElementById("bestDeadline").innerText = formatTime(response.bestDeadline.deadline); - document.getElementById("bestMiner").innerHTML = formatMinerName(response.bestDeadline.minerRS, response.bestDeadline.miner, null, true); - document.getElementById("bestNonce").innerText = response.bestDeadline.nonce; - } else { - document.getElementById("bestDeadline").innerText = noneFoundYet; - document.getElementById("bestMiner").innerText = noneFoundYet; - document.getElementById("bestNonce").innerText = noneFoundYet; - } - }); -} - -function getAccountExplorerLink(id) { - return "https://explorer.burstcoin.network/?action=account&account=" + id; -} - -function formatMinerName(rs, id, name, includeLink) { - if (name == null) { - miners.forEach(miner => { - if (miner.address === id || miner.addressRS === rs) { - name = miner.name; - } - }) - } - name = escapeHtml(name); - rs = escapeHtml(rs); - if (includeLink) { - rs = "" + rs + ""; - } - return name == null || name === "" ? rs : rs + " (" + name + ")"; -} - -function getTop10Miners() { - fetch("api/getTop10Miners").then(http => { - return http.json(); - }).then(response => { - let topTenMiners = response.topMiners; - let topMinerNames = Array(); - let topMinerShares = Array(); - let minerColors = colors.slice(0, topTenMiners.length + 1); - for (let i = 0; i < topTenMiners.length; i++) { - let miner = topTenMiners[i]; - topMinerNames.push(formatMinerName(miner.addressRS, miner.address, miner.name, false)); - topMinerShares.push(miner.share * 100); - } - topMinerNames.push("Other"); - topMinerShares.push(response.othersShare * 100); - if (chart == null) { - chart = new Chart(document.getElementById("sharesChart"), { - type: "pie", - data: { - datasets: [{ - data: topMinerShares, - backgroundColor: minerColors - }], - labels: topMinerNames - }, - options: { - title: { - display: true, - text: "Pool Shares" - }, - responsive: true, - maintainAspectRatio: false, - } - }); - } else { - chart.data.datasets[0].data = topMinerShares; - chart.data.datasets[0].backgroundColor = minerColors; - chart.data.labels = topMinerNames; - chart.update(); - } - }); -} - -function getMiners() { - fetch("/api/getMiners").then(http => { - return http.json(); - }).then(response => { - let table = document.getElementById("miners"); - table.innerHTML = "MinerCurrent DeadlinePending BalanceEffective CapacityConfirmed DeadlinesShareSoftware"; - for (let i = 0; i < response.miners.length; i++) { - let miner = response.miners[i]; - let currentRoundDeadline = miner.currentRoundBestDeadline == null ? "" : formatTime(miner.currentRoundBestDeadline); - let minerAddress = formatMinerName(miner.addressRS, miner.address, miner.name, true); - let userAgent = escapeHtml(miner.userAgent == null? "Unknown" : miner.userAgent); - table.innerHTML += ""+minerAddress+""+currentRoundDeadline+""+miner.pendingBalance+""+formatCapacity(miner.estimatedCapacity)+" TB"+miner.nConf+" / " + maxSubmissions + ""+(parseFloat(miner.share)*100).toFixed(3)+"%"+userAgent+""; - } - document.getElementById("minerCount").innerText = response.miners.length; - document.getElementById("poolCapacity").innerText = formatCapacity(response.poolCapacity) + " TB"; - miners = response.miners; - }); -} - -function prepareMinerInfo(address) { - setCookie("getMinerLastValue", address); - let minerAddress = escapeHtml(document.getElementById("minerAddress")); - let minerName = escapeHtml(document.getElementById("minerName")); - let minerPending = escapeHtml(document.getElementById("minerPending")); - let minerMinimumPayout = escapeHtml(document.getElementById("minerMinimumPayout")); - let minerCapacity = escapeHtml(document.getElementById("minerCapacity")); - let minerNConf = escapeHtml(document.getElementById("minerNConf")); - let minerShare = escapeHtml(document.getElementById("minerShare")); - let minerSoftware = escapeHtml(document.getElementById("minerSoftware")); - let setMinimumPayoutButton = $("#setMinimumPayoutButton"); - - minerAddress.innerText = address; - minerName.innerText = loading; - minerPending.innerText = loading; - minerMinimumPayout.innerText = loading; - minerCapacity.innerText = loading; - minerNConf.innerText = loading; - minerShare.innerText = loading; - minerSoftware.innerText = loading; - - let miner = null; - miners.forEach(aMiner => { - if (aMiner.addressRS === address || aMiner.address.toString() === address || aMiner.name === address) { - miner = aMiner; - } - }); - - if (miner == null) { - minerName.innerText = minerNotFound; - minerPending.innerText = minerNotFound; - minerMinimumPayout.innerText = minerNotFound; - minerCapacity.innerText = minerNotFound; - minerNConf.innerText = minerNotFound; - minerShare.innerText = minerNotFound; - minerSoftware.innerText = minerNotFound; - setMinimumPayoutButton.hide(); - return; - } - - let name = escapeHtml(miner.name == null ? "Not Set" : miner.name); - let userAgent = escapeHtml(miner.userAgent == null ? "Unknown" : miner.userAgent); - - minerAddress.innerText = miner.addressRS; - minerName.innerText = name; - minerPending.innerText = miner.pendingBalance; - minerMinimumPayout.innerText = miner.minimumPayout; - minerCapacity.innerText = formatCapacity(miner.estimatedCapacity); - minerNConf.innerText = miner.nConf; - minerShare.innerText = (parseFloat(miner.share)*100).toFixed(3) + "%"; - minerSoftware.innerText = userAgent; - setMinimumPayoutButton.show(); -} - -function formatCapacity(capacity) { - return parseFloat(capacity).toFixed(3); -} - -function onPageLoad() { - document.getElementById("addressInput").value = getCookie("getMinerLastValue"); - $('#minerInfoModal').on('show.bs.modal', function (event) { - prepareMinerInfo(document.getElementById("addressInput").value); - }); - $('#setMinimumPayoutModal').on('show.bs.modal', function (event) { - document.getElementById("setMinimumAddress").value = escapeHtml(document.getElementById("minerAddress").innerText); - $("#setMinimumResult").hide(); - }); - document.getElementById("addressInput").addEventListener("keyup", function (event) { - if (event.keyCode === 13) { - event.preventDefault(); - document.getElementById("getMinerButton").click(); - } - }); - document.getElementById("icon").onerror = function () { - this.style.display = "none"; - } -} - -function generateSetMinimumMessage() { - let address = escapeHtml(document.getElementById("setMinimumAddress").value); - let newPayout = escapeHtml(document.getElementById("setMinimumAmount").value); - if (document.getElementById("setMinimumAmount").value === "") { - alert("Please set new minimum payout"); - return; - } - fetch("/api/getSetMinimumMessage?address="+address+"&newPayout="+newPayout).then(http => { - return http.json(); - }).then(response => { - document.getElementById("setMinimumMessage").value = escapeHtml(response.message); - }); -} - -function getWonBlocks() { - fetch("/api/getWonBlocks").then(response => { - return response.json(); - }).then(response => { - let wonBlocks = response.wonBlocks; - let table = document.getElementById("wonBlocksTable"); - table.innerHTML = "HeightIDWinnerReward + Fees"; - for (let i = 0; i < wonBlocks.length; i++) { - let wonBlock = wonBlocks[i]; - let height = escapeHtml(wonBlock.height); - let id = escapeHtml(wonBlock.id); - let reward = escapeHtml(wonBlock.reward); - let minerName = formatMinerName(wonBlock.generatorRS, wonBlock.generator, null, true); - table.innerHTML += ""+height+""+id+""+minerName+""+reward+""; - } - }); -} - -function setCookie(name, value) { - document.cookie = name + "=" + value + ";"; -} - -function getCookie(name) { - name += "="; - const decodedCookie = decodeURIComponent(document.cookie); - const ca =decodedCookie.split(';'); - for(let i = 0; i { - return http.json(); - }).then(response => { - document.getElementById("setMinimumResultText").innerText = response; - $("#setMinimumResult").show(); - }); -} - -getPoolInfo(); -getCurrentRound(); -getMiners(); -getTop10Miners(); - -setInterval(updateRoundElapsed, 1000); -setInterval(getCurrentRound, 10000); -setInterval(getMiners, 60000); /* TODO only refresh this when we detect that we forged a block */ -setInterval(getTop10Miners, 60000); +const noneFoundYet = "None found yet!"; +const loading = "Loading..."; +const minerNotFound = "Miner not found"; + +const genesisBaseTarget = 4398046511104 / 240; + +let maxSubmissions = "Unknown"; + +let miners = new Array(0); +const colors = [ + "#3366CC", + "#DC3912", + "#FF9900", + "#109618", + "#990099", + "#3B3EAC", + "#0099C6", + "#DD4477", + "#66AA00", + "#B82E2E", + "#316395", + "#994499", + "#22AA99", + "#AAAA11", + "#6633CC", + "#E67300", + "#8B0707", + "#329262", + "#5574A6", + "#3B3EAC" +]; + +const entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' +}; + +function escapeHtml(string) { + return typeof string === 'string' ? String(string).replace(/[&<>"'`=\/]/g, function (s) { + return entityMap[s]; + }) : string; +} + +let chart = null; + +function filterTimePart(part, suffix) { + if (part === 0) { + part = null; + } else { + part = part.toString() + suffix; + } + return part; +} + +function formatTime(secs) { + secs = parseInt(secs, 10); + if (secs === null || secs < 0) return ""; + if (secs === 0) return "0s"; + let years = filterTimePart(Math.floor(secs / 3600 / 24 / 365), "y"); + let days = filterTimePart(Math.floor((secs / 3600 / 24) % 365), "d"); + let hours = filterTimePart(Math.floor((secs / 3600) % 24), "h"); + let minutes = filterTimePart(Math.floor(secs / 60) % 60, "m"); + let seconds = filterTimePart(secs % 60, "s"); + + let result = ""; + if (years !== null) result += " " + years; + if (days !== null) result += " " + days; + if (hours !== null) result += " " + hours; + if (minutes !== null) result += " " + minutes; + if (seconds !== null) result += " " + seconds; + return result.substr(1); +} + +function formatBaseTarget(baseTarget) { + return (genesisBaseTarget / baseTarget).toFixed(3) + " TB" +} + +function getPoolInfo() { + fetch("/api/getConfig").then(http => { + return http.json(); + }).then(response => { + maxSubmissions = response.nAvg + response.processLag; + document.getElementById("poolName").innerText = response.poolName; + document.getElementById("poolAccount").innerHTML = formatMinerName(response.poolAccountRS, response.poolAccount, response.poolAccount, true); + document.getElementById("nAvg").innerText = response.nAvg; + document.getElementById("nMin").innerText = response.nMin; + document.getElementById("maxDeadline").innerText = response.maxDeadline; + document.getElementById("processLag").innerText = response.processLag + " Blocks"; + document.getElementById("feeRecipient").innerText = response.feeRecipientRS; + document.getElementById("poolFee").innerText = (parseFloat(response.poolFeePercentage)*100).toFixed(3) + "%"; + document.getElementById("winnerReward").innerText = (parseFloat(response.winnerRewardPercentage)*100).toFixed(3) + "%"; + document.getElementById("minimumPayout").innerText = response.defaultMinimumPayout + " BURST"; + document.getElementById("minPayoutsAtOnce").innerText = response.minPayoutsPerTransaction; + document.getElementById("payoutTxFee").innerText = response.transactionFee + " BURST"; + document.getElementById("poolVersion").innerText = response.version; + }); +} + +let roundStart = 0; + +function updateRoundElapsed() { + document.getElementById("currentRoundElapsed").innerText = formatTime(parseInt((new Date().getTime() / 1000).toFixed()) - roundStart); +} + +function getCurrentRound() { + fetch("/api/getCurrentRound").then(http => { + return http.json(); + }).then(response => { + roundStart = response.roundStart; + document.getElementById("blockHeight").innerText = response.miningInfo.height; + document.getElementById("netDiff").innerText = formatBaseTarget(response.miningInfo.baseTarget); + document.getElementById("baseTarget").innerText = response.miningInfo.baseTarget; + if (response.bestDeadline != null) { + document.getElementById("bestDeadline").innerText = formatTime(response.bestDeadline.deadline); + document.getElementById("bestMiner").innerHTML = formatMinerName(response.bestDeadline.minerRS, response.bestDeadline.miner, null, true); + document.getElementById("bestNonce").innerText = response.bestDeadline.nonce; + } else { + document.getElementById("bestDeadline").innerText = noneFoundYet; + document.getElementById("bestMiner").innerText = noneFoundYet; + document.getElementById("bestNonce").innerText = noneFoundYet; + } + }); +} + +function getAccountExplorerLink(id) { + return "https://explorer.burstcoin.network/?action=account&account=" + id; +} + +function formatMinerName(rs, id, name, includeLink) { + if (name == null) { + miners.forEach(miner => { + if (miner.address === id || miner.addressRS === rs) { + name = miner.name; + } + }) + } + name = escapeHtml(name); + rs = escapeHtml(rs); + if (includeLink) { + rs = "" + rs + ""; + } + return name == null || name === "" ? rs : rs + " (" + name + ")"; +} + +function getTop10Miners() { + fetch("api/getTop10Miners").then(http => { + return http.json(); + }).then(response => { + let topTenMiners = response.topMiners; + let topMinerNames = Array(); + let topMinerShares = Array(); + let minerColors = colors.slice(0, topTenMiners.length + 1); + for (let i = 0; i < topTenMiners.length; i++) { + let miner = topTenMiners[i]; + topMinerNames.push(formatMinerName(miner.addressRS, miner.address, miner.name, false)); + topMinerShares.push(miner.share * 100); + } + topMinerNames.push("Other"); + topMinerShares.push(response.othersShare * 100); + if (chart == null) { + chart = new Chart(document.getElementById("sharesChart"), { + type: "pie", + data: { + datasets: [{ + data: topMinerShares, + backgroundColor: minerColors + }], + labels: topMinerNames + }, + options: { + title: { + display: true, + text: "Pool Shares" + }, + responsive: true, + maintainAspectRatio: false, + } + }); + } else { + chart.data.datasets[0].data = topMinerShares; + chart.data.datasets[0].backgroundColor = minerColors; + chart.data.labels = topMinerNames; + chart.update(); + } + }); +} + +function getMiners() { + fetch("/api/getMiners").then(http => { + return http.json(); + }).then(response => { + let table = document.getElementById("miners"); + table.innerHTML = "MinerCurrent DeadlinePending BalanceEffective CapacityConfirmed DeadlinesShareSoftware"; + for (let i = 0; i < response.miners.length; i++) { + let miner = response.miners[i]; + let currentRoundDeadline = miner.currentRoundBestDeadline == null ? "" : formatTime(miner.currentRoundBestDeadline); + let minerAddress = formatMinerName(miner.addressRS, miner.address, miner.name, true); + let userAgent = escapeHtml(miner.userAgent == null? "Unknown" : miner.userAgent); + table.innerHTML += ""+minerAddress+""+currentRoundDeadline+""+miner.pendingBalance+""+formatCapacity(miner.estimatedCapacity)+" TB"+miner.nConf+" / " + maxSubmissions + ""+(parseFloat(miner.share)*100).toFixed(3)+"%"+userAgent+""; + } + document.getElementById("minerCount").innerText = response.miners.length; + document.getElementById("poolCapacity").innerText = formatCapacity(response.poolCapacity) + " TB"; + miners = response.miners; + }); +} + +function prepareMinerInfo(address) { + setCookie("getMinerLastValue", address); + let minerAddress = escapeHtml(document.getElementById("minerAddress")); + let minerName = escapeHtml(document.getElementById("minerName")); + let minerPending = escapeHtml(document.getElementById("minerPending")); + let minerMinimumPayout = escapeHtml(document.getElementById("minerMinimumPayout")); + let minerCapacity = escapeHtml(document.getElementById("minerCapacity")); + let minerNConf = escapeHtml(document.getElementById("minerNConf")); + let minerShare = escapeHtml(document.getElementById("minerShare")); + let minerSoftware = escapeHtml(document.getElementById("minerSoftware")); + let setMinimumPayoutButton = $("#setMinimumPayoutButton"); + + minerAddress.innerText = address; + minerName.innerText = loading; + minerPending.innerText = loading; + minerMinimumPayout.innerText = loading; + minerCapacity.innerText = loading; + minerNConf.innerText = loading; + minerShare.innerText = loading; + minerSoftware.innerText = loading; + + let miner = null; + miners.forEach(aMiner => { + if (aMiner.addressRS === address || aMiner.address.toString() === address || aMiner.name === address) { + miner = aMiner; + } + }); + + if (miner == null) { + minerName.innerText = minerNotFound; + minerPending.innerText = minerNotFound; + minerMinimumPayout.innerText = minerNotFound; + minerCapacity.innerText = minerNotFound; + minerNConf.innerText = minerNotFound; + minerShare.innerText = minerNotFound; + minerSoftware.innerText = minerNotFound; + setMinimumPayoutButton.hide(); + return; + } + + let name = escapeHtml(miner.name == null ? "Not Set" : miner.name); + let userAgent = escapeHtml(miner.userAgent == null ? "Unknown" : miner.userAgent); + + minerAddress.innerText = miner.addressRS; + minerName.innerText = name; + minerPending.innerText = miner.pendingBalance; + minerMinimumPayout.innerText = miner.minimumPayout; + minerCapacity.innerText = formatCapacity(miner.estimatedCapacity); + minerNConf.innerText = miner.nConf; + minerShare.innerText = (parseFloat(miner.share)*100).toFixed(3) + "%"; + minerSoftware.innerText = userAgent; + setMinimumPayoutButton.show(); +} + +function formatCapacity(capacity) { + return parseFloat(capacity).toFixed(3); +} + +function onPageLoad() { + document.getElementById("addressInput").value = getCookie("getMinerLastValue"); + $('#minerInfoModal').on('show.bs.modal', function (event) { + prepareMinerInfo(document.getElementById("addressInput").value); + }); + $('#setMinimumPayoutModal').on('show.bs.modal', function (event) { + document.getElementById("setMinimumAddress").value = escapeHtml(document.getElementById("minerAddress").innerText); + $("#setMinimumResult").hide(); + }); + document.getElementById("addressInput").addEventListener("keyup", function (event) { + if (event.keyCode === 13) { + event.preventDefault(); + document.getElementById("getMinerButton").click(); + } + }); + document.getElementById("icon").onerror = function () { + this.style.display = "none"; + } +} + +function generateSetMinimumMessage() { + let address = escapeHtml(document.getElementById("setMinimumAddress").value); + let newPayout = escapeHtml(document.getElementById("setMinimumAmount").value); + if (document.getElementById("setMinimumAmount").value === "") { + alert("Please set new minimum payout"); + return; + } + fetch("/api/getSetMinimumMessage?address="+address+"&newPayout="+newPayout).then(http => { + return http.json(); + }).then(response => { + document.getElementById("setMinimumMessage").value = escapeHtml(response.message); + }); +} + +function getWonBlocks() { + fetch("/api/getWonBlocks").then(response => { + return response.json(); + }).then(response => { + let wonBlocks = response.wonBlocks; + let table = document.getElementById("wonBlocksTable"); + table.innerHTML = "HeightIDWinnerReward + Fees"; + for (let i = 0; i < wonBlocks.length; i++) { + let wonBlock = wonBlocks[i]; + let height = escapeHtml(wonBlock.height); + let id = escapeHtml(wonBlock.id); + let reward = escapeHtml(wonBlock.reward); + let minerName = formatMinerName(wonBlock.generatorRS, wonBlock.generator, null, true); + table.innerHTML += ""+height+""+id+""+minerName+""+reward+""; + } + }); +} + +function setCookie(name, value) { + document.cookie = name + "=" + value + ";"; +} + +function getCookie(name) { + name += "="; + const decodedCookie = decodeURIComponent(document.cookie); + const ca =decodedCookie.split(';'); + for(let i = 0; i { + return http.json(); + }).then(response => { + document.getElementById("setMinimumResultText").innerText = response; + $("#setMinimumResult").show(); + }); +} + +getPoolInfo(); +getCurrentRound(); +getMiners(); +getTop10Miners(); + +setInterval(updateRoundElapsed, 1000); +setInterval(getCurrentRound, 10000); +setInterval(getMiners, 60000); /* TODO only refresh this when we detect that we forged a block */ +setInterval(getTop10Miners, 60000);