Add burnt/miner fee split info

This commit is contained in:
Willian Mitsuda 2021-07-28 18:44:50 -03:00
parent 8cacd01f42
commit f0e96990ef
2 changed files with 256 additions and 186 deletions

View File

@ -16,6 +16,7 @@ import Timestamp from "../components/Timestamp";
import InternalTransactionOperation from "../components/InternalTransactionOperation"; import InternalTransactionOperation from "../components/InternalTransactionOperation";
import MethodName from "../components/MethodName"; import MethodName from "../components/MethodName";
import TransactionType from "../components/TransactionType"; import TransactionType from "../components/TransactionType";
import RewardSplit from "./RewardSplit";
import GasValue from "../components/GasValue"; import GasValue from "../components/GasValue";
import FormattedBalance from "../components/FormattedBalance"; import FormattedBalance from "../components/FormattedBalance";
import TokenTransferItem from "../TokenTransferItem"; import TokenTransferItem from "../TokenTransferItem";
@ -33,198 +34,213 @@ const Details: React.FC<DetailsProps> = ({
txData, txData,
internalOps, internalOps,
sendsEthToMiner, sendsEthToMiner,
}) => ( }) => {
<ContentFrame tabs> const hasEIP1559 =
<InfoRow title="Transaction Hash"> txData.blockBaseFeePerGas !== undefined &&
<div className="flex items-baseline space-x-2"> txData.blockBaseFeePerGas !== null;
<span className="font-hash">{txData.transactionHash}</span>
<Copy value={txData.transactionHash} /> return (
</div> <ContentFrame tabs>
</InfoRow> <InfoRow title="Transaction Hash">
<InfoRow title="Status"> <div className="flex items-baseline space-x-2">
{txData.status ? ( <span className="font-hash">{txData.transactionHash}</span>
<span className="flex items-center w-min rounded-lg space-x-1 px-3 py-1 bg-green-50 text-green-500 text-xs"> <Copy value={txData.transactionHash} />
<FontAwesomeIcon icon={faCheckCircle} size="1x" />
<span>Success</span>
</span>
) : (
<span className="flex items-center w-min rounded-lg space-x-1 px-3 py-1 bg-red-50 text-red-500 text-xs">
<FontAwesomeIcon icon={faTimesCircle} size="1x" />
<span>Fail</span>
</span>
)}
</InfoRow>
<InfoRow title="Block">
<div className="flex items-baseline space-x-2">
<BlockLink blockTag={txData.blockNumber} />
<BlockConfirmations confirmations={txData.confirmations} />
</div>
</InfoRow>
<InfoRow title="Timestamp">
<Timestamp value={txData.timestamp} />
</InfoRow>
<InfoRow title="From">
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.from}>
<DecoratedAddressLink
address={txData.from}
miner={txData.from === txData.miner}
txFrom
/>
</AddressHighlighter>
<Copy value={txData.from} />
</div>
</InfoRow>
<InfoRow title={txData.to ? "Interacted With (To)" : "Contract Created"}>
{txData.to ? (
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.to}>
<DecoratedAddressLink
address={txData.to}
miner={txData.to === txData.miner}
txTo
/>
</AddressHighlighter>
<Copy value={txData.to} />
</div>
) : (
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.createdContractAddress!}>
<DecoratedAddressLink
address={txData.createdContractAddress!}
creation
txTo
/>
</AddressHighlighter>
<Copy value={txData.createdContractAddress!} />
</div>
)}
{internalOps && (
<div className="mt-2 space-y-1">
{internalOps.map((op, i) => (
<InternalTransactionOperation
key={i}
txData={txData}
internalOp={op}
/>
))}
</div>
)}
</InfoRow>
<InfoRow title="Transaction Action">
<MethodName data={txData.data} />
</InfoRow>
{txData.tokenTransfers.length > 0 && (
<InfoRow title={`Tokens Transferred (${txData.tokenTransfers.length})`}>
<div>
{txData.tokenTransfers.map((t, i) => (
<TokenTransferItem
key={i}
t={t}
txData={txData}
tokenMetas={txData.tokenMetas}
/>
))}
</div> </div>
</InfoRow> </InfoRow>
)} <InfoRow title="Status">
<InfoRow title="Value"> {txData.status ? (
<span className="rounded bg-gray-100 px-2 py-1 text-xs"> <span className="flex items-center w-min rounded-lg space-x-1 px-3 py-1 bg-green-50 text-green-500 text-xs">
{ethers.utils.formatEther(txData.value)} Ether <FontAwesomeIcon icon={faCheckCircle} size="1x" />
</span> <span>Success</span>
</InfoRow>
<InfoRow
title={
<>
Type (
<ExternalLink href="https://eips.ethereum.org/EIPS/eip-2718">
EIP-2718
</ExternalLink>
)
</>
}
>
<TransactionType type={txData.type} />
</InfoRow>
{txData.blockBaseFeePerGas && (
<InfoRow title="Block Base Fee">
<span>
<FormattedBalance value={txData.blockBaseFeePerGas} decimals={9} />{" "}
Gwei (
<FormattedBalance
value={txData.blockBaseFeePerGas}
decimals={0}
/>{" "}
wei)
</span>
</InfoRow>
)}
{txData.type === 2 && (
<>
<InfoRow title="Max Priority Fee Per Gas">
<span>
<FormattedBalance value={txData.maxPriorityFeePerGas!} /> Ether (
<FormattedBalance
value={txData.maxPriorityFeePerGas!}
decimals={9}
/>{" "}
Gwei)
</span> </span>
</InfoRow> ) : (
<InfoRow title="Max Fee Per Gas"> <span className="flex items-center w-min rounded-lg space-x-1 px-3 py-1 bg-red-50 text-red-500 text-xs">
<span> <FontAwesomeIcon icon={faTimesCircle} size="1x" />
<FormattedBalance value={txData.maxFeePerGas!} /> Ether ( <span>Fail</span>
<FormattedBalance value={txData.maxFeePerGas!} decimals={9} /> Gwei)
</span>
</InfoRow>
</>
)}
<InfoRow title="Transaction Fee">
<FormattedBalance value={txData.fee} /> Ether
</InfoRow>
<InfoRow title="Gas Price">
<div className="flex items-baseline space-x-1">
<span>
<FormattedBalance value={txData.gasPrice} /> Ether (
<FormattedBalance value={txData.gasPrice} decimals={9} /> Gwei)
</span>
{sendsEthToMiner && (
<span className="rounded text-yellow-500 bg-yellow-100 text-xs px-2 py-1">
Flashbots
</span> </span>
)} )}
</div> </InfoRow>
</InfoRow> <InfoRow title="Block">
<InfoRow title="Gas Used/Limit"> <div className="flex items-baseline space-x-2">
<div className="flex space-x-3 items-baseline"> <BlockLink blockTag={txData.blockNumber} />
<div> <BlockConfirmations confirmations={txData.confirmations} />
<GasValue value={txData.gasUsed} /> /{" "}
<GasValue value={txData.gasLimit} />
</div> </div>
<PercentageBar </InfoRow>
perc={ <InfoRow title="Timestamp">
Math.round( <Timestamp value={txData.timestamp} />
(txData.gasUsed.toNumber() / txData.gasLimit.toNumber()) * 10000 </InfoRow>
) / 100 <InfoRow title="From">
} <div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.from}>
<DecoratedAddressLink
address={txData.from}
miner={txData.from === txData.miner}
txFrom
/>
</AddressHighlighter>
<Copy value={txData.from} />
</div>
</InfoRow>
<InfoRow title={txData.to ? "Interacted With (To)" : "Contract Created"}>
{txData.to ? (
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.to}>
<DecoratedAddressLink
address={txData.to}
miner={txData.to === txData.miner}
txTo
/>
</AddressHighlighter>
<Copy value={txData.to} />
</div>
) : (
<div className="flex items-baseline space-x-2 -ml-1">
<AddressHighlighter address={txData.createdContractAddress!}>
<DecoratedAddressLink
address={txData.createdContractAddress!}
creation
txTo
/>
</AddressHighlighter>
<Copy value={txData.createdContractAddress!} />
</div>
)}
{internalOps && (
<div className="mt-2 space-y-1">
{internalOps.map((op, i) => (
<InternalTransactionOperation
key={i}
txData={txData}
internalOp={op}
/>
))}
</div>
)}
</InfoRow>
<InfoRow title="Transaction Action">
<MethodName data={txData.data} />
</InfoRow>
{txData.tokenTransfers.length > 0 && (
<InfoRow title={`Tokens Transferred (${txData.tokenTransfers.length})`}>
<div>
{txData.tokenTransfers.map((t, i) => (
<TokenTransferItem
key={i}
t={t}
txData={txData}
tokenMetas={txData.tokenMetas}
/>
))}
</div>
</InfoRow>
)}
<InfoRow title="Value">
<span className="rounded bg-gray-100 px-2 py-1 text-xs">
{ethers.utils.formatEther(txData.value)} Ether
</span>
</InfoRow>
<InfoRow
title={
<>
Type (
<ExternalLink href="https://eips.ethereum.org/EIPS/eip-2718">
EIP-2718
</ExternalLink>
)
</>
}
>
<TransactionType type={txData.type} />
</InfoRow>
{hasEIP1559 && (
<InfoRow title="Block Base Fee">
<span>
<FormattedBalance value={txData.blockBaseFeePerGas!} decimals={9} />{" "}
Gwei (
<FormattedBalance
value={txData.blockBaseFeePerGas!}
decimals={0}
/>{" "}
wei)
</span>
</InfoRow>
)}
{txData.type === 2 && (
<>
<InfoRow title="Max Priority Fee Per Gas">
<span>
<FormattedBalance value={txData.maxPriorityFeePerGas!} /> Ether (
<FormattedBalance
value={txData.maxPriorityFeePerGas!}
decimals={9}
/>{" "}
Gwei)
</span>
</InfoRow>
<InfoRow title="Max Fee Per Gas">
<span>
<FormattedBalance value={txData.maxFeePerGas!} /> Ether (
<FormattedBalance
value={txData.maxFeePerGas!}
decimals={9}
/>{" "}
Gwei)
</span>
</InfoRow>
</>
)}
<InfoRow title="Transaction Fee">
<div className="space-y-2">
<div>
<FormattedBalance value={txData.fee} /> Ether
</div>
{hasEIP1559 && <RewardSplit txData={txData} />}
</div>
</InfoRow>
<InfoRow title="Gas Price">
<div className="flex items-baseline space-x-1">
<span>
<FormattedBalance value={txData.gasPrice} /> Ether (
<FormattedBalance value={txData.gasPrice} decimals={9} /> Gwei)
</span>
{sendsEthToMiner && (
<span className="rounded text-yellow-500 bg-yellow-100 text-xs px-2 py-1">
Flashbots
</span>
)}
</div>
</InfoRow>
<InfoRow title="Gas Used/Limit">
<div className="flex space-x-3 items-baseline">
<div>
<GasValue value={txData.gasUsed} /> /{" "}
<GasValue value={txData.gasLimit} />
</div>
<PercentageBar
perc={
Math.round(
(txData.gasUsed.toNumber() / txData.gasLimit.toNumber()) * 10000
) / 100
}
/>
</div>
</InfoRow>
<InfoRow title="Ether Price">N/A</InfoRow>
<InfoRow title="Nonce">{txData.nonce}</InfoRow>
<InfoRow title="Position in Block">
<span className="rounded px-2 py-1 bg-gray-100 text-gray-500 text-xs">
{txData.transactionIndex}
</span>
</InfoRow>
<InfoRow title="Input Data">
<textarea
className="w-full h-40 bg-gray-50 text-gray-500 font-mono focus:outline-none border rounded p-2"
value={txData.data}
readOnly
/> />
</div> </InfoRow>
</InfoRow> </ContentFrame>
<InfoRow title="Ether Price">N/A</InfoRow> );
<InfoRow title="Nonce">{txData.nonce}</InfoRow> };
<InfoRow title="Position in Block">
<span className="rounded px-2 py-1 bg-gray-100 text-gray-500 text-xs">
{txData.transactionIndex}
</span>
</InfoRow>
<InfoRow title="Input Data">
<textarea
className="w-full h-40 bg-gray-50 text-gray-500 font-mono focus:outline-none border rounded p-2"
value={txData.data}
readOnly
/>
</InfoRow>
</ContentFrame>
);
export default React.memo(Details); export default React.memo(Details);

View File

@ -0,0 +1,54 @@
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBurn, faCoins } from "@fortawesome/free-solid-svg-icons";
import FormattedBalance from "../components/FormattedBalance";
import { TransactionData } from "../types";
type RewardSplitProps = {
txData: TransactionData;
};
const RewardSplit: React.FC<RewardSplitProps> = ({ txData }) => {
const burntFees = txData.blockBaseFeePerGas!.mul(txData.gasUsed);
const minerReward = txData.gasPrice.mul(txData.gasUsed).sub(burntFees);
const burntPerc =
burntFees.mul(10000).div(txData.gasPrice.mul(txData.gasUsed)).toNumber() /
100;
return (
<div className="inline-flex space-x-2">
<span className="flex space-x-1 text-orange-500">
<span title="Burnt fees">
<FontAwesomeIcon icon={faBurn} size="1x" />
</span>
<span>
<span className="line-through">
<FormattedBalance value={burntFees} />
</span>{" "}
Ether
</span>
</span>
<span className="flex space-x-1">
<span className="text-yellow-300" title="Miner fees">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
<span>
<FormattedBalance value={minerReward} /> Ether
</span>
</span>
<div className="self-center w-40 border rounded border-gray-200">
<div className="w-full h-5 rounded bg-orange-500 relative">
<div
className="absolute top-0 right-0 bg-yellow-200 h-full rounded-r"
style={{ width: `${100 - burntPerc}%` }}
></div>
<div className="w-full h-full absolute flex mix-blend-multiply text-sans text-gray-600">
<span className="m-auto">{burntPerc}%</span>
</div>
</div>
</div>
</div>
);
};
export default React.memo(RewardSplit);