Skip to content

Commit

Permalink
Remove unused components
Browse files Browse the repository at this point in the history
  • Loading branch information
ifavo committed Nov 29, 2024
1 parent b390fb2 commit c39494e
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 492 deletions.
38 changes: 11 additions & 27 deletions app/[locale]/address/[addressOrName]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,23 @@
import AllowanceDashboard from 'components/allowances/dashboard/AllowanceDashboard';
import { getChainName } from 'lib/utils/chains';
import { shortenAddress } from 'lib/utils/formatting';
import { getTranslations } from 'next-intl/server';
import { getAddressAndDomainName } from 'lib/utils/whois';
import type { Metadata, NextPage } from 'next';
import { getTranslations, unstable_setRequestLocale } from 'next-intl/server';
import { notFound } from 'next/navigation';
import AllowanceDashboard from 'components/allowances/dashboard/AllowanceDashboard';
import { Address } from 'viem';

interface Props {
params: {
locale: string;
addressOrName: string;
locale: string;
};
}

export const generateMetadata = async ({ params: { locale, addressOrName }, searchParams }): Promise<Metadata> => {
const t = await getTranslations({ locale });

export default async function Page({ params: { addressOrName, locale } }: Props) {
const t = await getTranslations();
const { address, domainName } = await getAddressAndDomainName(addressOrName);
const addressDisplay = domainName ?? shortenAddress(address);

const chainName = getChainName(Number(searchParams.chainId || 1));

const title = !!searchParams.chainId
? t('address.meta.title_chain', { addressDisplay, chainName })
: t('address.meta.title', { addressDisplay });

return {
title,
description: t('common.meta.description', { chainName: chainName ?? 'Ethereum' }),
};
};

const AddressPage: NextPage<Props> = async ({ params }) => {
unstable_setRequestLocale(params.locale);
if (!address) {
notFound();
}

return <AllowanceDashboard />;
};

export default AddressPage;
}
145 changes: 92 additions & 53 deletions components/common/AddressSearchBox.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,101 @@
import { ArrowRightCircleIcon } from '@heroicons/react/24/outline';
import { XMarkIcon } from '@heroicons/react/24/solid';
import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl';
import { useRouter } from 'next/navigation';
import { parseInputAddress } from 'lib/utils/whois';
import { ChangeEventHandler, FormEventHandler, HTMLAttributes } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useWallet } from '@vechain/dapp-kit-react';
import Button from './Button';
import SearchBox from './SearchBox';
import Spinner from './Spinner';

interface Props extends Omit<HTMLAttributes<HTMLInputElement>, 'onSubmit'> {
onSubmit: FormEventHandler<HTMLFormElement>;
onChange: ChangeEventHandler<HTMLInputElement>;
value: string;
placeholder: string;
import Input from './Input';
import { ArrowRightCircleIcon } from '@heroicons/react/24/outline';
import { MagnifyingGlassIcon, XMarkIcon } from '@heroicons/react/24/solid';

interface Props {
className?: string;
placeholder?: string;
onSubmit?: (address: string) => void;
id?: string;
value?: string;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
}

const AddressSearchBox = ({ onSubmit, onChange, value, placeholder, className, ...props }: Props) => {
const {
data: isValid,
isLoading: validating,
refetch,
} = useQuery({
queryKey: ['validate', value],
queryFn: async () => !!(await parseInputAddress(value)),
enabled: !!value,
// Chances of this data changing while the user is on the page are very slim
staleTime: Infinity,
});

const handleSubmit: FormEventHandler<HTMLFormElement> = async (event) => {
event.preventDefault();

// If the validation is still loading, then we await it so that the submit happens immediately after validation
// Note: since the validation is cached, this does not cause an extra network request
const { data: isValid } = await refetch();

if (!isValid || !value) return;
onSubmit(event);
};
export const AddressSearchBox = ({ className, placeholder, onSubmit, id, value, onChange }: Props) => {
const t = useTranslations();
const router = useRouter();
const { account: connectedAddress } = useWallet();
const [inputValue, setInputValue] = useState('');
const [isValid, setIsValid] = useState(false);
const [hasInput, setHasInput] = useState(false);
const [isValidating, setIsValidating] = useState(false);

const validateInput = useCallback(async (val: string) => {
const trimmedValue = val?.trim() || '';
setHasInput(!!trimmedValue);

if (!trimmedValue) {
setIsValid(false);
return;
}

setIsValidating(true);
try {
// Check if it's a valid address or can be resolved to one
const address = await parseInputAddress(trimmedValue);
setIsValid(!!address);
} catch {
setIsValid(false);
} finally {
setIsValidating(false);
}
}, []);

useEffect(() => {
validateInput(value ?? inputValue);
}, [value, inputValue, validateInput]);

const handleSubmit = useCallback(
async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const address = await parseInputAddress(value ?? inputValue);
if (!address) return;

if (onSubmit) {
onSubmit(address);
} else {
router.push(`/address/${address}`);
}
},
[value, inputValue, onSubmit, router],
);

return (
<SearchBox
onSubmit={handleSubmit}
onChange={onChange}
value={value}
placeholder={placeholder}
className={className}
{...props}
>
{value && validating && <Spinner className="w-4 h-4" />}
{value && !validating && !isValid && <XMarkIcon className="w-6 h-6 text-red-500" />}
{value && !validating && isValid && (
<Button style="tertiary" size="none" aria-label="Check Address">
<ArrowRightCircleIcon className="w-6 h-6" />
</Button>
)}
</SearchBox>
<form onSubmit={handleSubmit} className={`h-9 flex gap-2 items-center border px-2 font-medium focus-within:ring-black dark:focus-within:ring-white ${className}`}>
<MagnifyingGlassIcon className="w-6 h-6 text-zinc-500 dark:text-zinc-300" />
<input
id={id}
type="text"
placeholder={placeholder ?? t('nav.search')}
value={value ?? inputValue}
onChange={onChange ?? ((e) => setInputValue(e.target.value))}
className="grow focus-visible:outline-none bg-transparent"
aria-label={placeholder ?? t('nav.search')}
/>
<Button
type="submit"
style="none"
size="none"
aria-label={t('buttons.check')}
className="focus-visible:outline-none focus-visible:ring-black dark:focus-visible:ring-white focus-visible:ring-2 focus-visible:rounded"
>
{hasInput && !isValidating && (
isValid ? (
<ArrowRightCircleIcon className="w-6 h-6" />
) : (
<XMarkIcon className="w-6 h-6 text-red-500" />
)
)}
{isValidating && (
<div className="w-6 h-6 border-2 border-t-transparent border-zinc-500 rounded-full animate-spin" />
)}
</Button>
</form>
);
};

export default AddressSearchBox;
2 changes: 1 addition & 1 deletion components/header/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import AddressSearchBox from 'components/common/AddressSearchBox';
import { AddressSearchBox } from 'components/common/AddressSearchBox';
import { useRouter } from 'lib/i18n/navigation';
import { useTranslations } from 'next-intl';
import { useState } from 'react';
Expand Down
58 changes: 0 additions & 58 deletions cypress/e2e/whois.cy.ts

This file was deleted.

2 changes: 0 additions & 2 deletions lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export const WHOIS_BASE_URL = 'https://whois.revoke.cash/generated';

export const ADDRESS_ZERO_PADDED = '0x0000000000000000000000000000000000000000000000000000000000000000';
export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000';
export const DUMMY_ADDRESS_PADDED = '0x0000000000000000000000000000000000000000000000000000000000000001';
Expand Down
24 changes: 3 additions & 21 deletions lib/hooks/ethereum/events/useEvents.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { ERC721_ABI } from 'lib/abis';
import { addressToTopic } from 'lib/utils';
import { generatePatchedAllowanceEvents } from 'lib/utils/allowances';
import { useMemo } from 'react';
import { Address, getAbiItem, toEventSelector } from 'viem';
import { useLogsFullBlockRange } from '../useLogsFullBlockRange';
import { useOpenSeaProxyAddress } from '../useOpenSeaProxyAddress';
import { usePermit2Events } from './usePermit2Events';

export const useEvents = (address: Address, chainId: number) => {
const { openSeaProxyAddress, isLoading: isOpenSeaProxyAddressLoading } = useOpenSeaProxyAddress(address);

const getErc721EventSelector = (eventName: 'Transfer' | 'Approval' | 'ApprovalForAll') => {
return toEventSelector(getAbiItem({ abi: ERC721_ABI, name: eventName }));
};
Expand Down Expand Up @@ -39,7 +35,7 @@ export const useEvents = (address: Address, chainId: number) => {
} = useLogsFullBlockRange('Approval', chainId, { topics: approvalTopics });

const {
data: approvalForAllUnpatched,
data: approvalForAll,
isLoading: isApprovalForAllLoading,
error: approvalForAllError,
} = useLogsFullBlockRange('ApprovalForAll', chainId, { topics: approvalForAllTopics });
Expand All @@ -50,30 +46,16 @@ export const useEvents = (address: Address, chainId: number) => {
error: permit2ApprovalError,
} = usePermit2Events(address, chainId);

// Manually patch the ApprovalForAll events
const approvalForAll = useMemo(() => {
if (!transferFrom || !transferTo || !approval || !approvalForAllUnpatched) return undefined;
return [
...approvalForAllUnpatched,
...generatePatchedAllowanceEvents(address, openSeaProxyAddress, [
...approval,
...approvalForAllUnpatched,
...transferFrom,
...transferTo,
]),
];
}, [transferFrom, transferTo, approval, approvalForAllUnpatched, openSeaProxyAddress]);

const isEventsLoading = isTransferFromLoading || isTransferToLoading || isApprovalLoading || isApprovalForAllLoading;
const isLoading = isOpenSeaProxyAddressLoading || isEventsLoading || isPermit2ApprovalLoading;
const isLoading = isEventsLoading || isPermit2ApprovalLoading;
const eventsError = transferFromError || transferToError || approvalError || approvalForAllError;
const error = eventsError || permit2ApprovalError;

const events = useMemo(() => {
if (!transferFrom || !transferTo || !approval || !approvalForAll || !permit2Approval) return undefined;
if (error || isLoading) return undefined;
return { transferFrom, transferTo, approval, approvalForAll, permit2Approval };
}, [transferFrom, transferTo, approval, approvalForAll, permit2Approval]);
}, [transferFrom, transferTo, approval, approvalForAll, permit2Approval, error, isLoading]);

return { events, isLoading, error };
};
4 changes: 0 additions & 4 deletions lib/hooks/ethereum/useLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,5 @@ export const useLogs = (name: string, chainId: number, filter: Filter) => {
enabled: !!chainId && ![filter?.fromBlock, filter?.toBlock, filter?.topics].includes(undefined),
});

useEffect(() => {
if (result.data) console.log(`${name} events`, result.data);
}, [result.data]);

return { ...result };
};
34 changes: 12 additions & 22 deletions lib/hooks/ethereum/useNameLookup.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
import { useQuery } from '@tanstack/react-query';
import { HOUR } from 'lib/utils/time';
import { lookupAvvyName, lookupEnsName, lookupUnsName } from 'lib/utils/whois';
import { DAY } from 'lib/utils/time';
import { resolveVetName } from 'lib/utils/whois';
import { Address } from 'viem';

export const useNameLookup = (address: Address) => {
const { data: ensName } = useQuery({
queryKey: ['ensName', address, { persist: true }],
queryFn: () => lookupEnsName(address),
export const useNameLookup = (address: Address | undefined) => {
const { data: domainName, isLoading } = useQuery({
queryKey: ['domainName', address, { persist: true }],
queryFn: async () => {
if (!address) return null;
return resolveVetName(address);
},
enabled: !!address,
staleTime: 12 * HOUR,
gcTime: 7 * DAY,
staleTime: 5 * DAY,
});

const { data: unsName } = useQuery({
queryKey: ['unsName', address, { persist: true }],
queryFn: () => lookupUnsName(address),
enabled: !!address,
staleTime: 12 * HOUR,
});

const { data: avvyName } = useQuery<string>({
queryKey: ['avvyName', address, { persist: true }],
queryFn: () => lookupAvvyName(address),
enabled: !!address,
staleTime: 12 * HOUR,
});

return { ensName, unsName, avvyName, domainName: ensName || unsName || avvyName };
return { domainName, isLoading };
};
Loading

0 comments on commit c39494e

Please sign in to comment.