From 50f4abf23fb49c6ed58b34e95dab5c020f8157a4 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 4 Sep 2021 03:19:42 -0300 Subject: [PATCH] Squash pending tx initial implementation --- src/Transaction.tsx | 23 ++- src/components/InternalSelfDestruct.tsx | 4 +- src/components/InternalTransfer.tsx | 7 +- src/transaction/Details.tsx | 192 ++++++++++++++---------- src/transaction/Logs.tsx | 6 +- src/transaction/RewardSplit.tsx | 6 +- src/types.ts | 28 ++-- src/useErigonHooks.ts | 80 ++++++---- 8 files changed, 207 insertions(+), 139 deletions(-) diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 94f998f..5d10101 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -2,6 +2,7 @@ import React, { useMemo, useContext } from "react"; import { Route, Switch, useParams } from "react-router-dom"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; +import ContentFrame from "./ContentFrame"; import Tab from "./components/Tab"; import Details from "./transaction/Details"; import Logs from "./transaction/Logs"; @@ -28,7 +29,7 @@ const Transaction: React.FC = () => { } for (const t of internalOps) { - if (t.to === txData.miner) { + if (t.to === txData.confirmedData?.miner) { return true; } } @@ -37,18 +38,30 @@ const Transaction: React.FC = () => { const selectionCtx = useSelection(); - const blockETHUSDPrice = useETHUSDOracle(provider, txData?.blockNumber); + const blockETHUSDPrice = useETHUSDOracle( + provider, + txData?.confirmedData?.blockNumber + ); return ( Transaction Details + {txData === null && ( + +
+ Transaction {txhash} not found. +
+
+ )} {txData && (
Overview - - Logs{txData && ` (${txData.logs.length})`} - + {txData.confirmedData?.blockNumber !== undefined && ( + + Logs{txData && ` (${txData.confirmedData?.logs?.length ?? 0})`} + + )}
diff --git a/src/components/InternalSelfDestruct.tsx b/src/components/InternalSelfDestruct.tsx index 384ef14..007fb32 100644 --- a/src/components/InternalSelfDestruct.tsx +++ b/src/components/InternalSelfDestruct.tsx @@ -22,7 +22,9 @@ const InternalSelfDestruct: React.FC = ({ const { provider } = useContext(RuntimeContext); const network = provider?.network; - const toMiner = txData.miner !== undefined && internalOp.to === txData.miner; + const toMiner = + txData.confirmedData?.miner !== undefined && + internalOp.to === txData.confirmedData.miner; return ( <> diff --git a/src/components/InternalTransfer.tsx b/src/components/InternalTransfer.tsx index b126d6f..dc53d05 100644 --- a/src/components/InternalTransfer.tsx +++ b/src/components/InternalTransfer.tsx @@ -16,8 +16,11 @@ const InternalTransfer: React.FC = ({ internalOp, }) => { const fromMiner = - txData.miner !== undefined && internalOp.from === txData.miner; - const toMiner = txData.miner !== undefined && internalOp.to === txData.miner; + txData.confirmedData?.miner !== undefined && + internalOp.from === txData.confirmedData.miner; + const toMiner = + txData.confirmedData?.miner !== undefined && + internalOp.to === txData.confirmedData.miner; return (
diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 6f46e7f..e5ba19a 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -43,8 +43,8 @@ const Details: React.FC = ({ ethUSDPrice, }) => { const hasEIP1559 = - txData.blockBaseFeePerGas !== undefined && - txData.blockBaseFeePerGas !== null; + txData.confirmedData?.blockBaseFeePerGas !== undefined && + txData.confirmedData?.blockBaseFeePerGas !== null; const [inputMode, setInputMode] = useState(0); const utfInput = useMemo(() => { @@ -66,7 +66,9 @@ const Details: React.FC = ({
- {txData.status ? ( + {txData.confirmedData === undefined ? ( + Pending + ) : txData.confirmedData.status ? ( Success @@ -78,38 +80,45 @@ const Details: React.FC = ({ )} - -
-
- - - - - -
-
- - -
-
-
- - - + {txData.confirmedData && ( + <> + +
+
+ + + + + +
+
+ + +
+
+
+ + + + + )}
@@ -126,22 +135,28 @@ const Details: React.FC = ({
+ ) : txData.confirmedData === undefined ? ( + + Pending contract creation + ) : (
- + - +
)} {internalOps && internalOps.length > 0 && ( @@ -218,68 +233,81 @@ const Details: React.FC = ({ )} - -
- - Ether ( - Gwei) - - {sendsEthToMiner && ( - - Flashbots + {txData.gasPrice && ( + +
+ + Ether ( + Gwei) - )} -
-
- -
-
- } - total={} + {sendsEthToMiner && ( + + Flashbots + + )} +
+ + )} + {txData.confirmedData && ( + +
+
+ } + total={} + /> +
+
- -
-
- {hasEIP1559 && ( + + )} + {txData.confirmedData && hasEIP1559 && ( - {" "} + {" "} Gwei ( {" "} wei) )} - -
-
- Ether{" "} - {ethUSDPrice && ( - - - - )} -
- {hasEIP1559 && } -
-
- - - + {txData.confirmedData && ( + <> + +
+
+ Ether{" "} + {ethUSDPrice && ( + + + + )} +
+ {hasEIP1559 && } +
+
+ + + + + )}
diff --git a/src/transaction/Logs.tsx b/src/transaction/Logs.tsx index b81fd9d..e57dc6a 100644 --- a/src/transaction/Logs.tsx +++ b/src/transaction/Logs.tsx @@ -10,8 +10,8 @@ type LogsProps = { const Logs: React.FC = ({ txData }) => (
Transaction Receipt Event Logs
- {txData && - txData.logs.map((l, i) => ( + {txData.confirmedData && + txData.confirmedData.logs.map((l, i) => (
@@ -24,7 +24,7 @@ const Logs: React.FC = ({ txData }) => (
diff --git a/src/transaction/RewardSplit.tsx b/src/transaction/RewardSplit.tsx index 8c45cd0..7d35a7e 100644 --- a/src/transaction/RewardSplit.tsx +++ b/src/transaction/RewardSplit.tsx @@ -11,8 +11,10 @@ type RewardSplitProps = { }; const RewardSplit: React.FC = ({ txData }) => { - const paidFees = txData.gasPrice.mul(txData.gasUsed); - const burntFees = txData.blockBaseFeePerGas!.mul(txData.gasUsed); + const paidFees = txData.gasPrice.mul(txData.confirmedData!.gasUsed); + const burntFees = txData.confirmedData!.blockBaseFeePerGas!.mul( + txData.confirmedData!.gasUsed + ); const minerReward = paidFees.sub(burntFees); const burntPerc = diff --git a/src/types.ts b/src/types.ts index 42c298d..5a5dad9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -38,29 +38,33 @@ export type ENSReverseCache = { export type TransactionData = { transactionHash: string; - status: boolean; - blockNumber: number; - transactionIndex: number; - blockTransactionCount: number; - confirmations: number; - timestamp: number; - miner?: string; from: string; - to: string; - createdContractAddress?: string; + to?: string; value: BigNumber; tokenTransfers: TokenTransfer[]; tokenMetas: TokenMetas; type: number; maxFeePerGas?: BigNumber | undefined; maxPriorityFeePerGas?: BigNumber | undefined; - fee: BigNumber; - blockBaseFeePerGas?: BigNumber | undefined | null; gasPrice: BigNumber; - gasUsed: BigNumber; gasLimit: BigNumber; nonce: number; data: string; + confirmedData?: ConfirmedTransactionData | undefined; +}; + +export type ConfirmedTransactionData = { + status: boolean; + blockNumber: number; + transactionIndex: number; + blockBaseFeePerGas?: BigNumber | undefined | null; + blockTransactionCount: number; + confirmations: number; + timestamp: number; + miner: string; + createdContractAddress?: string; + fee: BigNumber; + gasUsed: BigNumber; logs: Log[]; }; diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 48bc5ac..477f7b4 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -174,8 +174,8 @@ export const useBlockData = ( export const useTxData = ( provider: JsonRpcProvider | undefined, txhash: string -): TransactionData | undefined => { - const [txData, setTxData] = useState(); +): TransactionData | undefined | null => { + const [txData, setTxData] = useState(); useEffect(() => { if (!provider) { @@ -187,24 +187,35 @@ export const useTxData = ( provider.getTransaction(txhash), provider.getTransactionReceipt(txhash), ]); - const _block = await readBlock(provider, _receipt.blockNumber.toString()); + if (_response === null) { + setTxData(null); + return; + } + + let _block: ExtendedBlock | undefined; + if (_response.blockNumber) { + _block = await readBlock(provider, _response.blockNumber.toString()); + } + document.title = `Transaction ${_response.hash} | Otterscan`; // Extract token transfers const tokenTransfers: TokenTransfer[] = []; - for (const l of _receipt.logs) { - if (l.topics.length !== 3) { - continue; + if (_receipt) { + for (const l of _receipt.logs) { + if (l.topics.length !== 3) { + continue; + } + if (l.topics[0] !== TRANSFER_TOPIC) { + continue; + } + tokenTransfers.push({ + token: l.address, + from: getAddress(hexDataSlice(arrayify(l.topics[1]), 12)), + to: getAddress(hexDataSlice(arrayify(l.topics[2]), 12)), + value: BigNumber.from(l.data), + }); } - if (l.topics[0] !== TRANSFER_TOPIC) { - continue; - } - tokenTransfers.push({ - token: l.address, - from: getAddress(hexDataSlice(arrayify(l.topics[1]), 12)), - to: getAddress(hexDataSlice(arrayify(l.topics[2]), 12)), - value: BigNumber.from(l.data), - }); } // Extract token meta @@ -227,31 +238,36 @@ export const useTxData = ( } setTxData({ - transactionHash: _receipt.transactionHash, - status: _receipt.status === 1, - blockNumber: _receipt.blockNumber, - transactionIndex: _receipt.transactionIndex, - blockTransactionCount: _block.transactionCount, - confirmations: _receipt.confirmations, - timestamp: _block.timestamp, - miner: _block.miner, - from: _receipt.from, - to: _receipt.to, - createdContractAddress: _receipt.contractAddress, + transactionHash: _response.hash, + from: _response.from, + to: _response.to, value: _response.value, tokenTransfers, tokenMetas, type: _response.type ?? 0, - fee: _response.gasPrice!.mul(_receipt.gasUsed), - blockBaseFeePerGas: _block.baseFeePerGas, maxFeePerGas: _response.maxFeePerGas, maxPriorityFeePerGas: _response.maxPriorityFeePerGas, gasPrice: _response.gasPrice!, - gasUsed: _receipt.gasUsed, gasLimit: _response.gasLimit, nonce: _response.nonce, data: _response.data, - logs: _receipt.logs, + confirmedData: + _receipt === null + ? undefined + : { + status: _receipt.status === 1, + blockNumber: _receipt.blockNumber, + transactionIndex: _receipt.transactionIndex, + blockBaseFeePerGas: _block!.baseFeePerGas, + blockTransactionCount: _block!.transactionCount, + confirmations: _receipt.confirmations, + timestamp: _block!.timestamp, + miner: _block!.miner, + createdContractAddress: _receipt.contractAddress, + fee: _response.gasPrice!.mul(_receipt.gasUsed), + gasUsed: _receipt.gasUsed, + logs: _receipt.logs, + }, }); }; readTxData(); @@ -262,13 +278,13 @@ export const useTxData = ( export const useInternalOperations = ( provider: JsonRpcProvider | undefined, - txData: TransactionData | undefined + txData: TransactionData | undefined | null ): InternalOperation[] | undefined => { const [intTransfers, setIntTransfers] = useState(); useEffect(() => { const traceTransfers = async () => { - if (!provider || !txData) { + if (!provider || !txData || !txData.confirmedData) { return; }