Merge branch 'feature/burn-mint-decorations' into feature/self-destruct-trace
This commit is contained in:
commit
177929069f
@ -13,7 +13,7 @@ import NavButton from "./components/NavButton";
|
|||||||
import Timestamp from "./components/Timestamp";
|
import Timestamp from "./components/Timestamp";
|
||||||
import GasValue from "./components/GasValue";
|
import GasValue from "./components/GasValue";
|
||||||
import BlockLink from "./components/BlockLink";
|
import BlockLink from "./components/BlockLink";
|
||||||
import AddressOrENSName from "./components/AddressOrENSName";
|
import DecoratedAddressLink from "./components/DecoratedAddressLink";
|
||||||
import TransactionValue from "./components/TransactionValue";
|
import TransactionValue from "./components/TransactionValue";
|
||||||
import HexValue from "./components/HexValue";
|
import HexValue from "./components/HexValue";
|
||||||
import { RuntimeContext } from "./useRuntime";
|
import { RuntimeContext } from "./useRuntime";
|
||||||
@ -159,10 +159,7 @@ const Block: React.FC = () => {
|
|||||||
in this block
|
in this block
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
<InfoRow title="Mined by">
|
<InfoRow title="Mined by">
|
||||||
<AddressOrENSName
|
<DecoratedAddressLink address={block.miner} miner />
|
||||||
address={block.miner}
|
|
||||||
minerAddress={block.miner}
|
|
||||||
/>
|
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
<InfoRow title="Block Reward">
|
<InfoRow title="Block Reward">
|
||||||
<TransactionValue value={block.blockReward.add(block.feeReward)} />
|
<TransactionValue value={block.blockReward.add(block.feeReward)} />
|
||||||
|
@ -2,11 +2,10 @@ import React from "react";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faCaretRight } from "@fortawesome/free-solid-svg-icons";
|
import { faCaretRight } from "@fortawesome/free-solid-svg-icons";
|
||||||
import AddressHighlighter from "./components/AddressHighlighter";
|
import AddressHighlighter from "./components/AddressHighlighter";
|
||||||
import AddressOrENSName from "./components/AddressOrENSName";
|
import DecoratedAddressLink from "./components/DecoratedAddressLink";
|
||||||
import AddressLink from "./components/AddressLink";
|
|
||||||
import TokenLogo from "./components/TokenLogo";
|
import TokenLogo from "./components/TokenLogo";
|
||||||
import FormattedBalance from "./components/FormattedBalance";
|
import FormattedBalance from "./components/FormattedBalance";
|
||||||
import { TokenMetas, TokenTransfer } from "./types";
|
import { AddressContext, TokenMetas, TokenTransfer } from "./types";
|
||||||
|
|
||||||
type TokenTransferItemProps = {
|
type TokenTransferItemProps = {
|
||||||
t: TokenTransfer;
|
t: TokenTransfer;
|
||||||
@ -17,7 +16,7 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
|
|||||||
t,
|
t,
|
||||||
tokenMetas,
|
tokenMetas,
|
||||||
}) => (
|
}) => (
|
||||||
<div className="flex items-baseline space-x-2 truncate">
|
<div className="flex items-baseline space-x-2 px-2 py-1 truncate hover:bg-gray-100">
|
||||||
<span className="text-gray-500">
|
<span className="text-gray-500">
|
||||||
<FontAwesomeIcon icon={faCaretRight} size="1x" />
|
<FontAwesomeIcon icon={faCaretRight} size="1x" />
|
||||||
</span>
|
</span>
|
||||||
@ -25,13 +24,16 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
|
|||||||
<div className="flex space-x-1">
|
<div className="flex space-x-1">
|
||||||
<span className="font-bold">From</span>
|
<span className="font-bold">From</span>
|
||||||
<AddressHighlighter address={t.from}>
|
<AddressHighlighter address={t.from}>
|
||||||
<AddressOrENSName address={t.from} />
|
<DecoratedAddressLink
|
||||||
|
address={t.from}
|
||||||
|
addressCtx={AddressContext.FROM}
|
||||||
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-1">
|
<div className="flex space-x-1">
|
||||||
<span className="font-bold">To</span>
|
<span className="font-bold">To</span>
|
||||||
<AddressHighlighter address={t.to}>
|
<AddressHighlighter address={t.to}>
|
||||||
<AddressOrENSName address={t.to} />
|
<DecoratedAddressLink address={t.to} addressCtx={AddressContext.TO} />
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-3 flex space-x-1">
|
<div className="col-span-3 flex space-x-1">
|
||||||
@ -48,7 +50,7 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
|
|||||||
<div className="self-center">
|
<div className="self-center">
|
||||||
<TokenLogo address={t.token} name={tokenMetas[t.token].name} />
|
<TokenLogo address={t.token} name={tokenMetas[t.token].name} />
|
||||||
</div>
|
</div>
|
||||||
<AddressLink
|
<DecoratedAddressLink
|
||||||
address={t.token}
|
address={t.token}
|
||||||
text={`${tokenMetas[t.token].name} (${
|
text={`${tokenMetas[t.token].name} (${
|
||||||
tokenMetas[t.token].symbol
|
tokenMetas[t.token].symbol
|
||||||
@ -56,7 +58,7 @@ const TokenTransferItem: React.FC<TokenTransferItemProps> = ({
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<AddressOrENSName address={t.token} />
|
<DecoratedAddressLink address={t.token} />
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,11 +4,18 @@ import { NavLink } from "react-router-dom";
|
|||||||
type AddressLinkProps = {
|
type AddressLinkProps = {
|
||||||
address: string;
|
address: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
|
dontOverrideColors?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AddressLink: React.FC<AddressLinkProps> = ({ address, text }) => (
|
const AddressLink: React.FC<AddressLinkProps> = ({
|
||||||
|
address,
|
||||||
|
text,
|
||||||
|
dontOverrideColors,
|
||||||
|
}) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
className="text-link-blue hover:text-link-blue-hover font-address truncate"
|
className={`${
|
||||||
|
dontOverrideColors ? "" : "text-link-blue hover:text-link-blue-hover"
|
||||||
|
} font-address truncate`}
|
||||||
to={`/address/${address}`}
|
to={`/address/${address}`}
|
||||||
>
|
>
|
||||||
<p className="truncate" title={text ?? address}>
|
<p className="truncate" title={text ?? address}>
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import { faCoins } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import Address from "./Address";
|
import Address from "./Address";
|
||||||
import AddressLink from "./AddressLink";
|
import AddressLink from "./AddressLink";
|
||||||
import ENSName from "./ENSName";
|
import ENSName from "./ENSName";
|
||||||
@ -10,21 +8,18 @@ type AddressOrENSNameProps = {
|
|||||||
address: string;
|
address: string;
|
||||||
ensName?: string;
|
ensName?: string;
|
||||||
selectedAddress?: string;
|
selectedAddress?: string;
|
||||||
minerAddress?: string;
|
text?: string;
|
||||||
|
dontOverrideColors?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const AddressOrENSName: React.FC<AddressOrENSNameProps> = ({
|
const AddressOrENSName: React.FC<AddressOrENSNameProps> = ({
|
||||||
address,
|
address,
|
||||||
ensName,
|
ensName,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
minerAddress,
|
text,
|
||||||
|
dontOverrideColors,
|
||||||
}) => (
|
}) => (
|
||||||
<div className="flex items-baseline space-x-1 truncate">
|
<>
|
||||||
{minerAddress !== undefined && minerAddress === address && (
|
|
||||||
<span className="text-yellow-400" title="Miner address">
|
|
||||||
<FontAwesomeIcon icon={faCoins} size="1x" />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{address === selectedAddress ? (
|
{address === selectedAddress ? (
|
||||||
<>
|
<>
|
||||||
{ensName ? (
|
{ensName ? (
|
||||||
@ -36,13 +31,21 @@ const AddressOrENSName: React.FC<AddressOrENSNameProps> = ({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{ensName ? (
|
{ensName ? (
|
||||||
<ENSNameLink name={ensName} address={address} />
|
<ENSNameLink
|
||||||
|
name={ensName}
|
||||||
|
address={address}
|
||||||
|
dontOverrideColors={dontOverrideColors}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<AddressLink address={address} />
|
<AddressLink
|
||||||
|
address={address}
|
||||||
|
text={text}
|
||||||
|
dontOverrideColors={dontOverrideColors}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default React.memo(AddressOrENSName);
|
export default React.memo(AddressOrENSName);
|
||||||
|
63
src/components/DecoratedAddressLink.tsx
Normal file
63
src/components/DecoratedAddressLink.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import {
|
||||||
|
faMoneyBillAlt,
|
||||||
|
faBurn,
|
||||||
|
faCoins,
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import AddressOrENSName from "./AddressOrENSName";
|
||||||
|
import { AddressContext, ZERO_ADDRESS } from "../types";
|
||||||
|
|
||||||
|
type DecoratedAddressLinkProps = {
|
||||||
|
address: string;
|
||||||
|
ensName?: string;
|
||||||
|
selectedAddress?: string;
|
||||||
|
text?: string;
|
||||||
|
addressCtx?: AddressContext;
|
||||||
|
miner?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DecoratedAddresssLink: React.FC<DecoratedAddressLinkProps> = ({
|
||||||
|
address,
|
||||||
|
ensName,
|
||||||
|
selectedAddress,
|
||||||
|
text,
|
||||||
|
addressCtx,
|
||||||
|
miner,
|
||||||
|
}) => {
|
||||||
|
const mint = addressCtx === AddressContext.FROM && address === ZERO_ADDRESS;
|
||||||
|
const burn = addressCtx === AddressContext.TO && address === ZERO_ADDRESS;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`flex items-baseline space-x-1 ${
|
||||||
|
mint ? "italic text-green-500 hover:text-green-700" : ""
|
||||||
|
} ${burn ? "line-through text-orange-500 hover:text-orange-700" : ""}`}
|
||||||
|
>
|
||||||
|
{mint && (
|
||||||
|
<span className="text-green-500" title="Mint address">
|
||||||
|
<FontAwesomeIcon icon={faMoneyBillAlt} size="1x" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{burn && (
|
||||||
|
<span className="text-orange-500" title="Burn address">
|
||||||
|
<FontAwesomeIcon icon={faBurn} size="1x" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{miner && (
|
||||||
|
<span className="text-yellow-400" title="Miner address">
|
||||||
|
<FontAwesomeIcon icon={faCoins} size="1x" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<AddressOrENSName
|
||||||
|
address={address}
|
||||||
|
ensName={ensName}
|
||||||
|
selectedAddress={selectedAddress}
|
||||||
|
text={text}
|
||||||
|
dontOverrideColors={mint || burn}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(DecoratedAddresssLink);
|
@ -5,11 +5,18 @@ import ENSLogo from "./ensLogo.svg";
|
|||||||
type ENSNameLinkProps = {
|
type ENSNameLinkProps = {
|
||||||
name: string;
|
name: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
dontOverrideColors?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ENSNameLink: React.FC<ENSNameLinkProps> = ({ name, address }) => (
|
const ENSNameLink: React.FC<ENSNameLinkProps> = ({
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
dontOverrideColors,
|
||||||
|
}) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
className="flex items-baseline space-x-1 font-sans text-link-blue hover:text-link-blue-hover truncate"
|
className={`flex items-baseline space-x-1 font-sans ${
|
||||||
|
dontOverrideColors ? "" : "text-link-blue hover:text-link-blue-hover"
|
||||||
|
} truncate`}
|
||||||
to={`/address/${name}`}
|
to={`/address/${name}`}
|
||||||
title={`${name}: ${address}`}
|
title={`${name}: ${address}`}
|
||||||
>
|
>
|
||||||
|
@ -3,7 +3,7 @@ import { ethers } from "ethers";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faAngleRight, faCoins } from "@fortawesome/free-solid-svg-icons";
|
import { faAngleRight, faCoins } from "@fortawesome/free-solid-svg-icons";
|
||||||
import AddressHighlighter from "./AddressHighlighter";
|
import AddressHighlighter from "./AddressHighlighter";
|
||||||
import AddressLink from "./AddressLink";
|
import DecoratedAddressLink from "./DecoratedAddressLink";
|
||||||
import { TransactionData, Transfer } from "../types";
|
import { TransactionData, Transfer } from "../types";
|
||||||
|
|
||||||
type InternalTransferProps = {
|
type InternalTransferProps = {
|
||||||
@ -38,7 +38,7 @@ const InternalTransfer: React.FC<InternalTransferProps> = ({
|
|||||||
<FontAwesomeIcon icon={faCoins} size="1x" />
|
<FontAwesomeIcon icon={faCoins} size="1x" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<AddressLink address={transfer.from} />
|
<DecoratedAddressLink address={transfer.from} />
|
||||||
</div>
|
</div>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
</div>
|
</div>
|
||||||
@ -55,7 +55,7 @@ const InternalTransfer: React.FC<InternalTransferProps> = ({
|
|||||||
<FontAwesomeIcon icon={faCoins} size="1x" />
|
<FontAwesomeIcon icon={faCoins} size="1x" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<AddressLink address={transfer.to} />
|
<DecoratedAddressLink address={transfer.to} />
|
||||||
</div>
|
</div>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@ import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons";
|
|||||||
import MethodName from "../components/MethodName";
|
import MethodName from "../components/MethodName";
|
||||||
import BlockLink from "../components/BlockLink";
|
import BlockLink from "../components/BlockLink";
|
||||||
import TransactionLink from "../components/TransactionLink";
|
import TransactionLink from "../components/TransactionLink";
|
||||||
import AddressOrENSName from "../components/AddressOrENSName";
|
import DecoratedAddressLink from "../components/DecoratedAddressLink";
|
||||||
import TimestampAge from "../components/TimestampAge";
|
import TimestampAge from "../components/TimestampAge";
|
||||||
import AddressHighlighter from "../components/AddressHighlighter";
|
import AddressHighlighter from "../components/AddressHighlighter";
|
||||||
import TransactionDirection, {
|
import TransactionDirection, {
|
||||||
@ -71,11 +71,11 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
|||||||
<span className="truncate">
|
<span className="truncate">
|
||||||
{tx.from && (
|
{tx.from && (
|
||||||
<AddressHighlighter address={tx.from}>
|
<AddressHighlighter address={tx.from}>
|
||||||
<AddressOrENSName
|
<DecoratedAddressLink
|
||||||
address={tx.from}
|
address={tx.from}
|
||||||
ensName={ensFrom}
|
ensName={ensFrom}
|
||||||
selectedAddress={selectedAddress}
|
selectedAddress={selectedAddress}
|
||||||
minerAddress={tx.miner}
|
miner={tx.miner === tx.from}
|
||||||
/>
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
)}
|
)}
|
||||||
@ -91,11 +91,11 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
|||||||
<span className="truncate">
|
<span className="truncate">
|
||||||
{tx.to && (
|
{tx.to && (
|
||||||
<AddressHighlighter address={tx.to}>
|
<AddressHighlighter address={tx.to}>
|
||||||
<AddressOrENSName
|
<DecoratedAddressLink
|
||||||
address={tx.to}
|
address={tx.to}
|
||||||
ensName={ensTo}
|
ensName={ensTo}
|
||||||
selectedAddress={selectedAddress}
|
selectedAddress={selectedAddress}
|
||||||
minerAddress={tx.miner}
|
miner={tx.miner === tx.to}
|
||||||
/>
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
)}
|
)}
|
||||||
|
@ -9,7 +9,7 @@ import ContentFrame from "../ContentFrame";
|
|||||||
import InfoRow from "../components/InfoRow";
|
import InfoRow from "../components/InfoRow";
|
||||||
import BlockLink from "../components/BlockLink";
|
import BlockLink from "../components/BlockLink";
|
||||||
import AddressHighlighter from "../components/AddressHighlighter";
|
import AddressHighlighter from "../components/AddressHighlighter";
|
||||||
import AddressOrENSName from "../components/AddressOrENSName";
|
import DecoratedAddressLink from "../components/DecoratedAddressLink";
|
||||||
import Copy from "../components/Copy";
|
import Copy from "../components/Copy";
|
||||||
import Timestamp from "../components/Timestamp";
|
import Timestamp from "../components/Timestamp";
|
||||||
import InternalTransfer from "../components/InternalTransfer";
|
import InternalTransfer from "../components/InternalTransfer";
|
||||||
@ -65,7 +65,10 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
<InfoRow title="From">
|
<InfoRow title="From">
|
||||||
<div className="flex items-baseline space-x-2 -ml-1">
|
<div className="flex items-baseline space-x-2 -ml-1">
|
||||||
<AddressHighlighter address={txData.from}>
|
<AddressHighlighter address={txData.from}>
|
||||||
<AddressOrENSName address={txData.from} minerAddress={txData.miner} />
|
<DecoratedAddressLink
|
||||||
|
address={txData.from}
|
||||||
|
miner={txData.from === txData.miner}
|
||||||
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
<Copy value={txData.from} />
|
<Copy value={txData.from} />
|
||||||
</div>
|
</div>
|
||||||
@ -73,7 +76,10 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
<InfoRow title="Interacted With (To)">
|
<InfoRow title="Interacted With (To)">
|
||||||
<div className="flex items-baseline space-x-2 -ml-1">
|
<div className="flex items-baseline space-x-2 -ml-1">
|
||||||
<AddressHighlighter address={txData.to}>
|
<AddressHighlighter address={txData.to}>
|
||||||
<AddressOrENSName address={txData.to} minerAddress={txData.miner} />
|
<DecoratedAddressLink
|
||||||
|
address={txData.to}
|
||||||
|
miner={txData.to === txData.miner}
|
||||||
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
<Copy value={txData.to} />
|
<Copy value={txData.to} />
|
||||||
</div>
|
</div>
|
||||||
@ -97,7 +103,7 @@ const Details: React.FC<DetailsProps> = ({
|
|||||||
</InfoRow>
|
</InfoRow>
|
||||||
{txData.tokenTransfers.length > 0 && (
|
{txData.tokenTransfers.length > 0 && (
|
||||||
<InfoRow title={`Tokens Transferred (${txData.tokenTransfers.length})`}>
|
<InfoRow title={`Tokens Transferred (${txData.tokenTransfers.length})`}>
|
||||||
<div className="space-y-2">
|
<div>
|
||||||
{txData.tokenTransfers.map((t, i) => (
|
{txData.tokenTransfers.map((t, i) => (
|
||||||
<TokenTransferItem key={i} t={t} tokenMetas={txData.tokenMetas} />
|
<TokenTransferItem key={i} t={t} tokenMetas={txData.tokenMetas} />
|
||||||
))}
|
))}
|
||||||
|
@ -57,6 +57,14 @@ export type TransactionData = {
|
|||||||
logs: ethers.providers.Log[];
|
logs: ethers.providers.Log[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The VOID...
|
||||||
|
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
||||||
|
|
||||||
|
export enum AddressContext {
|
||||||
|
FROM,
|
||||||
|
TO,
|
||||||
|
}
|
||||||
|
|
||||||
export type From = {
|
export type From = {
|
||||||
current: string;
|
current: string;
|
||||||
depth: number;
|
depth: number;
|
||||||
|
Loading…
Reference in New Issue
Block a user