First working iteration of sender/nonce navigation

This commit is contained in:
Willian Mitsuda 2021-12-27 15:48:46 -03:00
parent 75a37f79d3
commit 47cbe36c8f
7 changed files with 140 additions and 2 deletions

View File

@ -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<TransactionLinkProps> = ({ txHash }) => (
<NavLink
className="text-link-blue hover:text-link-blue-hover font-hash"
to={`/tx/${txHash}`}
to={transactionURL(txHash)}
>
<p className="truncate">{txHash}</p>
</NavLink>

View File

@ -1,3 +1,3 @@
export const MIN_API_LEVEL = 5;
export const MIN_API_LEVEL = 6;
export const PAGE_SIZE = 25;

View File

@ -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<DetailsProps> = ({
</div>
<div className="flex items-baseline pl-3">
<Nonce value={txData.nonce} />
<NavNonce
sender={txData.from}
nonce={txData.nonce}
latestBlockNumber={undefined}
/>
</div>
</div>
</InfoRow>

View File

@ -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<NavButtonProps> = ({
txHash,
disabled,
children,
}) => {
if (disabled || txHash === undefined) {
return (
<span className="bg-link-blue bg-opacity-10 text-gray-400 rounded px-2 py-1 text-xs">
{children}
</span>
);
}
return (
<NavLink
className="transition-colors bg-link-blue bg-opacity-10 text-link-blue hover:bg-opacity-100 hover:text-white disabled:bg-link-blue disabled:text-gray-400 disabled:cursor-default rounded px-2 py-1 text-xs"
to={transactionURL(txHash)}
>
{children}
</NavLink>
);
};
export default NavButton;

View File

@ -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<NavNonceProps> = ({
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 (
<div className="pl-2 self-center flex space-x-1">
<NavButton txHash={prevTxHash} disabled={nonce === 0}>
<FontAwesomeIcon icon={faChevronLeft} />
</NavButton>
<NavButton
txHash={nextTxHash}
disabled={latestBlockNumber === undefined || nonce >= latestBlockNumber}
>
<FontAwesomeIcon icon={faChevronRight} />
</NavButton>
<NavButton
txHash={lastTxHash}
disabled={latestBlockNumber === undefined || nonce >= latestBlockNumber}
>
<FontAwesomeIcon icon={faChevronRight} />
<FontAwesomeIcon icon={faChevronRight} />
</NavButton>
</div>
);
};
export default React.memo(NavNonce);

View File

@ -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,

View File

@ -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<string | undefined>();
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;
};