2021-07-26 22:59:07 +00:00
|
|
|
import React, { useEffect, useMemo, useContext } from "react";
|
2021-07-01 18:21:40 +00:00
|
|
|
import { useParams, NavLink } from "react-router-dom";
|
2021-07-26 23:46:11 +00:00
|
|
|
import { BigNumber, ethers } from "ethers";
|
2021-07-29 00:59:21 +00:00
|
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
2021-08-08 06:51:21 +00:00
|
|
|
import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn";
|
2021-07-01 18:21:40 +00:00
|
|
|
import StandardFrame from "./StandardFrame";
|
|
|
|
import StandardSubtitle from "./StandardSubtitle";
|
2021-07-23 22:46:21 +00:00
|
|
|
import NavBlock from "./block/NavBlock";
|
2021-07-01 18:21:40 +00:00
|
|
|
import ContentFrame from "./ContentFrame";
|
2021-07-28 07:24:48 +00:00
|
|
|
import InfoRow from "./components/InfoRow";
|
2021-07-01 18:21:40 +00:00
|
|
|
import Timestamp from "./components/Timestamp";
|
|
|
|
import GasValue from "./components/GasValue";
|
2021-07-28 07:40:38 +00:00
|
|
|
import PercentageBar from "./components/PercentageBar";
|
2021-07-01 18:21:40 +00:00
|
|
|
import BlockLink from "./components/BlockLink";
|
2021-07-19 03:38:38 +00:00
|
|
|
import DecoratedAddressLink from "./components/DecoratedAddressLink";
|
2021-07-03 21:51:57 +00:00
|
|
|
import TransactionValue from "./components/TransactionValue";
|
2021-07-26 23:46:11 +00:00
|
|
|
import FormattedBalance from "./components/FormattedBalance";
|
2021-07-03 22:40:47 +00:00
|
|
|
import HexValue from "./components/HexValue";
|
2021-07-09 05:07:20 +00:00
|
|
|
import { RuntimeContext } from "./useRuntime";
|
2021-07-04 01:42:06 +00:00
|
|
|
import { useLatestBlockNumber } from "./useLatestBlock";
|
2021-07-23 22:46:21 +00:00
|
|
|
import { blockTxsURL } from "./url";
|
2021-07-26 22:59:07 +00:00
|
|
|
import { useBlockData } from "./useErigonHooks";
|
2021-07-01 18:21:40 +00:00
|
|
|
|
|
|
|
type BlockParams = {
|
|
|
|
blockNumberOrHash: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
const Block: React.FC = () => {
|
2021-07-09 05:07:20 +00:00
|
|
|
const { provider } = useContext(RuntimeContext);
|
2021-07-01 18:21:40 +00:00
|
|
|
const params = useParams<BlockParams>();
|
|
|
|
|
2021-07-26 22:59:07 +00:00
|
|
|
const block = useBlockData(provider, params.blockNumberOrHash);
|
2021-07-01 18:21:40 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (block) {
|
|
|
|
document.title = `Block #${block.number} | Otterscan`;
|
|
|
|
}
|
|
|
|
}, [block]);
|
|
|
|
|
|
|
|
const extraStr = useMemo(() => {
|
|
|
|
try {
|
|
|
|
return block && ethers.utils.toUtf8String(block.extraData);
|
|
|
|
} catch (err) {
|
2021-07-03 22:15:22 +00:00
|
|
|
console.error("Error while converting block extra data to string");
|
2021-07-01 18:21:40 +00:00
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
}, [block]);
|
2021-07-29 00:59:21 +00:00
|
|
|
const burntFees =
|
2021-07-26 23:46:11 +00:00
|
|
|
block?.baseFeePerGas && block.baseFeePerGas.mul(block.gasUsed);
|
2021-07-29 00:59:21 +00:00
|
|
|
const netFeeReward = block && block.feeReward.sub(burntFees ?? 0);
|
2021-07-28 07:24:48 +00:00
|
|
|
const gasUsedPerc =
|
|
|
|
block && block.gasUsed.mul(10000).div(block.gasLimit).toNumber() / 100;
|
2021-07-01 18:21:40 +00:00
|
|
|
|
2021-07-08 19:02:42 +00:00
|
|
|
const latestBlockNumber = useLatestBlockNumber(provider);
|
2021-07-04 01:42:06 +00:00
|
|
|
|
2021-07-01 18:21:40 +00:00
|
|
|
return (
|
|
|
|
<StandardFrame>
|
|
|
|
<StandardSubtitle>
|
2021-07-23 22:20:49 +00:00
|
|
|
<div className="flex space-x-1 items-baseline">
|
|
|
|
<span>Block</span>
|
|
|
|
<span className="text-base text-gray-500">
|
|
|
|
#{params.blockNumberOrHash}
|
|
|
|
</span>
|
|
|
|
{block && (
|
2021-07-23 22:46:21 +00:00
|
|
|
<NavBlock
|
|
|
|
blockNumber={block.number}
|
|
|
|
latestBlockNumber={latestBlockNumber}
|
|
|
|
/>
|
2021-07-23 22:20:49 +00:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</StandardSubtitle>
|
|
|
|
{block && (
|
|
|
|
<ContentFrame>
|
|
|
|
<InfoRow title="Block Height">
|
|
|
|
<span className="font-bold">
|
|
|
|
{ethers.utils.commify(block.number)}
|
|
|
|
</span>
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Timestamp">
|
|
|
|
<Timestamp value={block.timestamp} />
|
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Transactions">
|
|
|
|
<NavLink
|
|
|
|
className="bg-link-blue bg-opacity-10 text-link-blue hover:bg-opacity-100 hover:text-white rounded-lg px-2 py-1 text-xs"
|
2021-07-23 22:46:21 +00:00
|
|
|
to={blockTxsURL(block.number)}
|
2021-07-01 18:21:40 +00:00
|
|
|
>
|
2021-08-02 18:43:37 +00:00
|
|
|
{block.transactionCount} transactions
|
2021-07-01 18:21:40 +00:00
|
|
|
</NavLink>{" "}
|
|
|
|
in this block
|
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Mined by">
|
2021-07-19 03:38:38 +00:00
|
|
|
<DecoratedAddressLink address={block.miner} miner />
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
2021-07-03 21:51:57 +00:00
|
|
|
<InfoRow title="Block Reward">
|
2021-07-26 23:46:11 +00:00
|
|
|
<TransactionValue
|
|
|
|
value={block.blockReward.add(netFeeReward ?? 0)}
|
|
|
|
/>
|
2021-07-03 22:14:03 +00:00
|
|
|
{!block.feeReward.isZero() && (
|
|
|
|
<>
|
|
|
|
{" "}
|
|
|
|
(<TransactionValue value={block.blockReward} hideUnit /> +{" "}
|
2021-07-26 23:46:11 +00:00
|
|
|
<TransactionValue
|
|
|
|
value={netFeeReward ?? BigNumber.from(0)}
|
|
|
|
hideUnit
|
|
|
|
/>
|
|
|
|
)
|
2021-07-03 22:14:03 +00:00
|
|
|
</>
|
|
|
|
)}
|
2021-07-03 21:51:57 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Uncles Reward">
|
|
|
|
<TransactionValue value={block.unclesReward} />
|
|
|
|
</InfoRow>
|
2021-07-01 18:21:40 +00:00
|
|
|
<InfoRow title="Size">
|
|
|
|
{ethers.utils.commify(block.size)} bytes
|
|
|
|
</InfoRow>
|
2021-07-26 23:46:11 +00:00
|
|
|
{block.baseFeePerGas && (
|
|
|
|
<InfoRow title="Base Fee">
|
|
|
|
<span>
|
|
|
|
<FormattedBalance value={block.baseFeePerGas} decimals={9} />{" "}
|
|
|
|
Gwei (
|
|
|
|
<FormattedBalance
|
|
|
|
value={block.baseFeePerGas}
|
|
|
|
decimals={0}
|
|
|
|
/>{" "}
|
|
|
|
wei)
|
|
|
|
</span>
|
|
|
|
</InfoRow>
|
|
|
|
)}
|
2021-07-29 00:59:21 +00:00
|
|
|
{burntFees && (
|
|
|
|
<InfoRow title="Burnt Fees">
|
|
|
|
<div className="flex items-baseline space-x-1">
|
|
|
|
<span className="flex space-x-1 text-orange-500">
|
|
|
|
<span title="Burnt fees">
|
|
|
|
<FontAwesomeIcon icon={faBurn} size="1x" />
|
|
|
|
</span>
|
|
|
|
<span>
|
|
|
|
<span className="line-through">
|
|
|
|
<FormattedBalance value={burntFees} />
|
|
|
|
</span>{" "}
|
|
|
|
Ether
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</div>
|
2021-07-26 23:46:11 +00:00
|
|
|
</InfoRow>
|
|
|
|
)}
|
2021-07-28 07:24:48 +00:00
|
|
|
<InfoRow title="Gas Used/Limit">
|
|
|
|
<div className="flex space-x-3 items-baseline">
|
|
|
|
<div>
|
|
|
|
<GasValue value={block.gasUsed} /> /{" "}
|
|
|
|
<GasValue value={block.gasLimit} />
|
|
|
|
</div>
|
2021-07-28 07:40:38 +00:00
|
|
|
<PercentageBar perc={gasUsedPerc!} />
|
2021-07-28 07:24:48 +00:00
|
|
|
</div>
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Extra Data">
|
|
|
|
{extraStr} (Hex:{" "}
|
|
|
|
<span className="font-data">{block.extraData}</span>)
|
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Ether Price">N/A</InfoRow>
|
2021-07-28 07:27:08 +00:00
|
|
|
<InfoRow title="Difficult">
|
|
|
|
{ethers.utils.commify(block.difficulty)}
|
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Total Difficult">
|
|
|
|
{ethers.utils.commify(block.totalDifficulty.toString())}
|
|
|
|
</InfoRow>
|
2021-07-01 18:21:40 +00:00
|
|
|
<InfoRow title="Hash">
|
2021-07-04 01:33:34 +00:00
|
|
|
<HexValue value={block.hash} />
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Parent Hash">
|
|
|
|
<BlockLink blockTag={block.parentHash} />
|
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Sha3Uncles">
|
2021-07-03 22:40:47 +00:00
|
|
|
<HexValue value={block.sha3Uncles} />
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="StateRoot">
|
2021-07-03 22:40:47 +00:00
|
|
|
<HexValue value={block.stateRoot} />
|
2021-07-01 18:21:40 +00:00
|
|
|
</InfoRow>
|
|
|
|
<InfoRow title="Nonce">
|
|
|
|
<span className="font-data">{block.nonce}</span>
|
|
|
|
</InfoRow>
|
|
|
|
</ContentFrame>
|
|
|
|
)}
|
|
|
|
</StandardFrame>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default React.memo(Block);
|