Skip to content
This repository has been archived by the owner on Feb 27, 2021. It is now read-only.

fix: add miner stats pagination by block range #232

Merged
merged 1 commit into from
Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ function App(props: any) {
useEffect(() => {
if (selectedNetwork && selectedNetwork.name !== query.network) {
setQuery({ network: selectedNetwork.name });
history.push({
pathname: history.location.pathname,
search: `?network=${selectedNetwork.name}`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this work if there are other parameters in the search pattern of the URI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, thanks. Maybe the supported params should be parts of a config object and standardized/globalized then too, toward fewer magic strings.

Would suggest new ticket for it.

Copy link
Member

@meowsbits meowsbits Jan 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... Or modify the handrolled History logic to use either a library (there must be one...?) and/or/thereby support arbitrary URI path/parameter/hash updates. So that this feature itself becomes some background "just works" magic.

});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedNetwork, setQuery]);
Expand Down Expand Up @@ -255,6 +259,7 @@ function App(props: any) {
<Switch>
<Route path={"/"} component={Dashboard} exact={true} />
<Route path={"/stats/miners"} component={MinerStatsPage} exact={true} />
<Route path={"/stats/miners/:block"} component={MinerStatsPage} />
<Route path={"/block/:hash/raw"} component={BlockRawContainer} />
<Route path={"/block/:hash"} component={Block} />
<Route path={"/blocks/:number"} component={NodeView} />
Expand Down
36 changes: 24 additions & 12 deletions src/components/BlockList/BlockList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Table, TableBody, TableCell, TableHead, TableRow, Typography, LinearProgress } from "@material-ui/core";
import { Table, TableBody, TableCell, TableHead, TableRow, Typography, LinearProgress, Tooltip } from "@material-ui/core";
import * as React from "react";
import Link from "@material-ui/core/Link";
import { hexToDate, hexToNumber, hexToString } from "@etclabscore/eserialize";
Expand Down Expand Up @@ -60,29 +60,41 @@ function BlockList({ blocks }: any) {
}

// Calculate difference of block timestamp from that of parent.
const timeDifferenceFromParent = (index === sortedBlocks.length-1) ? 0 : hexToNumber(b.timestamp) - hexToNumber(sortedBlocks[index+1].timestamp);
const timeDifferenceFromParent = (index === sortedBlocks.length - 1) ? 0 : hexToNumber(b.timestamp) - hexToNumber(sortedBlocks[index + 1].timestamp);

return (
<TableRow key={b.number} style={authorHashStyle}>
<TableCell style={rightPaddingFix}>
<Typography>
<Link
<Typography>
<Link
component={({ className, children }: { children: any, className: string }) => (
<RouterLink className={className} to={`/address/${b.miner}`} >
{children}
</RouterLink>
)}>
{authorHashShort}
</Link>
&nbsp;<sup>{hexToString(b.extraData).substring(0, 20)}</sup>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually we might want to refactor this address/+extradata format out to a configurable/standard, eg. substring length, abbreviations, sanitization, ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. lets make a ticket for that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

</Typography>
</TableCell>
<TableCell component="th" scope="row">
<Link
component={({ className, children }: { children: any, className: string }) => (
<RouterLink className={className} to={`/address/${b.miner}`} >
<RouterLink className={className} to={`/block/${b.hash}`} >
{children}
</RouterLink>
)}>
{authorHashShort}
{parseInt(b.number, 16)}
</Link>
&nbsp;<sup>{hexToString(b.extraData).substring(0,20)}</sup>
</Typography>
</TableCell>
<TableCell component="th" scope="row"><Typography>{parseInt(b.number, 16)}</Typography></TableCell>
<TableCell style={rightPaddingFix}>
<Typography>{t("Timestamp Date", { date: hexToDate(b.timestamp) })}&nbsp;<sub>({+timeDifferenceFromParent > 0 ? `+${timeDifferenceFromParent}` : `-${timeDifferenceFromParent}`}s)</sub></Typography>
<Typography>{t("Timestamp Date", { date: hexToDate(b.timestamp) })}&nbsp;<sub>({timeDifferenceFromParent > 0 ? `+${timeDifferenceFromParent}` : `-${timeDifferenceFromParent}`}s)</sub></Typography>
</TableCell>
<TableCell style={rightPaddingFix}>
<Typography><sub>{txTypes.transact}</sub><sup>{txTypes.create === 0 ? "" : txTypes.create}</sup></Typography>
<Tooltip title={t("Create Transactions", {count: txTypes.create})} placement="top">
<Typography variant="caption" color="textSecondary">{txTypes.create === 0 ? "" : txTypes.create}</Typography>
</Tooltip>
<Typography>{txTypes.transact}</Typography>
</TableCell>
<TableCell style={rightPaddingFix}>
<LinearProgress value={filledPercent} variant="determinate" />
Expand All @@ -91,7 +103,7 @@ function BlockList({ blocks }: any) {
<Typography>{hexToNumber(b.gasLimit)}</Typography>
</TableCell>
<TableCell>
<Typography>{b.uncles.length === 0 ? '' : b.uncles.length}</Typography>
<Typography>{b.uncles.length === 0 ? "" : b.uncles.length}</Typography>
</TableCell>
<TableCell style={rightPaddingFix}>
<Link
Expand Down
35 changes: 35 additions & 0 deletions src/components/BlockPagination/BlockPagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

import React from "react";
import { Grid, IconButton, Typography } from "@material-ui/core";
import { ArrowForwardIos, ArrowBackIos } from "@material-ui/icons";

interface IProps {
from: number;
to: number;
disableNext?: boolean;
disablePrev?: boolean;
onNext?: () => void;
onPrev?: () => void;
style?: any;
}

const BlockPagination: React.FC<IProps> = (props) => {

return (
<Grid container>
<Grid container justify="flex-end">
<IconButton onClick={props.onPrev} disabled={props.disablePrev}>
<ArrowBackIos />
</IconButton>
<IconButton onClick={props.onNext} disabled={props.disableNext}>
<ArrowForwardIos />
</IconButton>
</Grid>
<Grid container justify="flex-end">
<Typography>Showing {(props.to - props.from) + 1} Block Range: <b>{props.to}</b> - {props.from}</Typography>
</Grid>
</Grid>
);
};

export default BlockPagination;
2 changes: 2 additions & 0 deletions src/components/BlockPagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import BlockPagination from "./BlockPagination";
export default BlockPagination;
4 changes: 2 additions & 2 deletions src/components/MinerStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const MinerStats: React.FC<IProps> = ({blocks}) => {
return (
<Grid container justify="space-evenly">
<Grid key="uncles" item xs={12} md={4} lg={4}>
<ChartCard title={t("Top Miners last blocks by address", { count: config.blockHistoryLength })}>
<ChartCard title={t("Miners by address")}>
<VictoryPie
cornerRadius={1}
// innerRadius={50}
Expand Down Expand Up @@ -82,7 +82,7 @@ const MinerStats: React.FC<IProps> = ({blocks}) => {
</ChartCard>
</Grid>
<Grid key="uncles" item xs={12} md={3} lg={3}>
<ChartCard title={t("Top Miners last blocks by extraData", { count: config.blockHistoryLength })}>
<ChartCard title={t("Miners by extraData", { count: config.blockHistoryLength })}>
<VictoryPie
colorScale="cool"
labelComponent={<CustomPieChartLabel />}
Expand Down
86 changes: 86 additions & 0 deletions src/components/StatCharts/StatCharts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from "react";
import BigNumber from "bignumber.js";
import { hashesToGH } from "../formatters";
import { hexToNumber } from "@etclabscore/eserialize";
import { Grid } from "@material-ui/core";
import ChartCard from "../ChartCard";
import { VictoryLine, VictoryBar, VictoryChart } from "victory";
import { useTranslation } from "react-i18next";

const config = {
blockTime: 15, // seconds
blockHistoryLength: 100,
chartHeight: 200,
chartWidth: 400,
};

const blockMapGasUsed = (block: any) => {
return {
x: hexToNumber(block.number),
y: new BigNumber(block.gasUsed).dividedBy(1000000),
};
};

const blockMapUncles = (block: any) => {
return {
x: hexToNumber(block.number),
y: block.uncles.length,
};
};

const blockMapHashRate = (block: any) => {
return {
x: hexToNumber(block.number),
y: hashesToGH(new BigNumber(block.difficulty, 16).dividedBy(config.blockTime)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm.. Using a hardcoded block time is a liiiitleee stretchy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea would be nice to calculate the block time for the list of blocks you are looking at. maybe a helper getBlockTimeFromBlocks(blocks)

};
};

const blockMapTransactionCount = (block: any) => {
return {
x: hexToNumber(block.number),
y: block.transactions.length,
};
};

interface IProps {
blocks: any[];
victoryTheme?: any;
}

const StatCharts: React.FC<IProps> = ({ blocks, victoryTheme }) => {
const { t } = useTranslation();
return (
<Grid item container>
<Grid key="hashChart" item xs={12} md={6} lg={3}>
<ChartCard title={t("Hash Rate")}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryLine data={blocks.map(blockMapHashRate)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="txChart" item xs={12} md={6} lg={3}>
<ChartCard title={t("Transaction count")}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapTransactionCount)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="gasUsed" item xs={12} md={6} lg={3}>
<ChartCard title={t("Gas Used")}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapGasUsed)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="uncles" item xs={12} md={6} lg={3}>
<ChartCard title={t("Uncles")}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapUncles)} />
</VictoryChart>
</ChartCard>
</Grid>
</Grid>
);
};

export default StatCharts;
2 changes: 2 additions & 0 deletions src/components/StatCharts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import StatCharts from "./StatCharts";
export default StatCharts;
64 changes: 3 additions & 61 deletions src/containers/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Grid, Typography, CircularProgress, Theme, Button } from "@material-ui/core";
import useMultiGethStore from "../stores/useMultiGethStore";
import BigNumber from "bignumber.js";
import * as React from "react";
import { VictoryBar, VictoryChart, VictoryLine } from "victory";
import { hashesToGH, weiToGwei } from "../components/formatters";
import { weiToGwei } from "../components/formatters";
import HashRate from "../components/HashRate";
import getBlocks, { useBlockNumber } from "../helpers";
import useInterval from "use-interval";
Expand All @@ -15,6 +13,7 @@ import { hexToNumber } from "@etclabscore/eserialize";
import EthereumJSONRPC from "@etclabscore/ethereum-json-rpc";
import { useTranslation } from "react-i18next";
import { ArrowForwardIos } from "@material-ui/icons";
import StatCharts from "../components/StatCharts";

const useState = React.useState;

Expand All @@ -25,34 +24,6 @@ const config = {
chartWidth: 400,
};

const blockMapGasUsed = (block: any) => {
return {
x: hexToNumber(block.number),
y: new BigNumber(block.gasUsed).dividedBy(1000000),
};
};

const blockMapUncles = (block: any) => {
return {
x: hexToNumber(block.number),
y: block.uncles.length,
};
};

const blockMapHashRate = (block: any) => {
return {
x: hexToNumber(block.number),
y: hashesToGH(new BigNumber(block.difficulty, 16).dividedBy(config.blockTime)),
};
};

const blockMapTransactionCount = (block: any) => {
return {
x: hexToNumber(block.number),
y: block.transactions.length,
};
};

export default (props: any) => {
const [erpc]: [EthereumJSONRPC] = useMultiGethStore();
const theme = useTheme<Theme>();
Expand Down Expand Up @@ -166,37 +137,8 @@ export default (props: any) => {
</ChartCard>
</Grid>
</Grid>
<Grid item container>
<Grid key="hashChart" item xs={12} md={6} lg={3}>
<ChartCard title={t("Hash Rate last blocks", { count: config.blockHistoryLength })}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryLine data={blocks.map(blockMapHashRate)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="txChart" item xs={12} md={6} lg={3}>
<ChartCard title={t("Transaction count last blocks", { count: config.blockHistoryLength })}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapTransactionCount)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="gasUsed" item xs={12} md={6} lg={3}>
<ChartCard title={t("Gas Used last blocks", { count: config.blockHistoryLength })}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapGasUsed)} />
</VictoryChart>
</ChartCard>
</Grid>
<Grid key="uncles" item xs={12} md={6} lg={3}>
<ChartCard title={t("Uncles last blocks", { count: config.blockHistoryLength })}>
<VictoryChart height={config.chartHeight} width={config.chartWidth} theme={victoryTheme as any}>
<VictoryBar data={blocks.map(blockMapUncles)} />
</VictoryChart>
</ChartCard>
</Grid>
</Grid>
</Grid>
<StatCharts victoryTheme={victoryTheme} blocks={blocks} />
<Grid container justify="flex-end">
<Button
color="primary"
Expand Down
Loading