diff --git a/app/daos/[daoAddress]/layout.tsx b/app/daos/[daoAddress]/layout.tsx index afe5b2799d..beb30c3182 100644 --- a/app/daos/[daoAddress]/layout.tsx +++ b/app/daos/[daoAddress]/layout.tsx @@ -3,6 +3,7 @@ import { Button, Center, Text, VStack, ChakraProvider, extendTheme } from '@chakra-ui/react'; import { theme } from '@decent-org/fractal-ui'; import { useRouter } from 'next/navigation'; +import Script from 'next/script'; import { ReactNode, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { useNetwork } from 'wagmi'; @@ -72,7 +73,7 @@ export default function DaoPageLayout({ params: { daoAddress?: string }; }) { const { node } = useFractal(); - const { nodeLoading, reloadingDAO } = useDAOController({ daoAddress }); + const { nodeLoading, reloadingDAO, errorLoading } = useDAOController({ daoAddress }); const daoMetadata = useDAOMetadata(); const { chain } = useNetwork(); const activeTheme = useMemo(() => { @@ -106,7 +107,7 @@ export default function DaoPageLayout({ display = childrenDisplay; } else if (!chain) { // if we're disconnected - if (nodeLoading || reloadingDAO || validSafe) { + if (nodeLoading || reloadingDAO || validSafe || !errorLoading) { display = children; } else { display = ; @@ -116,7 +117,7 @@ export default function DaoPageLayout({ const invalidChain = !supportedChains.map(c => c.chainId).includes(chain.id); if (invalidChain) { display = ; - } else if (nodeLoading || reloadingDAO || validSafe) { + } else if (nodeLoading || reloadingDAO || validSafe || !errorLoading) { display = children; } else { display = ; @@ -126,6 +127,21 @@ export default function DaoPageLayout({ return ( {node?.daoName ? `${node.daoName} | ${APP_NAME}` : APP_NAME} + {node && node.daoAddress === '0x167bE4073f52aD2Aa0D6d6FeddF0F1f79a82B98e' && ( + + )} {display} ); diff --git a/app/page.tsx b/app/page.tsx index f07e82b9e1..7ba6206c08 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -14,6 +14,7 @@ import ExternalLink from '../src/components/ui/links/ExternalLink'; import ClientOnly from '../src/components/ui/utils/ClientOnly'; import { BASE_ROUTES } from '../src/constants/routes'; import { URL_DOCS } from '../src/constants/url'; +import ethLizardsLogo from '../src/metadata/lizzardsDAO/assets/logo.png'; import { useFractal } from '../src/providers/App/AppProvider'; import { disconnectedChain } from '../src/providers/NetworkConfig/NetworkConfigProvider'; @@ -59,6 +60,12 @@ const FEATURED_DAOS = new Map([ descKey: 'awakeDesc', address: '0x36C19472D4CA942710cA9aF01a03cED4dBc6eC0a', }, + { + iconSrc: ethLizardsLogo.src, + titleKey: 'ethlizardsTitle', + descKey: 'ethlizardsDesc', + address: '0x167bE4073f52aD2Aa0D6d6FeddF0F1f79a82B98e', + }, ], ], [ @@ -76,6 +83,12 @@ const FEATURED_DAOS = new Map([ descKey: 'awakeDesc', address: '0xdD6CeFA62239272f1eDf755ba6471eacb7DF2Fa5', }, + { + iconSrc: ethLizardsLogo.src, + titleKey: 'ethlizardsTitle', + descKey: 'ethlizardsDesc', + address: '0x167bE4073f52aD2Aa0D6d6FeddF0F1f79a82B98e', // TODO: Change to mainnet address once it will be there + }, ], ], [ @@ -93,6 +106,12 @@ const FEATURED_DAOS = new Map([ descKey: 'awakeDesc', address: '0xdD6CeFA62239272f1eDf755ba6471eacb7DF2Fa5', // TODO: Change to Sepolia Address once it will be there }, + { + iconSrc: ethLizardsLogo.src, + titleKey: 'ethlizardsTitle', + descKey: 'ethlizardsDesc', + address: '0x167bE4073f52aD2Aa0D6d6FeddF0F1f79a82B98e', // TODO: Change to Sepolia address once it will be there + }, ], ], ]); @@ -216,6 +235,12 @@ export default function HomePage() { paddingBottom="1.5rem" > {features.map((feature, index) => { + if ( + typeof location !== 'undefined' && + location.pathname === 'app.fractalframework.xyz' + ) { + return null; + } return ( - {Object.keys(vote.choice as SnapshotWeightedVotingChoice).map((choice: any) => { + {Object.keys(vote.choice as SnapshotWeightedVotingChoice).map((choiceIdx: any) => { + if (!(vote.choice as SnapshotWeightedVotingChoice)[choiceIdx]) { + return null; + } return ( - + - {proposal.choices[(choice as any as number) - 1]} + {proposal.choices[(choiceIdx as number) - 1]} ); diff --git a/src/components/Proposals/SnapshotProposalDetails/SnapshotProposalVotes.tsx b/src/components/Proposals/SnapshotProposalDetails/SnapshotProposalVotes.tsx index bb63523b6a..003e659167 100644 --- a/src/components/Proposals/SnapshotProposalDetails/SnapshotProposalVotes.tsx +++ b/src/components/Proposals/SnapshotProposalDetails/SnapshotProposalVotes.tsx @@ -63,7 +63,7 @@ export default function SnapshotProposalVotes({ proposal }: ISnapshotProposalVot {proposal.privacy === 'shutter' && proposal.state !== FractalProposalState.CLOSED ? `? ${strategySymbol}` - : `${votesBreakdownChoiceTotal} ${strategySymbol}`} + : `${votesBreakdownChoiceTotal.toFixed(2)} ${strategySymbol}`} ); diff --git a/src/components/ui/menus/DAOSearch/SearchDisplay.tsx b/src/components/ui/menus/DAOSearch/SearchDisplay.tsx index 0d758cc1a9..cce35469b1 100644 --- a/src/components/ui/menus/DAOSearch/SearchDisplay.tsx +++ b/src/components/ui/menus/DAOSearch/SearchDisplay.tsx @@ -1,5 +1,6 @@ import { Box, Flex, Text, Button } from '@chakra-ui/react'; import { useRouter } from 'next/navigation'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { DAO_ROUTES } from '../../../../constants/routes'; import useDisplayName from '../../../../hooks/utils/useDisplayName'; @@ -28,8 +29,11 @@ export function SearchDisplay({ closeDrawer, }: ISearchDisplay) { const { t } = useTranslation(['common', 'dashboard']); - const { action } = useFractal(); + const { action, node } = useFractal(); const { push } = useRouter(); + const isCurrentSafe = useMemo(() => { + return !!node && !!node.daoAddress && node.daoAddress === address; + }, [node, address]); if (loading && address) { return ( @@ -49,12 +53,14 @@ export function SearchDisplay({ { - onClickView(); - if (closeDrawer) closeDrawer(); - action.resetDAO(); - push(DAO_ROUTES.dao.relative(address)); + if (!isCurrentSafe) { + onClickView(); + if (closeDrawer) closeDrawer(); + action.resetDAO(); + push(DAO_ROUTES.dao.relative(address)); + } }} - cursor="default" + cursor={isCurrentSafe ? 'not-allowed' : 'default'} justifyContent="space-between" > - {t('labelDAOFound')} + {t(isCurrentSafe ? 'labelCurrentDAO' : 'labelDAOFound')} - + {!isCurrentSafe && ( + + )} ); } diff --git a/src/hooks/DAO/loaders/snapshot/useSnapshotProposal.ts b/src/hooks/DAO/loaders/snapshot/useSnapshotProposal.ts index f42d265327..f1d7f86a01 100644 --- a/src/hooks/DAO/loaders/snapshot/useSnapshotProposal.ts +++ b/src/hooks/DAO/loaders/snapshot/useSnapshotProposal.ts @@ -80,7 +80,7 @@ export default function useSnapshotProposal(proposal: FractalProposal | null | u const votesQueryResult = await client .query({ query: gql`query SnapshotProposalVotes { - votes(where: {proposal: "${snapshotProposal.snapshotProposalId}"}, first: 100) { + votes(where: {proposal: "${snapshotProposal.snapshotProposalId}"}, first: 500) { id voter vp diff --git a/src/hooks/DAO/loaders/useFractalNode.ts b/src/hooks/DAO/loaders/useFractalNode.ts index b9383cca7d..5bd8cd4b9c 100644 --- a/src/hooks/DAO/loaders/useFractalNode.ts +++ b/src/hooks/DAO/loaders/useFractalNode.ts @@ -20,6 +20,7 @@ export const useFractalNode = ({ daoAddress }: { 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 { action } = useFractal(); const safeAPI = useSafeAPI(); @@ -87,12 +88,14 @@ export const useFractalNode = ({ daoAddress }: { daoAddress?: string }) => { const setDAO = useCallback( async (_chainId: number, _daoAddress: string) => { setNodeLoading(true); + setErrorLoading(false); if (utils.isAddress(_daoAddress) && safeAPI) { try { const safeInfo = await requestWithRetries(fetchSafeInfo, 5); if (!safeInfo) { currentValidSafe.current = undefined; action.resetDAO(); + setErrorLoading(true); } else { currentValidSafe.current = _chainId + _daoAddress; action.dispatch({ @@ -103,16 +106,19 @@ export const useFractalNode = ({ daoAddress }: { daoAddress?: string }) => { 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); } setNodeLoading(false); }, @@ -128,5 +134,5 @@ export const useFractalNode = ({ daoAddress }: { daoAddress?: string }) => { } }, [daoAddress, setDAO, currentValidSafe, chainId]); - return nodeLoading; + return { nodeLoading, errorLoading }; }; diff --git a/src/hooks/DAO/proposal/useCastVote.ts b/src/hooks/DAO/proposal/useCastVote.ts index 8ea9724cba..2e6b93e77a 100644 --- a/src/hooks/DAO/proposal/useCastVote.ts +++ b/src/hooks/DAO/proposal/useCastVote.ts @@ -143,7 +143,9 @@ const useCastVote = ({ const mappedSnapshotWeightedChoice: { [choiceKey: number]: number } = {}; if (extendedSnapshotProposal.type === 'weighted') { snapshotWeightedChoice.forEach((value, choiceIndex) => { - mappedSnapshotWeightedChoice[choiceIndex + 1] = value; + if (value > 0) { + mappedSnapshotWeightedChoice[choiceIndex + 1] = value; + } }); } const choice = diff --git a/src/hooks/DAO/useDAOController.ts b/src/hooks/DAO/useDAOController.ts index a91af59f21..7735b6937a 100644 --- a/src/hooks/DAO/useDAOController.ts +++ b/src/hooks/DAO/useDAOController.ts @@ -30,7 +30,7 @@ export default function useDAOController({ daoAddress }: { daoAddress?: string } } }, [daoAddress, currentDAOAddress, action]); - const nodeLoading = useFractalNode({ daoAddress: currentDAOAddress }); + const { nodeLoading, errorLoading } = useFractalNode({ daoAddress: currentDAOAddress }); useGovernanceContracts(); useFractalGuardContracts({}); useFractalFreeze({ parentSafeAddress: parentAddress }); @@ -38,5 +38,5 @@ export default function useDAOController({ daoAddress }: { daoAddress?: string } useFractalTreasury(); useERC20Claim(); useSnapshotProposals(); - return { nodeLoading, reloadingDAO }; + return { nodeLoading, reloadingDAO, errorLoading }; } diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index d59cf73c70..f8c3645e61 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -37,6 +37,7 @@ "home": "Home", "labelViewDAO": "View Safe", "labelDAOFound": "Safe found", + "labelCurrentDAO": "This is Safe you are currently viewing", "labelEtherscan": "View on Etherscan", "errorInvalidENSAddress": "Invalid ENS name or address", "errorInvalidENSName": "Invalid ENS name", diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index 318340cae7..fa4f0adb7b 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -13,6 +13,8 @@ "decentDesc": "We are an open-source collective that unites builders toward global decentralization.", "awakeTitle": "AwakeVC", "awakeDesc": "Awake Internet Protocols combine AI and FinTech to empower Decentralized Private Equity for the multiverse. Welcome to Awakened Value Co-creation aka AwakeVC.", + "ethlizardsTitle": "Lizard DAO", + "ethlizardsDesc": "Ethlizards brings together an exceptional mix of avid gamers, visionary builders, and savvy investors, establishing itself as a highly esteemed partner in the GameFi ecosystem.", "featureLink": "Explore >", "readyCTA": "Ready to start?", "createButton": "+ Start from Scratch", diff --git a/src/metadata/lizzardsDAO/index.ts b/src/metadata/lizzardsDAO/index.ts index db2a286bb4..8f50d2767e 100644 --- a/src/metadata/lizzardsDAO/index.ts +++ b/src/metadata/lizzardsDAO/index.ts @@ -25,13 +25,14 @@ const LIZZARDS_DAO_METADATA: DAOMetadata = { sections: [ { title: 'Description', - content: ' for this proposal or just click on the link to learn more about the proposal', + content: + 'Ethlizards brings together an exceptional mix of avid gamers, visionary builders, and savvy investors, establishing itself as a highly esteemed partner in the GameFi ecosystem.', background: undefined, - link: { - position: 'start', - text: 'Vote here', - url: '/proposals/0xe10c44fceb1b43f74c42bd6efc9316e9ce14109ac8a166e5266fc78499cb4fea', - }, + // link: { + // position: 'start', + // text: 'Vote here', + // url: '/proposals/0xe10c44fceb1b43f74c42bd6efc9316e9ce14109ac8a166e5266fc78499cb4fea', + // }, }, { title: 'Elemental Lizards coming soon',