Skip to content
This repository has been archived by the owner on Jul 22, 2020. It is now read-only.

Commit

Permalink
feat: impl of TdS leaderboard (pending additional fields & styling)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnygleason committed Jul 12, 2019
1 parent 6abeaed commit c6abb10
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 2 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"url": "http://github.com/solana-labs/blockexplorer/issues"
},
"dependencies": {
"@nivo/bar": "^0.59.2",
"@nivo/line": "^0.59.2",
"@solana/web3.js": "^0.16.10",
"babel-plugin-transform-runtime": "^6.23.0",
Expand Down
10 changes: 9 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Bx2BlankComponent from './v2/Bx2BlankComponent';
import Bx2PanelValidatorsOverview from './v2/Bx2PanelValidatorsOverview';
import Bx2PanelValidators from './v2/Bx2PanelValidators';
import Bx2PanelValidatorDetail from './v2/Bx2PanelValidatorDetail';
import Bx2PanelTourDeSolLeaderboard from './v2/Bx2PanelTourDeSolLeaderboard';
import {stylesV2, themeV2} from './v2/ThemeV2';

const history = createBrowserHistory();
Expand All @@ -43,6 +44,9 @@ const BxDataTableThemed = withStyles(stylesV1)(BxDataTable);

const Bx2AppBarThemed = withStyles(stylesV2)(Bx2AppBar);
const Bx2NavDrawerThemed = withStyles(stylesV2)(Bx2NavDrawer);
const Bx2PanelTourDeSolLeaderboardThemed = withStyles(stylesV2)(
Bx2PanelTourDeSolLeaderboard,
);
const Bx2PanelValidatorsOverviewThemed = withStyles(stylesV2)(
Bx2PanelValidatorsOverview,
);
Expand Down Expand Up @@ -730,7 +734,11 @@ class App extends Component {
path="/v2/tourdesol"
exact
render={() => (
<Bx2BlankComponentThemed message="Hello Tour De Sol" />
<Bx2PanelTourDeSolLeaderboardThemed
currentBlock={this.state.globalStats['!blk-last-slot']}
nodes={this.state.nodes}
supply={this.state.supply || 0}
/>
)}
/>
<Route
Expand Down
320 changes: 320 additions & 0 deletions src/v2/Bx2PanelTourDeSolLeaderboard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
import React, {Component} from 'react';
import Paper from '@material-ui/core/Paper';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Typography from '@material-ui/core/Typography';
import _ from 'lodash';
import PropTypes from 'prop-types';
import {Link as RouterLink} from 'react-router-dom';
import Link from '@material-ui/core/Link';
import Grid from '@material-ui/core/Grid';
import CardContent from '@material-ui/core/CardContent';
import Card from '@material-ui/core/Card';
import {Button} from '@material-ui/core';
import {Bar} from '@nivo/bar';

import BxEntityLink from './Bx2EntityLink';
import BxHelpLink from './Bx2HelpLink';

class Bx2PanelTourDeSolLeaderboard extends Component {
renderValidators() {
const {nodes, currentBlock} = this.props;

// eslint-disable-next-line no-restricted-properties
const totalSupplySOL = (this.props.supply / Math.pow(2, 34)).toFixed(2);

const totalSupply = this.props.supply;

const stakedSupply = _.reduce(
nodes,
(a, n) => {
if (n && n.voteAccount && n.voteAccount.stake) {
a += n.voteAccount.stake;
}

return a;
},
0,
);

const stakedPercentage = ((stakedSupply / totalSupply) * 100.0).toFixed(2);

const DEFAULT_STAGE_LENGTH_BLOCKS = (7 * 24 * 60 * 60) / 0.8;
const PROLOGUE_LENGTH_BLOCKS = DEFAULT_STAGE_LENGTH_BLOCKS / 3;

let i = 0;

let stages = _.map(
[
{title: 'Prologue', is_prologue: true},
{title: 'Stage 1', is_prologue: false},
{title: 'Stage 2 (preamble)', is_prologue: true},
{title: 'Stage 2', is_prologue: false},
{title: 'Stage 3 (preamble)', is_prologue: true},
{title: 'Stage 3', is_prologue: false},
],
v => {
v.start_height = i;
v.end_height =
i +
(v.is_prologue
? PROLOGUE_LENGTH_BLOCKS
: DEFAULT_STAGE_LENGTH_BLOCKS) -
1;
i = v.end_height + 1;

return v;
},
);

function getIndicator(x) {
if (x.start_height <= currentBlock && x.end_height > currentBlock) {
return 'LIVE!';
} else if (x.start_height > currentBlock) {
return 'Coming Soon!';
} else {
return 'Finished.';
}
}

return (
<div style={{marginLeft: 240, marginRight: 80}}>
<div style={{marginTop: 60, whiteSpace: 'preserve'}}>
<code>Current Block: {currentBlock}</code>
<br />
<ul>
{_.map(_.filter(stages, x => !x.is_prologue), x => (
<li key={x.title}>
<Button>
{x.title} : block {x.start_height} to {x.end_height} =>{' '}
{getIndicator(x)}
</Button>
</li>
))}
</ul>
</div>
<p />
<div>
{/*
* STYLING NOTE: this link appears to have custom BarComponent styling
*
* https://nivo.rocks/storybook/?path=/story/bar-race-chart--demo
*
*/}
<Bar
width={800}
height={400}
layout="horizontal"
margin={{top: 26, right: 120, bottom: 26, left: 60}}
data={_.map(nodes, x => {
return {
id: x.pubkey,
value: (x.voteAccount && x.voteAccount.stake) || 0,
};
})}
keys={['value']}
colors={{scheme: 'blue_green'}}
colorBy="indexValue"
/>
</div>
<p />
<div>
<Grid container justify="center" spacing={1} className="sideBySide">
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Stage Duration Blocks
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
TODO
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Days Left In Stage
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
TODO
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Total SOL in Circulation
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
{totalSupplySOL} SOL
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Total Bonded Tokens
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
{stakedSupply + ' Lamports'}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Current Network Inflation Rate
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
TODO
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
# Active Validators
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
{this.props.nodes.length}
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
# Inactive Validators
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
TODO
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item>
<Card>
<CardContent>
<Typography variant="h5" component="h2" align="center">
Circulating Supply Staked
<BxHelpLink text="Leader" term="leader" />
</Typography>
<Typography component="p" align="center">
<span title={stakedSupply + ' Lamports'}>
{stakedPercentage}%
</span>
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
</div>
<Paper style={{marginTop: 10, marginLeft: 240}}>
<Typography
variant="h6"
id="tableTitle"
style={{textAlign: 'left', padding: '16px'}}
>
Active Validators {this.props.nodes.length}
<BxHelpLink text="Transaction" term="transaction" />
<br />
<Link component={RouterLink} to={'/v2/validators'}>
See All
</Link>
</Typography>
<Table>
<TableHead>
<TableRow>
<TableCell>
<div>
Node Pubkey
<BxHelpLink text="Transaction" term="transaction" />
</div>
<div>
Vote Pubkey
<BxHelpLink text="Account" term="account" />
</div>
</TableCell>
<TableCell>
Stake
<BxHelpLink text="Program" term="program-id" />
</TableCell>
<TableCell align="right">
Uptime
<BxHelpLink text="Block Height" term="block-height" />
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{_.map(nodes, row => (
<TableRow key={row.pubkey}>
<TableCell
component="th"
scope="row"
title={JSON.stringify(row, null, 2)}
>
<BxEntityLink validator_id={row.pubkey} />
<br />
<BxEntityLink
prg_id={row.voteAccount && row.voteAccount.votePubkey}
/>
</TableCell>
<TableCell align="right" style={{verticalAlign: 'middle'}}>
{(row.voteAccount && row.voteAccount.stake) || 0} Lamports
</TableCell>
<TableCell align="right">TODO</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
</div>
);
}

render() {
const {nodes} = this.props;

if (nodes) {
return this.renderValidators();
}

return (
<Paper>
<Typography variant="h6" id="tableTitle" style={{textAlign: 'left'}}>
(ERROR - No data.)
</Typography>
</Paper>
);
}
}

Bx2PanelTourDeSolLeaderboard.propTypes = {
nodes: PropTypes.array.isRequired,
supply: PropTypes.number.isRequired,
currentBlock: PropTypes.number.isRequired,
};

export default Bx2PanelTourDeSolLeaderboard;
19 changes: 18 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,23 @@
lodash "^4.17.11"
react-motion "^0.5.2"

"@nivo/bar@^0.59.2":
version "0.59.2"
resolved "https://registry.yarnpkg.com/@nivo/bar/-/bar-0.59.2.tgz#eed30bb20b8090119b36afd3c87cb8edf0726dc7"
integrity sha512-zIjDZ5ekXlC6G+spLHCv3yyW12fZt5HhDWtmgx0zH+3londrM2zKrfvvoJrME6jowJwyZhFZN6ym7aiJAggU9Q==
dependencies:
"@nivo/annotations" "0.59.1"
"@nivo/axes" "0.59.2"
"@nivo/colors" "0.59.0"
"@nivo/core" "0.59.1"
"@nivo/legends" "0.59.1"
"@nivo/tooltip" "0.59.1"
d3-scale "^3.0.0"
d3-shape "^1.2.2"
lodash "^4.17.11"
react-motion "^0.5.2"
recompose "^0.30.0"

"@nivo/[email protected]":
version "0.59.0"
resolved "https://registry.yarnpkg.com/@nivo/colors/-/colors-0.59.0.tgz#326f7941de7387099732143063f657a461bd1dfb"
Expand Down Expand Up @@ -5330,7 +5347,7 @@ d3-scale@^3.0.0:
d3-time "1"
d3-time-format "2"

d3-shape@^1.3.5:
d3-shape@^1.2.2, d3-shape@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.5.tgz#e81aea5940f59f0a79cfccac012232a8987c6033"
integrity sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==
Expand Down

0 comments on commit c6abb10

Please sign in to comment.