From fda85b1ac54a9349d866119d7fcd01d83c59cfa4 Mon Sep 17 00:00:00 2001 From: Davide Carpini Date: Mon, 4 Nov 2024 15:42:52 +0100 Subject: [PATCH] fix: decouple fetch vechain domain --- .../api/fetchVechainDomain.ts | 78 +++++++++++++++++ .../useVechainDomain.catch.test.tsx | 31 +++++++ .../useVechainDomain.test.tsx | 15 ++-- .../useVechainDomain/useVechainDomain.ts | 86 +++++-------------- 4 files changed, 137 insertions(+), 73 deletions(-) create mode 100644 packages/dapp-kit-react/src/hooks/useVechainDomain/api/fetchVechainDomain.ts create mode 100644 packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.catch.test.tsx diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/api/fetchVechainDomain.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/fetchVechainDomain.ts new file mode 100644 index 00000000..65fecd6d --- /dev/null +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/api/fetchVechainDomain.ts @@ -0,0 +1,78 @@ +import { addressUtils } from '@vechain/sdk-core'; +import type { DAppKitContext } from '../../../types'; +import { getDomain } from './getDomain'; +import { getAddress } from './getAddress'; + +export interface VechainDomainResult { + address: string | undefined; + domain: string | undefined; + isValidAddressOrDomain: boolean; +} + +/** + * Function to fetch the vechain domain of an account and vice versa by passing the connex object + */ +export const fetchVechainDomain = async ({ + addressOrDomain, + connex, +}: { + addressOrDomain?: string | null; + connex: DAppKitContext['connex']; +}): Promise => { + if (!addressOrDomain) { + return { + address: undefined, + domain: undefined, + isValidAddressOrDomain: false, + }; + } + + const isValidAddress = addressUtils.isAddress(addressOrDomain); + + if (isValidAddress) { + try { + const domainName = await getDomain({ + address: addressOrDomain, + connex, + }); + return { + address: addressOrDomain, + domain: domainName, + isValidAddressOrDomain: true, + }; + } catch (err) { + console.error('Error getting domain: ', err); + return { + address: addressOrDomain, + domain: undefined, + isValidAddressOrDomain: true, + }; + } + } + + try { + const domainAddress = await getAddress({ + domain: addressOrDomain, + connex, + }); + if (domainAddress === '0x0000000000000000000000000000000000000000') { + return { + address: undefined, + domain: undefined, + isValidAddressOrDomain: false, + }; + } + return { + address: domainAddress, + domain: addressOrDomain, + isValidAddressOrDomain: true, + }; + } catch (err) { + console.error('Error getting address: ', err); + return { + address: undefined, + domain: undefined, + isValidAddressOrDomain: false, + }; + } +}; diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.catch.test.tsx b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.catch.test.tsx new file mode 100644 index 00000000..c763a391 --- /dev/null +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.catch.test.tsx @@ -0,0 +1,31 @@ +import { renderHook, waitFor } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import { useVechainDomain } from './useVechainDomain'; +import { wrapper } from '../../../test'; + +vi.mock('./api/fetchVechainDomain', () => ({ + ...vi.importActual('./api/fetchVechainDomain'), + fetchVechainDomain: vi.fn().mockImplementation(async () => { + throw new Error('Network error'); + }), +})); + +describe('useVechainDomain error handling', () => { + it('should handle error when fetching domain', async () => { + const { result } = renderHook( + () => useVechainDomain({ addressOrDomain: 'test.vet' }), + { wrapper }, + ); + + expect(result.current.isLoading).toBe(true); + + await waitFor(() => { + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); + }); + }); +}); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx index 24f5d8bc..8073a2ae 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.test.tsx @@ -38,19 +38,20 @@ vi.mock('./api/getAddress', () => ({ })); describe('useVechainDomain', () => { - it('should return initial state', () => { + it('should return initial state', async () => { const { result } = renderHook( () => useVechainDomain({ addressOrDomain: null }), { wrapper, }, ); - - expect(result.current).toEqual({ - address: undefined, - domain: undefined, - isLoading: false, - isValidAddressOrDomain: false, + await waitFor(() => { + expect(result.current).toEqual({ + address: undefined, + domain: undefined, + isLoading: false, + isValidAddressOrDomain: false, + }); }); }); diff --git a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts index 0c192dd9..dd7599f5 100644 --- a/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts +++ b/packages/dapp-kit-react/src/hooks/useVechainDomain/useVechainDomain.ts @@ -1,14 +1,12 @@ import { useEffect, useState } from 'react'; -import { addressUtils } from '@vechain/sdk-core'; import { useConnex } from '../../DAppKitProvider/hooks/useConnex'; -import { getDomain } from './api/getDomain'; -import { getAddress } from './api/getAddress'; +import { + fetchVechainDomain, + type VechainDomainResult, +} from './api/fetchVechainDomain'; -interface UseVechainDomainReturnType { - address: string | undefined; - domain: string | undefined; +interface UseVechainDomainReturnType extends VechainDomainResult { isLoading: boolean; - isValidAddressOrDomain: boolean; } /** @@ -20,71 +18,27 @@ export const useVechainDomain = ({ addressOrDomain?: string | null; }): UseVechainDomainReturnType => { const connex = useConnex(); - - const [address, setAddress] = useState(undefined); - const [domain, setDomain] = useState(undefined); + const [result, setResult] = useState({ + address: undefined, + domain: undefined, + isValidAddressOrDomain: false, + }); const [isLoading, setIsLoading] = useState(false); - const [isValidAddressOrDomain, setIsValidAddressOrDomain] = useState(false); - - const isFalsy = !addressOrDomain; - const isValidAddress = !isFalsy && addressUtils.isAddress(addressOrDomain); useEffect(() => { - if (isFalsy) { - setAddress(undefined); - setDomain(undefined); - setIsLoading(false); - setIsValidAddressOrDomain(false); - return; - } - - // if the addressOrDomain is an address, get the domain - if (isValidAddress) { - setAddress(addressOrDomain); - setIsValidAddressOrDomain(true); - setIsLoading(true); - getDomain({ address: addressOrDomain, connex }) - .then((domainAddress) => { - setDomain(domainAddress); - }) - .catch((err) => { - console.error('Error getting domain: ', err); - setDomain(undefined); - }) - .finally(() => { - setIsLoading(false); - }); - - return; - } - - // if the addressOrDomain is a domain, get the address setIsLoading(true); - getAddress({ domain: addressOrDomain, connex }) - .then((domainAddress) => { - if ( - domainAddress === - '0x0000000000000000000000000000000000000000' - ) { - setDomain(undefined); - setAddress(undefined); - setIsValidAddressOrDomain(false); - return; - } - setDomain(addressOrDomain); - setAddress(domainAddress); - setIsValidAddressOrDomain(true); - }) + fetchVechainDomain({ addressOrDomain, connex }) + .then(setResult) .catch((err) => { - console.error('Error getting address: ', err); - setAddress(undefined); - setDomain(undefined); - setIsValidAddressOrDomain(false); + console.error('Error fetching vechain domain: ', err); + setResult({ + address: undefined, + domain: undefined, + isValidAddressOrDomain: false, + }); }) - .finally(() => { - setIsLoading(false); - }); + .finally(() => setIsLoading(false)); }, [addressOrDomain, connex]); - return { address, domain, isLoading, isValidAddressOrDomain }; + return { ...result, isLoading }; };