otterscan/src/AddressTransactions.tsx

186 lines
6.3 KiB
TypeScript
Raw Normal View History

import React, { useState, useEffect, useContext } from "react";
import {
useParams,
2021-11-25 09:28:45 +00:00
useNavigate,
Routes,
Route,
2021-11-25 09:28:45 +00:00
useSearchParams,
} from "react-router-dom";
import { getAddress, isAddress } from "@ethersproject/address";
2021-09-05 20:39:11 +00:00
import { Tab } from "@headlessui/react";
2021-07-01 18:21:40 +00:00
import Blockies from "react-blockies";
2021-09-10 07:31:24 +00:00
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons/faQuestionCircle";
2021-07-01 18:21:40 +00:00
import StandardFrame from "./StandardFrame";
import StandardSubtitle from "./StandardSubtitle";
import Copy from "./components/Copy";
2021-09-06 06:34:13 +00:00
import NavTab from "./components/NavTab";
import AddressTransactionResults from "./address/AddressTransactionResults";
2021-07-24 23:33:45 +00:00
import Contracts from "./address/Contracts";
2021-07-09 05:07:20 +00:00
import { RuntimeContext } from "./useRuntime";
import { useAppConfigContext } from "./useAppConfig";
import { useSingleMetadata } from "./useSourcify";
2021-10-21 21:25:57 +00:00
import SourcifyLogo from "./sourcify.svg";
2021-07-01 18:21:40 +00:00
const AddressTransactions: React.FC = () => {
2021-07-09 05:07:20 +00:00
const { provider } = useContext(RuntimeContext);
2021-11-25 09:28:45 +00:00
const { addressOrName, direction } = useParams();
if (addressOrName === undefined) {
throw new Error("addressOrName couldn't be undefined here");
}
const navigate = useNavigate();
const [searchParams] = useSearchParams();
2021-07-01 18:21:40 +00:00
2021-11-25 09:28:45 +00:00
const [checksummedAddress, setChecksummedAddress] = useState<
string | undefined
>();
const [isENS, setENS] = useState<boolean>();
2021-07-02 19:20:50 +00:00
const [error, setError] = useState<boolean>();
// If it looks like it is an ENS name, try to resolve it
useEffect(() => {
2021-11-25 09:28:45 +00:00
// TODO: handle and offer fallback to bad checksummed addresses
if (isAddress(addressOrName)) {
setENS(false);
setError(false);
// Normalize to checksummed address
2021-11-25 09:28:45 +00:00
const _checksummedAddress = getAddress(addressOrName);
if (_checksummedAddress !== addressOrName) {
// Request came with a non-checksummed address; fix the URL
2021-11-25 09:28:45 +00:00
navigate(
`/address/${_checksummedAddress}${
2021-11-25 09:28:45 +00:00
direction ? "/" + direction : ""
}?${searchParams.toString()}`,
{ replace: true }
);
2021-11-25 09:28:45 +00:00
return;
}
2021-11-25 09:28:45 +00:00
setChecksummedAddress(_checksummedAddress);
2021-11-25 09:28:45 +00:00
document.title = `Address ${_checksummedAddress} | Otterscan`;
return;
}
2021-07-08 19:02:42 +00:00
if (!provider) {
return;
}
const resolveName = async () => {
2021-11-25 09:28:45 +00:00
const resolvedAddress = await provider.resolveName(addressOrName);
if (resolvedAddress !== null) {
setENS(true);
2021-07-02 19:20:50 +00:00
setError(false);
setChecksummedAddress(resolvedAddress);
2021-11-25 09:28:45 +00:00
document.title = `Address ${addressOrName} | Otterscan`;
2021-07-02 19:20:50 +00:00
} else {
setENS(false);
2021-07-02 19:20:50 +00:00
setError(true);
setChecksummedAddress(undefined);
}
};
resolveName();
2021-11-25 09:28:45 +00:00
}, [provider, addressOrName, navigate, direction, searchParams]);
2021-07-01 18:21:40 +00:00
const { sourcifySource } = useAppConfigContext();
const addressMetadata = useSingleMetadata(
checksummedAddress,
2021-09-06 21:32:11 +00:00
provider?.network.chainId,
sourcifySource
2021-09-06 00:13:01 +00:00
);
2021-07-14 06:52:31 +00:00
2021-07-01 18:21:40 +00:00
return (
<StandardFrame>
2021-07-02 19:20:50 +00:00
{error ? (
<span className="text-base">
2021-11-25 09:28:45 +00:00
"{addressOrName}" is not an ETH address or ENS name.
2021-07-02 19:20:50 +00:00
</span>
) : (
checksummedAddress && (
2021-07-01 18:21:40 +00:00
<>
2021-07-02 19:20:50 +00:00
<StandardSubtitle>
<div className="flex space-x-2 items-baseline">
<Blockies
className="self-center rounded"
seed={checksummedAddress.toLowerCase()}
scale={3}
/>
<span>Address</span>
<span className="font-address text-base text-gray-500">
{checksummedAddress}
</span>
<Copy value={checksummedAddress} rounded />
{isENS && (
<span className="rounded-lg px-2 py-1 bg-gray-200 text-gray-500 text-xs">
2021-11-25 09:28:45 +00:00
ENS: {addressOrName}
2021-07-02 19:20:50 +00:00
</span>
2021-07-01 18:21:40 +00:00
)}
</div>
2021-07-02 19:20:50 +00:00
</StandardSubtitle>
2021-09-05 20:39:11 +00:00
<Tab.Group>
<Tab.List className="flex space-x-2 border-l border-r border-t rounded-t-lg bg-white">
2021-09-06 06:43:20 +00:00
<NavTab href={`/address/${checksummedAddress}`}>
Overview
</NavTab>
<NavTab href={`/address/${checksummedAddress}/contract`}>
2021-09-10 07:31:24 +00:00
<span
2021-09-10 08:16:06 +00:00
className={`flex items-baseline space-x-2 ${
addressMetadata === undefined ? "italic opacity-50" : ""
2021-09-10 07:31:24 +00:00
}`}
>
2021-09-10 08:16:06 +00:00
<span>Contract</span>
{addressMetadata === undefined ? (
2021-09-10 08:16:06 +00:00
<span className="self-center">
<FontAwesomeIcon
className="animate-spin"
icon={faCircleNotch}
/>
2021-09-10 07:31:24 +00:00
</span>
) : addressMetadata === null ? (
2021-09-10 08:16:06 +00:00
<span className="self-center text-red-500">
2021-09-10 07:31:24 +00:00
<FontAwesomeIcon icon={faQuestionCircle} />
</span>
) : (
<span className="self-center">
<img
2021-10-21 21:25:57 +00:00
src={SourcifyLogo}
alt="Sourcify logo"
title="Verified by Sourcify"
width={16}
height={16}
/>
2021-09-10 07:31:24 +00:00
</span>
)}
</span>
2021-09-06 06:43:20 +00:00
</NavTab>
2021-09-05 20:39:11 +00:00
</Tab.List>
<Tab.Panels>
2021-11-25 09:28:45 +00:00
<Routes>
<Route
path="*"
element={
<AddressTransactionResults address={checksummedAddress} />
2021-11-25 09:28:45 +00:00
}
/>
<Route
path="contract"
element={
<Contracts
checksummedAddress={checksummedAddress}
rawMetadata={addressMetadata}
/>
}
/>
</Routes>
2021-09-05 20:39:11 +00:00
</Tab.Panels>
</Tab.Group>
2021-07-01 18:21:40 +00:00
</>
2021-07-02 19:20:50 +00:00
)
)}
2021-07-01 18:21:40 +00:00
</StandardFrame>
);
};
2021-11-25 09:28:45 +00:00
export default AddressTransactions;