From 56dbd827c21e02a7802eb833293274a6ba2fee3a Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:48:03 -0500 Subject: [PATCH 01/29] create hook to retrieve master copy address and return comparison boolean. --- src/hooks/utils/useMasterCopy.ts | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/hooks/utils/useMasterCopy.ts diff --git a/src/hooks/utils/useMasterCopy.ts b/src/hooks/utils/useMasterCopy.ts new file mode 100644 index 0000000000..8967b29f82 --- /dev/null +++ b/src/hooks/utils/useMasterCopy.ts @@ -0,0 +1,67 @@ +import { ModuleProxyFactory } from '@fractal-framework/fractal-contracts'; +import { Contract, constants } from 'ethers'; +import { getEventRPC } from '../../helpers'; +import { useFractal } from '../../providers/App/AppProvider'; +import { CacheKeys } from './cache/cacheDefaults'; +import { useLocalStorage } from './cache/useLocalStorage'; + +export function useMasterCopy() { + const { getValue, setValue } = useLocalStorage(); + const { + baseContracts: { + zodiacModuleProxyFactoryContract, + linearVotingMasterCopyContract, + linearVotingERC721MasterCopyContract, + multisigFreezeGuardMasterCopyContract, + freezeMultisigVotingMasterCopyContract, + freezeERC721VotingMasterCopyContract, + }, + } = useFractal(); + + const isOzLinearVoting = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === linearVotingMasterCopyContract.asProvider.address; + const isOzLinearVotingERC721 = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === linearVotingERC721MasterCopyContract.asProvider.address; + const isMultisigFreezeGuard = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === multisigFreezeGuardMasterCopyContract.asProvider.address; + const isMultisigFreezeVoting = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === freezeMultisigVotingMasterCopyContract.asProvider.address; + const isERC721FreezeVoting = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === freezeERC721VotingMasterCopyContract.asProvider.address; + + async function getMasterCopyAddress( + contract: Contract, + proxyAddress: string | `0x${string}` + ): Promise<[string, string | null]> { + const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); + if (cachedValue) return [cachedValue, null] as const; + + const filter = contract.filters.ModuleProxyCreation(proxyAddress, null); + return contract.queryFilter(filter).then(proxiesCreated => { + if (proxiesCreated.length === 0) { + return [constants.AddressZero, 'No proxies created'] as const; + } + const masterCopyAddress = proxiesCreated[0].args!.masterCopy; + setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, masterCopyAddress); + return [masterCopyAddress, null] as const; + }); + } + + async function getZodiacModuleProxyMasterCopyData(proxyAddress: string | `0x${string}`) { + const contract = getEventRPC(zodiacModuleProxyFactoryContract); + const [masterCopyAddress, error] = await getMasterCopyAddress(contract, proxyAddress); + if (error) { + console.error(error); + } + return { + address: masterCopyAddress, + isOzLinearVoting: isOzLinearVoting(masterCopyAddress), + isOzLinearVotingERC721: isOzLinearVotingERC721(masterCopyAddress), + isMultisigFreezeGuard: isMultisigFreezeGuard(masterCopyAddress), + isMultisigFreezeVoting: isMultisigFreezeVoting(masterCopyAddress), + isERC721FreezeVoting: isERC721FreezeVoting(masterCopyAddress), + }; + } + + return { getZodiacModuleProxyMasterCopyData }; +} From 6851abd3c227e6f88f458caf4398c6b04991a25d Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:48:15 -0500 Subject: [PATCH 02/29] cleans up logic - removes left-over useLocalStorage logic - uses useMasterCopy hook to retrieve master copy address --- .../DAO/loaders/useGovernanceContracts.ts | 104 ++++++------------ 1 file changed, 36 insertions(+), 68 deletions(-) diff --git a/src/hooks/DAO/loaders/useGovernanceContracts.ts b/src/hooks/DAO/loaders/useGovernanceContracts.ts index e68eac73e3..b97c99c613 100644 --- a/src/hooks/DAO/loaders/useGovernanceContracts.ts +++ b/src/hooks/DAO/loaders/useGovernanceContracts.ts @@ -1,6 +1,5 @@ import { Azorius, - ModuleProxyFactory, LinearERC20Voting, VotesERC20, VotesERC20Wrapper, @@ -9,32 +8,29 @@ import { import { ethers } from 'ethers'; import { useCallback, useEffect, useRef, useState } from 'react'; import { LockRelease, LockRelease__factory } from '../../../assets/typechain-types/dcnt'; -import { getEventRPC } from '../../../helpers'; import { useFractal } from '../../../providers/App/AppProvider'; import { GovernanceContractAction } from '../../../providers/App/governanceContracts/action'; import { ContractConnection } from '../../../types'; import { getAzoriusModuleFromModules } from '../../../utils'; -import { CacheKeys } from '../../utils/cache/cacheDefaults'; -import { useLocalStorage } from '../../utils/cache/useLocalStorage'; import { useEthersProvider } from '../../utils/useEthersProvider'; +import { useMasterCopy } from '../../utils/useMasterCopy'; import useSignerOrProvider from '../../utils/useSignerOrProvider'; -const AZORIUS_MODULE_CACHE_KEY = 'azorius_module_gov_'; export const useGovernanceContracts = () => { // tracks the current valid DAO address; helps prevent unnecessary calls const currentValidAddress = useRef(); const { node, baseContracts: { - zodiacModuleProxyFactoryContract, - linearVotingMasterCopyContract, - linearVotingERC721MasterCopyContract, votesTokenMasterCopyContract, fractalAzoriusMasterCopyContract, votesERC20WrapperMasterCopyContract, + linearVotingMasterCopyContract, + linearVotingERC721MasterCopyContract, }, action, } = useFractal(); + const { getZodiacModuleProxyMasterCopyData } = useMasterCopy(); const provider = useEthersProvider(); const signerOrProvider = useSignerOrProvider(); @@ -44,8 +40,6 @@ export const useGovernanceContracts = () => { const [lastChainId, setLastChainId] = useState(); - const { setValue, getValue } = useLocalStorage(); - const loadGovernanceContracts = useCallback(async () => { const { fractalModules } = node; @@ -78,31 +72,20 @@ export const useGovernanceContracts = () => { ) )[1]; + let isOzLinearVoting, + isOzLinearVotingERC721 = false; if (!votingContractMasterCopyAddress) { - const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + votingContractAddress); - votingContractMasterCopyAddress = cachedValue; - if (!cachedValue) { - const rpc = getEventRPC(zodiacModuleProxyFactoryContract); - const filter = rpc.filters.ModuleProxyCreation(votingContractAddress, null); - votingContractMasterCopyAddress = await rpc.queryFilter(filter).then(proxiesCreated => { - setValue( - CacheKeys.MASTER_COPY_PREFIX + votingContractAddress, - proxiesCreated[0].args.masterCopy - ); - return proxiesCreated[0].args.masterCopy; - }); - } + const masterCopyData = await getZodiacModuleProxyMasterCopyData(votingContractAddress); + isOzLinearVoting = masterCopyData.isOzLinearVoting; + isOzLinearVotingERC721 = masterCopyData.isOzLinearVotingERC721; } - if (votingContractMasterCopyAddress === linearVotingMasterCopyContract.asProvider.address) { + if (isOzLinearVoting) { ozLinearVotingContract = { asSigner: linearVotingMasterCopyContract.asSigner.attach(votingContractAddress!), asProvider: linearVotingMasterCopyContract.asProvider.attach(votingContractAddress!), }; - } else if ( - votingContractMasterCopyAddress === - linearVotingERC721MasterCopyContract.asProvider.address - ) { + } else if (isOzLinearVotingERC721) { erc721LinearVotingContract = { asSigner: linearVotingERC721MasterCopyContract.asSigner.attach(votingContractAddress!), asProvider: linearVotingERC721MasterCopyContract.asProvider.attach( @@ -110,6 +93,7 @@ export const useGovernanceContracts = () => { ), }; } + if (ozLinearVotingContract) { if (!govTokenAddress) { govTokenAddress = await ozLinearVotingContract.asProvider.governanceToken(); @@ -121,27 +105,29 @@ export const useGovernanceContracts = () => { // so we catch it and return undefined return undefined; }); - const possibleLockRelease = new ethers.Contract( - govTokenAddress, - LockRelease__factory.abi, - signerOrProvider - ) as LockRelease; + if (underlyingTokenAddress) { + const possibleLockRelease = new ethers.Contract( + govTokenAddress, + LockRelease__factory.abi, + signerOrProvider + ) as LockRelease; - const lockedToken = await possibleLockRelease.token().catch(() => { - // if the underlying token is not an ERC20Wrapper, this will throw an error, - // so we catch it and return undefined - return undefined; - }); + const lockedToken = await possibleLockRelease.token().catch(() => { + // if the underlying token is not an ERC20Wrapper, this will throw an error, + // so we catch it and return undefined + return undefined; + }); - if (lockedToken) { - lockReleaseContract = { - asSigner: LockRelease__factory.connect(govTokenAddress, signerOrProvider), - asProvider: LockRelease__factory.connect(govTokenAddress, provider), - }; - tokenContract = { - asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(lockedToken), - asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(lockedToken), - }; + if (lockedToken) { + lockReleaseContract = { + asSigner: LockRelease__factory.connect(govTokenAddress, signerOrProvider), + asProvider: LockRelease__factory.connect(govTokenAddress, provider), + }; + tokenContract = { + asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(lockedToken), + asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(lockedToken), + }; + } } else if (!underlyingTokenAddress) { tokenContract = { asSigner: votesTokenMasterCopyContract.asSigner.attach(govTokenAddress), @@ -155,14 +141,6 @@ export const useGovernanceContracts = () => { } } if (!!ozLinearVotingContract && !!tokenContract) { - // cache the addresses for future use, saves on query requests - setValue(AZORIUS_MODULE_CACHE_KEY + azoriusModuleContract.address, { - votingContractAddress, - govTokenAddress, - underlyingTokenAddress, - votingContractMasterCopyAddress, - }); - currentValidAddress.current = node.daoAddress; action.dispatch({ type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, payload: { @@ -175,10 +153,6 @@ export const useGovernanceContracts = () => { }, }); } else if (!!erc721LinearVotingContract) { - setValue(AZORIUS_MODULE_CACHE_KEY + azoriusModuleContract.address, { - votingContractAddress, - votingContractMasterCopyAddress, - }); currentValidAddress.current = node.daoAddress; action.dispatch({ type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, @@ -192,10 +166,6 @@ export const useGovernanceContracts = () => { }, }); } else if (!!erc721LinearVotingContract) { - setValue(AZORIUS_MODULE_CACHE_KEY + azoriusModuleContract.address, { - votingContractAddress, - votingContractMasterCopyAddress, - }); currentValidAddress.current = node.daoAddress; action.dispatch({ type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, @@ -237,17 +207,15 @@ export const useGovernanceContracts = () => { } }, [ action, - getValue, - setValue, provider, signerOrProvider, - linearVotingMasterCopyContract, votesTokenMasterCopyContract, - zodiacModuleProxyFactoryContract, fractalAzoriusMasterCopyContract, votesERC20WrapperMasterCopyContract, - linearVotingERC721MasterCopyContract, node, + getZodiacModuleProxyMasterCopyData, + linearVotingMasterCopyContract, + linearVotingERC721MasterCopyContract, ]); useEffect(() => { From 3b56545f6a54ae40060a23037b157aef1fd55911 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:54:56 -0500 Subject: [PATCH 03/29] update rest of location with new master copy hook for consistency --- .../ui/menus/ManageDAO/ManageDAOMenu.tsx | 38 +++----------- .../DAO/loaders/useFractalGuardContracts.ts | 52 +++++-------------- src/hooks/DAO/loaders/useFractalModules.ts | 40 +++----------- src/hooks/utils/useMasterCopy.ts | 8 +++ 4 files changed, 33 insertions(+), 105 deletions(-) diff --git a/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx b/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx index 3b51aa0d4d..154e3bca26 100644 --- a/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx +++ b/src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx @@ -2,14 +2,12 @@ import { VEllipsis } from '@decent-org/fractal-ui'; import { ERC20FreezeVoting, ERC721FreezeVoting, - ModuleProxyFactory, MultisigFreezeVoting, } from '@fractal-framework/fractal-contracts'; import { BigNumber } from 'ethers'; import { useRouter } from 'next/navigation'; import { useMemo, useCallback, useState, useEffect } from 'react'; import { DAO_ROUTES } from '../../../../constants/routes'; -import { getEventRPC } from '../../../../helpers'; import { isWithinFreezePeriod, isWithinFreezeProposalPeriod, @@ -17,9 +15,8 @@ import { import useSubmitProposal from '../../../../hooks/DAO/proposal/useSubmitProposal'; import useUserERC721VotingTokens from '../../../../hooks/DAO/proposal/useUserERC721VotingTokens'; import useClawBack from '../../../../hooks/DAO/useClawBack'; -import { CacheKeys } from '../../../../hooks/utils/cache/cacheDefaults'; -import { useLocalStorage } from '../../../../hooks/utils/cache/useLocalStorage'; import useBlockTimestamp from '../../../../hooks/utils/useBlockTimestamp'; +import { useMasterCopy } from '../../../../hooks/utils/useMasterCopy'; import { useFractal } from '../../../../providers/App/AppProvider'; import { FractalGuardContracts, @@ -71,8 +68,7 @@ export function ManageDAOMenu({ const currentTime = BigNumber.from(useBlockTimestamp()); const { push } = useRouter(); const safeAddress = fractalNode?.daoAddress; - const { setValue, getValue } = useLocalStorage(); - + const { getZodiacModuleProxyMasterCopyData } = useMasterCopy(); const { getCanUserCreateProposal } = useSubmitProposal(); const { getUserERC721VotingTokens } = useUserERC721VotingTokens(undefined, safeAddress, false); const { handleClawBack } = useClawBack({ @@ -117,32 +113,11 @@ export function ManageDAOMenu({ 0 ) )[1]; - const cachedMasterCopyAddress = getValue( - CacheKeys.MASTER_COPY_PREFIX + votingContractAddress - ); - let votingContractMasterCopyAddress = cachedMasterCopyAddress; - if (!votingContractMasterCopyAddress) { - const rpc = getEventRPC(zodiacModuleProxyFactoryContract); - const filter = rpc.filters.ModuleProxyCreation(votingContractAddress, null); - votingContractMasterCopyAddress = await rpc - .queryFilter(filter) - .then(proxiesCreated => { - return proxiesCreated[0].args.masterCopy; - }); - setValue( - CacheKeys.MASTER_COPY_PREFIX + votingContractAddress, - votingContractMasterCopyAddress - ); - } + const masterCopyData = await getZodiacModuleProxyMasterCopyData(votingContractAddress); - if ( - votingContractMasterCopyAddress === linearVotingMasterCopyContract.asProvider.address - ) { + if (masterCopyData.isOzLinearVoting) { result = GovernanceType.AZORIUS_ERC20; - } else if ( - votingContractMasterCopyAddress === - linearVotingERC721MasterCopyContract.asProvider.address - ) { + } else if (masterCopyData.isOzLinearVotingERC721) { result = GovernanceType.AZORIUS_ERC721; } } @@ -162,8 +137,7 @@ export function ManageDAOMenu({ safeAddress, type, zodiacModuleProxyFactoryContract, - getValue, - setValue, + getZodiacModuleProxyMasterCopyData, ]); const handleNavigateToSettings = useCallback( diff --git a/src/hooks/DAO/loaders/useFractalGuardContracts.ts b/src/hooks/DAO/loaders/useFractalGuardContracts.ts index 4bee36e77f..bf4281ab94 100644 --- a/src/hooks/DAO/loaders/useFractalGuardContracts.ts +++ b/src/hooks/DAO/loaders/useFractalGuardContracts.ts @@ -1,11 +1,6 @@ -import { - ModuleProxyFactory, - AzoriusFreezeGuard, - MultisigFreezeGuard, -} from '@fractal-framework/fractal-contracts'; +import { AzoriusFreezeGuard, MultisigFreezeGuard } from '@fractal-framework/fractal-contracts'; import { constants } from 'ethers'; import { useCallback, useEffect, useRef } from 'react'; -import { getEventRPC } from '../../../helpers'; import { useFractal } from '../../../providers/App/AppProvider'; import { GuardContractAction } from '../../../providers/App/guardContracts/action'; import { @@ -14,9 +9,8 @@ import { FreezeGuardType, FreezeVotingType, } from '../../../types'; -import { CacheKeys } from '../../utils/cache/cacheDefaults'; -import { useLocalStorage } from '../../utils/cache/useLocalStorage'; import { useEthersProvider } from '../../utils/useEthersProvider'; +import { useMasterCopy } from '../../utils/useMasterCopy'; import { FractalModuleData, FractalModuleType } from './../../../types/fractal'; export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: boolean }) => { // load key for component; helps prevent unnecessary calls @@ -24,7 +18,6 @@ export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: const { node: { daoAddress, safe, fractalModules, isModulesLoaded }, baseContracts: { - zodiacModuleProxyFactoryContract, freezeERC20VotingMasterCopyContract, freezeERC721VotingMasterCopyContract, freezeMultisigVotingMasterCopyContract, @@ -38,25 +31,7 @@ export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: network: { chainId }, } = useEthersProvider(); - const { setValue, getValue } = useLocalStorage(); - - const getMasterCopyAddress = useCallback( - async (proxyAddress: string): Promise => { - const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); - if (cachedValue) return cachedValue; - const filter = getEventRPC( - zodiacModuleProxyFactoryContract - ).filters.ModuleProxyCreation(proxyAddress, null); - return getEventRPC(zodiacModuleProxyFactoryContract) - .queryFilter(filter) - .then(proxiesCreated => { - if (proxiesCreated.length === 0) return constants.AddressZero; - setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, proxiesCreated[0].args.masterCopy); - return proxiesCreated[0].args.masterCopy; - }); - }, - [zodiacModuleProxyFactoryContract, getValue, setValue] - ); + const { getZodiacModuleProxyMasterCopyData } = useMasterCopy(); const loadFractalGuardContracts = useCallback( async ( @@ -84,10 +59,8 @@ export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: freezeGuardType = FreezeGuardType.AZORIUS; } else { const hasNoGuard = _safe.guard === constants.AddressZero; - const guardMasterCopyAddress = await getMasterCopyAddress(guard!); - const isSafeGuard = - guardMasterCopyAddress === multisigFreezeGuardMasterCopyContract.asProvider.address; - if (isSafeGuard && !hasNoGuard) { + const masterCopyData = await getZodiacModuleProxyMasterCopyData(guard!); + if (masterCopyData.isMultisigFreezeGuard && !hasNoGuard) { freezeGuardContract = { asSigner: multisigFreezeGuardMasterCopyContract.asSigner.attach(guard!), asProvider: multisigFreezeGuardMasterCopyContract.asProvider.attach(guard!), @@ -98,13 +71,12 @@ export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: if (!!freezeGuardContract) { const votingAddress = await freezeGuardContract.asProvider.freezeVoting(); - const votingMasterCopyAddress = await getMasterCopyAddress(votingAddress); - const freezeVotingType = - votingMasterCopyAddress === freezeMultisigVotingMasterCopyContract.asProvider.address - ? FreezeVotingType.MULTISIG - : votingMasterCopyAddress === freezeERC721VotingMasterCopyContract.asProvider.address - ? FreezeVotingType.ERC721 - : FreezeVotingType.ERC20; + const masterCopyData = await getZodiacModuleProxyMasterCopyData(votingAddress); + const freezeVotingType = masterCopyData.isMultisigFreezeVoting + ? FreezeVotingType.MULTISIG + : masterCopyData.isERC721FreezeVoting + ? FreezeVotingType.ERC721 + : FreezeVotingType.ERC20; const freezeVotingContract = freezeVotingType === FreezeVotingType.MULTISIG @@ -133,12 +105,12 @@ export const useFractalGuardContracts = ({ loadOnMount = true }: { loadOnMount?: } }, [ - getMasterCopyAddress, freezeERC20VotingMasterCopyContract, freezeERC721VotingMasterCopyContract, freezeMultisigVotingMasterCopyContract, azoriusFreezeGuardMasterCopyContract, multisigFreezeGuardMasterCopyContract, + getZodiacModuleProxyMasterCopyData, ] ); diff --git a/src/hooks/DAO/loaders/useFractalModules.ts b/src/hooks/DAO/loaders/useFractalModules.ts index a68ba409e7..a09d54c46b 100644 --- a/src/hooks/DAO/loaders/useFractalModules.ts +++ b/src/hooks/DAO/loaders/useFractalModules.ts @@ -1,52 +1,28 @@ -import { ModuleProxyFactory } from '@fractal-framework/fractal-contracts'; -import { constants, utils } from 'ethers'; import { useCallback } from 'react'; -import { getEventRPC } from '../../../helpers'; import { useFractal } from '../../../providers/App/AppProvider'; import { FractalModuleData, FractalModuleType } from '../../../types'; -import { CacheKeys } from '../../utils/cache/cacheDefaults'; -import { useLocalStorage } from './../../utils/cache/useLocalStorage'; +import { useMasterCopy } from '../../utils/useMasterCopy'; export const useFractalModules = () => { const { - baseContracts: { - zodiacModuleProxyFactoryContract, - fractalAzoriusMasterCopyContract, - fractalModuleMasterCopyContract, - }, + baseContracts: { fractalAzoriusMasterCopyContract, fractalModuleMasterCopyContract }, } = useFractal(); - const { setValue, getValue } = useLocalStorage(); - + const { getZodiacModuleProxyMasterCopyData } = useMasterCopy(); const lookupModules = useCallback( async (_moduleAddresses: string[]) => { - const rpc = getEventRPC(zodiacModuleProxyFactoryContract); - const getMasterCopyAddress = async (proxyAddress: string): Promise => { - const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); - if (cachedValue) return cachedValue; - const filter = rpc.filters.ModuleProxyCreation(proxyAddress, null); - return rpc.queryFilter(filter).then(proxiesCreated => { - if (proxiesCreated.length === 0) return constants.AddressZero; - setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, proxiesCreated[0].args.masterCopy); - return proxiesCreated[0].args.masterCopy; - }); - }; - const modules = await Promise.all( _moduleAddresses.map(async moduleAddress => { - const masterCopyAddress = await getMasterCopyAddress(moduleAddress); + const masterCopyData = await getZodiacModuleProxyMasterCopyData(moduleAddress); let safeModule: FractalModuleData; - if ( - utils.getAddress(masterCopyAddress) === - fractalAzoriusMasterCopyContract.asSigner.address - ) { + if (masterCopyData.isAzorius) { safeModule = { moduleContract: fractalAzoriusMasterCopyContract.asSigner.attach(moduleAddress), moduleAddress: moduleAddress, moduleType: FractalModuleType.AZORIUS, }; - } else if (masterCopyAddress === fractalModuleMasterCopyContract.asSigner.address) { + } else if (masterCopyData.isFractalModule) { safeModule = { moduleContract: fractalModuleMasterCopyContract.asSigner.attach(moduleAddress), moduleAddress: moduleAddress, @@ -66,11 +42,9 @@ export const useFractalModules = () => { return modules; }, [ - zodiacModuleProxyFactoryContract, fractalAzoriusMasterCopyContract, fractalModuleMasterCopyContract, - getValue, - setValue, + getZodiacModuleProxyMasterCopyData, ] ); return lookupModules; diff --git a/src/hooks/utils/useMasterCopy.ts b/src/hooks/utils/useMasterCopy.ts index 8967b29f82..98ebc8d6a0 100644 --- a/src/hooks/utils/useMasterCopy.ts +++ b/src/hooks/utils/useMasterCopy.ts @@ -15,6 +15,8 @@ export function useMasterCopy() { multisigFreezeGuardMasterCopyContract, freezeMultisigVotingMasterCopyContract, freezeERC721VotingMasterCopyContract, + fractalAzoriusMasterCopyContract, + fractalModuleMasterCopyContract, }, } = useFractal(); @@ -28,6 +30,10 @@ export function useMasterCopy() { masterCopyAddress === freezeMultisigVotingMasterCopyContract.asProvider.address; const isERC721FreezeVoting = (masterCopyAddress: string | `0x${string}`) => masterCopyAddress === freezeERC721VotingMasterCopyContract.asProvider.address; + const isAzorius = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === fractalAzoriusMasterCopyContract.asProvider.address; + const isFractalModule = (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === fractalModuleMasterCopyContract.asProvider.address; async function getMasterCopyAddress( contract: Contract, @@ -60,6 +66,8 @@ export function useMasterCopy() { isMultisigFreezeGuard: isMultisigFreezeGuard(masterCopyAddress), isMultisigFreezeVoting: isMultisigFreezeVoting(masterCopyAddress), isERC721FreezeVoting: isERC721FreezeVoting(masterCopyAddress), + isAzorius: isAzorius(masterCopyAddress), + isFractalModule: isFractalModule(masterCopyAddress), }; } From a3b647da38d607a490aa3f08fd7637158fe7d2d3 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:14:59 -0500 Subject: [PATCH 04/29] add useCallback to fix re-renders --- src/hooks/utils/useMasterCopy.ts | 132 ++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 47 deletions(-) diff --git a/src/hooks/utils/useMasterCopy.ts b/src/hooks/utils/useMasterCopy.ts index 98ebc8d6a0..35d0a27ab9 100644 --- a/src/hooks/utils/useMasterCopy.ts +++ b/src/hooks/utils/useMasterCopy.ts @@ -1,5 +1,6 @@ import { ModuleProxyFactory } from '@fractal-framework/fractal-contracts'; import { Contract, constants } from 'ethers'; +import { useCallback } from 'react'; import { getEventRPC } from '../../helpers'; import { useFractal } from '../../providers/App/AppProvider'; import { CacheKeys } from './cache/cacheDefaults'; @@ -20,56 +21,93 @@ export function useMasterCopy() { }, } = useFractal(); - const isOzLinearVoting = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === linearVotingMasterCopyContract.asProvider.address; - const isOzLinearVotingERC721 = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === linearVotingERC721MasterCopyContract.asProvider.address; - const isMultisigFreezeGuard = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === multisigFreezeGuardMasterCopyContract.asProvider.address; - const isMultisigFreezeVoting = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === freezeMultisigVotingMasterCopyContract.asProvider.address; - const isERC721FreezeVoting = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === freezeERC721VotingMasterCopyContract.asProvider.address; - const isAzorius = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === fractalAzoriusMasterCopyContract.asProvider.address; - const isFractalModule = (masterCopyAddress: string | `0x${string}`) => - masterCopyAddress === fractalModuleMasterCopyContract.asProvider.address; + const isOzLinearVoting = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === linearVotingMasterCopyContract.asProvider.address, + [linearVotingMasterCopyContract] + ); + const isOzLinearVotingERC721 = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === linearVotingERC721MasterCopyContract.asProvider.address, + [linearVotingERC721MasterCopyContract] + ); + const isMultisigFreezeGuard = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === multisigFreezeGuardMasterCopyContract.asProvider.address, + [multisigFreezeGuardMasterCopyContract] + ); + const isMultisigFreezeVoting = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === freezeMultisigVotingMasterCopyContract.asProvider.address, + [freezeMultisigVotingMasterCopyContract] + ); + const isERC721FreezeVoting = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === freezeERC721VotingMasterCopyContract.asProvider.address, + [freezeERC721VotingMasterCopyContract] + ); + const isAzorius = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === fractalAzoriusMasterCopyContract.asProvider.address, + [fractalAzoriusMasterCopyContract] + ); + const isFractalModule = useCallback( + (masterCopyAddress: string | `0x${string}`) => + masterCopyAddress === fractalModuleMasterCopyContract.asProvider.address, + [fractalModuleMasterCopyContract] + ); - async function getMasterCopyAddress( - contract: Contract, - proxyAddress: string | `0x${string}` - ): Promise<[string, string | null]> { - const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); - if (cachedValue) return [cachedValue, null] as const; + const getMasterCopyAddress = useCallback( + async function ( + contract: Contract, + proxyAddress: string | `0x${string}` + ): Promise<[string, string | null]> { + const cachedValue = getValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress); + if (cachedValue) return [cachedValue, null] as const; - const filter = contract.filters.ModuleProxyCreation(proxyAddress, null); - return contract.queryFilter(filter).then(proxiesCreated => { - if (proxiesCreated.length === 0) { - return [constants.AddressZero, 'No proxies created'] as const; - } - const masterCopyAddress = proxiesCreated[0].args!.masterCopy; - setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, masterCopyAddress); - return [masterCopyAddress, null] as const; - }); - } + const filter = contract.filters.ModuleProxyCreation(proxyAddress, null); + return contract.queryFilter(filter).then(proxiesCreated => { + if (proxiesCreated.length === 0) { + return [constants.AddressZero, 'No proxies created'] as const; + } + const masterCopyAddress = proxiesCreated[0].args!.masterCopy; + setValue(CacheKeys.MASTER_COPY_PREFIX + proxyAddress, masterCopyAddress); + return [masterCopyAddress, null] as const; + }); + }, + [getValue, setValue] + ); - async function getZodiacModuleProxyMasterCopyData(proxyAddress: string | `0x${string}`) { - const contract = getEventRPC(zodiacModuleProxyFactoryContract); - const [masterCopyAddress, error] = await getMasterCopyAddress(contract, proxyAddress); - if (error) { - console.error(error); - } - return { - address: masterCopyAddress, - isOzLinearVoting: isOzLinearVoting(masterCopyAddress), - isOzLinearVotingERC721: isOzLinearVotingERC721(masterCopyAddress), - isMultisigFreezeGuard: isMultisigFreezeGuard(masterCopyAddress), - isMultisigFreezeVoting: isMultisigFreezeVoting(masterCopyAddress), - isERC721FreezeVoting: isERC721FreezeVoting(masterCopyAddress), - isAzorius: isAzorius(masterCopyAddress), - isFractalModule: isFractalModule(masterCopyAddress), - }; - } + const getZodiacModuleProxyMasterCopyData = useCallback( + async function (proxyAddress: string | `0x${string}`) { + const contract = getEventRPC(zodiacModuleProxyFactoryContract); + const [masterCopyAddress, error] = await getMasterCopyAddress(contract, proxyAddress); + if (error) { + console.error(error); + } + return { + address: masterCopyAddress, + isOzLinearVoting: isOzLinearVoting(masterCopyAddress), + isOzLinearVotingERC721: isOzLinearVotingERC721(masterCopyAddress), + isMultisigFreezeGuard: isMultisigFreezeGuard(masterCopyAddress), + isMultisigFreezeVoting: isMultisigFreezeVoting(masterCopyAddress), + isERC721FreezeVoting: isERC721FreezeVoting(masterCopyAddress), + isAzorius: isAzorius(masterCopyAddress), + isFractalModule: isFractalModule(masterCopyAddress), + }; + }, + [ + zodiacModuleProxyFactoryContract, + getMasterCopyAddress, + isAzorius, + isFractalModule, + isERC721FreezeVoting, + isMultisigFreezeGuard, + isMultisigFreezeVoting, + isOzLinearVoting, + isOzLinearVotingERC721, + ] + ); return { getZodiacModuleProxyMasterCopyData }; } From 55c9dca798592086d96189cd7efe89f06ea566be Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Tue, 27 Feb 2024 21:38:40 -0500 Subject: [PATCH 05/29] Remove double instance of error logging initializing --- app/layout.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index c49bffdac5..4d42fef51a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,19 +1,12 @@ -'use client'; - import '@fontsource/ibm-plex-mono'; import '@fontsource/ibm-plex-sans'; import 'i18next'; -import { ReactNode, useEffect } from 'react'; +import { ReactNode } from 'react'; import 'react-toastify/dist/ReactToastify.min.css'; import { APP_NAME } from '../src/constants/common'; -import { initErrorLogging } from '../src/helpers/errorLogging'; import Providers from '../src/providers/Providers'; export default function RootLayout({ children }: { children: ReactNode }) { - useEffect(() => { - initErrorLogging(); - }, []); - return ( From 0265e413d64f70c84747c9f7dd7b0df8b1dccad4 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Tue, 27 Feb 2024 21:41:10 -0500 Subject: [PATCH 06/29] clear timer when switch daos - instances where a multisig is loaded first causes this timer to continue in the background. --- src/hooks/DAO/loaders/useProposals.ts | 16 +++++++++++++--- src/hooks/utils/useUpdateTimer.tsx | 7 ++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/hooks/DAO/loaders/useProposals.ts b/src/hooks/DAO/loaders/useProposals.ts index a0db356762..245365fa3a 100644 --- a/src/hooks/DAO/loaders/useProposals.ts +++ b/src/hooks/DAO/loaders/useProposals.ts @@ -13,21 +13,31 @@ export const useDAOProposals = () => { action, } = useFractal(); + const { setMethodOnInterval, clearIntervals } = useUpdateTimer(daoAddress); const loadAzoriusProposals = useAzoriusProposals(); const loadSafeMultisigProposals = useSafeMultisigProposals(); - const { setMethodOnInterval } = useUpdateTimer(daoAddress); + const loadDAOProposals = useCallback(async () => { if (type === GovernanceType.AZORIUS_ERC20 || type === GovernanceType.AZORIUS_ERC721) { // load Azorius proposals and strategies + const proposals = await loadAzoriusProposals(); action.dispatch({ type: FractalGovernanceAction.SET_PROPOSALS, - payload: await loadAzoriusProposals(), + payload: proposals, }); + clearIntervals(); } else if (type === GovernanceType.MULTISIG) { // load mulisig proposals setMethodOnInterval(loadSafeMultisigProposals); } - }, [type, loadAzoriusProposals, action, loadSafeMultisigProposals, setMethodOnInterval]); + }, [ + type, + loadAzoriusProposals, + action, + loadSafeMultisigProposals, + setMethodOnInterval, + clearIntervals, + ]); return loadDAOProposals; }; diff --git a/src/hooks/utils/useUpdateTimer.tsx b/src/hooks/utils/useUpdateTimer.tsx index f51ed91550..cb9230b9a0 100644 --- a/src/hooks/utils/useUpdateTimer.tsx +++ b/src/hooks/utils/useUpdateTimer.tsx @@ -39,6 +39,11 @@ export const useUpdateTimer = (safeAddress?: string | null) => { [isActive] ); + // clear intervals + const clearIntervals = () => { + timers.current.forEach(timer => clearInterval(timer)); + }; + // Clear intervals when the component is unmounted to avoid memory leaks useEffect(() => { const nodeTimers = timers.current; @@ -54,5 +59,5 @@ export const useUpdateTimer = (safeAddress?: string | null) => { } }, [safeAddress]); - return { setMethodOnInterval }; + return { setMethodOnInterval, clearIntervals }; }; From 09833514449193a2b9b60e4dfd5244577fb01879 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Tue, 27 Feb 2024 21:43:06 -0500 Subject: [PATCH 07/29] loading key no longer needed - The key and other additional dependencies was causing additional renders --- .../DAO/loaders/useGovernanceContracts.ts | 287 ++++++++---------- 1 file changed, 133 insertions(+), 154 deletions(-) diff --git a/src/hooks/DAO/loaders/useGovernanceContracts.ts b/src/hooks/DAO/loaders/useGovernanceContracts.ts index b97c99c613..3c4deccd52 100644 --- a/src/hooks/DAO/loaders/useGovernanceContracts.ts +++ b/src/hooks/DAO/loaders/useGovernanceContracts.ts @@ -6,7 +6,7 @@ import { LinearERC721Voting, } from '@fractal-framework/fractal-contracts'; import { ethers } from 'ethers'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import { LockRelease, LockRelease__factory } from '../../../assets/typechain-types/dcnt'; import { useFractal } from '../../../providers/App/AppProvider'; import { GovernanceContractAction } from '../../../providers/App/governanceContracts/action'; @@ -31,179 +31,163 @@ export const useGovernanceContracts = () => { action, } = useFractal(); const { getZodiacModuleProxyMasterCopyData } = useMasterCopy(); - const provider = useEthersProvider(); const signerOrProvider = useSignerOrProvider(); - const { - network: { chainId }, - } = provider; - const [lastChainId, setLastChainId] = useState(); + const { fractalModules, isModulesLoaded, daoAddress } = node; const loadGovernanceContracts = useCallback(async () => { - const { fractalModules } = node; - const azoriusModule = getAzoriusModuleFromModules(fractalModules); const azoriusModuleContract = azoriusModule?.moduleContract as Azorius; - if (node.isModulesLoaded) { - if (!!azoriusModuleContract) { - const azoriusContract = { - asProvider: fractalAzoriusMasterCopyContract.asProvider.attach( - azoriusModuleContract.address - ), - asSigner: fractalAzoriusMasterCopyContract.asSigner.attach(azoriusModuleContract.address), - }; + if (!!azoriusModuleContract) { + const azoriusContract = { + asProvider: fractalAzoriusMasterCopyContract.asProvider.attach( + azoriusModuleContract.address + ), + asSigner: fractalAzoriusMasterCopyContract.asSigner.attach(azoriusModuleContract.address), + }; - let votingContractMasterCopyAddress: string | undefined; - let govTokenAddress: string | undefined; + let votingContractMasterCopyAddress: string | undefined; + let govTokenAddress: string | undefined; - let ozLinearVotingContract: ContractConnection | undefined; - let erc721LinearVotingContract: ContractConnection | undefined; - let tokenContract: ContractConnection | undefined; - let underlyingTokenAddress: string | undefined; - let lockReleaseContract: ContractConnection | null = null; + let ozLinearVotingContract: ContractConnection | undefined; + let erc721LinearVotingContract: ContractConnection | undefined; + let tokenContract: ContractConnection | undefined; + let underlyingTokenAddress: string | undefined; + let lockReleaseContract: ContractConnection | null = null; - // @dev assumes the first strategy is the voting contract - const votingContractAddress = ( - await azoriusContract.asProvider.getStrategies( - '0x0000000000000000000000000000000000000001', - 0 - ) - )[1]; + // @dev assumes the first strategy is the voting contract + const votingContractAddress = ( + await azoriusContract.asProvider.getStrategies( + '0x0000000000000000000000000000000000000001', + 0 + ) + )[1]; - let isOzLinearVoting, - isOzLinearVotingERC721 = false; - if (!votingContractMasterCopyAddress) { - const masterCopyData = await getZodiacModuleProxyMasterCopyData(votingContractAddress); - isOzLinearVoting = masterCopyData.isOzLinearVoting; - isOzLinearVotingERC721 = masterCopyData.isOzLinearVotingERC721; - } + let isOzLinearVoting, + isOzLinearVotingERC721 = false; + if (!votingContractMasterCopyAddress) { + const masterCopyData = await getZodiacModuleProxyMasterCopyData(votingContractAddress); + isOzLinearVoting = masterCopyData.isOzLinearVoting; + isOzLinearVotingERC721 = masterCopyData.isOzLinearVotingERC721; + } - if (isOzLinearVoting) { - ozLinearVotingContract = { - asSigner: linearVotingMasterCopyContract.asSigner.attach(votingContractAddress!), - asProvider: linearVotingMasterCopyContract.asProvider.attach(votingContractAddress!), - }; - } else if (isOzLinearVotingERC721) { - erc721LinearVotingContract = { - asSigner: linearVotingERC721MasterCopyContract.asSigner.attach(votingContractAddress!), - asProvider: linearVotingERC721MasterCopyContract.asProvider.attach( - votingContractAddress! - ), - }; - } + if (isOzLinearVoting) { + ozLinearVotingContract = { + asSigner: linearVotingMasterCopyContract.asSigner.attach(votingContractAddress!), + asProvider: linearVotingMasterCopyContract.asProvider.attach(votingContractAddress!), + }; + } else if (isOzLinearVotingERC721) { + erc721LinearVotingContract = { + asSigner: linearVotingERC721MasterCopyContract.asSigner.attach(votingContractAddress!), + asProvider: linearVotingERC721MasterCopyContract.asProvider.attach( + votingContractAddress! + ), + }; + } - if (ozLinearVotingContract) { - if (!govTokenAddress) { - govTokenAddress = await ozLinearVotingContract.asProvider.governanceToken(); - } - const possibleERC20Wrapper = - votesERC20WrapperMasterCopyContract.asProvider.attach(govTokenAddress); - underlyingTokenAddress = await possibleERC20Wrapper.underlying().catch(() => { - // if the underlying token is not an ERC20Wrapper, this will throw an error, - // so we catch it and return undefined - return undefined; - }); - if (underlyingTokenAddress) { - const possibleLockRelease = new ethers.Contract( - govTokenAddress, - LockRelease__factory.abi, - signerOrProvider - ) as LockRelease; + if (ozLinearVotingContract) { + govTokenAddress = await ozLinearVotingContract.asProvider.governanceToken(); + const possibleERC20Wrapper = + votesERC20WrapperMasterCopyContract.asProvider.attach(govTokenAddress); + underlyingTokenAddress = await possibleERC20Wrapper.underlying().catch(() => { + // if the underlying token is not an ERC20Wrapper, this will throw an error, + // so we catch it and return undefined + return undefined; + }); + const possibleLockRelease = new ethers.Contract( + govTokenAddress, + LockRelease__factory.abi, + provider + ) as LockRelease; - const lockedToken = await possibleLockRelease.token().catch(() => { - // if the underlying token is not an ERC20Wrapper, this will throw an error, - // so we catch it and return undefined - return undefined; - }); + const lockedToken = await possibleLockRelease.token().catch(() => { + // if the underlying token is not an ERC20Wrapper, this will throw an error, + // so we catch it and return undefined + return undefined; + }); - if (lockedToken) { - lockReleaseContract = { - asSigner: LockRelease__factory.connect(govTokenAddress, signerOrProvider), - asProvider: LockRelease__factory.connect(govTokenAddress, provider), - }; - tokenContract = { - asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(lockedToken), - asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(lockedToken), - }; - } - } else if (!underlyingTokenAddress) { - tokenContract = { - asSigner: votesTokenMasterCopyContract.asSigner.attach(govTokenAddress), - asProvider: votesTokenMasterCopyContract.asProvider.attach(govTokenAddress), - }; - } else { - tokenContract = { - asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(govTokenAddress), - asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(govTokenAddress), - }; - } - } - if (!!ozLinearVotingContract && !!tokenContract) { - action.dispatch({ - type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, - payload: { - ozLinearVotingContract, - erc721LinearVotingContract: null, - azoriusContract, - tokenContract, - underlyingTokenAddress, - lockReleaseContract, - }, - }); - } else if (!!erc721LinearVotingContract) { - currentValidAddress.current = node.daoAddress; - action.dispatch({ - type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, - payload: { - ozLinearVotingContract: null, - lockReleaseContract: null, - erc721LinearVotingContract, - azoriusContract, - tokenContract: null, - underlyingTokenAddress, - }, - }); - } else if (!!erc721LinearVotingContract) { - currentValidAddress.current = node.daoAddress; - action.dispatch({ - type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, - payload: { - ozLinearVotingContract: null, - erc721LinearVotingContract, - azoriusContract, - tokenContract: null, - underlyingTokenAddress, - lockReleaseContract: null, - }, - }); + if (lockedToken) { + lockReleaseContract = { + asSigner: LockRelease__factory.connect(govTokenAddress, signerOrProvider), + asProvider: LockRelease__factory.connect(govTokenAddress, provider), + }; + tokenContract = { + asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(lockedToken), + asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(lockedToken), + }; + } else if (!underlyingTokenAddress) { + tokenContract = { + asSigner: votesTokenMasterCopyContract.asSigner.attach(govTokenAddress), + asProvider: votesTokenMasterCopyContract.asProvider.attach(govTokenAddress), + }; } else { - currentValidAddress.current = node.daoAddress; - action.dispatch({ - type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, - payload: { - ozLinearVotingContract: null, - erc721LinearVotingContract: null, - azoriusContract: null, - tokenContract: null, - lockReleaseContract: null, - }, - }); + tokenContract = { + asSigner: votesERC20WrapperMasterCopyContract.asSigner.attach(govTokenAddress), + asProvider: votesERC20WrapperMasterCopyContract.asProvider.attach(govTokenAddress), + }; } + } + if (!!ozLinearVotingContract && !!tokenContract) { + action.dispatch({ + type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, + payload: { + ozLinearVotingContract, + erc721LinearVotingContract: null, + azoriusContract, + tokenContract, + underlyingTokenAddress, + lockReleaseContract, + }, + }); + } else if (!!erc721LinearVotingContract) { + action.dispatch({ + type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, + payload: { + ozLinearVotingContract: null, + lockReleaseContract: null, + erc721LinearVotingContract, + azoriusContract, + tokenContract: null, + underlyingTokenAddress, + }, + }); + } else if (!!erc721LinearVotingContract) { + action.dispatch({ + type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, + payload: { + ozLinearVotingContract: null, + erc721LinearVotingContract, + azoriusContract, + tokenContract: null, + underlyingTokenAddress, + lockReleaseContract: null, + }, + }); } else { - currentValidAddress.current = node.daoAddress; action.dispatch({ type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, payload: { ozLinearVotingContract: null, - azoriusContract: null, erc721LinearVotingContract: null, + azoriusContract: null, tokenContract: null, lockReleaseContract: null, }, }); } + } else { + action.dispatch({ + type: GovernanceContractAction.SET_GOVERNANCE_CONTRACT, + payload: { + ozLinearVotingContract: null, + azoriusContract: null, + erc721LinearVotingContract: null, + tokenContract: null, + lockReleaseContract: null, + }, + }); } }, [ action, @@ -212,21 +196,16 @@ export const useGovernanceContracts = () => { votesTokenMasterCopyContract, fractalAzoriusMasterCopyContract, votesERC20WrapperMasterCopyContract, - node, getZodiacModuleProxyMasterCopyData, linearVotingMasterCopyContract, linearVotingERC721MasterCopyContract, + fractalModules, ]); useEffect(() => { - if ( - (!!node.daoAddress && - node.isModulesLoaded && - node.daoAddress !== currentValidAddress.current) || - lastChainId !== chainId - ) { - setLastChainId(chainId); + if (currentValidAddress.current !== daoAddress && isModulesLoaded) { loadGovernanceContracts(); + currentValidAddress.current = daoAddress; } - }, [node, loadGovernanceContracts, lastChainId, chainId]); + }, [isModulesLoaded, loadGovernanceContracts, daoAddress]); }; From a896bf7f950625c55d3c9deeb7f93c0f0b1a2618 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 28 Feb 2024 08:59:28 -0500 Subject: [PATCH 08/29] empty commit From de8243631ab5d9fe7c22dec77e97347e80c78969 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:25:56 -0500 Subject: [PATCH 09/29] fix fonts not loadding; REadd use client --- app/layout.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/layout.tsx b/app/layout.tsx index 4d42fef51a..8dd2d9a6be 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,3 +1,4 @@ +'use client'; import '@fontsource/ibm-plex-mono'; import '@fontsource/ibm-plex-sans'; import 'i18next'; From 569b4d198e5d835dfb009f8542a44a0957dca595 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:34:02 -0500 Subject: [PATCH 10/29] revert and move imports instead --- app/layout.tsx | 4 ---- src/providers/Providers.tsx | 4 +++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index 8dd2d9a6be..51970ce0bf 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,9 +1,5 @@ -'use client'; -import '@fontsource/ibm-plex-mono'; -import '@fontsource/ibm-plex-sans'; import 'i18next'; import { ReactNode } from 'react'; -import 'react-toastify/dist/ReactToastify.min.css'; import { APP_NAME } from '../src/constants/common'; import Providers from '../src/providers/Providers'; diff --git a/src/providers/Providers.tsx b/src/providers/Providers.tsx index 4a871cdbfb..2968441281 100644 --- a/src/providers/Providers.tsx +++ b/src/providers/Providers.tsx @@ -14,7 +14,9 @@ import { FractalErrorBoundary, initErrorLogging } from '../helpers/errorLogging' import { AppProvider } from './App/AppProvider'; import { NetworkConfigProvider } from './NetworkConfig/NetworkConfigProvider'; import { wagmiConfig, chains } from './NetworkConfig/rainbow-kit.config'; - +import '@fontsource/ibm-plex-mono'; +import '@fontsource/ibm-plex-sans'; +import 'react-toastify/dist/ReactToastify.min.css'; export default function Providers({ children }: { children: ReactNode }) { useEffect(() => { initErrorLogging(); From d6b52e143c07ef3ae2c24a592964c5313b4a754e Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 28 Feb 2024 16:58:16 -0500 Subject: [PATCH 11/29] Use wagmi public client as requestor in proxy target request function parameter --- src/components/ui/forms/ABISelector.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/ui/forms/ABISelector.tsx b/src/components/ui/forms/ABISelector.tsx index b886e0c75e..1daeb21148 100644 --- a/src/components/ui/forms/ABISelector.tsx +++ b/src/components/ui/forms/ABISelector.tsx @@ -4,7 +4,7 @@ import { isAddress } from 'ethers/lib/utils'; import detectProxyTarget from 'evm-proxy-detection'; import { useMemo, useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { useEnsAddress } from 'wagmi'; +import { useEnsAddress, usePublicClient } from 'wagmi'; import { logError } from '../../../helpers/errorLogging'; import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider'; import { useEIP1193Providers } from '../../../providers/NetworkConfig/utils'; @@ -32,13 +32,14 @@ export default function ABISelector({ target, onChange, onFetchABI }: IABISelect const { t } = useTranslation('common'); const { eip1193InfuraProvider } = useEIP1193Providers(); const { data: ensAddress } = useEnsAddress({ name: target }); + const client = usePublicClient(); useEffect(() => { const loadABI = async () => { if (target && ((ensAddress && isAddress(ensAddress)) || isAddress(target))) { try { - const requestFunc = ({ method, params }: { method: string; params: any[] }) => - eip1193InfuraProvider.send(method, params); + const requestFunc = ({ method, params }: { method: any; params: any }) => + client.request({ method, params }); const proxy = await detectProxyTarget(ensAddress || target, requestFunc); @@ -71,7 +72,7 @@ export default function ABISelector({ target, onChange, onFetchABI }: IABISelect } }; loadABI(); - }, [target, ensAddress, etherscanAPIBaseUrl, onFetchABI, eip1193InfuraProvider]); + }, [target, ensAddress, etherscanAPIBaseUrl, onFetchABI, client]); /* * This makes component quite scoped to proposal / proposal template creation From a40b61e036ee1cd6e63db3105c9f1e7bc1a3f280 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 28 Feb 2024 16:58:53 -0500 Subject: [PATCH 12/29] Remove unused references to Infura EIP1193Provider --- src/components/ui/forms/ABISelector.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/ui/forms/ABISelector.tsx b/src/components/ui/forms/ABISelector.tsx index 1daeb21148..e7ee44c602 100644 --- a/src/components/ui/forms/ABISelector.tsx +++ b/src/components/ui/forms/ABISelector.tsx @@ -7,7 +7,6 @@ import { useTranslation } from 'react-i18next'; import { useEnsAddress, usePublicClient } from 'wagmi'; import { logError } from '../../../helpers/errorLogging'; import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider'; -import { useEIP1193Providers } from '../../../providers/NetworkConfig/utils'; import { LabelComponent } from './InputComponent'; export type ABIElement = { @@ -30,7 +29,6 @@ export default function ABISelector({ target, onChange, onFetchABI }: IABISelect const [abi, setABI] = useState([]); const { etherscanAPIBaseUrl } = useNetworkConfig(); const { t } = useTranslation('common'); - const { eip1193InfuraProvider } = useEIP1193Providers(); const { data: ensAddress } = useEnsAddress({ name: target }); const client = usePublicClient(); From b24e97c755b54fd4a0914bd79da6d849a06bacf1 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 28 Feb 2024 16:59:05 -0500 Subject: [PATCH 13/29] Delete unused useEIP1193Providers hook --- src/providers/NetworkConfig/utils.ts | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/providers/NetworkConfig/utils.ts diff --git a/src/providers/NetworkConfig/utils.ts b/src/providers/NetworkConfig/utils.ts deleted file mode 100644 index b45225025a..0000000000 --- a/src/providers/NetworkConfig/utils.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { InfuraProvider } from '@ethersproject/providers'; -import { useMemo } from 'react'; -import { useNetworkConfig } from './NetworkConfigProvider'; - -export const useEIP1193Providers = () => { - const { chainId } = useNetworkConfig(); - - // Unfortunately, usePublicClient from wagmi package does not return instance that compatible with EIP1193 standard - // And that's required for Proxy Detection - const eip1193InfuraProvider = useMemo( - () => new InfuraProvider(chainId, process.env.NEXT_PUBLIC_INFURA_API_KEY!), - [chainId] - ); - - return { eip1193InfuraProvider }; -}; From ca8067216137df4e6d35c65e4da58a1b9ae4bfa3 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 28 Feb 2024 16:59:22 -0500 Subject: [PATCH 14/29] Remove reference to unused NEXT_PUBLIC_INFURA_API_KEY env var --- .env | 2 -- 1 file changed, 2 deletions(-) diff --git a/.env b/.env index 455c7f30e0..df3aabc62a 100644 --- a/.env +++ b/.env @@ -6,8 +6,6 @@ NEXT_PUBLIC_ALCHEMY_SEPOLIA_API_KEY="" NEXT_PUBLIC_ALCHEMY_TESTING_API_KEY="" # ABI selector (*) NEXT_PUBLIC_ETHERSCAN_API_KEY="" -# wallet providers (*) -NEXT_PUBLIC_INFURA_API_KEY="" # IPFS pinning (*) NEXT_PUBLIC_INFURA_IPFS_API_KEY="" # IPFS pinning (*) From adce53c5a8a8c73f11aa52ca7dc177fd69c9fd09 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:17:52 -0500 Subject: [PATCH 15/29] ensure the DAO resets when navigating DAOs - readd updating ref to null when DAO is not loaded --- src/hooks/DAO/loaders/useGovernanceContracts.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/DAO/loaders/useGovernanceContracts.ts b/src/hooks/DAO/loaders/useGovernanceContracts.ts index 3c4deccd52..cc8999e124 100644 --- a/src/hooks/DAO/loaders/useGovernanceContracts.ts +++ b/src/hooks/DAO/loaders/useGovernanceContracts.ts @@ -176,6 +176,7 @@ export const useGovernanceContracts = () => { lockReleaseContract: null, }, }); + currentValidAddress.current = null; } } else { action.dispatch({ @@ -188,6 +189,7 @@ export const useGovernanceContracts = () => { lockReleaseContract: null, }, }); + currentValidAddress.current = null; } }, [ action, From 50270d1fb9d9c79d5e2632a3a5becd041ab9ce6f Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:13:28 -0500 Subject: [PATCH 16/29] reset DAO when navigating to parent address --- src/components/pages/DaoDashboard/Info/ParentLink.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/pages/DaoDashboard/Info/ParentLink.tsx b/src/components/pages/DaoDashboard/Info/ParentLink.tsx index abc5459822..1e5e4d9196 100644 --- a/src/components/pages/DaoDashboard/Info/ParentLink.tsx +++ b/src/components/pages/DaoDashboard/Info/ParentLink.tsx @@ -10,6 +10,7 @@ import { useFractal } from '../../../../providers/App/AppProvider'; export function ParentLink() { const { node: { nodeHierarchy }, + action, } = useFractal(); const { t } = useTranslation('breadcrumbs'); @@ -22,6 +23,7 @@ export function ParentLink() { color="gold.500" _hover={{ textDecoration: 'none', color: 'gold.500-hover' }} href={DAO_ROUTES.dao.relative(nodeHierarchy.parentAddress)} + onClick={action.resetDAO} marginBottom="1rem" as={NextLink} > From 8bd02326fa81a7ccf2cfd74ca3833d8aa42c3857 Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:24:53 -0500 Subject: [PATCH 17/29] fix state not updating --- .../DaoDashboard/Info/InfoGovernance.tsx | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/components/pages/DaoDashboard/Info/InfoGovernance.tsx b/src/components/pages/DaoDashboard/Info/InfoGovernance.tsx index 95a7e8471c..6603d28907 100644 --- a/src/components/pages/DaoDashboard/Info/InfoGovernance.tsx +++ b/src/components/pages/DaoDashboard/Info/InfoGovernance.tsx @@ -20,33 +20,34 @@ export function InfoGovernance() { } = useFractal(); const provider = useEthersProvider(); const { getTimeDuration } = useTimeHelpers(); - const [timelockPeriod, setTimelockPeriod] = useState(); const [executionPeriod, setExecutionPeriod] = useState(); useEffect(() => { const setTimelockInfo = async () => { - if (!timelockPeriod && !executionPeriod) { - const formatBlocks = async (blocks: number): Promise => { - return getTimeDuration(await blocksToSeconds(blocks, provider)); - }; - if (freezeGuardType == FreezeGuardType.MULTISIG) { - if (freezeGuardContract) { - const freezeGuard = freezeGuardContract.asProvider as MultisigFreezeGuard; - setTimelockPeriod(await formatBlocks(await freezeGuard.timelockPeriod())); - setExecutionPeriod(await formatBlocks(await freezeGuard.executionPeriod())); - } - } else if (dao?.isAzorius) { - const azoriusGovernance = governance as AzoriusGovernance; - const timelock = azoriusGovernance.votingStrategy?.timeLockPeriod; - if (timelock?.formatted) { - setTimelockPeriod(timelock.formatted); - } - // TODO Azorius execution period - // We don't have room to fit a 5th row on this card currently, - // so leaving this off until we can have a discussion with design - // setExecutionPeriod(await freezeGuard.executionPeriod()); + const formatBlocks = async (blocks: number): Promise => { + return getTimeDuration(await blocksToSeconds(blocks, provider)); + }; + if (freezeGuardType == FreezeGuardType.MULTISIG) { + if (freezeGuardContract) { + const freezeGuard = freezeGuardContract.asProvider as MultisigFreezeGuard; + setTimelockPeriod(await formatBlocks(await freezeGuard.timelockPeriod())); + setExecutionPeriod(await formatBlocks(await freezeGuard.executionPeriod())); + } + } else if (dao?.isAzorius) { + const azoriusGovernance = governance as AzoriusGovernance; + const timelock = azoriusGovernance.votingStrategy?.timeLockPeriod; + if (timelock?.formatted) { + setTimelockPeriod(timelock.formatted); } + // TODO Azorius execution period + // We don't have room to fit a 5th row on this card currently, + // so leaving this off until we can have a discussion with design + // setExecutionPeriod(await freezeGuard.executionPeriod()); } + return () => { + setTimelockPeriod(undefined); + setExecutionPeriod(undefined); + }; }; setTimelockInfo(); From ec44d5bf9e8e5c09f069f29e0195335c9b24a65d Mon Sep 17 00:00:00 2001 From: David Colon <38386583+Da-Colon@users.noreply.github.com> Date: Fri, 1 Mar 2024 09:19:19 -0500 Subject: [PATCH 18/29] remove unneeded dependency --- src/hooks/DAO/loaders/useFractalGovernance.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hooks/DAO/loaders/useFractalGovernance.ts b/src/hooks/DAO/loaders/useFractalGovernance.ts index c6cfb92d42..c5fbc0796f 100644 --- a/src/hooks/DAO/loaders/useFractalGovernance.ts +++ b/src/hooks/DAO/loaders/useFractalGovernance.ts @@ -81,12 +81,11 @@ export const useFractalGovernance = () => { } = governanceContracts; const newLoadKey = - daoAddress + (azoriusContract ? '1' : '0') + nodeHierarchy.parentAddress + !!guardContracts.freezeGuardContract; - if (isLoaded && daoAddress && newLoadKey !== loadKey.current) { + if (isLoaded && newLoadKey !== loadKey.current) { loadKey.current = newLoadKey; if (azoriusContract) { @@ -115,11 +114,8 @@ export const useFractalGovernance = () => { payload: GovernanceType.MULTISIG, }); } - } else if (!isLoaded) { - loadKey.current = undefined; } }, [ - daoAddress, governanceContracts, loadDAOProposals, loadUnderlyingERC20Token, From bc7b1ab35f6342207fb8697098356d6fd72540ab Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 11:12:41 -0500 Subject: [PATCH 19/29] Fix padding on featured DAO cards past the first row --- app/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index b4d4bb8dd8..31966ad421 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -227,8 +227,8 @@ export default function HomePage() { desc={t(feature.descKey)} address={feature.address} marginBottom="2rem" - paddingEnd={{ sm: '0rem', lg: index === 0 ? '0.56rem' : '0rem' }} - paddingStart={{ sm: '0rem', lg: index === 1 ? '0.56rem' : '0rem' }} + paddingEnd={{ sm: '0rem', lg: index % 2 === 0 ? '0.56rem' : '0rem' }} + paddingStart={{ sm: '0rem', lg: index % 2 === 1 ? '0.56rem' : '0rem' }} /> ); })} From 73d532f893c1ac729916fa1bfc8424c1630107de Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 11:13:35 -0500 Subject: [PATCH 20/29] My prettier did a lil formatting on save --- src/i18n/locales/en/home.json | 48 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index fa4f0adb7b..2e2b85096d 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -1,25 +1,25 @@ { - "homeTitle": "Welcome to Fractal", - "homeDesc": "Are you outgrowing your Multisig? Fractal extends Safe treasuries into on-chain hierarchies of permissions, token flows, and governance.", - "govern": "Govern", - "governDesc": "Choose a governance per sub-Safe. Create and authorize proposals. Decentralize on any timeline.", - "structure": "Structure", - "structureDesc": "Start with any Safe Multisig. Connect teams in flexible sub-Safe hierarchies for agile delivery.", - "operate": "Operate", - "operateDesc": "Unleash on-chain efficiency with reuseable, streamed, and permissioned transactions.", - "featuredTitle": "Featured Organizations", - "featuredDesc": "Here are some projects using Fractal to convert their Safe Multisig into DAOs as they decentralize:", - "decentTitle": "Decent DAO", - "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", - "homeAttribution": "Made with 💜 by <1>Decent DAO", - "audit": "Audit", - "learnCTA": "Explore the Docs to see how Fractal works", - "getStartedButton": "Get Started" -} \ No newline at end of file + "homeTitle": "Welcome to Fractal", + "homeDesc": "Are you outgrowing your Multisig? Fractal extends Safe treasuries into on-chain hierarchies of permissions, token flows, and governance.", + "govern": "Govern", + "governDesc": "Choose a governance per sub-Safe. Create and authorize proposals. Decentralize on any timeline.", + "structure": "Structure", + "structureDesc": "Start with any Safe Multisig. Connect teams in flexible sub-Safe hierarchies for agile delivery.", + "operate": "Operate", + "operateDesc": "Unleash on-chain efficiency with reuseable, streamed, and permissioned transactions.", + "featuredTitle": "Featured Organizations", + "featuredDesc": "Here are some projects using Fractal to convert their Safe Multisig into DAOs as they decentralize:", + "decentTitle": "Decent DAO", + "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", + "homeAttribution": "Made with 💜 by <1>Decent DAO", + "audit": "Audit", + "learnCTA": "Explore the Docs to see how Fractal works", + "getStartedButton": "Get Started" +} From 0f99c5c3ea6a86ab9885dc47fac6b47e02589691 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 11:14:01 -0500 Subject: [PATCH 21/29] Add strings for Shutter DAO title and description --- src/i18n/locales/en/home.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index 2e2b85096d..ba991a7d0d 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -15,6 +15,8 @@ "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.", + "shutterTitle": "Shutter DAO 0x36", + "shutterDesc": "Shutter is an anti-frontrunning/malicious MEV protocol using threshold encryption. The Shutter protoDAO is a pragmatic, step-by-step approach towards decentralization, prioritizing community involvement and learning from each phase while maintaining operational reliability and security.", "featureLink": "Explore >", "readyCTA": "Ready to start?", "createButton": "+ Start from Scratch", From 4b0c84a655f57f328c3dbd211a10d2d65bab46d0 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 11:14:15 -0500 Subject: [PATCH 22/29] Add Shutter icon just the logo --- public/images/shutter-icon-only-logo.svg | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 public/images/shutter-icon-only-logo.svg diff --git a/public/images/shutter-icon-only-logo.svg b/public/images/shutter-icon-only-logo.svg new file mode 100644 index 0000000000..23e44bf15e --- /dev/null +++ b/public/images/shutter-icon-only-logo.svg @@ -0,0 +1,8 @@ + + + + + + + + From 8c44629f43dfaa785ff8ea0646d95372edd6d6bd Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 11:14:30 -0500 Subject: [PATCH 23/29] Add a card for Shutter DAO 0x36 --- app/page.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/page.tsx b/app/page.tsx index 31966ad421..657e054c99 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -48,6 +48,12 @@ const FEATURED_DAOS = new Map([ [ mainnet.id, [ + { + iconSrc: '/images/shutter-icon-only-logo.svg', + titleKey: 'shutterTitle', + descKey: 'shutterDesc', + address: '0x36bD3044ab68f600f6d3e081056F34f2a58432c4', + }, { iconSrc: '/images/icon-decent.svg', titleKey: 'decentTitle', From ec410bfc550b0171dc8a2dad1be62edec695291f Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 12:10:41 -0500 Subject: [PATCH 24/29] Update language in Shutter Description --- src/i18n/locales/en/home.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index ba991a7d0d..4d29d1d5da 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -16,7 +16,7 @@ "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.", "shutterTitle": "Shutter DAO 0x36", - "shutterDesc": "Shutter is an anti-frontrunning/malicious MEV protocol using threshold encryption. The Shutter protoDAO is a pragmatic, step-by-step approach towards decentralization, prioritizing community involvement and learning from each phase while maintaining operational reliability and security.", + "shutterDesc": "Shutter is an anti-frontrunning/malicious MEV protocol using threshold encryption. Shutter DAO 0x36 is a pragmatic, step-by-step approach towards decentralization, prioritizing community involvement and learning from each phase while maintaining operational reliability and security.", "featureLink": "Explore >", "readyCTA": "Ready to start?", "createButton": "+ Start from Scratch", From f1b27732a9de386fc76aad56784f10c9becbf85f Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 12:35:44 -0500 Subject: [PATCH 25/29] If there are no featured DAOs for a supported network, don't render the Featured Organizations section at all --- app/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/page.tsx b/app/page.tsx index 657e054c99..2c2dce594b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -198,7 +198,7 @@ export default function HomePage() { } /> - {features ? ( + {features && features.length > 0 ? ( <> Date: Fri, 1 Mar 2024 12:36:09 -0500 Subject: [PATCH 26/29] Remove all stale DAOs from Mainnet and Sepolia Featured Organizations (wrong addresses) --- app/page.tsx | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index 2c2dce594b..9c95c9d971 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -66,37 +66,9 @@ 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 - }, - ], - ], - [ - sepolia.id, - [ - { - iconSrc: '/images/icon-decent.svg', - titleKey: 'decentTitle', - descKey: 'decentDesc', - address: '0xD26c85D435F02DaB8B220cd4D2d398f6f646e235', // TODO: Change to Sepolia Address once it will be there - }, - { - iconSrc: '/images/icon-awakevc.svg', - titleKey: 'awakeTitle', - 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 - }, ], ], + [sepolia.id, []], ]); export default function HomePage() { From 26f098d074ce5e6abe906e4ddc0e5583df22f701 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 12:36:29 -0500 Subject: [PATCH 27/29] Add Myosin icon, title, description --- public/images/icon-myosin.svg | 6 ++++++ src/i18n/locales/en/home.json | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 public/images/icon-myosin.svg diff --git a/public/images/icon-myosin.svg b/public/images/icon-myosin.svg new file mode 100644 index 0000000000..1f40756ebf --- /dev/null +++ b/public/images/icon-myosin.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/i18n/locales/en/home.json b/src/i18n/locales/en/home.json index 4d29d1d5da..bf2b983277 100644 --- a/src/i18n/locales/en/home.json +++ b/src/i18n/locales/en/home.json @@ -17,6 +17,8 @@ "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.", "shutterTitle": "Shutter DAO 0x36", "shutterDesc": "Shutter is an anti-frontrunning/malicious MEV protocol using threshold encryption. Shutter DAO 0x36 is a pragmatic, step-by-step approach towards decentralization, prioritizing community involvement and learning from each phase while maintaining operational reliability and security.", + "myosinTitle": "Myosin", + "myosinDesc": "The Ultimate Marketing Network. Supercharging growth for web3 companies & onboarding brands into the future of the internet.", "featureLink": "Explore >", "readyCTA": "Ready to start?", "createButton": "+ Start from Scratch", From 007a0ca29f3aee6e54cd1b556da11bad75c844e9 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 12:36:40 -0500 Subject: [PATCH 28/29] Add Myosin as a featured Sepolia organization --- app/page.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/page.tsx b/app/page.tsx index 9c95c9d971..666bf3e65f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -68,7 +68,17 @@ const FEATURED_DAOS = new Map([ }, ], ], - [sepolia.id, []], + [ + sepolia.id, + [ + { + iconSrc: '/images/icon-myosin.svg', + titleKey: 'myosinTitle', + descKey: 'myosinDesc', + address: '0xdef90A94273a1A1A72B33D39129fa41E6C08Be3a', + }, + ], + ], ]); export default function HomePage() { From 1a568d4fcd4e910fc4ea3a1b56aef065691a08cf Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Fri, 1 Mar 2024 12:49:50 -0500 Subject: [PATCH 29/29] Bump version to 0.1.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a43bbbad3..b28277fdf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fractal-interface", - "version": "0.1.7", + "version": "0.1.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "fractal-interface", - "version": "0.1.7", + "version": "0.1.8", "dependencies": { "@apollo/client": "^3.7.10", "@chakra-ui/next-js": "^2.2.0", diff --git a/package.json b/package.json index 636560cb9d..0aae53eb67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fractal-interface", - "version": "0.1.7", + "version": "0.1.8", "private": true, "dependencies": { "@apollo/client": "^3.7.10",