Split block confirmation data into its own hook
This commit is contained in:
parent
34f812aed0
commit
e3a21bd4b2
|
@ -1,10 +1,12 @@
|
||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
import { formatEther } from "@ethersproject/units";
|
import { formatEther } from "@ethersproject/units";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight";
|
import { faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight";
|
||||||
import AddressHighlighter from "./AddressHighlighter";
|
import AddressHighlighter from "./AddressHighlighter";
|
||||||
import DecoratedAddressLink from "./DecoratedAddressLink";
|
import DecoratedAddressLink from "./DecoratedAddressLink";
|
||||||
import TransactionAddress from "./TransactionAddress";
|
import TransactionAddress from "./TransactionAddress";
|
||||||
|
import { RuntimeContext } from "../useRuntime";
|
||||||
|
import { useBlockDataFromTransaction } from "../useErigonHooks";
|
||||||
import { useChainInfo } from "../useChainInfo";
|
import { useChainInfo } from "../useChainInfo";
|
||||||
import { TransactionData, InternalOperation } from "../types";
|
import { TransactionData, InternalOperation } from "../types";
|
||||||
|
|
||||||
|
@ -17,12 +19,12 @@ const InternalSelfDestruct: React.FC<InternalSelfDestructProps> = ({
|
||||||
txData,
|
txData,
|
||||||
internalOp,
|
internalOp,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const block = useBlockDataFromTransaction(provider, txData);
|
||||||
const {
|
const {
|
||||||
nativeCurrency: { symbol },
|
nativeCurrency: { symbol },
|
||||||
} = useChainInfo();
|
} = useChainInfo();
|
||||||
const toMiner =
|
const toMiner = block?.miner !== undefined && internalOp.to === block.miner;
|
||||||
txData.confirmedData?.miner !== undefined &&
|
|
||||||
internalOp.to === txData.confirmedData.miner;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -8,7 +8,7 @@ import AddressHighlighter from "./AddressHighlighter";
|
||||||
import DecoratedAddressLink from "./DecoratedAddressLink";
|
import DecoratedAddressLink from "./DecoratedAddressLink";
|
||||||
import USDAmount from "./USDAmount";
|
import USDAmount from "./USDAmount";
|
||||||
import { RuntimeContext } from "../useRuntime";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import { useHasCode } from "../useErigonHooks";
|
import { useBlockDataFromTransaction, useHasCode } from "../useErigonHooks";
|
||||||
import { useChainInfo } from "../useChainInfo";
|
import { useChainInfo } from "../useChainInfo";
|
||||||
import { useETHUSDOracle } from "../usePriceOracle";
|
import { useETHUSDOracle } from "../usePriceOracle";
|
||||||
import { TransactionData, InternalOperation } from "../types";
|
import { TransactionData, InternalOperation } from "../types";
|
||||||
|
@ -22,17 +22,16 @@ const InternalTransfer: React.FC<InternalTransferProps> = ({
|
||||||
txData,
|
txData,
|
||||||
internalOp,
|
internalOp,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const block = useBlockDataFromTransaction(provider, txData);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
nativeCurrency: { symbol, decimals },
|
nativeCurrency: { symbol, decimals },
|
||||||
} = useChainInfo();
|
} = useChainInfo();
|
||||||
const fromMiner =
|
const fromMiner =
|
||||||
txData.confirmedData?.miner !== undefined &&
|
block?.miner !== undefined && internalOp.from === block.miner;
|
||||||
internalOp.from === txData.confirmedData.miner;
|
const toMiner = block?.miner !== undefined && internalOp.to === block.miner;
|
||||||
const toMiner =
|
|
||||||
txData.confirmedData?.miner !== undefined &&
|
|
||||||
internalOp.to === txData.confirmedData.miner;
|
|
||||||
|
|
||||||
const { provider } = useContext(RuntimeContext);
|
|
||||||
const blockETHUSDPrice = useETHUSDOracle(
|
const blockETHUSDPrice = useETHUSDOracle(
|
||||||
provider,
|
provider,
|
||||||
txData.confirmedData?.blockNumber
|
txData.confirmedData?.blockNumber
|
||||||
|
|
|
@ -4,7 +4,7 @@ import DecoratedAddressLink from "./DecoratedAddressLink";
|
||||||
import { useSelectedTransaction } from "../useSelectedTransaction";
|
import { useSelectedTransaction } from "../useSelectedTransaction";
|
||||||
import { useBlockNumberContext } from "../useBlockTagContext";
|
import { useBlockNumberContext } from "../useBlockTagContext";
|
||||||
import { RuntimeContext } from "../useRuntime";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import { useHasCode } from "../useErigonHooks";
|
import { useBlockDataFromTransaction, useHasCode } from "../useErigonHooks";
|
||||||
import { AddressContext, ChecksummedAddress } from "../types";
|
import { AddressContext, ChecksummedAddress } from "../types";
|
||||||
|
|
||||||
type TransactionAddressProps = {
|
type TransactionAddressProps = {
|
||||||
|
@ -23,6 +23,8 @@ const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
||||||
const creation = address === txData?.confirmedData?.createdContractAddress;
|
const creation = address === txData?.confirmedData?.createdContractAddress;
|
||||||
|
|
||||||
const { provider } = useContext(RuntimeContext);
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const block = useBlockDataFromTransaction(provider, txData);
|
||||||
|
|
||||||
const blockNumber = useBlockNumberContext();
|
const blockNumber = useBlockNumberContext();
|
||||||
const toHasCode = useHasCode(
|
const toHasCode = useHasCode(
|
||||||
provider,
|
provider,
|
||||||
|
@ -39,7 +41,7 @@ const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
||||||
<DecoratedAddressLink
|
<DecoratedAddressLink
|
||||||
address={address}
|
address={address}
|
||||||
addressCtx={addressCtx}
|
addressCtx={addressCtx}
|
||||||
miner={address === txData?.confirmedData?.miner}
|
miner={address === block?.miner}
|
||||||
txFrom={address === txData?.from}
|
txFrom={address === txData?.from}
|
||||||
txTo={address === txData?.to || creation}
|
txTo={address === txData?.to || creation}
|
||||||
creation={creation}
|
creation={creation}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import {
|
||||||
} from "../sourcify/useSourcify";
|
} from "../sourcify/useSourcify";
|
||||||
import { RuntimeContext } from "../useRuntime";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import {
|
import {
|
||||||
|
useBlockDataFromTransaction,
|
||||||
useSendsToMiner,
|
useSendsToMiner,
|
||||||
useTokenTransfers,
|
useTokenTransfers,
|
||||||
useTransactionError,
|
useTransactionError,
|
||||||
|
@ -57,10 +58,10 @@ type DetailsProps = {
|
||||||
|
|
||||||
const Details: React.FC<DetailsProps> = ({ txData }) => {
|
const Details: React.FC<DetailsProps> = ({ txData }) => {
|
||||||
const { provider } = useContext(RuntimeContext);
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const block = useBlockDataFromTransaction(provider, txData);
|
||||||
|
|
||||||
const hasEIP1559 =
|
const hasEIP1559 =
|
||||||
txData.confirmedData?.blockBaseFeePerGas !== undefined &&
|
block?.baseFeePerGas !== undefined && block?.baseFeePerGas !== null;
|
||||||
txData.confirmedData?.blockBaseFeePerGas !== null;
|
|
||||||
|
|
||||||
const fourBytes =
|
const fourBytes =
|
||||||
txData.to !== null ? extract4Bytes(txData.data) ?? "0x" : "0x";
|
txData.to !== null ? extract4Bytes(txData.data) ?? "0x" : "0x";
|
||||||
|
@ -74,7 +75,7 @@ const Details: React.FC<DetailsProps> = ({ txData }) => {
|
||||||
const [sendsEthToMiner, internalOps] = useSendsToMiner(
|
const [sendsEthToMiner, internalOps] = useSendsToMiner(
|
||||||
provider,
|
provider,
|
||||||
txData.confirmedData ? txData.transactionHash : undefined,
|
txData.confirmedData ? txData.transactionHash : undefined,
|
||||||
txData.confirmedData?.miner
|
block?.miner
|
||||||
);
|
);
|
||||||
|
|
||||||
const tokenTransfers = useTokenTransfers(txData);
|
const tokenTransfers = useTokenTransfers(txData);
|
||||||
|
@ -222,22 +223,24 @@ const Details: React.FC<DetailsProps> = ({ txData }) => {
|
||||||
confirmations={txData.confirmedData.confirmations}
|
confirmations={txData.confirmedData.confirmations}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{block && (
|
||||||
<div className="flex space-x-2 items-baseline pl-3">
|
<div className="flex space-x-2 items-baseline pl-3">
|
||||||
<RelativePosition
|
<RelativePosition
|
||||||
pos={txData.confirmedData.transactionIndex}
|
pos={txData.confirmedData.transactionIndex}
|
||||||
total={txData.confirmedData.blockTransactionCount - 1}
|
total={block.transactionCount - 1}
|
||||||
/>
|
/>
|
||||||
<PercentagePosition
|
<PercentagePosition
|
||||||
perc={
|
perc={
|
||||||
txData.confirmedData.transactionIndex /
|
txData.confirmedData.transactionIndex /
|
||||||
(txData.confirmedData.blockTransactionCount - 1)
|
(block.transactionCount - 1)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
<InfoRow title="Timestamp">
|
<InfoRow title="Timestamp">
|
||||||
<Timestamp value={txData.confirmedData.timestamp} />
|
{block && <Timestamp value={block.timestamp} />}
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -366,18 +369,10 @@ const Details: React.FC<DetailsProps> = ({ txData }) => {
|
||||||
</div>
|
</div>
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
)}
|
)}
|
||||||
{txData.confirmedData && hasEIP1559 && (
|
{block && hasEIP1559 && (
|
||||||
<InfoRow title="Block Base Fee">
|
<InfoRow title="Block Base Fee">
|
||||||
<FormattedBalance
|
<FormattedBalance value={block.baseFeePerGas!} decimals={9} /> Gwei (
|
||||||
value={txData.confirmedData.blockBaseFeePerGas!}
|
<FormattedBalance value={block.baseFeePerGas!} decimals={0} /> wei)
|
||||||
decimals={9}
|
|
||||||
/>{" "}
|
|
||||||
Gwei (
|
|
||||||
<FormattedBalance
|
|
||||||
value={txData.confirmedData.blockBaseFeePerGas!}
|
|
||||||
decimals={0}
|
|
||||||
/>{" "}
|
|
||||||
wei)
|
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
)}
|
)}
|
||||||
{txData.confirmedData && (
|
{txData.confirmedData && (
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
|
import { BigNumber } from "@ethersproject/bignumber";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn";
|
import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn";
|
||||||
import { faCoins } from "@fortawesome/free-solid-svg-icons/faCoins";
|
import { faCoins } from "@fortawesome/free-solid-svg-icons/faCoins";
|
||||||
import FormattedBalance from "../components/FormattedBalance";
|
import FormattedBalance from "../components/FormattedBalance";
|
||||||
import PercentageGauge from "../components/PercentageGauge";
|
import PercentageGauge from "../components/PercentageGauge";
|
||||||
import { TransactionData } from "../types";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
|
import { useBlockDataFromTransaction } from "../useErigonHooks";
|
||||||
import { useChainInfo } from "../useChainInfo";
|
import { useChainInfo } from "../useChainInfo";
|
||||||
|
import { TransactionData } from "../types";
|
||||||
|
|
||||||
type RewardSplitProps = {
|
type RewardSplitProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const RewardSplit: React.FC<RewardSplitProps> = ({ txData }) => {
|
const RewardSplit: React.FC<RewardSplitProps> = ({ txData }) => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const block = useBlockDataFromTransaction(provider, txData);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
nativeCurrency: { symbol },
|
nativeCurrency: { symbol },
|
||||||
} = useChainInfo();
|
} = useChainInfo();
|
||||||
const paidFees = txData.gasPrice.mul(txData.confirmedData!.gasUsed);
|
const paidFees = txData.gasPrice.mul(txData.confirmedData!.gasUsed);
|
||||||
const burntFees = txData.confirmedData!.blockBaseFeePerGas!.mul(
|
const burntFees = block
|
||||||
txData.confirmedData!.gasUsed
|
? block.baseFeePerGas!.mul(txData.confirmedData!.gasUsed)
|
||||||
);
|
: BigNumber.from(0);
|
||||||
|
|
||||||
const minerReward = paidFees.sub(burntFees);
|
const minerReward = paidFees.sub(burntFees);
|
||||||
const burntPerc =
|
const burntPerc =
|
||||||
|
|
|
@ -50,11 +50,7 @@ export type ConfirmedTransactionData = {
|
||||||
status: boolean;
|
status: boolean;
|
||||||
blockNumber: number;
|
blockNumber: number;
|
||||||
transactionIndex: number;
|
transactionIndex: number;
|
||||||
blockBaseFeePerGas?: BigNumber | undefined | null;
|
|
||||||
blockTransactionCount: number;
|
|
||||||
confirmations: number;
|
confirmations: number;
|
||||||
timestamp: number;
|
|
||||||
miner: string;
|
|
||||||
createdContractAddress?: string;
|
createdContractAddress?: string;
|
||||||
fee: BigNumber;
|
fee: BigNumber;
|
||||||
gasUsed: BigNumber;
|
gasUsed: BigNumber;
|
||||||
|
|
|
@ -155,12 +155,15 @@ const blockDataFetcher = async (
|
||||||
return await readBlock(provider, blockNumberOrHash);
|
return await readBlock(provider, blockNumberOrHash);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: some callers may use only block headers?
|
||||||
export const useBlockData = (
|
export const useBlockData = (
|
||||||
provider: JsonRpcProvider | undefined,
|
provider: JsonRpcProvider | undefined,
|
||||||
blockNumberOrHash: string
|
blockNumberOrHash: string | undefined
|
||||||
): ExtendedBlock | null | undefined => {
|
): ExtendedBlock | null | undefined => {
|
||||||
const { data, error } = useSWRImmutable(
|
const { data, error } = useSWRImmutable(
|
||||||
provider !== undefined ? [provider, blockNumberOrHash] : null,
|
provider !== undefined && blockNumberOrHash !== undefined
|
||||||
|
? [provider, blockNumberOrHash]
|
||||||
|
: null,
|
||||||
blockDataFetcher
|
blockDataFetcher
|
||||||
);
|
);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -169,6 +172,19 @@ export const useBlockData = (
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useBlockDataFromTransaction = (
|
||||||
|
provider: JsonRpcProvider | undefined,
|
||||||
|
txData: TransactionData | null | undefined
|
||||||
|
): ExtendedBlock | null | undefined => {
|
||||||
|
const block = useBlockData(
|
||||||
|
provider,
|
||||||
|
txData?.confirmedData
|
||||||
|
? txData.confirmedData.blockNumber.toString()
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
export const useTxData = (
|
export const useTxData = (
|
||||||
provider: JsonRpcProvider | undefined,
|
provider: JsonRpcProvider | undefined,
|
||||||
txhash: string
|
txhash: string
|
||||||
|
@ -191,11 +207,6 @@ export const useTxData = (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _block: ExtendedBlock | null | undefined;
|
|
||||||
if (_response.blockNumber) {
|
|
||||||
_block = await readBlock(provider, _response.blockNumber.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
document.title = `Transaction ${_response.hash} | Otterscan`;
|
document.title = `Transaction ${_response.hash} | Otterscan`;
|
||||||
|
|
||||||
setTxData({
|
setTxData({
|
||||||
|
@ -217,11 +228,7 @@ export const useTxData = (
|
||||||
status: _receipt.status === 1,
|
status: _receipt.status === 1,
|
||||||
blockNumber: _receipt.blockNumber,
|
blockNumber: _receipt.blockNumber,
|
||||||
transactionIndex: _receipt.transactionIndex,
|
transactionIndex: _receipt.transactionIndex,
|
||||||
blockBaseFeePerGas: _block!.baseFeePerGas,
|
|
||||||
blockTransactionCount: _block!.transactionCount,
|
|
||||||
confirmations: _receipt.confirmations,
|
confirmations: _receipt.confirmations,
|
||||||
timestamp: _block!.timestamp,
|
|
||||||
miner: _block!.miner,
|
|
||||||
createdContractAddress: _receipt.contractAddress,
|
createdContractAddress: _receipt.contractAddress,
|
||||||
fee: _response.gasPrice!.mul(_receipt.gasUsed),
|
fee: _response.gasPrice!.mul(_receipt.gasUsed),
|
||||||
gasUsed: _receipt.gasUsed,
|
gasUsed: _receipt.gasUsed,
|
||||||
|
|
Loading…
Reference in New Issue