Initial tracking ot self-destructs

This commit is contained in:
Willian Mitsuda 2021-07-17 15:58:33 -03:00
parent 1ab77bb819
commit 683da61778
7 changed files with 152 additions and 23 deletions

View File

@ -105,19 +105,24 @@ const Transaction: React.FC = () => {
readBlock();
}, [provider, txhash]);
const transfers = useInternalTransfers(provider, txData);
const intTransfers = useInternalTransfers(provider, txData);
const sendsEthToMiner = useMemo(() => {
if (!txData || !transfers) {
if (!txData || !intTransfers) {
return false;
}
for (const t of transfers) {
for (const t of intTransfers.transfers) {
if (t.to === txData.miner) {
return true;
}
}
for (const t of intTransfers.selfDestructs) {
if (t.to === txData.miner) {
return true;
}
}
return false;
}, [txData, transfers]);
}, [txData, intTransfers]);
const selectionCtx = useSelection();
@ -136,7 +141,7 @@ const Transaction: React.FC = () => {
<Route path="/tx/:txhash/" exact>
<Details
txData={txData}
transfers={transfers}
internalTransfers={intTransfers}
sendsEthToMiner={sendsEthToMiner}
/>
</Route>

View File

@ -0,0 +1,82 @@
import React from "react";
import { ethers } from "ethers";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faAngleRight,
faBomb,
faCoins,
} from "@fortawesome/free-solid-svg-icons";
import AddressHighlighter from "./AddressHighlighter";
import AddressLink from "./AddressLink";
import { TransactionData, Transfer } from "../types";
type InternalSelfDestructProps = {
txData: TransactionData;
transfer: Transfer;
};
const InternalSelfDestruct: React.FC<InternalSelfDestructProps> = ({
txData,
transfer,
}) => {
const fromMiner =
txData.miner !== undefined && transfer.from === txData.miner;
const toMiner = txData.miner !== undefined && transfer.to === txData.miner;
return (
<>
<div className="flex items-baseline space-x-1 text-xs">
<span className="text-gray-500">
<span className="text-red-900">
<FontAwesomeIcon icon={faBomb} size="1x" />
</span>{" "}
SELF DESTRUCT
</span>
<span>Contract</span>
<div className="flex items-baseline">
<AddressHighlighter address={transfer.from}>
<div
className={`flex items-baseline space-x-1 ${
fromMiner ? "rounded px-2 py-1 bg-yellow-100" : ""
}`}
>
{fromMiner && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
<AddressLink address={transfer.from} />
</div>
</AddressHighlighter>
</div>
</div>
{!transfer.value.isZero() && (
<div className="ml-5 flex items-baseline space-x-1 text-xs">
<span className="text-gray-500">
<FontAwesomeIcon icon={faAngleRight} size="1x" /> TRANSFER
</span>
<span>{ethers.utils.formatEther(transfer.value)} Ether</span>
<div className="flex items-baseline">
<span className="text-gray-500">To</span>
<AddressHighlighter address={transfer.to}>
<div
className={`flex items-baseline space-x-1 ${
toMiner ? "rounded px-2 py-1 bg-yellow-100" : ""
}`}
>
{toMiner && (
<span className="text-yellow-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
<AddressLink address={transfer.to} />
</div>
</AddressHighlighter>
</div>
</div>
)}
</>
);
};
export default React.memo(InternalSelfDestruct);

View File

@ -5,12 +5,31 @@ export const getTransactionTransfers = async (
provider: ethers.providers.JsonRpcProvider,
txData: TransactionData
) => {
const r = await provider.send("ots_getTransactionTransfers", [
const rawTransfers = await provider.send("ots_getTransactionTransfers", [
txData.transactionHash,
]);
const _transfers: Transfer[] = [];
for (const t of r) {
for (const t of rawTransfers) {
_transfers.push({
from: ethers.utils.getAddress(t.from),
to: ethers.utils.getAddress(t.to),
value: t.value,
});
}
return _transfers;
};
export const getTransactionSelfDestructs = async (
provider: ethers.providers.JsonRpcProvider,
txData: TransactionData
) => {
const rawTransfers = await provider.send("ots_getTransactionSelfDestructs", [
txData.transactionHash,
]);
const _transfers: Transfer[] = [];
for (const t of rawTransfers) {
_transfers.push({
from: ethers.utils.getAddress(t.from),
to: ethers.utils.getAddress(t.to),

View File

@ -1,3 +1,3 @@
export const MIN_API_LEVEL = 1;
export const MIN_API_LEVEL = 2;
export const PAGE_SIZE = 25;

View File

@ -13,21 +13,22 @@ import AddressOrENSName from "../components/AddressOrENSName";
import Copy from "../components/Copy";
import Timestamp from "../components/Timestamp";
import InternalTransfer from "../components/InternalTransfer";
import InternalSelfDestruct from "../components/InternalSelfDestruct";
import MethodName from "../components/MethodName";
import GasValue from "../components/GasValue";
import FormattedBalance from "../components/FormattedBalance";
import TokenTransferItem from "../TokenTransferItem";
import { TransactionData, Transfer } from "../types";
import { InternalTransfers, TransactionData } from "../types";
type DetailsProps = {
txData: TransactionData;
transfers?: Transfer[];
internalTransfers?: InternalTransfers;
sendsEthToMiner: boolean;
};
const Details: React.FC<DetailsProps> = ({
txData,
transfers,
internalTransfers,
sendsEthToMiner,
}) => (
<ContentFrame tabs>
@ -76,12 +77,19 @@ const Details: React.FC<DetailsProps> = ({
</AddressHighlighter>
<Copy value={txData.to} />
</div>
{transfers && (
<div className="mt-2 space-y-1">
{transfers.map((t, i) => (
<InternalTransfer key={i} txData={txData} transfer={t} />
))}
</div>
{internalTransfers && (
<>
<div className="mt-2 space-y-1">
{internalTransfers.transfers.map((t, i) => (
<InternalTransfer key={i} txData={txData} transfer={t} />
))}
</div>
<div className="mt-2 space-y-1">
{internalTransfers.selfDestructs.map((t, i) => (
<InternalSelfDestruct key={i} txData={txData} transfer={t} />
))}
</div>
</>
)}
</InfoRow>
<InfoRow title="Transaction Action">

View File

@ -68,6 +68,11 @@ export type Transfer = {
value: BigNumber;
};
export type InternalTransfers = {
transfers: Transfer[];
selfDestructs: Transfer[];
};
export type TokenTransfer = {
token: string;
from: string;

View File

@ -1,13 +1,16 @@
import { ethers } from "ethers";
import { useState, useEffect } from "react";
import { getTransactionTransfers } from "./nodeFunctions";
import { TransactionData, Transfer } from "./types";
import {
getTransactionSelfDestructs,
getTransactionTransfers,
} from "./nodeFunctions";
import { InternalTransfers, TransactionData } from "./types";
export const useInternalTransfers = (
provider: ethers.providers.JsonRpcProvider | undefined,
txData: TransactionData | undefined
) => {
const [transfers, setTransfers] = useState<Transfer[]>();
): InternalTransfers | undefined => {
const [intTransfers, setIntTransfers] = useState<InternalTransfers>();
useEffect(() => {
const traceTransfers = async () => {
@ -16,10 +19,17 @@ export const useInternalTransfers = (
}
const _transfers = await getTransactionTransfers(provider, txData);
setTransfers(_transfers);
const _selfDestructs = await getTransactionSelfDestructs(
provider,
txData
);
for (const s of _selfDestructs) {
s.value = provider.formatter.bigNumber(s.value);
}
setIntTransfers({ transfers: _transfers, selfDestructs: _selfDestructs });
};
traceTransfers();
}, [provider, txData]);
return transfers;
return intTransfers;
};