2021-07-30 06:26:24 +00:00
|
|
|
import React, { useState, useEffect, useContext, useMemo } from "react";
|
2021-07-29 18:09:28 +00:00
|
|
|
import { ethers } from "ethers";
|
2021-07-30 06:26:24 +00:00
|
|
|
import { Line } from "react-chartjs-2";
|
|
|
|
import { ChartData, ChartOptions } from "chart.js";
|
2021-07-29 18:53:52 +00:00
|
|
|
import { Transition } from "@headlessui/react";
|
2021-07-29 18:09:28 +00:00
|
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
2021-07-30 02:05:23 +00:00
|
|
|
import {
|
|
|
|
faBurn,
|
|
|
|
faCoins,
|
|
|
|
faCube,
|
|
|
|
faGasPump,
|
|
|
|
} from "@fortawesome/free-solid-svg-icons";
|
2021-07-30 07:42:39 +00:00
|
|
|
import BlockRow from "./BlockRow";
|
2021-07-30 07:41:29 +00:00
|
|
|
import { ExtendedBlock, readBlock } from "../../useErigonHooks";
|
|
|
|
import { RuntimeContext } from "../../useRuntime";
|
2021-07-29 18:09:28 +00:00
|
|
|
|
2021-07-29 18:53:52 +00:00
|
|
|
const MAX_BLOCK_HISTORY = 20;
|
2021-07-29 18:09:28 +00:00
|
|
|
|
2021-07-30 06:26:24 +00:00
|
|
|
const options: ChartOptions = {
|
|
|
|
animation: false,
|
|
|
|
plugins: {
|
|
|
|
legend: {
|
|
|
|
display: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
scales: {
|
|
|
|
x: {
|
|
|
|
ticks: {
|
|
|
|
callback: function (v) {
|
|
|
|
// @ts-ignore
|
|
|
|
return ethers.utils.commify(this.getLabelForValue(v));
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
y: {
|
|
|
|
beginAtZero: true,
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: "Burnt fees",
|
|
|
|
},
|
|
|
|
ticks: {
|
|
|
|
callback: (v) => `${v} Gwei`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-07-29 18:09:28 +00:00
|
|
|
type BlocksProps = {
|
|
|
|
latestBlock: ethers.providers.Block;
|
|
|
|
};
|
|
|
|
|
|
|
|
const Blocks: React.FC<BlocksProps> = ({ latestBlock }) => {
|
|
|
|
const { provider } = useContext(RuntimeContext);
|
|
|
|
const [blocks, setBlock] = useState<ExtendedBlock[]>([]);
|
2021-07-30 02:46:59 +00:00
|
|
|
const [now, setNow] = useState<number>(Date.now());
|
2021-07-29 18:09:28 +00:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!provider) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const _readBlock = async () => {
|
|
|
|
const extBlock = await readBlock(provider, latestBlock.number.toString());
|
2021-07-30 02:46:59 +00:00
|
|
|
setNow(Date.now());
|
2021-07-29 18:09:28 +00:00
|
|
|
setBlock((_blocks) => {
|
|
|
|
if (_blocks.length > 0 && latestBlock.number === _blocks[0].number) {
|
|
|
|
return _blocks;
|
|
|
|
}
|
2021-07-30 07:46:39 +00:00
|
|
|
|
|
|
|
// Leave the last block because of transition animation
|
|
|
|
const newBlocks = [extBlock, ..._blocks].slice(
|
|
|
|
0,
|
|
|
|
MAX_BLOCK_HISTORY + 1
|
|
|
|
);
|
|
|
|
|
|
|
|
// Little hack to fix out of order block notifications
|
|
|
|
newBlocks.sort((a, b) => a.number - b.number);
|
|
|
|
return newBlocks;
|
2021-07-29 18:09:28 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
_readBlock();
|
|
|
|
}, [provider, latestBlock]);
|
|
|
|
|
2021-07-30 06:26:24 +00:00
|
|
|
const data: ChartData = useMemo(() => {
|
|
|
|
return {
|
|
|
|
labels: blocks.map((b) => b.number.toString()).reverse(),
|
|
|
|
datasets: [
|
|
|
|
{
|
|
|
|
label: "Burnt fees (Gwei)",
|
|
|
|
data: blocks
|
|
|
|
.map((b) => b.gasUsed.mul(b.baseFeePerGas!).toNumber() / 1e9)
|
|
|
|
.reverse(),
|
|
|
|
fill: true,
|
|
|
|
backgroundColor: "#FDBA74",
|
|
|
|
borderColor: "#F97316",
|
|
|
|
tension: 0.2,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
}, [blocks]);
|
|
|
|
|
2021-07-29 18:09:28 +00:00
|
|
|
return (
|
2021-07-30 01:56:06 +00:00
|
|
|
<div className="w-full mb-auto">
|
2021-07-30 02:38:58 +00:00
|
|
|
<div className="px-9 pt-3 pb-12 divide-y-2">
|
2021-07-30 06:26:24 +00:00
|
|
|
<div>
|
|
|
|
<Line data={data} height={100} options={options} />
|
|
|
|
</div>
|
|
|
|
<div className="mt-5 grid grid-cols-8 px-3 py-2">
|
2021-07-30 02:05:23 +00:00
|
|
|
<div className="flex space-x-1 items-baseline">
|
|
|
|
<span className="text-gray-500">
|
|
|
|
<FontAwesomeIcon icon={faCube} />
|
|
|
|
</span>
|
|
|
|
<span>Block</span>
|
|
|
|
</div>
|
2021-07-29 18:09:28 +00:00
|
|
|
<div className="text-right flex space-x-1 justify-end items-baseline">
|
|
|
|
<span className="text-gray-500">
|
|
|
|
<FontAwesomeIcon icon={faGasPump} />
|
|
|
|
</span>
|
|
|
|
<span>Gas used</span>
|
|
|
|
</div>
|
2021-07-30 02:05:23 +00:00
|
|
|
<div className="text-right">Gas target</div>
|
|
|
|
<div className="text-right">Base fee</div>
|
|
|
|
<div className="text-right col-span-2 flex space-x-1 justify-end items-baseline">
|
|
|
|
<span className="text-yellow-400">
|
|
|
|
<FontAwesomeIcon icon={faCoins} />
|
|
|
|
</span>
|
|
|
|
<span>Rewards</span>
|
|
|
|
</div>
|
2021-07-29 18:09:28 +00:00
|
|
|
<div className="text-right flex space-x-1 justify-end items-baseline">
|
|
|
|
<span className="text-orange-500">
|
|
|
|
<FontAwesomeIcon icon={faBurn} />
|
|
|
|
</span>
|
|
|
|
<span>Burnt fees</span>
|
|
|
|
</div>
|
2021-07-30 02:32:29 +00:00
|
|
|
<div className="text-right">Age</div>
|
2021-07-29 18:09:28 +00:00
|
|
|
</div>
|
2021-07-29 18:53:52 +00:00
|
|
|
{blocks.map((b, i) => (
|
|
|
|
<Transition
|
|
|
|
key={b.hash}
|
|
|
|
show={i < MAX_BLOCK_HISTORY}
|
|
|
|
appear
|
|
|
|
enter="transition transform ease-out duration-500"
|
|
|
|
enterFrom="opacity-0 -translate-y-10"
|
|
|
|
enterTo="opacity-100 translate-y-0"
|
|
|
|
leave="transition transform ease-out duration-1000"
|
|
|
|
leaveFrom="opacity-100 translate-y-0"
|
|
|
|
leaveTo="opacity-0 translate-y-10"
|
|
|
|
>
|
2021-07-30 07:42:39 +00:00
|
|
|
<BlockRow now={now} block={b} />
|
2021-07-29 18:53:52 +00:00
|
|
|
</Transition>
|
2021-07-29 18:09:28 +00:00
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default React.memo(Blocks);
|