diff --git a/src/Home.tsx b/src/Home.tsx index 0509330..474c3d4 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -7,7 +7,7 @@ import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; import Logo from "./Logo"; import Timestamp from "./components/Timestamp"; import { RuntimeContext } from "./useRuntime"; -import { useLatestBlock } from "./useLatestBlock"; +import { useLatestBlockHeader } from "./useLatestBlock"; import { blockURL } from "./url"; import { useGenericSearch } from "./search/search"; @@ -17,7 +17,7 @@ const Home: React.FC = () => { const { provider } = useContext(RuntimeContext); const [searchRef, handleChange, handleSubmit] = useGenericSearch(); - const latestBlock = useLatestBlock(provider); + const latestBlock = useLatestBlockHeader(provider); const [isScanning, setScanning] = useState(false); document.title = "Home | Otterscan"; diff --git a/src/PriceBox.tsx b/src/PriceBox.tsx index 1e2586a..60b0903 100644 --- a/src/PriceBox.tsx +++ b/src/PriceBox.tsx @@ -6,7 +6,7 @@ import { faGasPump } from "@fortawesome/free-solid-svg-icons/faGasPump"; import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Interface.json"; import { RuntimeContext } from "./useRuntime"; import { formatValue } from "./components/formatter"; -import { useLatestBlock } from "./useLatestBlock"; +import { useLatestBlockHeader } from "./useLatestBlock"; import { useChainInfo } from "./useChainInfo"; const ETH_FEED_DECIMALS = 8; @@ -17,7 +17,7 @@ const PriceBox: React.FC = () => { const { nativeCurrency: { symbol }, } = useChainInfo(); - const latestBlock = useLatestBlock(provider); + const latestBlock = useLatestBlockHeader(provider); const maybeOutdated: boolean = latestBlock !== undefined && diff --git a/src/special/london/London.tsx b/src/special/london/London.tsx index 60e22f2..369d215 100644 --- a/src/special/london/London.tsx +++ b/src/special/london/London.tsx @@ -1,5 +1,5 @@ import React, { useContext } from "react"; -import { useLatestBlock } from "../../useLatestBlock"; +import { useLatestBlockHeader } from "../../useLatestBlock"; import { RuntimeContext } from "../../useRuntime"; import Countdown from "./Countdown"; import Blocks from "./Blocks"; @@ -7,7 +7,7 @@ import { londonBlockNumber } from "./params"; const London: React.FC = () => { const { provider } = useContext(RuntimeContext); - const block = useLatestBlock(provider); + const block = useLatestBlockHeader(provider); if (!provider || !block) { return
; } diff --git a/src/useLatestBlock.ts b/src/useLatestBlock.ts index ba5e21a..ef26cde 100644 --- a/src/useLatestBlock.ts +++ b/src/useLatestBlock.ts @@ -2,7 +2,12 @@ import { useState, useEffect } from "react"; import { Block } from "@ethersproject/abstract-provider"; import { JsonRpcProvider } from "@ethersproject/providers"; -export const useLatestBlock = (provider?: JsonRpcProvider) => { +/** + * Returns the latest block header AND hook an internal listener + * that'll update and trigger a component render as a side effect + * every time it is notified of a new block by the web3 provider. + */ +export const useLatestBlockHeader = (provider?: JsonRpcProvider) => { const [latestBlock, setLatestBlock] = useState(); useEffect(() => { @@ -10,16 +15,7 @@ export const useLatestBlock = (provider?: JsonRpcProvider) => { return; } - // TODO: remove duplicated code - 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 getAndSetBlockHeader = async (blockNumber: number) => { const _raw = await provider.send("erigon_getHeaderByNumber", [ blockNumber, ]); @@ -27,9 +23,18 @@ export const useLatestBlock = (provider?: JsonRpcProvider) => { setLatestBlock(_block); }; - provider.on("block", listener); + // Immediately read and set the latest block header + const readLatestBlock = async () => { + const blockNum = await provider.getBlockNumber(); + await getAndSetBlockHeader(blockNum); + }; + readLatestBlock(); + + // Hook a listener that'll update the latest block header + // every time it is notified of a new block + provider.on("block", getAndSetBlockHeader); return () => { - provider.removeListener("block", listener); + provider.removeListener("block", getAndSetBlockHeader); }; }, [provider]); @@ -40,6 +45,8 @@ export const useLatestBlock = (provider?: JsonRpcProvider) => { * Returns the latest block number AND hook an internal listener * that'll update and trigger a component render as a side effect * every time it is notified of a new block by the web3 provider. + * + * This hook is cheaper than useLatestBlockHeader. */ export const useLatestBlockNumber = (provider?: JsonRpcProvider) => { const [latestBlock, setLatestBlock] = useState();