diff --git a/src/Block.tsx b/src/Block.tsx index 058ac39..bcffc27 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -1,15 +1,23 @@ import React, { useEffect, useState, useMemo } from "react"; import { useParams, NavLink } from "react-router-dom"; import { ethers, BigNumber } from "ethers"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faChevronLeft, + faChevronRight, +} from "@fortawesome/free-solid-svg-icons"; import { provider } from "./ethersconfig"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; import ContentFrame from "./ContentFrame"; +import NavButton from "./components/NavButton"; import Timestamp from "./components/Timestamp"; import GasValue from "./components/GasValue"; import BlockLink from "./components/BlockLink"; import AddressLink from "./components/AddressLink"; import TransactionValue from "./components/TransactionValue"; +import HexValue from "./components/HexValue"; +import { useLatestBlockNumber } from "./useLatestBlock"; type BlockParams = { blockNumberOrHash: string; @@ -89,6 +97,8 @@ const Block: React.FC = () => { } }, [block]); + const latestBlockNumber = useLatestBlockNumber(); + return ( @@ -100,9 +110,36 @@ const Block: React.FC = () => { {block && ( - - {ethers.utils.commify(block.number)} - +
+ + {ethers.utils.commify(block.number)} + + + + + = latestBlockNumber + } + > + + + = latestBlockNumber + } + > + + + +
@@ -155,16 +192,16 @@ const Block: React.FC = () => { N/A - {block.hash} + - {block.sha3Uncles} + - {block.stateRoot} + {block.nonce} diff --git a/src/Home.tsx b/src/Home.tsx index 7b7a814..82c3cdb 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,9 +1,10 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { NavLink, useHistory } from "react-router-dom"; import { ethers } from "ethers"; import Logo from "./Logo"; import Timestamp from "./components/Timestamp"; -import { provider } from "./ethersconfig"; +import { useLatestBlock } from "./useLatestBlock"; +import { ERIGON_NODE } from "./ethersconfig"; const Home: React.FC = () => { const [search, setSearch] = useState(); @@ -24,29 +25,7 @@ const Home: React.FC = () => { history.push(`/search?q=${search}`); }; - const [latestBlock, setLatestBlock] = useState(); - useEffect(() => { - const readLatestBlock = async () => { - const blockNum = await provider.getBlockNumber(); - const _raw = await provider.send("erigon_getHeaderByNumber", [blockNum]); - const _block = provider.formatter.block(_raw); - setLatestBlock(_block); - }; - readLatestBlock(); - - const listener = async (blockNumber: number) => { - const _raw = await provider.send("erigon_getHeaderByNumber", [ - blockNumber, - ]); - const _block = provider.formatter.block(_raw); - setLatestBlock(_block); - }; - - provider.on("block", listener); - return () => { - provider.removeListener("block", listener); - }; - }, []); + const latestBlock = useLatestBlock(); document.title = "Home | Otterscan"; @@ -85,6 +64,9 @@ const Home: React.FC = () => { )} + + Using Erigon node at {ERIGON_NODE} + diff --git a/src/components/HexValue.tsx b/src/components/HexValue.tsx new file mode 100644 index 0000000..3b62fcf --- /dev/null +++ b/src/components/HexValue.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +type HexValueProps = { + value: string; +}; + +const HexValue: React.FC = ({ value }) => { + const shards: string[] = [value.slice(0, 10)]; + for (let i = 10; i < value.length; i += 8) { + shards.push(value.slice(i, i + 8)); + } + + return ( + <> + {shards.map((s, i) => ( + + {s} + + ))} + + ); +}; + +export default React.memo(HexValue); diff --git a/src/components/NavButton.tsx b/src/components/NavButton.tsx new file mode 100644 index 0000000..a9c1a9d --- /dev/null +++ b/src/components/NavButton.tsx @@ -0,0 +1,31 @@ +import { NavLink } from "react-router-dom"; + +type NavButtonProps = { + blockNum: number; + disabled?: boolean; +}; + +const NavButton: React.FC = ({ + blockNum, + disabled, + children, +}) => { + if (disabled) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +export default NavButton; diff --git a/src/ethersconfig.ts b/src/ethersconfig.ts index e0a9fd5..6b24d6d 100644 --- a/src/ethersconfig.ts +++ b/src/ethersconfig.ts @@ -1,6 +1,8 @@ import { ethers } from "ethers"; +export const ERIGON_NODE = "http://127.0.0.1:8545"; + export const provider = new ethers.providers.JsonRpcProvider( - "http://127.0.0.1:8545", + ERIGON_NODE, "mainnet" ); diff --git a/src/useLatestBlock.ts b/src/useLatestBlock.ts new file mode 100644 index 0000000..fba4011 --- /dev/null +++ b/src/useLatestBlock.ts @@ -0,0 +1,55 @@ +import { useState, useEffect } from "react"; +import { ethers } from "ethers"; +import { provider } from "./ethersconfig"; + +export const useLatestBlock = () => { + const [latestBlock, setLatestBlock] = useState(); + + useEffect(() => { + const readLatestBlock = async () => { + const blockNum = await provider.getBlockNumber(); + const _raw = await provider.send("erigon_getHeaderByNumber", [blockNum]); + const _block = provider.formatter.block(_raw); + setLatestBlock(_block); + }; + readLatestBlock(); + + const listener = async (blockNumber: number) => { + const _raw = await provider.send("erigon_getHeaderByNumber", [ + blockNumber, + ]); + const _block = provider.formatter.block(_raw); + setLatestBlock(_block); + }; + + provider.on("block", listener); + return () => { + provider.removeListener("block", listener); + }; + }, []); + + return latestBlock; +}; + +export const useLatestBlockNumber = () => { + const [latestBlock, setLatestBlock] = useState(); + + useEffect(() => { + const readLatestBlock = async () => { + const blockNum = await provider.getBlockNumber(); + setLatestBlock(blockNum); + }; + readLatestBlock(); + + const listener = async (blockNumber: number) => { + setLatestBlock(blockNumber); + }; + + provider.on("block", listener); + return () => { + provider.removeListener("block", listener); + }; + }, []); + + return latestBlock; +};