From 1b32f4e8886a533d65fc9e88402ec78d1abfbd75 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 5 Jul 2021 00:34:40 -0300 Subject: [PATCH] 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;