From 4be13e72f9b0d24dcc81b3891f8d89236fc01def Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Thu, 28 Mar 2024 22:21:05 -0400 Subject: [PATCH] temp --- src/hooks/DAO/loaders/useFractalNode.ts | 115 ++++++++++++------------ src/hooks/DAO/useDAOController.ts | 34 ++++--- src/i18n/locales/en/common.json | 4 +- src/pages/DAOController.tsx | 13 ++- src/pages/LoadingProblem.tsx | 2 +- 5 files changed, 81 insertions(+), 87 deletions(-) diff --git a/src/hooks/DAO/loaders/useFractalNode.ts b/src/hooks/DAO/loaders/useFractalNode.ts index 56caf81741..c576dfdbde 100644 --- a/src/hooks/DAO/loaders/useFractalNode.ts +++ b/src/hooks/DAO/loaders/useFractalNode.ts @@ -1,4 +1,5 @@ import { useQuery } from '@apollo/client'; +import SafeServiceClient, { SafeInfoResponse } from '@safe-global/safe-service-client'; import { utils } from 'ethers'; import { useCallback, useEffect, useRef, useState } from 'react'; import { DAOQueryDocument, DAOQueryQuery } from '../../../../.graphclient'; @@ -18,14 +19,12 @@ export const useFractalNode = ({ addressPrefix, daoAddress, }: { - addressPrefix: string; - daoAddress: string; + addressPrefix?: string; + daoAddress?: string; }) => { // tracks the current valid Safe address and chain id; helps prevent unnecessary calls const currentValidSafe = useRef(); - const [nodeLoading, setNodeLoading] = useState(true); const [errorLoading, setErrorLoading] = useState(false); - const [wrongNetwork, setWrongNetwork] = useState(false); const { action } = useFractal(); const safeAPI = useSafeAPI(); @@ -58,7 +57,7 @@ export const useFractalNode = ({ return; }, []); - const { subgraphChainName, addressPrefix: connectedAddressPrefix } = useNetworkConfig(); + const { subgraphChainName } = useNetworkConfig(); useQuery(DAOQueryDocument, { variables: { daoAddress }, @@ -83,68 +82,66 @@ export const useFractalNode = ({ pollInterval: ONE_MINUTE, }); - const fetchSafeInfo = useCallback(async () => { - if (daoAddress && safeAPI) { - const safeInfo = await safeAPI.getSafeInfo(utils.getAddress(daoAddress)); - return safeInfo; - } - }, [safeAPI, daoAddress]); + const reset = useCallback( + ({ error }: { error: boolean }) => { + currentValidSafe.current = undefined; + action.resetDAO(); + setErrorLoading(error); + }, + [action], + ); const setDAO = useCallback( - async (_addressPrefix: string, _daoAddress: string, _connectedAddressPrefix: string) => { - setNodeLoading(true); + async (_addressPrefix: string, _daoAddress: string) => { setErrorLoading(false); - setWrongNetwork(false); - - if (_connectedAddressPrefix !== _addressPrefix) { - currentValidSafe.current = undefined; - action.resetDAO(); - setWrongNetwork(true); - } else if (utils.isAddress(_daoAddress) && safeAPI) { - try { - const safeInfo = await requestWithRetries(fetchSafeInfo, 5); - if (!safeInfo) { - currentValidSafe.current = undefined; - action.resetDAO(); - setErrorLoading(true); - } else { - currentValidSafe.current = _addressPrefix + _daoAddress; - action.dispatch({ - type: NodeAction.SET_FRACTAL_MODULES, - payload: await lookupModules(safeInfo.modules), - }); - action.dispatch({ - type: NodeAction.SET_SAFE_INFO, - payload: safeInfo, - }); - setErrorLoading(false); - } - } catch (e) { - // network error - currentValidSafe.current = undefined; - action.resetDAO(); - setErrorLoading(true); - } - } else { - // invalid address - currentValidSafe.current = undefined; - action.resetDAO(); - setErrorLoading(true); + + if (!utils.isAddress(_daoAddress) || !safeAPI) { + reset({ error: true }); + return; + } + + let safeInfo; + + try { + safeInfo = await requestWithRetries( + () => safeAPI.getSafeInfo(utils.getAddress(_daoAddress)), + 5, + ); + } catch (e) { + reset({ error: true }); + return; } - setNodeLoading(false); + + if (safeInfo === undefined) { + reset({ error: true }); + return; + } + + currentValidSafe.current = _addressPrefix + _daoAddress; + action.dispatch({ + type: NodeAction.SET_FRACTAL_MODULES, + payload: await lookupModules(safeInfo.modules), + }); + + action.dispatch({ + type: NodeAction.SET_SAFE_INFO, + payload: safeInfo, + }); + setErrorLoading(false); }, - [safeAPI, action, requestWithRetries, fetchSafeInfo, lookupModules], + [action, lookupModules, requestWithRetries, reset, safeAPI], ); useEffect(() => { - if ( - addressPrefix + daoAddress !== currentValidSafe.current || - addressPrefix !== connectedAddressPrefix - ) { - setNodeLoading(true); - setDAO(addressPrefix, daoAddress, connectedAddressPrefix); + if (addressPrefix === undefined || daoAddress === undefined) { + reset({ error: false }); + return; + } + + if (addressPrefix + daoAddress !== currentValidSafe.current) { + setDAO(addressPrefix, daoAddress); } - }, [daoAddress, addressPrefix, setDAO, currentValidSafe, connectedAddressPrefix]); + }, [addressPrefix, daoAddress, setDAO, reset]); - return { nodeLoading, errorLoading, wrongNetwork }; + return { errorLoading }; }; diff --git a/src/hooks/DAO/useDAOController.ts b/src/hooks/DAO/useDAOController.ts index c8fb7a81ca..4a1fe87985 100644 --- a/src/hooks/DAO/useDAOController.ts +++ b/src/hooks/DAO/useDAOController.ts @@ -1,6 +1,7 @@ -import { useEffect } from 'react'; +import { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useFractal } from '../../providers/App/AppProvider'; +import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider'; import { useERC20Claim } from './loaders/governance/useERC20Claim'; import { useSnapshotProposals } from './loaders/snapshot/useSnapshotProposals'; import { useFractalFreeze } from './loaders/useFractalFreeze'; @@ -13,33 +14,27 @@ import { useGovernanceContracts } from './loaders/useGovernanceContracts'; export default function useDAOController() { const [searchParams] = useSearchParams(); const addressWithPrefix = searchParams.get('dao'); + const validDaoQueryString = /^[^\s:]+:[^\s:]+$/; + const invalidQuery = addressWithPrefix === null || !validDaoQueryString.test(addressWithPrefix); - if (addressWithPrefix === null) { - throw new Error('address is null'); - } + const prefixAndAddress = addressWithPrefix?.split(':'); + const addressPrefix = prefixAndAddress?.[0]; + const daoAddress = prefixAndAddress?.[1]; - if (!addressWithPrefix.includes(':')) { - throw new Error("address doesn't include prefix"); - } - - const prefixAndAddress = addressWithPrefix.split(':'); - const addressPrefix = prefixAndAddress[0]; - const daoAddress = prefixAndAddress[1]; + const { addressPrefix: connectedAddressPrefix } = useNetworkConfig(); + const wrongNetwork = addressPrefix !== connectedAddressPrefix; const { node: { nodeHierarchy: { parentAddress }, }, - action, } = useFractal(); - useEffect(() => { - if (!daoAddress) { - action.resetDAO(); - } - }, [action, daoAddress]); + const { errorLoading } = useFractalNode({ + addressPrefix, + daoAddress, + }); - const { nodeLoading, errorLoading, wrongNetwork } = useFractalNode({ addressPrefix, daoAddress }); useGovernanceContracts(); useFractalGuardContracts({}); useFractalFreeze({ parentSafeAddress: parentAddress }); @@ -47,5 +42,6 @@ export default function useDAOController() { useFractalTreasury(); useERC20Claim(); useSnapshotProposals(); - return { nodeLoading, errorLoading, wrongNetwork }; + + return { invalidQuery, wrongNetwork, errorLoading }; } diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 2e61c550cb..603f6481c1 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -98,9 +98,11 @@ "isMeSuffix": " (you)", "refresh": "Refresh", "invalidSafe1": "We couldn't find a Safe at this address on {{chain}}.", - "invalidSafe2": "Please double check the address then try refreshing.", + "invalidSafe2": "Please double check the address then try again.", "wrongNetwork1": "Fractal is currently connected to {{chain}}.", "wrongNetwork2": "Try switching the app to the correct chain for your Safe.", + "badQueryParam1": "The DAO address in the URL isn't formatted correctly", + "badQueryParam2": "", "showMore": "Show More", "showLess": "Show Less", "poweredBy": "Powered by", diff --git a/src/pages/DAOController.tsx b/src/pages/DAOController.tsx index fd710306b3..a2738edf4f 100644 --- a/src/pages/DAOController.tsx +++ b/src/pages/DAOController.tsx @@ -4,12 +4,10 @@ import { useMemo } from 'react'; import { Outlet } from 'react-router-dom'; import useDAOController from '../hooks/DAO/useDAOController'; import useDAOMetadata from '../hooks/DAO/useDAOMetadata'; -import { useFractal } from '../providers/App/AppProvider'; import LoadingProblem from './LoadingProblem'; export default function DAOController() { - const { node } = useFractal(); - const { nodeLoading, errorLoading, wrongNetwork } = useDAOController(); + const { errorLoading, wrongNetwork, invalidQuery } = useDAOController(); const daoMetadata = useDAOMetadata(); const activeTheme = useMemo(() => { if (daoMetadata && daoMetadata.bodyBackground) { @@ -34,7 +32,6 @@ export default function DAOController() { return theme; }, [daoMetadata]); - const validSafe = node.safe; let display; if (import.meta.env.VITE_APP_TESTING_ENVIRONMENT) { @@ -45,10 +42,12 @@ export default function DAOController() { ); } else if (wrongNetwork) { display = ; - } else if (nodeLoading || validSafe || !errorLoading) { - display = ; - } else { + } else if (invalidQuery) { + display = ; + } else if (errorLoading) { display = ; + } else { + display = ; } return display; diff --git a/src/pages/LoadingProblem.tsx b/src/pages/LoadingProblem.tsx index 552d1d6966..b2740641fc 100644 --- a/src/pages/LoadingProblem.tsx +++ b/src/pages/LoadingProblem.tsx @@ -2,7 +2,7 @@ import { Center, Text, VStack } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; import { useNetworkConfig } from '../providers/NetworkConfig/NetworkConfigProvider'; -function LoadingProblem({ type }: { type: 'invalidSafe' | 'wrongNetwork' }) { +function LoadingProblem({ type }: { type: 'invalidSafe' | 'wrongNetwork' | 'badQueryParam' }) { const { name } = useNetworkConfig(); const { t } = useTranslation('common');