diff --git a/src/components/TransactionLink.tsx b/src/components/TransactionLink.tsx index 8db23f3..06fde64 100644 --- a/src/components/TransactionLink.tsx +++ b/src/components/TransactionLink.tsx @@ -1,5 +1,6 @@ import React from "react"; import { NavLink } from "react-router-dom"; +import { transactionURL } from "../url"; type TransactionLinkProps = { txHash: string; @@ -8,7 +9,7 @@ type TransactionLinkProps = { const TransactionLink: React.FC = ({ txHash }) => (

{txHash}

diff --git a/src/params.ts b/src/params.ts index d1464c6..b1ef13b 100644 --- a/src/params.ts +++ b/src/params.ts @@ -1,3 +1,3 @@ -export const MIN_API_LEVEL = 5; +export const MIN_API_LEVEL = 6; export const PAGE_SIZE = 25; diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 695a686..8c0d779 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -15,6 +15,7 @@ import BlockConfirmations from "../components/BlockConfirmations"; import TransactionAddress from "../components/TransactionAddress"; import Copy from "../components/Copy"; import Nonce from "../components/Nonce"; +import NavNonce from "./NavNonce"; import Timestamp from "../components/Timestamp"; import InternalTransactionOperation from "../components/InternalTransactionOperation"; import MethodName from "../components/MethodName"; @@ -253,6 +254,11 @@ const Details: React.FC = ({
+
diff --git a/src/transaction/NavButton.tsx b/src/transaction/NavButton.tsx new file mode 100644 index 0000000..34f847d --- /dev/null +++ b/src/transaction/NavButton.tsx @@ -0,0 +1,33 @@ +import { NavLink } from "react-router-dom"; +import { transactionURL } from "../url"; + +// TODO: extract common component with block/NavButton +type NavButtonProps = { + txHash: string | undefined; + disabled?: boolean; +}; + +const NavButton: React.FC = ({ + txHash, + disabled, + children, +}) => { + if (disabled || txHash === undefined) { + return ( + + {children} + + ); + } + + return ( + + {children} + + ); +}; + +export default NavButton; diff --git a/src/transaction/NavNonce.tsx b/src/transaction/NavNonce.tsx new file mode 100644 index 0000000..f17c5cc --- /dev/null +++ b/src/transaction/NavNonce.tsx @@ -0,0 +1,56 @@ +import React, { useContext } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChevronLeft } from "@fortawesome/free-solid-svg-icons/faChevronLeft"; +import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight"; +import NavButton from "./NavButton"; +import { ChecksummedAddress } from "../types"; +import { RuntimeContext } from "../useRuntime"; +import { useTransactionBySenderAndNonce } from "../useErigonHooks"; + +type NavNonceProps = { + sender: ChecksummedAddress; + nonce: number; + latestBlockNumber: number | undefined; +}; + +const NavNonce: React.FC = ({ + sender, + nonce, + latestBlockNumber, +}) => { + const { provider } = useContext(RuntimeContext); + const prevTxHash = useTransactionBySenderAndNonce( + provider, + sender, + nonce - 1 + ); + const nextTxHash = useTransactionBySenderAndNonce( + provider, + sender, + nonce + 1 + ); + const lastTxHash = nextTxHash; + + return ( +
+ + + + = latestBlockNumber} + > + + + = latestBlockNumber} + > + + + +
+ ); +}; + +export default React.memo(NavNonce); diff --git a/src/url.ts b/src/url.ts index 471c9d8..2216bf6 100644 --- a/src/url.ts +++ b/src/url.ts @@ -18,6 +18,8 @@ export const blockURL = (blockNum: BlockTag) => `/block/${blockNum}`; export const blockTxsURL = (blockNum: BlockTag) => `/block/${blockNum}/txs`; +export const transactionURL = (txHash: string) => `/tx/${txHash}`; + export enum SourcifySource { // Resolve trusted IPNS for root IPFS IPFS_IPNS, diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index e63a718..d26fcd0 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -502,3 +502,43 @@ export const useTransactionError = ( return [errorMsg, data, isCustomError]; }; + +export const useTransactionBySenderAndNonce = ( + provider: JsonRpcProvider | undefined, + sender: ChecksummedAddress | undefined, + nonce: number | undefined +): string | undefined => { + const [txHash, setTxHash] = useState(); + + useEffect(() => { + // Reset + setTxHash(undefined); + + if ( + provider === undefined || + sender === undefined || + nonce === undefined || + nonce < 0 + ) { + return; + } + + const readTxHash = async () => { + const result = (await provider.send( + "ots_getTransactionBySenderAndNonce", + [sender, nonce] + )) as string; + + // Empty or success + if (result === "0x") { + setTxHash(undefined); + return; + } + + setTxHash(result); + }; + readTxHash(); + }, [provider, sender, nonce]); + + return txHash; +};