otterscan/src/components/DecoratedAddressLink.tsx

169 lines
4.8 KiB
TypeScript
Raw Normal View History

2022-08-07 02:32:08 +00:00
import React, { PropsWithChildren, useContext } from "react";
import { NavLink } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faStar } from "@fortawesome/free-solid-svg-icons/faStar";
import { faBomb } from "@fortawesome/free-solid-svg-icons/faBomb";
import { faMoneyBillAlt } from "@fortawesome/free-solid-svg-icons/faMoneyBillAlt";
import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn";
import { faCoins } from "@fortawesome/free-solid-svg-icons/faCoins";
2021-11-25 18:48:17 +00:00
import SourcifyLogo from "../sourcify/SourcifyLogo";
2022-02-27 16:39:25 +00:00
import PlainAddress from "./PlainAddress";
2021-11-25 18:50:59 +00:00
import { Metadata } from "../sourcify/useSourcify";
2022-02-27 16:39:25 +00:00
import { RuntimeContext } from "../useRuntime";
import { useResolvedAddress } from "../useResolvedAddresses";
import { AddressContext, ChecksummedAddress, ZERO_ADDRESS } from "../types";
import { resolverRendererRegistry } from "../api/address-resolver";
type DecoratedAddressLinkProps = {
2022-02-27 16:39:25 +00:00
address: ChecksummedAddress;
selectedAddress?: ChecksummedAddress | undefined;
2022-02-27 16:22:59 +00:00
addressCtx?: AddressContext | undefined;
creation?: boolean | undefined;
miner?: boolean | undefined;
selfDestruct?: boolean | undefined;
txFrom?: boolean | undefined;
txTo?: boolean | undefined;
metadata?: Metadata | null | undefined;
2022-02-27 16:54:20 +00:00
eoa?: boolean | undefined;
};
2021-10-31 00:14:11 +00:00
const DecoratedAddressLink: React.FC<DecoratedAddressLinkProps> = ({
address,
selectedAddress,
addressCtx,
creation,
miner,
2021-07-19 07:19:24 +00:00
selfDestruct,
txFrom,
txTo,
metadata,
2022-02-27 16:54:20 +00:00
eoa,
}) => {
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 ${
txFrom ? "bg-skin-from" : ""
} ${txTo ? "bg-skin-to" : ""} ${
2022-08-08 04:56:24 +00:00
mint ? "italic text-emerald-500 hover:text-emerald-700" : ""
} ${burn ? "line-through text-orange-500 hover:text-orange-700" : ""} ${
selfDestruct ? "line-through opacity-70 hover:opacity-100" : ""
}`}
>
{creation && (
2022-08-08 04:56:24 +00:00
<span className="text-amber-300" title="Contract creation">
<FontAwesomeIcon icon={faStar} size="1x" />
</span>
)}
{selfDestruct && (
<span className="text-red-800" title="Self destruct">
<FontAwesomeIcon icon={faBomb} size="1x" />
</span>
)}
{mint && (
2022-08-08 04:56:24 +00:00
<span className="text-emerald-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 && (
2022-08-08 04:56:24 +00:00
<span className="text-amber-400" title="Miner address">
<FontAwesomeIcon icon={faCoins} size="1x" />
</span>
)}
{metadata && (
<NavLink
className="self-center flex-shrink-0 flex items-center"
to={`/address/${address}/contract`}
>
2021-11-25 18:48:17 +00:00
<SourcifyLogo />
</NavLink>
)}
2022-02-27 16:39:25 +00:00
<ResolvedAddress
address={address}
selectedAddress={selectedAddress}
dontOverrideColors={mint || burn}
/>
{!mint && !burn && (
<>
{eoa === true && (
<AddressLegend title="Externally owned account">
2022-03-06 00:06:35 +00:00
[EOA]
</AddressLegend>
)}
{eoa === false && (
2022-03-06 00:06:35 +00:00
<AddressLegend title="Contract account">[C]</AddressLegend>
)}
</>
2022-02-27 16:54:20 +00:00
)}
</div>
);
};
2022-02-27 16:39:25 +00:00
type ResolvedAddressProps = {
address: ChecksummedAddress;
selectedAddress?: ChecksummedAddress | undefined;
dontOverrideColors?: boolean;
};
const ResolvedAddress: React.FC<ResolvedAddressProps> = ({
address,
selectedAddress,
dontOverrideColors,
}) => {
const { provider } = useContext(RuntimeContext);
const resolvedAddress = useResolvedAddress(provider, address);
const linkable = address !== selectedAddress;
if (!provider || !resolvedAddress) {
return (
<PlainAddress
address={address}
linkable={linkable}
dontOverrideColors={dontOverrideColors}
/>
);
}
const [resolver, resolvedName] = resolvedAddress;
const renderer = resolverRendererRegistry.get(resolver);
if (renderer === undefined) {
return (
<PlainAddress
address={address}
linkable={linkable}
dontOverrideColors={dontOverrideColors}
/>
);
}
return renderer(
provider.network.chainId,
address,
resolvedName,
linkable,
!!dontOverrideColors
);
};
2022-03-02 09:35:05 +00:00
type AddressLegendProps = {
title: string;
};
2022-08-07 02:32:08 +00:00
const AddressLegend: React.FC<PropsWithChildren<AddressLegendProps>> = ({
title,
children,
}) => (
<span className="text-xs text-gray-400/70 not-italic" title={title}>
2022-03-02 09:35:05 +00:00
{children}
</span>
);
2021-10-31 00:14:11 +00:00
export default React.memo(DecoratedAddressLink);