From 9538ec4c5421197d3f1f302b72b9879c73046936 Mon Sep 17 00:00:00 2001 From: Paul Cramer Date: Fri, 2 Aug 2024 12:58:31 -0700 Subject: [PATCH] Use chainId instead of chain --- src/identity/hooks/useName.ts | 6 +++--- src/identity/types.ts | 4 ++-- src/identity/utils/getName.test.tsx | 16 ++++++++-------- src/identity/utils/getName.ts | 12 ++++++------ src/network/getChainPublicClient.ts | 16 ++++++++++++++-- src/wallet/components/WalletDropdownBaseName.tsx | 6 +++--- src/wallet/types.ts | 4 ++-- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/identity/hooks/useName.ts b/src/identity/hooks/useName.ts index 6dbf48d217..eb7e6a7010 100644 --- a/src/identity/hooks/useName.ts +++ b/src/identity/hooks/useName.ts @@ -14,15 +14,15 @@ import { getName } from '../utils/getName'; * - `{UseQueryResult}`: The rest of useQuery return values. including isLoading, isError, error, isFetching, refetch, etc. */ export const useName = ( - { address, chain = mainnet }: UseNameOptions, + { address, chainId = mainnet.id }: UseNameOptions, queryOptions?: UseNameQueryOptions, ) => { const { enabled = true, cacheTime } = queryOptions ?? {}; - const ensActionKey = `ens-name-${address}-${chain.id}`; + const ensActionKey = `ens-name-${address}-${chainId}`; return useQuery({ queryKey: ['useName', ensActionKey], queryFn: async () => { - return await getName({ address, chain }); + return await getName({ address, chainId }); }, gcTime: cacheTime, enabled, diff --git a/src/identity/types.ts b/src/identity/types.ts index 7a25f198e0..85fa62626b 100644 --- a/src/identity/types.ts +++ b/src/identity/types.ts @@ -119,7 +119,7 @@ export type GetAvatarReturnType = string | null; */ export type GetName = { address: Address; - chain?: Chain; + chainId?: number; // Optional chainId for domain resolution }; /** @@ -184,7 +184,7 @@ export type UseAttestations = { */ export type UseNameOptions = { address: Address; // The Ethereum address for which the ENS name is to be fetched. - chain?: Chain; // Optional chain for domain resolution + chainId: number; // chainId for domain resolution }; /** diff --git a/src/identity/utils/getName.test.tsx b/src/identity/utils/getName.test.tsx index 2f949bff50..8e174cb719 100644 --- a/src/identity/utils/getName.test.tsx +++ b/src/identity/utils/getName.test.tsx @@ -58,7 +58,7 @@ describe('getName', () => { it('should return mainnet username', async () => { const expectedEnsName = 'leo.eth'; mockGetEnsName.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: mainnet }); + const name = await getName({ address: walletAddress, chainId: mainnet.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(mainnet); }); @@ -66,7 +66,7 @@ describe('getName', () => { it('should return sepolia username', async () => { const expectedEnsName = 'leo.test.eth'; mockGetEnsName.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: sepolia }); + const name = await getName({ address: walletAddress, chainId: sepolia.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(sepolia); }); @@ -76,7 +76,7 @@ describe('getName', () => { mockReadContract.mockResolvedValue(expectedEnsName); const name = await getName({ address: walletAddress, - chain: baseSepolia, + chainId: baseSepolia.id, }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(baseSepolia); @@ -85,7 +85,7 @@ describe('getName', () => { it('should return custom mainnet username', async () => { const expectedEnsName = 'leo.custommainnet.eth'; mockReadContract.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: base }); + const name = await getName({ address: walletAddress, chainId: base.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(base); }); @@ -94,7 +94,7 @@ describe('getName', () => { const expectedEnsName = null; mockReadContract.mockResolvedValue(expectedEnsName); mockGetEnsName.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: base }); + const name = await getName({ address: walletAddress, chainId: base.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(base); }); @@ -104,14 +104,14 @@ describe('getName', () => { const expectedEnsName = 'registered.eth'; mockReadContract.mockResolvedValue(expectedBaseName); mockGetEnsName.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: base }); + const name = await getName({ address: walletAddress, chainId: base.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(base); }); it('should throw an error on unsupported chain', async () => { await expect( - getName({ address: walletAddress, chain: optimism }), + getName({ address: walletAddress, chainId: optimism.id }), ).rejects.toBe( 'ChainId not supported, name resolution is only supported on Ethereum and Base.', ); @@ -121,7 +121,7 @@ describe('getName', () => { const expectedEnsName = 'zizzamia.eth'; mockReadContract.mockRejectedValue(new Error('This is an error')); mockGetEnsName.mockResolvedValue(expectedEnsName); - const name = await getName({ address: walletAddress, chain: base }); + const name = await getName({ address: walletAddress, chainId: base.id }); expect(name).toBe(expectedEnsName); expect(getChainPublicClient).toHaveBeenCalledWith(base); }); diff --git a/src/identity/utils/getName.ts b/src/identity/utils/getName.ts index 331f994124..aa4e1b18f6 100644 --- a/src/identity/utils/getName.ts +++ b/src/identity/utils/getName.ts @@ -15,10 +15,10 @@ import { convertReverseNodeToBytes } from './convertReverseNodeToBytes'; export const getName = async ({ address, - chain = mainnet, + chainId = mainnet.id, }: GetName): Promise => { - const chainIsBase = isBase({ chainId: chain.id }); - const chainIsEthereum = isEthereum({ chainId: chain.id }); + const chainIsBase = isBase({ chainId }); + const chainIsEthereum = isEthereum({ chainId }); const chainSupportsUniversalResolver = chainIsEthereum || chainIsBase; if (!chainSupportsUniversalResolver) { @@ -27,14 +27,14 @@ export const getName = async ({ ); } - let client = getChainPublicClient(chain); + let client = getChainPublicClient(chainId); if (chainIsBase) { const addressReverseNode = convertReverseNodeToBytes(address, base.id); try { const baseName = await client.readContract({ abi: L2ResolverAbi, - address: RESOLVER_ADDRESSES_BY_CHAIN_ID[chain.id], + address: RESOLVER_ADDRESSES_BY_CHAIN_ID[chainId], functionName: 'name', args: [addressReverseNode], }); @@ -47,7 +47,7 @@ export const getName = async ({ } // Default to mainnet - client = getChainPublicClient(mainnet); + client = getChainPublicClient(mainnet.id); // ENS username const ensName = await client.getEnsName({ address, diff --git a/src/network/getChainPublicClient.ts b/src/network/getChainPublicClient.ts index 8f98f415d7..2b471ef528 100644 --- a/src/network/getChainPublicClient.ts +++ b/src/network/getChainPublicClient.ts @@ -1,7 +1,19 @@ import { http, createPublicClient } from 'viem'; -import type { Chain } from 'viem/chains'; +import { type Chain, base, baseSepolia, goerli, mainnet } from 'viem/chains'; + +const supportedChains = [mainnet, goerli, base, baseSepolia]; + +function getChainFromId(chainId: number): Chain | undefined { + return supportedChains.find((chain) => chain.id === chainId); +} + +export function getChainPublicClient(chainId: number) { + const chain = getChainFromId(chainId); + + if (!chain) { + throw new Error(`Unsupported chain ID: ${chainId}`); + } -export function getChainPublicClient(chain: Chain) { return createPublicClient({ chain: chain, transport: http(), diff --git a/src/wallet/components/WalletDropdownBaseName.tsx b/src/wallet/components/WalletDropdownBaseName.tsx index cbf512803d..1975fd878e 100644 --- a/src/wallet/components/WalletDropdownBaseName.tsx +++ b/src/wallet/components/WalletDropdownBaseName.tsx @@ -10,15 +10,15 @@ export function WalletDropdownBaseName({ className, }: WalletDropdownBaseNameReact) { const { address } = useAccount(); - const { chain } = useWalletContext(); + const { chainId } = useWalletContext(); - if (!address || !chain) { + if (!address || !chainId) { return null; } const { data: baseName, isLoading } = useName({ address, - chain, + chainId, }); const hasBaseUserName = !!baseName; diff --git a/src/wallet/types.ts b/src/wallet/types.ts index 631a2566f9..0c78ae678f 100644 --- a/src/wallet/types.ts +++ b/src/wallet/types.ts @@ -1,6 +1,6 @@ import type { UserOperation } from 'permissionless'; import type { Dispatch, ReactNode, SetStateAction } from 'react'; -import type { Address, Chain, PublicClient } from 'viem'; +import type { Address, PublicClient } from 'viem'; import type { UseBalanceReturnType, UseReadContractReturnType } from 'wagmi'; import type { SwapError } from '../swap'; @@ -61,7 +61,7 @@ export type UseGetTokenBalanceResponse = { */ export type WalletContextType = { address?: Address | null; // The Ethereum address to fetch the avatar and name for. - chain?: Chain; // Optional chain for domain resolution + chainId?: number; // Optional chainId for domain resolution isOpen: boolean; setIsOpen: Dispatch>; };