From 6dc6e63b9559e8542532d21878f160b0d5f98c13 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:03:01 -0300 Subject: [PATCH 1/4] Signal miner address on transaction page and blokc ktransaction list --- src/BlockTransactions.tsx | 1 + src/Transaction.tsx | 76 ++++++----------------------- src/components/InternalTransfer.tsx | 57 ++++++++++++++++++++++ src/search/TransactionItem.tsx | 22 ++++++--- src/types.ts | 54 +++++++++++++++++++- 5 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 src/components/InternalTransfer.tsx diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index d0bb9b8..47be1a8 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -55,6 +55,7 @@ const BlockTransactions: React.FC = () => { return { blockNumber: blockNumber.toNumber(), timestamp: _block.timestamp, + miner: _block.miner, idx: i, hash: t.hash, from: t.from, diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 2d95833..da0d33d 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -5,7 +5,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle, faTimesCircle, - faAngleRight, faCaretRight, } from "@fortawesome/free-solid-svg-icons"; import { provider } from "./ethersconfig"; @@ -17,10 +16,18 @@ import BlockLink from "./components/BlockLink"; import AddressLink from "./components/AddressLink"; import Copy from "./components/Copy"; import Timestamp from "./components/Timestamp"; +import InternalTransfer from "./components/InternalTransfer"; import TokenLogo from "./components/TokenLogo"; import GasValue from "./components/GasValue"; import FormattedBalance from "./components/FormattedBalance"; import erc20 from "./erc20.json"; +import { + From, + TokenMetas, + TokenTransfer, + TransactionData, + Transfer, +} from "./types"; const USE_OTS = true; @@ -31,56 +38,6 @@ type TransactionParams = { txhash: string; }; -type TransactionData = { - transactionHash: string; - status: boolean; - blockNumber: number; - transactionIndex: number; - confirmations: number; - timestamp: number; - from: string; - to: string; - value: BigNumber; - tokenTransfers: TokenTransfer[]; - tokenMetas: TokenMetas; - fee: BigNumber; - gasPrice: BigNumber; - gasLimit: BigNumber; - gasUsed: BigNumber; - gasUsedPerc: number; - nonce: number; - data: string; - logs: ethers.providers.Log[]; -}; - -type From = { - current: string; - depth: number; -}; - -type Transfer = { - from: string; - to: string; - value: BigNumber; -}; - -type TokenTransfer = { - token: string; - from: string; - to: string; - value: BigNumber; -}; - -type TokenMeta = { - name: string; - symbol: string; - decimals: number; -}; - -type TokenMetas = { - [tokenAddress: string]: TokenMeta; -}; - const Transaction: React.FC = () => { const params = useParams(); const { txhash } = params; @@ -142,6 +99,7 @@ const Transaction: React.FC = () => { transactionIndex: _receipt.transactionIndex, confirmations: _receipt.confirmations, timestamp: _block.timestamp, + miner: _block.miner, from: _receipt.from, to: _receipt.to, value: _response.value, @@ -289,17 +247,11 @@ const Transaction: React.FC = () => { {transfers ? (
{transfers.map((t, i) => ( -
- - {" "} - TRANSFER - - {ethers.utils.formatEther(t.value)} Ether - From - - To - -
+ ))}
) : ( diff --git a/src/components/InternalTransfer.tsx b/src/components/InternalTransfer.tsx new file mode 100644 index 0000000..ac8f7d7 --- /dev/null +++ b/src/components/InternalTransfer.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { ethers } from "ethers"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faAngleRight, faCoins } from "@fortawesome/free-solid-svg-icons"; +import AddressLink from "./AddressLink"; +import { TransactionData, Transfer } from "../types"; + +type InternalTransferProps = { + txData: TransactionData; + transfer: Transfer; +}; + +const InternalTransfer: React.FC = ({ + txData, + transfer, +}) => { + const fromMiner = + txData.miner !== undefined && transfer.from === txData.miner; + const toMiner = txData.miner !== undefined && transfer.to === txData.miner; + + return ( +
+ + TRANSFER + + {ethers.utils.formatEther(transfer.value)} Ether + From +
+ {fromMiner && ( + + + + )} + +
+ To +
+ {toMiner && ( + + + + )} + +
+
+ ); +}; + +export default React.memo(InternalTransfer); diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 4e74b35..b901f16 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -1,6 +1,9 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons"; +import { + faExclamationCircle, + faCoins, +} from "@fortawesome/free-solid-svg-icons"; import MethodName from "../components/MethodName"; import BlockLink from "../components/BlockLink"; import TransactionLink from "../components/TransactionLink"; @@ -63,11 +66,18 @@ const TransactionItem: React.FC = ({ {tx.from && ( - +
+ {tx.miner && tx.miner === tx.from && ( + + + + )} + +
)}
diff --git a/src/types.ts b/src/types.ts index 170fe58..404721d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,9 @@ -import { BigNumber } from "ethers"; +import { ethers, BigNumber } from "ethers"; export type ProcessedTransaction = { blockNumber: number; timestamp: number; + miner?: string; idx: number; hash: string; from?: string; @@ -23,3 +24,54 @@ export type TransactionChunk = { export type ENSReverseCache = { [address: string]: string; }; + +export type TransactionData = { + transactionHash: string; + status: boolean; + blockNumber: number; + transactionIndex: number; + confirmations: number; + timestamp: number; + miner?: string; + from: string; + to: string; + value: BigNumber; + tokenTransfers: TokenTransfer[]; + tokenMetas: TokenMetas; + fee: BigNumber; + gasPrice: BigNumber; + gasLimit: BigNumber; + gasUsed: BigNumber; + gasUsedPerc: number; + nonce: number; + data: string; + logs: ethers.providers.Log[]; +}; + +export type From = { + current: string; + depth: number; +}; + +export type Transfer = { + from: string; + to: string; + value: BigNumber; +}; + +export type TokenTransfer = { + token: string; + from: string; + to: string; + value: BigNumber; +}; + +export type TokenMeta = { + name: string; + symbol: string; + decimals: number; +}; + +export type TokenMetas = { + [tokenAddress: string]: TokenMeta; +}; From 1b32f4e8886a533d65fc9e88402ec78d1abfbd75 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:34:40 -0300 Subject: [PATCH 2/4] Highlight flashbot-like txs inside blocks --- src/BlockTransactions.tsx | 67 +++++++++++++++++-------- src/components/TransactionDirection.tsx | 28 +++++++++-- src/search/TransactionItem.tsx | 13 ++++- src/types.ts | 1 + 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 47be1a8..87e73de 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -11,7 +11,7 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import BlockLink from "./components/BlockLink"; -import { ProcessedTransaction } from "./types"; +import { ProcessedTransaction, Transfer } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; import { useENSCache } from "./useReverseCache"; @@ -49,28 +49,51 @@ const BlockTransactions: React.FC = () => { ]); document.title = `Block #${_block.number} Transactions | Otterscan`; - setTxs( - _block.transactions - .map((t, i) => { - return { - blockNumber: blockNumber.toNumber(), - timestamp: _block.timestamp, - miner: _block.miner, - idx: i, - hash: t.hash, - from: t.from, - to: t.to, - value: t.value, - fee: provider.formatter - .bigNumber(_receipts[i].gasUsed) - .mul(t.gasPrice!), - gasPrice: t.gasPrice!, - data: t.data, - status: provider.formatter.number(_receipts[i].status), - }; - }) - .reverse() + const responses = _block.transactions + .map((t, i): ProcessedTransaction => { + return { + blockNumber: blockNumber.toNumber(), + timestamp: _block.timestamp, + miner: _block.miner, + idx: i, + hash: t.hash, + from: t.from, + to: t.to, + value: t.value, + fee: provider.formatter + .bigNumber(_receipts[i].gasUsed) + .mul(t.gasPrice!), + gasPrice: t.gasPrice!, + data: t.data, + status: provider.formatter.number(_receipts[i].status), + }; + }) + .reverse(); + + const internalChecks = await Promise.all( + responses.map(async (res) => { + const r = await provider.send("ots_getTransactionTransfers", [ + res.hash, + ]); + for (const t of r) { + if ( + res.miner && + (res.miner === ethers.utils.getAddress(t.from) || + res.miner === ethers.utils.getAddress(t.to)) + ) { + return true; + } + } + return false; + }) ); + for (let i = 0; i < responses.length; i++) { + if (internalChecks[i]) { + responses[i].internalMinerInteraction = true; + } + } + + setTxs(responses); }; readBlock(); }, [blockNumber]); diff --git a/src/components/TransactionDirection.tsx b/src/components/TransactionDirection.tsx index ee22e12..927bda1 100644 --- a/src/components/TransactionDirection.tsx +++ b/src/components/TransactionDirection.tsx @@ -1,6 +1,9 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faLongArrowAltRight } from "@fortawesome/free-solid-svg-icons"; +import { + faCoins, + faLongArrowAltRight, +} from "@fortawesome/free-solid-svg-icons"; export enum Direction { IN, @@ -9,12 +12,18 @@ export enum Direction { INTERNAL, } +export enum Flags { + MINER, +} + type TransactionDirectionProps = { direction?: Direction; + flags?: Flags; }; const TransactionDirection: React.FC = ({ direction, + flags, }) => { let bgColor = "bg-green-50"; let fgColor = "text-green-500"; @@ -34,6 +43,11 @@ const TransactionDirection: React.FC = ({ msg = "INT"; } + if (flags === Flags.MINER) { + bgColor = "bg-yellow-50"; + fgColor = "text-yellow-400"; + } + return ( = ({ : "w-5 h-5 rounded-full flex justify-center items-center" } text-xs font-bold`} > - {msg ?? ( - - - + {flags === Flags.MINER ? ( + + ) : ( + msg ?? ( + + + + ) )} ); diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index b901f16..57ce084 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -11,6 +11,7 @@ import AddressOrENSName from "../components/AddressOrENSName"; import TimestampAge from "../components/TimestampAge"; import TransactionDirection, { Direction, + Flags, } from "../components/TransactionDirection"; import TransactionValue from "../components/TransactionValue"; import { ENSReverseCache, ProcessedTransaction } from "../types"; @@ -45,9 +46,14 @@ const TransactionItem: React.FC = ({ const ensFrom = ensCache && tx.from && ensCache[tx.from]; const ensTo = ensCache && tx.to && ensCache[tx.to]; + const flash = tx.gasPrice.isZero() && tx.internalMinerInteraction; return ( -
+
{tx.status === 0 && ( @@ -81,7 +87,10 @@ const TransactionItem: React.FC = ({ )} - + diff --git a/src/types.ts b/src/types.ts index 404721d..36537f8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -8,6 +8,7 @@ export type ProcessedTransaction = { hash: string; from?: string; to?: string; + internalMinerInteraction?: boolean; value: BigNumber; fee: BigNumber; gasPrice: BigNumber; From 8ebc07806462cbb7d900da8a45829d8407665c27 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:37:05 -0300 Subject: [PATCH 3/4] Darken internal transactions --- src/components/TransactionDirection.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/TransactionDirection.tsx b/src/components/TransactionDirection.tsx index 927bda1..3695a77 100644 --- a/src/components/TransactionDirection.tsx +++ b/src/components/TransactionDirection.tsx @@ -41,6 +41,7 @@ const TransactionDirection: React.FC = ({ msg = "SELF"; } else if (direction === Direction.INTERNAL) { msg = "INT"; + bgColor = "bg-green-100" } if (flags === Flags.MINER) { From 560e47ed17a5b4e0b7dd45caa8069f449ef51bd9 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:46:25 -0300 Subject: [PATCH 4/4] Remove unused import --- src/BlockTransactions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 87e73de..c780485 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -11,7 +11,7 @@ import ResultHeader from "./search/ResultHeader"; import PendingResults from "./search/PendingResults"; import TransactionItem from "./search/TransactionItem"; import BlockLink from "./components/BlockLink"; -import { ProcessedTransaction, Transfer } from "./types"; +import { ProcessedTransaction } from "./types"; import { PAGE_SIZE } from "./params"; import { useFeeToggler } from "./search/useFeeToggler"; import { useENSCache } from "./useReverseCache";