Extract and generalize ETH address fixing logic
This commit is contained in:
parent
d9592fe196
commit
3bfe0d0055
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect, useContext } from "react";
|
import React, { useEffect, useContext, useCallback } from "react";
|
||||||
import {
|
import {
|
||||||
useParams,
|
useParams,
|
||||||
useNavigate,
|
useNavigate,
|
||||||
|
@ -6,7 +6,6 @@ import {
|
||||||
Route,
|
Route,
|
||||||
useSearchParams,
|
useSearchParams,
|
||||||
} from "react-router-dom";
|
} from "react-router-dom";
|
||||||
import { getAddress, isAddress } from "@ethersproject/address";
|
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
import Blockies from "react-blockies";
|
import Blockies from "react-blockies";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
@ -21,7 +20,9 @@ import AddressTransactionResults from "./address/AddressTransactionResults";
|
||||||
import Contracts from "./address/Contracts";
|
import Contracts from "./address/Contracts";
|
||||||
import { RuntimeContext } from "./useRuntime";
|
import { RuntimeContext } from "./useRuntime";
|
||||||
import { useAppConfigContext } from "./useAppConfig";
|
import { useAppConfigContext } from "./useAppConfig";
|
||||||
|
import { useAddressOrENSFromURL } from "./useResolvedAddresses";
|
||||||
import { useSingleMetadata } from "./sourcify/useSourcify";
|
import { useSingleMetadata } from "./sourcify/useSourcify";
|
||||||
|
import { ChecksummedAddress } from "./types";
|
||||||
|
|
||||||
const AddressTransactions: React.FC = () => {
|
const AddressTransactions: React.FC = () => {
|
||||||
const { provider } = useContext(RuntimeContext);
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
@ -32,56 +33,29 @@ const AddressTransactions: React.FC = () => {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
const urlFixer = useCallback(
|
||||||
const [checksummedAddress, setChecksummedAddress] = useState<
|
(address: ChecksummedAddress) => {
|
||||||
string | undefined
|
|
||||||
>();
|
|
||||||
const [isENS, setENS] = useState<boolean>();
|
|
||||||
const [error, setError] = useState<boolean>();
|
|
||||||
|
|
||||||
// If it looks like it is an ENS name, try to resolve it
|
|
||||||
useEffect(() => {
|
|
||||||
// TODO: handle and offer fallback to bad checksummed addresses
|
|
||||||
if (isAddress(addressOrName)) {
|
|
||||||
setENS(false);
|
|
||||||
setError(false);
|
|
||||||
|
|
||||||
// Normalize to checksummed address
|
|
||||||
const _checksummedAddress = getAddress(addressOrName);
|
|
||||||
if (_checksummedAddress !== addressOrName) {
|
|
||||||
// Request came with a non-checksummed address; fix the URL
|
|
||||||
navigate(
|
navigate(
|
||||||
`/address/${_checksummedAddress}${
|
`/address/${address}${
|
||||||
direction ? "/" + direction : ""
|
direction ? "/" + direction : ""
|
||||||
}?${searchParams.toString()}`,
|
}?${searchParams.toString()}`,
|
||||||
{ replace: true }
|
{ replace: true }
|
||||||
);
|
);
|
||||||
return;
|
},
|
||||||
}
|
[navigate, direction, searchParams]
|
||||||
|
);
|
||||||
|
const [checksummedAddress, isENS, error] = useAddressOrENSFromURL(
|
||||||
|
addressOrName,
|
||||||
|
urlFixer
|
||||||
|
);
|
||||||
|
|
||||||
setChecksummedAddress(_checksummedAddress);
|
useEffect(() => {
|
||||||
document.title = `Address ${_checksummedAddress} | Otterscan`;
|
if (isENS || checksummedAddress === undefined) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!provider) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const resolveName = async () => {
|
|
||||||
const resolvedAddress = await provider.resolveName(addressOrName);
|
|
||||||
if (resolvedAddress !== null) {
|
|
||||||
setENS(true);
|
|
||||||
setError(false);
|
|
||||||
setChecksummedAddress(resolvedAddress);
|
|
||||||
document.title = `Address ${addressOrName} | Otterscan`;
|
document.title = `Address ${addressOrName} | Otterscan`;
|
||||||
} else {
|
} else {
|
||||||
setENS(false);
|
document.title = `Address ${checksummedAddress} | Otterscan`;
|
||||||
setError(true);
|
|
||||||
setChecksummedAddress(undefined);
|
|
||||||
}
|
}
|
||||||
};
|
}, [addressOrName, checksummedAddress, isENS]);
|
||||||
resolveName();
|
|
||||||
}, [provider, addressOrName, navigate, direction, searchParams]);
|
|
||||||
|
|
||||||
const { sourcifySource } = useAppConfigContext();
|
const { sourcifySource } = useAppConfigContext();
|
||||||
const addressMetadata = useSingleMetadata(
|
const addressMetadata = useSingleMetadata(
|
||||||
|
|
|
@ -1,8 +1,68 @@
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef, useContext } from "react";
|
||||||
import { JsonRpcProvider } from "@ethersproject/providers";
|
import { JsonRpcProvider } from "@ethersproject/providers";
|
||||||
import { ProcessedTransaction, TransactionData } from "./types";
|
import { getAddress, isAddress } from "@ethersproject/address";
|
||||||
import { batchPopulate, ResolvedAddresses } from "./api/address-resolver";
|
import { batchPopulate, ResolvedAddresses } from "./api/address-resolver";
|
||||||
import { TraceGroup } from "./useErigonHooks";
|
import { TraceGroup } from "./useErigonHooks";
|
||||||
|
import { RuntimeContext } from "./useRuntime";
|
||||||
|
import {
|
||||||
|
ChecksummedAddress,
|
||||||
|
ProcessedTransaction,
|
||||||
|
TransactionData,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
export const useAddressOrENSFromURL = (
|
||||||
|
addressOrName: string,
|
||||||
|
urlFixer: (address: ChecksummedAddress) => void
|
||||||
|
): [
|
||||||
|
ChecksummedAddress | undefined,
|
||||||
|
boolean | undefined,
|
||||||
|
boolean | undefined
|
||||||
|
] => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const [checksummedAddress, setChecksummedAddress] = useState<
|
||||||
|
ChecksummedAddress | undefined
|
||||||
|
>();
|
||||||
|
const [isENS, setENS] = useState<boolean>();
|
||||||
|
const [error, setError] = useState<boolean>();
|
||||||
|
|
||||||
|
// If it looks like it is an ENS name, try to resolve it
|
||||||
|
useEffect(() => {
|
||||||
|
// TODO: handle and offer fallback to bad checksummed addresses
|
||||||
|
if (isAddress(addressOrName)) {
|
||||||
|
// Normalize to checksummed address
|
||||||
|
const _checksummedAddress = getAddress(addressOrName);
|
||||||
|
if (_checksummedAddress !== addressOrName) {
|
||||||
|
// Request came with a non-checksummed address; fix the URL
|
||||||
|
urlFixer(_checksummedAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setENS(false);
|
||||||
|
setError(false);
|
||||||
|
setChecksummedAddress(_checksummedAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const resolveName = async () => {
|
||||||
|
const resolvedAddress = await provider.resolveName(addressOrName);
|
||||||
|
if (resolvedAddress !== null) {
|
||||||
|
setENS(true);
|
||||||
|
setError(false);
|
||||||
|
setChecksummedAddress(resolvedAddress);
|
||||||
|
} else {
|
||||||
|
setENS(false);
|
||||||
|
setError(true);
|
||||||
|
setChecksummedAddress(undefined);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
resolveName();
|
||||||
|
}, [provider, addressOrName, urlFixer]);
|
||||||
|
|
||||||
|
return [checksummedAddress, isENS, error];
|
||||||
|
};
|
||||||
|
|
||||||
export type AddressCollector = () => string[];
|
export type AddressCollector = () => string[];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue