diff --git a/src/components/ui/menus/DAOSearch/SearchDisplay.tsx b/src/components/ui/menus/DAOSearch/SearchDisplay.tsx index 3e02346a5..55d47c569 100644 --- a/src/components/ui/menus/DAOSearch/SearchDisplay.tsx +++ b/src/components/ui/menus/DAOSearch/SearchDisplay.tsx @@ -4,6 +4,7 @@ import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Address } from 'viem'; import { SafeDisplayRow } from '../../../../pages/home/SafeDisplayRow'; +import { getNetworkConfig } from '../../../../providers/NetworkConfig/useNetworkConfigStore'; import { useDaoInfoStore } from '../../../../store/daoInfo/useDaoInfoStore'; import { ErrorBoundary } from '../../utils/ErrorBoundary'; import { MySafesErrorFallback } from '../../utils/MySafesErrorFallback'; @@ -13,7 +14,7 @@ interface ISearchDisplay { errorMessage: string | undefined; address: Address | undefined; onClickView: Function; - networkPrefix: string; + chainId: number; } export function SearchDisplay({ @@ -21,7 +22,7 @@ export function SearchDisplay({ errorMessage, address, onClickView, - networkPrefix, + chainId, }: ISearchDisplay) { const { t } = useTranslation(['common', 'dashboard']); const node = useDaoInfoStore(); @@ -90,7 +91,7 @@ export function SearchDisplay({ { onClickView(); }} diff --git a/src/components/ui/menus/DAOSearch/index.tsx b/src/components/ui/menus/DAOSearch/index.tsx index 9c1112391..a3dc58a0f 100644 --- a/src/components/ui/menus/DAOSearch/index.tsx +++ b/src/components/ui/menus/DAOSearch/index.tsx @@ -21,8 +21,7 @@ export function DAOSearch() { const { t } = useTranslation(['dashboard']); const [localInput, setLocalInput] = useState(''); const [typing, setTyping] = useState(false); - const { errorMessage, isLoading, address, setSearchString, safeFoundNetworkPrefixes } = - useSearchDao(); + const { errorMessage, isLoading, setSearchString, resolvedAddressesWithPrefix } = useSearchDao(); const { isOpen, onOpen, onClose } = useDisclosure(); const ref = useRef(null); @@ -65,9 +64,8 @@ export function DAOSearch() { const showResults = useMemo(() => { if (typing) return false; if (isLoading) return true; - const hasMessage = errorMessage !== undefined || address !== undefined; - return hasMessage; - }, [address, errorMessage, typing, isLoading]); + return errorMessage === undefined; + }, [errorMessage, typing, isLoading]); useEffect(() => { if (localInput) { @@ -150,13 +148,13 @@ export function DAOSearch() { w="full" position="absolute" > - {safeFoundNetworkPrefixes.map(networkPrefix => ( + {resolvedAddressesWithPrefix.map(resolved => ( ))} diff --git a/src/hooks/DAO/useSearchDao.ts b/src/hooks/DAO/useSearchDao.ts index c80ba5d12..2974f98c9 100644 --- a/src/hooks/DAO/useSearchDao.ts +++ b/src/hooks/DAO/useSearchDao.ts @@ -1,39 +1,70 @@ -import { useState, useEffect } from 'react'; +import SafeApiKit from '@safe-global/api-kit'; +import { useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNetworkConfigStore } from '../../providers/NetworkConfig/useNetworkConfigStore'; -import { useIsSafe } from '../safe/useIsSafe'; -import useAddress from '../utils/useAddress'; +import { Address } from 'viem'; +import { useResolveAddressMultiChain } from '../utils/useResolveAddressMultiChain'; +type ResolvedAddressWithPrefix = { + address: Address; + chainId: number; +}; export const useSearchDao = () => { + const { resolveAddressMultiChain, isLoading: isAddressLoading } = useResolveAddressMultiChain(); const [searchString, setSearchString] = useState(''); const [errorMessage, setErrorMessage] = useState(); - // This hook needs to search all supoorted chains for the address - const { address, isValid, isLoading: isAddressLoading } = useAddress(searchString); - const { isSafe, isSafeLoading, safeFoundNetworkPrefixes } = useIsSafe(address); - const { t } = useTranslation('dashboard'); - const { chain } = useNetworkConfigStore(); + const [isSafeLookupLoading, setIsSafeLookupLoading] = useState(false); + const [resolvedAddressesWithPrefix, setSafeResolvedAddressesWithPrefix] = useState< + ResolvedAddressWithPrefix[] + >([]); + + const findSafes = useCallback( + async (resolvedAddressesWithChainId: { address: Address; chainId: number }[]) => { + setIsSafeLookupLoading(true); + for await (const resolved of resolvedAddressesWithChainId) { + const safeAPI = new SafeApiKit({ chainId: BigInt(resolved.chainId) }); + safeAPI.getSafeCreationInfo(resolved.address); + try { + await safeAPI.getSafeCreationInfo(resolved.address); + + setSafeResolvedAddressesWithPrefix(prevState => [...prevState, resolved]); + } catch (e) { + // Safe not found + continue; + } + } + setIsSafeLookupLoading(false); + }, + [], + ); - const isLoading = isAddressLoading === true || isSafeLoading === true; + const resolveInput = useCallback( + async (input: string) => { + const { resolved, isValid } = await resolveAddressMultiChain(input); + if (isValid) { + await findSafes(resolved); + } else { + setErrorMessage('Invalid search'); + } + }, + [findSafes, resolveAddressMultiChain], + ); + + const { t } = useTranslation('dashboard'); useEffect(() => { setErrorMessage(undefined); - - if (searchString === '' || isLoading || isSafe || isValid === undefined) { + setSafeResolvedAddressesWithPrefix([]); + if (searchString === '') { return; } - if (isValid === true) { - setErrorMessage(t('errorFailedSearch')); - } else { - setErrorMessage(t('errorInvalidSearch')); - } - }, [chain.name, isLoading, isSafe, isValid, searchString, t]); + resolveInput(searchString).catch(() => setErrorMessage(t('errorInvalidSearch'))); + }, [resolveInput, searchString, t]); return { - safeFoundNetworkPrefixes, + resolvedAddressesWithPrefix, errorMessage, - isLoading, - address, + isLoading: isAddressLoading || isSafeLookupLoading, setSearchString, searchString, };