Parameterize erigon node url

This commit is contained in:
Willian Mitsuda 2021-07-08 16:02:42 -03:00
parent 3e58030a43
commit da16ce8ad6
13 changed files with 216 additions and 86 deletions

3
public/config.json Normal file
View File

@ -0,0 +1,3 @@
{
"erigonURL": "http://localhost:8545"
}

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useMemo, useContext } from "react";
import { useParams, useLocation, useHistory } from "react-router-dom"; import { useParams, useLocation, useHistory } from "react-router-dom";
import { ethers } from "ethers"; import { ethers } from "ethers";
import queryString from "query-string"; import queryString from "query-string";
@ -12,9 +12,9 @@ import ResultHeader from "./search/ResultHeader";
import PendingResults from "./search/PendingResults"; import PendingResults from "./search/PendingResults";
import TransactionItem from "./search/TransactionItem"; import TransactionItem from "./search/TransactionItem";
import { SearchController } from "./search/search"; import { SearchController } from "./search/search";
import { ProviderContext } from "./useProvider";
import { useENSCache } from "./useReverseCache"; import { useENSCache } from "./useReverseCache";
import { useFeeToggler } from "./search/useFeeToggler"; import { useFeeToggler } from "./search/useFeeToggler";
import { provider } from "./ethersconfig";
type BlockParams = { type BlockParams = {
addressOrName: string; addressOrName: string;
@ -26,6 +26,7 @@ type PageParams = {
}; };
const AddressTransactions: React.FC = () => { const AddressTransactions: React.FC = () => {
const provider = useContext(ProviderContext);
const params = useParams<BlockParams>(); const params = useParams<BlockParams>();
const location = useLocation<PageParams>(); const location = useLocation<PageParams>();
const history = useHistory(); const history = useHistory();
@ -59,6 +60,9 @@ const AddressTransactions: React.FC = () => {
return; return;
} }
if (!provider) {
return;
}
const resolveName = async () => { const resolveName = async () => {
const resolvedAddress = await provider.resolveName(params.addressOrName); const resolvedAddress = await provider.resolveName(params.addressOrName);
if (resolvedAddress !== null) { if (resolvedAddress !== null) {
@ -72,20 +76,30 @@ const AddressTransactions: React.FC = () => {
} }
}; };
resolveName(); resolveName();
}, [params.addressOrName, history, params.direction, location.search]); }, [
provider,
params.addressOrName,
history,
params.direction,
location.search,
]);
const [controller, setController] = useState<SearchController>(); const [controller, setController] = useState<SearchController>();
useEffect(() => { useEffect(() => {
if (!checksummedAddress) { if (!provider || !checksummedAddress) {
return; return;
} }
const readFirstPage = async () => { const readFirstPage = async () => {
const _controller = await SearchController.firstPage(checksummedAddress); const _controller = await SearchController.firstPage(
provider,
checksummedAddress
);
setController(_controller); setController(_controller);
}; };
const readMiddlePage = async (next: boolean) => { const readMiddlePage = async (next: boolean) => {
const _controller = await SearchController.middlePage( const _controller = await SearchController.middlePage(
provider,
checksummedAddress, checksummedAddress,
hash!, hash!,
next next
@ -93,15 +107,18 @@ const AddressTransactions: React.FC = () => {
setController(_controller); setController(_controller);
}; };
const readLastPage = async () => { const readLastPage = async () => {
const _controller = await SearchController.lastPage(checksummedAddress); const _controller = await SearchController.lastPage(
provider,
checksummedAddress
);
setController(_controller); setController(_controller);
}; };
const prevPage = async () => { const prevPage = async () => {
const _controller = await controller!.prevPage(hash!); const _controller = await controller!.prevPage(provider, hash!);
setController(_controller); setController(_controller);
}; };
const nextPage = async () => { const nextPage = async () => {
const _controller = await controller!.nextPage(hash!); const _controller = await controller!.nextPage(provider, hash!);
setController(_controller); setController(_controller);
}; };
@ -127,10 +144,10 @@ const AddressTransactions: React.FC = () => {
readLastPage(); readLastPage();
} }
} }
}, [checksummedAddress, params.direction, hash, controller]); }, [provider, checksummedAddress, params.direction, hash, controller]);
const page = useMemo(() => controller?.getPage(), [controller]); const page = useMemo(() => controller?.getPage(), [controller]);
const reverseCache = useENSCache(page); const reverseCache = useENSCache(provider, page);
document.title = `Address ${params.addressOrName} | Otterscan`; document.title = `Address ${params.addressOrName} | Otterscan`;

View File

@ -3,40 +3,47 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Home from "./Home"; import Home from "./Home";
import Search from "./Search"; import Search from "./Search";
import Title from "./Title"; import Title from "./Title";
import { useProvider, ProviderContext } from "./useProvider";
const Block = React.lazy(() => import("./Block")); const Block = React.lazy(() => import("./Block"));
const BlockTransactions = React.lazy(() => import("./BlockTransactions")); const BlockTransactions = React.lazy(() => import("./BlockTransactions"));
const AddressTransactions = React.lazy(() => import("./AddressTransactions")); const AddressTransactions = React.lazy(() => import("./AddressTransactions"));
const Transaction = React.lazy(() => import("./Transaction")); const Transaction = React.lazy(() => import("./Transaction"));
const App = () => ( const App = () => {
<Suspense fallback={<>LOADING</>}> const provider = useProvider();
<Router>
<Switch> return (
<Route path="/" exact> <Suspense fallback={<>LOADING</>}>
<Home /> <ProviderContext.Provider value={provider}>
</Route> <Router>
<Route path="/search" exact> <Switch>
<Search /> <Route path="/" exact>
</Route> <Home />
<Route> </Route>
<Title /> <Route path="/search" exact>
<Route path="/block/:blockNumberOrHash" exact> <Search />
<Block /> </Route>
</Route> <Route>
<Route path="/block/:blockNumber/txs" exact> <Title />
<BlockTransactions /> <Route path="/block/:blockNumberOrHash" exact>
</Route> <Block />
<Route path="/tx/:txhash"> </Route>
<Transaction /> <Route path="/block/:blockNumber/txs" exact>
</Route> <BlockTransactions />
<Route path="/address/:addressOrName/:direction?"> </Route>
<AddressTransactions /> <Route path="/tx/:txhash">
</Route> <Transaction />
</Route> </Route>
</Switch> <Route path="/address/:addressOrName/:direction?">
</Router> <AddressTransactions />
</Suspense> </Route>
); </Route>
</Switch>
</Router>
</ProviderContext.Provider>
</Suspense>
);
};
export default React.memo(App); export default React.memo(App);

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState, useMemo } from "react"; import React, { useEffect, useState, useMemo, useContext } from "react";
import { useParams, NavLink } from "react-router-dom"; import { useParams, NavLink } from "react-router-dom";
import { ethers, BigNumber } from "ethers"; import { ethers, BigNumber } from "ethers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -6,7 +6,6 @@ import {
faChevronLeft, faChevronLeft,
faChevronRight, faChevronRight,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { provider } from "./ethersconfig";
import StandardFrame from "./StandardFrame"; import StandardFrame from "./StandardFrame";
import StandardSubtitle from "./StandardSubtitle"; import StandardSubtitle from "./StandardSubtitle";
import ContentFrame from "./ContentFrame"; import ContentFrame from "./ContentFrame";
@ -17,6 +16,7 @@ import BlockLink from "./components/BlockLink";
import AddressOrENSName from "./components/AddressOrENSName"; import AddressOrENSName from "./components/AddressOrENSName";
import TransactionValue from "./components/TransactionValue"; import TransactionValue from "./components/TransactionValue";
import HexValue from "./components/HexValue"; import HexValue from "./components/HexValue";
import { ProviderContext } from "./useProvider";
import { useLatestBlockNumber } from "./useLatestBlock"; import { useLatestBlockNumber } from "./useLatestBlock";
type BlockParams = { type BlockParams = {
@ -34,10 +34,15 @@ interface ExtendedBlock extends ethers.providers.Block {
} }
const Block: React.FC = () => { const Block: React.FC = () => {
const provider = useContext(ProviderContext);
const params = useParams<BlockParams>(); const params = useParams<BlockParams>();
const [block, setBlock] = useState<ExtendedBlock>(); const [block, setBlock] = useState<ExtendedBlock>();
useEffect(() => { useEffect(() => {
if (!provider) {
return;
}
const readBlock = async () => { const readBlock = async () => {
let blockPromise: Promise<any>; let blockPromise: Promise<any>;
if (ethers.utils.isHexString(params.blockNumberOrHash, 32)) { if (ethers.utils.isHexString(params.blockNumberOrHash, 32)) {
@ -80,7 +85,7 @@ const Block: React.FC = () => {
setBlock(extBlock); setBlock(extBlock);
}; };
readBlock(); readBlock();
}, [params.blockNumberOrHash]); }, [provider, params.blockNumberOrHash]);
useEffect(() => { useEffect(() => {
if (block) { if (block) {
@ -97,7 +102,7 @@ const Block: React.FC = () => {
} }
}, [block]); }, [block]);
const latestBlockNumber = useLatestBlockNumber(); const latestBlockNumber = useLatestBlockNumber(provider);
return ( return (
<StandardFrame> <StandardFrame>

View File

@ -1,8 +1,7 @@
import React, { useEffect, useState, useMemo } from "react"; import React, { useEffect, useState, useMemo, useContext } from "react";
import { useParams, useLocation } from "react-router"; import { useParams, useLocation } from "react-router";
import { ethers } from "ethers"; import { ethers } from "ethers";
import queryString from "query-string"; import queryString from "query-string";
import { provider } from "./ethersconfig";
import StandardFrame from "./StandardFrame"; import StandardFrame from "./StandardFrame";
import StandardSubtitle from "./StandardSubtitle"; import StandardSubtitle from "./StandardSubtitle";
import ContentFrame from "./ContentFrame"; import ContentFrame from "./ContentFrame";
@ -14,6 +13,7 @@ import BlockLink from "./components/BlockLink";
import { ProcessedTransaction } from "./types"; import { ProcessedTransaction } from "./types";
import { PAGE_SIZE } from "./params"; import { PAGE_SIZE } from "./params";
import { useFeeToggler } from "./search/useFeeToggler"; import { useFeeToggler } from "./search/useFeeToggler";
import { ProviderContext } from "./useProvider";
import { useENSCache } from "./useReverseCache"; import { useENSCache } from "./useReverseCache";
type BlockParams = { type BlockParams = {
@ -25,6 +25,7 @@ type PageParams = {
}; };
const BlockTransactions: React.FC = () => { const BlockTransactions: React.FC = () => {
const provider = useContext(ProviderContext);
const params = useParams<BlockParams>(); const params = useParams<BlockParams>();
const location = useLocation<PageParams>(); const location = useLocation<PageParams>();
const qs = queryString.parse(location.search); const qs = queryString.parse(location.search);
@ -42,6 +43,10 @@ const BlockTransactions: React.FC = () => {
const [txs, setTxs] = useState<ProcessedTransaction[]>(); const [txs, setTxs] = useState<ProcessedTransaction[]>();
useEffect(() => { useEffect(() => {
if (!provider) {
return;
}
const readBlock = async () => { const readBlock = async () => {
const [_block, _receipts] = await Promise.all([ const [_block, _receipts] = await Promise.all([
provider.getBlockWithTransactions(blockNumber.toNumber()), provider.getBlockWithTransactions(blockNumber.toNumber()),
@ -94,7 +99,7 @@ const BlockTransactions: React.FC = () => {
setTxs(processedResponses); setTxs(processedResponses);
}; };
readBlock(); readBlock();
}, [blockNumber]); }, [provider, blockNumber]);
const page = useMemo(() => { const page = useMemo(() => {
if (!txs) { if (!txs) {
@ -105,7 +110,7 @@ const BlockTransactions: React.FC = () => {
}, [txs, pageNumber]); }, [txs, pageNumber]);
const total = useMemo(() => txs?.length ?? 0, [txs]); const total = useMemo(() => txs?.length ?? 0, [txs]);
const reverseCache = useENSCache(page); const reverseCache = useENSCache(provider, page);
document.title = `Block #${blockNumber} Txns | Otterscan`; document.title = `Block #${blockNumber} Txns | Otterscan`;

View File

@ -1,12 +1,13 @@
import React, { useState } from "react"; import React, { useState, useContext } from "react";
import { NavLink, useHistory } from "react-router-dom"; import { NavLink, useHistory } from "react-router-dom";
import { ethers } from "ethers"; import { ethers } from "ethers";
import Logo from "./Logo"; import Logo from "./Logo";
import Timestamp from "./components/Timestamp"; import Timestamp from "./components/Timestamp";
import { ProviderContext } from "./useProvider";
import { useLatestBlock } from "./useLatestBlock"; import { useLatestBlock } from "./useLatestBlock";
import { ERIGON_NODE } from "./ethersconfig";
const Home: React.FC = () => { const Home: React.FC = () => {
const provider = useContext(ProviderContext);
const [search, setSearch] = useState<string>(); const [search, setSearch] = useState<string>();
const [canSubmit, setCanSubmit] = useState<boolean>(false); const [canSubmit, setCanSubmit] = useState<boolean>(false);
const history = useHistory(); const history = useHistory();
@ -25,7 +26,7 @@ const Home: React.FC = () => {
history.push(`/search?q=${search}`); history.push(`/search?q=${search}`);
}; };
const latestBlock = useLatestBlock(); const latestBlock = useLatestBlock(provider);
document.title = "Home | Otterscan"; document.title = "Home | Otterscan";
@ -65,7 +66,11 @@ const Home: React.FC = () => {
</NavLink> </NavLink>
)} )}
<span className="mx-auto mt-5 text-xs text-gray-500"> <span className="mx-auto mt-5 text-xs text-gray-500">
Using Erigon node at {ERIGON_NODE} {provider ? (
<>Using Erigon node at {provider.connection.url}</>
) : (
<>Waiting for the provider...</>
)}
</span> </span>
</form> </form>
</div> </div>

View File

@ -1,4 +1,10 @@
import React, { useState, useEffect, useCallback, useMemo } from "react"; import React, {
useState,
useEffect,
useCallback,
useMemo,
useContext,
} from "react";
import { Route, Switch, useParams } from "react-router-dom"; import { Route, Switch, useParams } from "react-router-dom";
import { BigNumber, ethers } from "ethers"; import { BigNumber, ethers } from "ethers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -6,7 +12,6 @@ import {
faCheckCircle, faCheckCircle,
faTimesCircle, faTimesCircle,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { provider } from "./ethersconfig";
import StandardFrame from "./StandardFrame"; import StandardFrame from "./StandardFrame";
import StandardSubtitle from "./StandardSubtitle"; import StandardSubtitle from "./StandardSubtitle";
import Tab from "./components/Tab"; import Tab from "./components/Tab";
@ -22,6 +27,7 @@ import FormattedBalance from "./components/FormattedBalance";
import TokenTransferItem from "./TokenTransferItem"; import TokenTransferItem from "./TokenTransferItem";
import erc20 from "./erc20.json"; import erc20 from "./erc20.json";
import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types"; import { TokenMetas, TokenTransfer, TransactionData, Transfer } from "./types";
import { ProviderContext } from "./useProvider";
const TRANSFER_TOPIC = const TRANSFER_TOPIC =
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
@ -31,11 +37,16 @@ type TransactionParams = {
}; };
const Transaction: React.FC = () => { const Transaction: React.FC = () => {
const provider = useContext(ProviderContext);
const params = useParams<TransactionParams>(); const params = useParams<TransactionParams>();
const { txhash } = params; const { txhash } = params;
const [txData, setTxData] = useState<TransactionData>(); const [txData, setTxData] = useState<TransactionData>();
useEffect(() => { useEffect(() => {
if (!provider) {
return;
}
const readBlock = async () => { const readBlock = async () => {
const [_response, _receipt] = await Promise.all([ const [_response, _receipt] = await Promise.all([
provider.getTransaction(txhash), provider.getTransaction(txhash),
@ -109,7 +120,7 @@ const Transaction: React.FC = () => {
}); });
}; };
readBlock(); readBlock();
}, [txhash]); }, [provider, txhash]);
const [transfers, setTransfers] = useState<Transfer[]>(); const [transfers, setTransfers] = useState<Transfer[]>();
const sendsEthToMiner = useMemo(() => { const sendsEthToMiner = useMemo(() => {
@ -126,7 +137,7 @@ const Transaction: React.FC = () => {
}, [txData, transfers]); }, [txData, transfers]);
const traceTransfersUsingOtsTrace = useCallback(async () => { const traceTransfersUsingOtsTrace = useCallback(async () => {
if (!txData) { if (!provider || !txData) {
return; return;
} }
@ -143,7 +154,7 @@ const Transaction: React.FC = () => {
} }
setTransfers(_transfers); setTransfers(_transfers);
}, [txData]); }, [provider, txData]);
useEffect(() => { useEffect(() => {
traceTransfersUsingOtsTrace(); traceTransfersUsingOtsTrace();
}, [traceTransfersUsingOtsTrace]); }, [traceTransfersUsingOtsTrace]);

View File

@ -1,9 +0,0 @@
import { ethers } from "ethers";
export const ERIGON_NODE =
process.env.REACT_APP_ERIGON_URL || "http://127.0.0.1:8545";
export const provider = new ethers.providers.JsonRpcProvider(
ERIGON_NODE,
"mainnet"
);

View File

@ -1,5 +1,4 @@
import { ethers } from "ethers"; import { ethers } from "ethers";
import { provider } from "../ethersconfig";
import { PAGE_SIZE } from "../params"; import { PAGE_SIZE } from "../params";
import { ProcessedTransaction, TransactionChunk } from "../types"; import { ProcessedTransaction, TransactionChunk } from "../types";
@ -27,7 +26,10 @@ export class SearchController {
} }
} }
private static rawToProcessed = (_rawRes: any) => { private static rawToProcessed = (
provider: ethers.providers.JsonRpcProvider,
_rawRes: any
) => {
const _res: ethers.providers.TransactionResponse[] = _rawRes.txs.map( const _res: ethers.providers.TransactionResponse[] = _rawRes.txs.map(
(t: any) => provider.formatter.transactionResponse(t) (t: any) => provider.formatter.transactionResponse(t)
); );
@ -56,6 +58,7 @@ export class SearchController {
}; };
private static async readBackPage( private static async readBackPage(
provider: ethers.providers.JsonRpcProvider,
address: string, address: string,
baseBlock: number baseBlock: number
): Promise<TransactionChunk> { ): Promise<TransactionChunk> {
@ -64,10 +67,11 @@ export class SearchController {
baseBlock, baseBlock,
PAGE_SIZE, PAGE_SIZE,
]); ]);
return this.rawToProcessed(_rawRes); return this.rawToProcessed(provider, _rawRes);
} }
private static async readForwardPage( private static async readForwardPage(
provider: ethers.providers.JsonRpcProvider,
address: string, address: string,
baseBlock: number baseBlock: number
): Promise<TransactionChunk> { ): Promise<TransactionChunk> {
@ -76,11 +80,14 @@ export class SearchController {
baseBlock, baseBlock,
PAGE_SIZE, PAGE_SIZE,
]); ]);
return this.rawToProcessed(_rawRes); return this.rawToProcessed(provider, _rawRes);
} }
static async firstPage(address: string): Promise<SearchController> { static async firstPage(
const newTxs = await SearchController.readBackPage(address, 0); provider: ethers.providers.JsonRpcProvider,
address: string
): Promise<SearchController> {
const newTxs = await SearchController.readBackPage(provider, address, 0);
return new SearchController( return new SearchController(
address, address,
newTxs.txs, newTxs.txs,
@ -91,14 +98,19 @@ export class SearchController {
} }
static async middlePage( static async middlePage(
provider: ethers.providers.JsonRpcProvider,
address: string, address: string,
hash: string, hash: string,
next: boolean next: boolean
): Promise<SearchController> { ): Promise<SearchController> {
const tx = await provider.getTransaction(hash); const tx = await provider.getTransaction(hash);
const newTxs = next const newTxs = next
? await SearchController.readBackPage(address, tx.blockNumber!) ? await SearchController.readBackPage(provider, address, tx.blockNumber!)
: await SearchController.readForwardPage(address, tx.blockNumber!); : await SearchController.readForwardPage(
provider,
address,
tx.blockNumber!
);
return new SearchController( return new SearchController(
address, address,
newTxs.txs, newTxs.txs,
@ -108,8 +120,11 @@ export class SearchController {
); );
} }
static async lastPage(address: string): Promise<SearchController> { static async lastPage(
const newTxs = await SearchController.readForwardPage(address, 0); provider: ethers.providers.JsonRpcProvider,
address: string
): Promise<SearchController> {
const newTxs = await SearchController.readForwardPage(provider, address, 0);
return new SearchController( return new SearchController(
address, address,
newTxs.txs, newTxs.txs,
@ -123,7 +138,10 @@ export class SearchController {
return this.txs.slice(this.pageStart, this.pageEnd); return this.txs.slice(this.pageStart, this.pageEnd);
} }
async prevPage(hash: string): Promise<SearchController> { async prevPage(
provider: ethers.providers.JsonRpcProvider,
hash: string
): Promise<SearchController> {
// Already on this page // Already on this page
if (this.txs[this.pageEnd - 1].hash === hash) { if (this.txs[this.pageEnd - 1].hash === hash) {
return this; return this;
@ -133,6 +151,7 @@ export class SearchController {
const overflowPage = this.txs.slice(0, this.pageStart); const overflowPage = this.txs.slice(0, this.pageStart);
const baseBlock = this.txs[0].blockNumber; const baseBlock = this.txs[0].blockNumber;
const prevPage = await SearchController.readForwardPage( const prevPage = await SearchController.readForwardPage(
provider,
this.address, this.address,
baseBlock baseBlock
); );
@ -148,7 +167,10 @@ export class SearchController {
return this; return this;
} }
async nextPage(hash: string): Promise<SearchController> { async nextPage(
provider: ethers.providers.JsonRpcProvider,
hash: string
): Promise<SearchController> {
// Already on this page // Already on this page
if (this.txs[this.pageStart].hash === hash) { if (this.txs[this.pageStart].hash === hash) {
return this; return this;
@ -158,6 +180,7 @@ export class SearchController {
const overflowPage = this.txs.slice(this.pageEnd); const overflowPage = this.txs.slice(this.pageEnd);
const baseBlock = this.txs[this.txs.length - 1].blockNumber; const baseBlock = this.txs[this.txs.length - 1].blockNumber;
const nextPage = await SearchController.readBackPage( const nextPage = await SearchController.readBackPage(
provider,
this.address, this.address,
baseBlock baseBlock
); );

25
src/useErigon.ts Normal file
View File

@ -0,0 +1,25 @@
import { useState, useEffect } from "react";
export type OtterscanConfig = {
erigonURL: string;
};
export const useErigon = (): [boolean?, OtterscanConfig?] => {
const [configOK, setConfigOK] = useState<boolean>();
const [config, setConfig] = useState<OtterscanConfig>();
useEffect(() => {
const readConfig = async () => {
const res = await fetch("/config.json");
if (res.ok) {
const _config: OtterscanConfig = await res.json();
setConfig(_config);
setConfigOK(res.ok);
}
};
readConfig();
}, []);
return [configOK, config];
};

View File

@ -1,11 +1,14 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { ethers } from "ethers"; import { ethers } from "ethers";
import { provider } from "./ethersconfig";
export const useLatestBlock = () => { export const useLatestBlock = (provider?: ethers.providers.JsonRpcProvider) => {
const [latestBlock, setLatestBlock] = useState<ethers.providers.Block>(); const [latestBlock, setLatestBlock] = useState<ethers.providers.Block>();
useEffect(() => { useEffect(() => {
if (!provider) {
return;
}
const readLatestBlock = async () => { const readLatestBlock = async () => {
const blockNum = await provider.getBlockNumber(); const blockNum = await provider.getBlockNumber();
const _raw = await provider.send("erigon_getHeaderByNumber", [blockNum]); const _raw = await provider.send("erigon_getHeaderByNumber", [blockNum]);
@ -26,15 +29,21 @@ export const useLatestBlock = () => {
return () => { return () => {
provider.removeListener("block", listener); provider.removeListener("block", listener);
}; };
}, []); }, [provider]);
return latestBlock; return latestBlock;
}; };
export const useLatestBlockNumber = () => { export const useLatestBlockNumber = (
provider?: ethers.providers.JsonRpcProvider
) => {
const [latestBlock, setLatestBlock] = useState<number>(); const [latestBlock, setLatestBlock] = useState<number>();
useEffect(() => { useEffect(() => {
if (!provider) {
return;
}
const readLatestBlock = async () => { const readLatestBlock = async () => {
const blockNum = await provider.getBlockNumber(); const blockNum = await provider.getBlockNumber();
setLatestBlock(blockNum); setLatestBlock(blockNum);
@ -49,7 +58,7 @@ export const useLatestBlockNumber = () => {
return () => { return () => {
provider.removeListener("block", listener); provider.removeListener("block", listener);
}; };
}, []); }, [provider]);
return latestBlock; return latestBlock;
}; };

26
src/useProvider.ts Normal file
View File

@ -0,0 +1,26 @@
import React from "react";
import { ethers } from "ethers";
import { useErigon } from "./useErigon";
export const DEFAULT_ERIGON_URL = "http://127.0.0.1:8545";
export const useProvider = (): ethers.providers.JsonRpcProvider | undefined => {
const [configOK, config] = useErigon();
if (!configOK) {
return undefined;
}
let erigonURL = config?.erigonURL;
if (erigonURL === "") {
console.info(`Using default erigon URL: ${DEFAULT_ERIGON_URL}`);
erigonURL = DEFAULT_ERIGON_URL;
} else {
console.log(`Using configured erigon URL: ${erigonURL}`);
}
return new ethers.providers.JsonRpcProvider(erigonURL, "mainnet");
};
export const ProviderContext = React.createContext<
ethers.providers.JsonRpcProvider | undefined
>(undefined);

View File

@ -1,12 +1,15 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { ethers } from "ethers";
import { ENSReverseCache, ProcessedTransaction } from "./types"; import { ENSReverseCache, ProcessedTransaction } from "./types";
import { provider } from "./ethersconfig";
export const useENSCache = (page?: ProcessedTransaction[]) => { export const useENSCache = (
provider?: ethers.providers.JsonRpcProvider,
page?: ProcessedTransaction[]
) => {
const [reverseCache, setReverseCache] = useState<ENSReverseCache>(); const [reverseCache, setReverseCache] = useState<ENSReverseCache>();
useEffect(() => { useEffect(() => {
if (!page) { if (!provider || !page) {
return; return;
} }
@ -38,7 +41,7 @@ export const useENSCache = (page?: ProcessedTransaction[]) => {
setReverseCache(cache); setReverseCache(cache);
}; };
reverseResolve(); reverseResolve();
}, [page]); }, [provider, page]);
return reverseCache; return reverseCache;
}; };