Initial ENS support for resolving names -> address on search
This commit is contained in:
parent
c2e37470e1
commit
62df32b82f
|
@ -1,5 +1,6 @@
|
||||||
import React, { useState, useEffect, useMemo } from "react";
|
import React, { useState, useEffect, useMemo } from "react";
|
||||||
import { useParams, useLocation, useHistory } from "react-router-dom";
|
import { useParams, useLocation, useHistory } from "react-router-dom";
|
||||||
|
import { ethers } from "ethers";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import Blockies from "react-blockies";
|
import Blockies from "react-blockies";
|
||||||
import StandardFrame from "./StandardFrame";
|
import StandardFrame from "./StandardFrame";
|
||||||
|
@ -12,10 +13,10 @@ import PendingResults from "./search/PendingResults";
|
||||||
import TransactionItem from "./search/TransactionItem";
|
import TransactionItem from "./search/TransactionItem";
|
||||||
import { SearchController } from "./search/search";
|
import { SearchController } from "./search/search";
|
||||||
import { useFeeToggler } from "./search/useFeeToggler";
|
import { useFeeToggler } from "./search/useFeeToggler";
|
||||||
import { ethers } from "ethers";
|
import { provider } from "./ethersconfig";
|
||||||
|
|
||||||
type BlockParams = {
|
type BlockParams = {
|
||||||
address: string;
|
addressOrName: string;
|
||||||
direction?: string;
|
direction?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,13 +34,33 @@ const AddressTransactions: React.FC = () => {
|
||||||
hash = qs.h as string;
|
hash = qs.h as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize to checksummed address
|
const [checksummedAddress, setChecksummedAddress] = useState<string>();
|
||||||
const checksummedAddress = useMemo(
|
const [isENS, setENS] = useState<boolean>();
|
||||||
() => ethers.utils.getAddress(params.address),
|
|
||||||
[params.address]
|
// If it looks like it is an ENS name, try to resolve it
|
||||||
);
|
useEffect(() => {
|
||||||
if (params.address !== checksummedAddress) {
|
if (ethers.utils.isAddress(params.addressOrName)) {
|
||||||
console.log("NORMALIZE");
|
// Normalize to checksummed address
|
||||||
|
setChecksummedAddress(ethers.utils.getAddress(params.addressOrName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveName = async () => {
|
||||||
|
const resolvedAddress = await provider.resolveName(params.addressOrName);
|
||||||
|
if (resolvedAddress !== null) {
|
||||||
|
setENS(true);
|
||||||
|
setChecksummedAddress(resolvedAddress);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
resolveName();
|
||||||
|
}, [params.addressOrName]);
|
||||||
|
|
||||||
|
// Request came with a non-checksummed address; fix the URL
|
||||||
|
if (
|
||||||
|
!isENS &&
|
||||||
|
checksummedAddress &&
|
||||||
|
params.addressOrName !== checksummedAddress
|
||||||
|
) {
|
||||||
history.replace(
|
history.replace(
|
||||||
`/address/${checksummedAddress}${
|
`/address/${checksummedAddress}${
|
||||||
params.direction ? "/" + params.direction : ""
|
params.direction ? "/" + params.direction : ""
|
||||||
|
@ -49,6 +70,10 @@ const AddressTransactions: React.FC = () => {
|
||||||
|
|
||||||
const [controller, setController] = useState<SearchController>();
|
const [controller, setController] = useState<SearchController>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!checksummedAddress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const readFirstPage = async () => {
|
const readFirstPage = async () => {
|
||||||
const _controller = await SearchController.firstPage(checksummedAddress);
|
const _controller = await SearchController.firstPage(checksummedAddress);
|
||||||
setController(_controller);
|
setController(_controller);
|
||||||
|
@ -100,24 +125,33 @@ const AddressTransactions: React.FC = () => {
|
||||||
|
|
||||||
const page = useMemo(() => controller?.getPage(), [controller]);
|
const page = useMemo(() => controller?.getPage(), [controller]);
|
||||||
|
|
||||||
document.title = `Address ${params.address} | Otterscan`;
|
document.title = `Address ${params.addressOrName} | Otterscan`;
|
||||||
|
|
||||||
const [feeDisplay, feeDisplayToggler] = useFeeToggler();
|
const [feeDisplay, feeDisplayToggler] = useFeeToggler();
|
||||||
|
|
||||||
|
if (!checksummedAddress) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StandardFrame>
|
<StandardFrame>
|
||||||
<StandardSubtitle>
|
<StandardSubtitle>
|
||||||
<div className="flex space-x-2 items-baseline">
|
<div className="flex space-x-2 items-baseline">
|
||||||
<Blockies
|
<Blockies
|
||||||
className="self-center rounded"
|
className="self-center rounded"
|
||||||
seed={params.address.toLowerCase()}
|
seed={checksummedAddress.toLowerCase()}
|
||||||
scale={3}
|
scale={3}
|
||||||
/>
|
/>
|
||||||
<span>Address</span>
|
<span>Address</span>
|
||||||
<span className="font-address text-base text-gray-500">
|
<span className="font-address text-base text-gray-500">
|
||||||
{params.address}
|
{checksummedAddress}
|
||||||
</span>
|
</span>
|
||||||
<Copy value={params.address} rounded />
|
<Copy value={checksummedAddress} rounded />
|
||||||
|
{isENS && (
|
||||||
|
<span className="rounded-lg px-2 py-1 bg-gray-200 text-gray-500 text-xs">
|
||||||
|
ENS: {params.addressOrName}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</StandardSubtitle>
|
</StandardSubtitle>
|
||||||
<ContentFrame>
|
<ContentFrame>
|
||||||
|
@ -130,7 +164,7 @@ const AddressTransactions: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<UndefinedPageControl
|
<UndefinedPageControl
|
||||||
address={params.address}
|
address={params.addressOrName}
|
||||||
isFirst={controller?.isFirst}
|
isFirst={controller?.isFirst}
|
||||||
isLast={controller?.isLast}
|
isLast={controller?.isLast}
|
||||||
prevHash={page ? page[0].hash : ""}
|
prevHash={page ? page[0].hash : ""}
|
||||||
|
@ -148,7 +182,7 @@ const AddressTransactions: React.FC = () => {
|
||||||
<TransactionItem
|
<TransactionItem
|
||||||
key={tx.hash}
|
key={tx.hash}
|
||||||
tx={tx}
|
tx={tx}
|
||||||
selectedAddress={params.address}
|
selectedAddress={params.addressOrName}
|
||||||
feeDisplay={feeDisplay}
|
feeDisplay={feeDisplay}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -159,7 +193,7 @@ const AddressTransactions: React.FC = () => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<UndefinedPageControl
|
<UndefinedPageControl
|
||||||
address={params.address}
|
address={params.addressOrName}
|
||||||
isFirst={controller.isFirst}
|
isFirst={controller.isFirst}
|
||||||
isLast={controller.isLast}
|
isLast={controller.isLast}
|
||||||
prevHash={page ? page[0].hash : ""}
|
prevHash={page ? page[0].hash : ""}
|
||||||
|
|
|
@ -30,7 +30,7 @@ const App = () => (
|
||||||
<Route path="/tx/:txhash">
|
<Route path="/tx/:txhash">
|
||||||
<Transaction />
|
<Transaction />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/address/:address/:direction?">
|
<Route path="/address/:addressOrName/:direction?">
|
||||||
<AddressTransactions />
|
<AddressTransactions />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
@ -27,7 +27,8 @@ const Search: React.FC = () => {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
history.replace("/");
|
// Assume it is an ENS name
|
||||||
|
history.replace(`/address/${q}`);
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue