Skip to content

Commit

Permalink
Add a new table for vspd instances.
Browse files Browse the repository at this point in the history
- Provide some explanation for revoked tickets.
- Hide legacy VSPs in a collapsible panel.
- Fix bug where sort icons were positioned under column titles rather than beside.
  • Loading branch information
jholdstock authored and dajohi committed Mar 1, 2021
1 parent 7fb31e7 commit 399bad5
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 6 deletions.
7 changes: 6 additions & 1 deletion src/assets/css/dataTables.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ table.dataTable {
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
background-repeat: no-repeat;
background-position: center right; }
background-position: right center; }
table.dataTable thead .sorting {
background-image: url("../images/sort.svg"); }
table.dataTable thead .sorting_asc {
Expand Down Expand Up @@ -371,6 +371,9 @@ table.dataTable td {
table {
text-align: right !important;
}
table.dataTable th {
text-transform: capitalize;
}
.rowHover:hover {
background-color: #e9f8fe !important; }
.poolId, .address, .address > a {
Expand All @@ -384,10 +387,12 @@ table.dataTable td {
.poolIdHeader, .addressHeader {
text-align: left !important;
}
#vspd-table > thead > tr > th, #vspd-table > tbody > tr ,
#stakepool-table > thead > tr > th, #stakepool-table > tbody > tr {
border-bottom: 1px solid #e2e2e2 !important;
white-space: nowrap;
}
#vspd-table > thead > tr > th ,
#stakepool-table > thead > tr > th {
font-weight: 700 !important;
}
Expand Down
7 changes: 6 additions & 1 deletion src/assets/css/decred-v5.css
Original file line number Diff line number Diff line change
Expand Up @@ -2870,7 +2870,7 @@ html[dir="rtl"] .lang-menu {

.vsp-description {
margin-top: 46px;
margin-bottom: 46px;
margin-bottom: 36px;
color: #596d81;
line-height: 22px;
text-decoration: none;
Expand Down Expand Up @@ -6779,4 +6779,9 @@ p.get-into__link {
margin-top: 26px;
font-weight: 700;
color: #fd714a;
}

.hidden-legacy-vsps {
margin-top: 18px;
color: #596d81;
}
115 changes: 113 additions & 2 deletions src/assets/js/vsp.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var APIstakepools = API_ROOT + '/?c=gsd';
var APIvspds = API_ROOT + '/?c=vsp';

// maxProportion is the maximum percentage of all network tickets that a VSP can
// hold before it is considered over capacity. These VSPs will be relegated to
Expand All @@ -8,15 +9,125 @@ var maxProportion = 5;
$(document).ready(function () {
if (window.location.href.indexOf('vsp') != -1) {
stakepoolFinder();
vspdFinder();
};
});

var vspdFinder = function() {
$("#vspd-data").html("Loading...");

var fields = ["voting", "voted", "revoked", "PoolFees", "Age"];

var tableMarkup = '<table id="vspd-table" class="datatables">' +
'<thead>' +
'<tr class="">' +
'<th class="addressHeader" style="padding-left: 2px; background-image: none;">Address</th>' +
'<th class="lastUpdatedHeader">Last Updated</th>';

$.each(fields, function (i, field) {
switch (field) {
case "PoolFees":
field = "Fees";
break;

default:
// add whitespaces to CamelCase
field = field.split(/(?=[A-Z])/).join(' ')
}

tableMarkup += '<th>' + field + '</th>';
});

tableMarkup += '</tr></thead><tbody>';

$.ajax({
url: APIvspds,
dataType: "json",
error: function (_, textStatus, errorThrown) {
errorMarkup = '<div class="ui-widget"><div class="ui-state-error ui-corner-all">' +
'<p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>' +
'<strong>Error:</strong> ' + textStatus + ": " + errorThrown + '</p></div></div>';
},
success: function (data, _) {
$.each(data, function (poolUrl, poolData) {
if (poolData["network"] === 'testnet') return;

var now = Math.floor((new Date).getTime() / 1000);
var lastUpdated = poolData["lastupdated"] - now;
var lastUpdateFormatted = moment.duration(lastUpdated, "seconds").humanize(true);
if (lastUpdateFormatted.indexOf("years") > 0) {
lastUpdateFormatted = "N/A";
}

tableMarkup += '<td class="address"><a target="_blank" rel="noopener noreferrer" href="https://' + poolUrl + '">' + poolUrl + '</a></td>';
tableMarkup += '<td class="lastUpdate dcrwebcode">' + lastUpdateFormatted + '</td>';

$.each(fields, function (_, field) {
var value = 'N/A';
var order = null;

if (poolData.hasOwnProperty(field)) value = poolData[field]

switch (field) {
case "PoolFees":
poolFees = "" + poolData["feepercentage"];
if (poolFees != "N/A" && poolFees.substr(-1) != "%") {
poolFees += "%";
}
value = poolFees
break;

case "Age":
var launchDate = new Date(poolData["launched"] * 1000);
var duration = moment.duration(launchDate - new Date()).humanize(false);
order = launchDate.getTime();

value = '<time' +
' style="white-space: nowrap' +
'" datetime="' + launchDate.toISOString() +
'" title="' + launchDate.toString() +
'">' + duration +
'</time>';
break;
}

if (order) {
tableMarkup += '<td class="dcrwebcode" data-order="' + order + '">' + value + '</td>';
} else {
tableMarkup += '<td class="dcrwebcode">' + value + '</td>';
}
});

tableMarkup += '</tr>';
});

tableMarkup += '</tbody></table>';

$("#vspd-data").html(tableMarkup);

$("#vspd-table").DataTable({
"ordering": true,
"order": [
[2, 'desc'] // sort by Voting
],
"jQueryUI": false,
"paging": false,
"searching": false,
"info": false,
'lengthChange': false
});

},
});

}

var stakepoolFinder = function() {
$("#stakepool-data").html("Loading...");

var fields = ["Live", "Immature", "Voted", "Missed", "ProportionMissed", "PoolFees", "UserCountActive", "Age"];

tableMarkup = '<table id="stakepool-table" class="datatables">' +
var tableMarkup = '<table id="stakepool-table" class="datatables">' +
'<thead>' +
'<tr class="">' +
'<th class="addressHeader" style="padding-left: 2px; background-image: none;">Address</th>' +
Expand Down Expand Up @@ -146,7 +257,7 @@ var stakepoolFinder = function() {
});

// Show the total percentage of all tickets that the VSPs manage.
$('<div><span style="font-weight: 700!important;">Tickets Held by Pools: </span><span class="dcrwebcode">' + totalPropLive.toFixed(2) + '%</span></div>').appendTo("#stakepool-data");
$('<div><span style="font-weight: 700!important;">Tickets held by legacy VSPs: </span><span class="dcrwebcode">' + totalPropLive.toFixed(2) + '%</span></div>').appendTo("#stakepool-data");
},
});
};
6 changes: 5 additions & 1 deletion src/layouts/vsp/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
</div>

<div class="subpage-content w-clearfix">
<div id="stakepool-data" class="stakepool-data"></div>
<div id="vspd-data" class="stakepool-data"></div>
<details>
<summary class="hidden-legacy-vsps">{{ T "stakepools_viewlegacy" }}</summary>
<div id="stakepool-data" class="stakepool-data"></div>
</details>
<div class="modalparagraph left" >{{ safeHTML (T "stakepools_warning_1") }}</div>
<div class="modalparagraph right">{{ safeHTML (T "stakepools_warning_2") }}</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion transifex_catalogs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@
"downloads_app_ledger": "Ledger Live is a web based wallet secured by the Ledger hardware wallet.",
"downloads_app_evercoin": "Evercoin is a non-custodial, mobile cryptocurrency wallet with built-in exchange.",
"downloads_app_trust": "Trust Wallet is a secure multi-coin wallet for Android and iOS.",
"stakepools_viewlegacy": "Click here to view legacy VSPs",
"stakepools_description": "Decred coin holders can opt-in to project governance by pseudorandomly locking their coins in exchange for tickets in order to earn staking rewards. By participating, stakeholders help secure the network by voting to approve the work of the miners, and gain voting rights on proposed changes to the Decred blockchain and project management via Politeia. For a complete explanation, see <a href=\"https://docs.decred.org/proof-of-stake/overview/\" target=\"_blank\" rel=\"noopener noreferrer\">the documentation</a>.<br /><br />Because tickets are called pseudorandomly and a wallet must be online to vote when a ticket is called, many people use a Voting Service Provider (VSP) using Decrediton or dcrwallet. VSPs lack access to your funds and are tasked with relaying your voting preferences to the network.<br /><br />The following VSPs have been reviewed by the community.",
"stakepools_warning_1": "<span class=\"modalparagraphbold\">Notice:</span>&nbsp;Missed tickets can be caused by a poorly connected Proof-of-Work (PoW) miner and may not necessarily be the fault of the provider.",
"stakepools_warning_1": "<span class=\"modalparagraphbold\">Notice:</span>&nbsp;Tickets may be revoked either because they were missed, or because they expired. Missed tickets can be caused by a poorly connected Proof-of-Work (PoW) miner and may not necessarily be the fault of the provider.",
"stakepools_warning_2": "<span class=\"modalparagraphbold\">Warning:</span>&nbsp;To encourage decentralization of the network, it is recommended to avoid providers that have over 5% of network votes.",
"stakepools_get_listed": "To get your VSP listed, you need to have at least three geographically-distributed voting wallets, and at least one ticket that has successfully voted on mainnet. You can find more information in the <a href='https://docs.decred.org/advanced/operating-a-vsp/' target=\"_blank\" rel=\"noopener noreferrer\">VSP docs</a>.",
"community_description": "Come and join our growing community, where you can connect with developers and other users, get information, ask questions, or just hang out. The public channels on Matrix, Telegram, and Discord have been bridged. You can choose any of these platforms and still participate in discussions with Decred community members on the others.",
Expand Down

0 comments on commit 399bad5

Please sign in to comment.