Skip to content

Commit

Permalink
Merge pull request #1489 from decentdao/make-azorious-load-faster
Browse files Browse the repository at this point in the history
[Maintenance] `canUserSubmitProposal` extracted to own component
  • Loading branch information
Da-Colon authored Apr 1, 2024
2 parents 2296daf + 1d6386e commit 1cbe52b
Show file tree
Hide file tree
Showing 19 changed files with 153 additions and 129 deletions.
4 changes: 3 additions & 1 deletion src/components/ProposalTemplates/ProposalTemplateCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useNavigate } from 'react-router-dom';
import { DAO_ROUTES } from '../../constants/routes';
import useRemoveProposalTemplate from '../../hooks/DAO/proposal/useRemoveProposalTemplate';
import useSubmitProposal from '../../hooks/DAO/proposal/useSubmitProposal';
import { useCanUserCreateProposal } from '../../hooks/utils/useCanUserSubmitProposal';
import { useFractal } from '../../providers/App/AppProvider';
import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider';
import { ProposalTemplate } from '../../types/createProposalTemplate';
Expand All @@ -32,7 +33,8 @@ export default function ProposalTemplateCard({
const { addressPrefix } = useNetworkConfig();

const { prepareRemoveProposalTemplateProposal } = useRemoveProposalTemplate();
const { submitProposal, canUserCreateProposal } = useSubmitProposal();
const { submitProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const { title, description } = proposalTemplate;

const openProposalForm = useFractalModal(ModalType.CREATE_PROPOSAL_FROM_TEMPLATE, {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ProposalTemplates/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Flex, Box, Button } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { DAO_ROUTES } from '../../constants/routes';
import useSubmitProposal from '../../hooks/DAO/proposal/useSubmitProposal';
import { useCanUserCreateProposal } from '../../hooks/utils/useCanUserSubmitProposal';
import { useFractal } from '../../providers/App/AppProvider';
import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider';
import { EmptyBox } from '../ui/containers/EmptyBox';
Expand All @@ -16,7 +16,7 @@ export default function ProposalTemplates() {
governance: { proposalTemplates },
} = useFractal();
const { addressPrefix } = useNetworkConfig();
const { canUserCreateProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();

return (
<Flex
Expand Down
4 changes: 2 additions & 2 deletions src/components/Proposals/ProposalsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button, Box, Flex } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { DAO_ROUTES } from '../../constants/routes';
import useSubmitProposal from '../../hooks/DAO/proposal/useSubmitProposal';
import { useCanUserCreateProposal } from '../../hooks/utils/useCanUserSubmitProposal';
import { useFractal } from '../../providers/App/AppProvider';
import { useNetworkConfig } from '../../providers/NetworkConfig/NetworkConfigProvider';
import { FractalProposal } from '../../types';
Expand All @@ -14,8 +14,8 @@ export function ProposalsList({ proposals }: { proposals: FractalProposal[] }) {
const {
node: { daoAddress },
} = useFractal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const { addressPrefix } = useNetworkConfig();
const { canUserCreateProposal } = useSubmitProposal();

const { t } = useTranslation('proposal');
return (
Expand Down
4 changes: 2 additions & 2 deletions src/components/pages/DAOTreasury/components/Assets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { SafeCollectibleResponse } from '@safe-global/safe-service-client';
import { ethers, BigNumber } from 'ethers';
import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import useSubmitProposal from '../../../../hooks/DAO/proposal/useSubmitProposal';
import useLidoStaking from '../../../../hooks/stake/lido/useLidoStaking';
import { useCanUserCreateProposal } from '../../../../hooks/utils/useCanUserSubmitProposal';
import useSignerOrProvider from '../../../../hooks/utils/useSignerOrProvider';
import { useFractal } from '../../../../providers/App/AppProvider';
import { useNetworkConfig } from '../../../../providers/NetworkConfig/NetworkConfigProvider';
Expand Down Expand Up @@ -215,7 +215,7 @@ export function Assets() {
node: { daoAddress },
treasury: { assetsFungible, assetsNonFungible },
} = useFractal();
const { canUserCreateProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const { staking } = useNetworkConfig();
const { t } = useTranslation('treasury');
const coinDisplay = useFormatCoins(assetsFungible);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useNavigate } from 'react-router-dom';
import { SettingsSection } from '..';
import { DAO_ROUTES } from '../../../../../constants/routes';
import useSubmitProposal from '../../../../../hooks/DAO/proposal/useSubmitProposal';
import { useCanUserCreateProposal } from '../../../../../hooks/utils/useCanUserSubmitProposal';
import { createAccountSubstring } from '../../../../../hooks/utils/useDisplayName';
import { useFractal } from '../../../../../providers/App/AppProvider';
import { useNetworkConfig } from '../../../../../providers/NetworkConfig/NetworkConfigProvider';
Expand All @@ -20,7 +21,8 @@ export default function MetadataContainer() {
const { t } = useTranslation(['settings', 'proposalMetadata']);
const navigate = useNavigate();

const { canUserCreateProposal, submitProposal } = useSubmitProposal();
const { submitProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const {
baseContracts,
node: { daoName, daoSnapshotURL, daoAddress, safe },
Expand Down
15 changes: 2 additions & 13 deletions src/components/ui/menus/ManageDAO/ManageDAOMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
isWithinFreezePeriod,
isWithinFreezeProposalPeriod,
} from '../../../../helpers/freezePeriodHelpers';
import useSubmitProposal from '../../../../hooks/DAO/proposal/useSubmitProposal';
import useUserERC721VotingTokens from '../../../../hooks/DAO/proposal/useUserERC721VotingTokens';
import useClawBack from '../../../../hooks/DAO/useClawBack';
import useSafeContracts from '../../../../hooks/safe/useSafeContracts';
import useBlockTimestamp from '../../../../hooks/utils/useBlockTimestamp';
import { useCanUserCreateProposal } from '../../../../hooks/utils/useCanUserSubmitProposal';
import { useMasterCopy } from '../../../../hooks/utils/useMasterCopy';
import { useFractal } from '../../../../providers/App/AppProvider';
import { useNetworkConfig } from '../../../../providers/NetworkConfig/NetworkConfigProvider';
Expand Down Expand Up @@ -51,7 +51,6 @@ export function ManageDAOMenu({
guardContracts,
fractalNode,
}: IManageDAOMenu) {
const [canUserCreateProposal, setCanUserCreateProposal] = useState(false);
const [governanceType, setGovernanceType] = useState(GovernanceType.MULTISIG);
const {
node: { safe },
Expand All @@ -62,23 +61,13 @@ export function ManageDAOMenu({
const navigate = useNavigate();
const safeAddress = fractalNode?.daoAddress;
const { getZodiacModuleProxyMasterCopyData } = useMasterCopy();
const { getCanUserCreateProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const { getUserERC721VotingTokens } = useUserERC721VotingTokens(undefined, safeAddress, false);
const { handleClawBack } = useClawBack({
parentAddress,
childSafeInfo: fractalNode,
});

useEffect(() => {
const loadCanUserCreateProposal = async () => {
if (safeAddress) {
setCanUserCreateProposal(await getCanUserCreateProposal(safeAddress));
}
};

loadCanUserCreateProposal();
}, [safeAddress, getCanUserCreateProposal]);

useEffect(() => {
const loadGovernanceType = async () => {
if (safe && safe.address && safe.address === safeAddress && type) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/modals/ForkProposalTemplateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { ChangeEventHandler, useState, useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { DAO_ROUTES } from '../../../constants/routes';
import useSubmitProposal from '../../../hooks/DAO/proposal/useSubmitProposal';
import { useIsSafe } from '../../../hooks/safe/useIsSafe';
import { validateAddress } from '../../../hooks/schemas/common/useValidationAddress';
import { useCanUserCreateProposal } from '../../../hooks/utils/useCanUserSubmitProposal';
import useSignerOrProvider from '../../../hooks/utils/useSignerOrProvider';
import { useFractal } from '../../../providers/App/AppProvider';
import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider';
Expand Down Expand Up @@ -36,7 +36,7 @@ export default function ForkProposalTemplateModal({
} = useFractal();

const { isSafe, isSafeLoading } = useIsSafe(targetDAOAddress);
const { getCanUserCreateProposal } = useSubmitProposal();
const { getCanUserCreateProposal } = useCanUserCreateProposal();

const handleAddressChange: ChangeEventHandler<HTMLInputElement> = e => {
setInputValue(e.target.value);
Expand Down
4 changes: 3 additions & 1 deletion src/components/ui/modals/ProposalTemplateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { DAO_ROUTES } from '../../../constants/routes';
import { logError } from '../../../helpers/errorLogging';
import { usePrepareProposal } from '../../../hooks/DAO/proposal/usePrepareProposal';
import useSubmitProposal from '../../../hooks/DAO/proposal/useSubmitProposal';
import { useCanUserCreateProposal } from '../../../hooks/utils/useCanUserSubmitProposal';
import { useFractal } from '../../../providers/App/AppProvider';
import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider';
import { ProposalTemplate } from '../../../types/createProposalTemplate';
Expand Down Expand Up @@ -43,7 +44,8 @@ export default function ProposalTemplateModal({
const [showAll, setShowAll] = useState(false);
const { t } = useTranslation(['proposalTemplate', 'proposal']);
const navigate = useNavigate();
const { submitProposal, canUserCreateProposal } = useSubmitProposal();
const { submitProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const { prepareProposal } = usePrepareProposal();

const handleParameterChange = ({
Expand Down
95 changes: 3 additions & 92 deletions src/hooks/DAO/proposal/useSubmitProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Azorius } from '@fractal-framework/fractal-contracts';
import axios from 'axios';
import { BigNumber, Signer, utils } from 'ethers';
import { getAddress, isAddress } from 'ethers/lib/utils';
import { useCallback, useMemo, useState, useEffect } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { toast } from 'react-toastify';
import { GnosisSafeL2__factory } from '../../../assets/typechain-types/usul/factories/@gnosis.pm/safe-contracts/contracts';
import { ADDRESS_MULTISIG_METADATA } from '../../../constants/common';
Expand All @@ -15,12 +15,7 @@ import { useSafeAPI } from '../../../providers/App/hooks/useSafeAPI';
import { useEthersProvider } from '../../../providers/Ethers/hooks/useEthersProvider';
import { useEthersSigner } from '../../../providers/Ethers/hooks/useEthersSigner';
import { useNetworkConfig } from '../../../providers/NetworkConfig/NetworkConfigProvider';
import {
MetaTransaction,
ProposalExecuteData,
GovernanceType,
ProposalMetadata,
} from '../../../types';
import { MetaTransaction, ProposalExecuteData, ProposalMetadata } from '../../../types';
import { buildSafeApiUrl, getAzoriusModuleFromModules } from '../../../utils';
import { getAverageBlockTime } from '../../../utils/contract';
import useSafeContracts from '../../safe/useSafeContracts';
Expand Down Expand Up @@ -58,7 +53,6 @@ interface ISubmitAzoriusProposal extends ISubmitProposal {

export default function useSubmitProposal() {
const [pendingCreateTx, setPendingCreateTx] = useState(false);
const [canUserCreateProposal, setCanUserCreateProposal] = useState(false);
const loadDAOProposals = useDAOProposals();
const signer = useEthersSigner();
const provider = useEthersProvider();
Expand All @@ -67,8 +61,6 @@ export default function useSubmitProposal() {
node: { safe, fractalModules },
guardContracts: { freezeVotingContractAddress },
governanceContracts: { ozLinearVotingContractAddress, erc721LinearVotingContractAddress },
governance: { type },
readOnly: { user },
} = useFractal();
const baseContracts = useSafeContracts();
const safeAPI = useSafeAPI();
Expand All @@ -90,87 +82,6 @@ export default function useSubmitProposal() {
const { chainId, safeBaseURL, addressPrefix } = useNetworkConfig();
const ipfsClient = useIPFSClient();

/**
* Performs a check whether user has access rights to create proposal for DAO
* @param {string} safeAddress - parameter to verify that user can create proposal for this specific DAO.
* Otherwise - it is checked for DAO from the global context.
* @returns {Promise<boolean>} - whether or not user has rights to create proposal either in global scope either for provided `safeAddress`.
*/
const getCanUserCreateProposal = useCallback(
async (safeAddress?: string): Promise<boolean> => {
if (!user.address || !safeAPI || !signerOrProvider) {
return false;
}

const checkIsMultisigOwner = (owners?: string[]) => {
return !!owners?.includes(user.address || '');
};

if (safeAddress && baseContracts) {
const safeInfo = await safeAPI.getSafeInfo(utils.getAddress(safeAddress));
const safeModules = await lookupModules(safeInfo.modules);
const azoriusModule = getAzoriusModuleFromModules(safeModules);

if (azoriusModule && azoriusModule.moduleContract) {
const azoriusContract = azoriusModule.moduleContract as Azorius;
// @dev assumes the first strategy is the voting contract
const votingContractAddress = (
await azoriusContract.getStrategies('0x0000000000000000000000000000000000000001', 0)
)[1];
const votingContract =
baseContracts.linearVotingMasterCopyContract.asProvider.attach(votingContractAddress);
const isProposer = await votingContract.isProposer(user.address);
return isProposer;
} else {
return checkIsMultisigOwner(safeInfo.owners);
}
} else {
if (type === GovernanceType.MULTISIG) {
const { owners } = safe || {};
return checkIsMultisigOwner(owners);
} else if (type === GovernanceType.AZORIUS_ERC20) {
if (ozLinearVotingContractAddress && user.address && baseContracts) {
const ozLinearVotingContract =
baseContracts.linearVotingMasterCopyContract.asProvider.attach(
ozLinearVotingContractAddress,
);
return ozLinearVotingContract.isProposer(user.address);
}
} else if (
type === GovernanceType.AZORIUS_ERC721 &&
baseContracts &&
erc721LinearVotingContractAddress
) {
const erc721LinearVotingContract =
baseContracts.linearVotingERC721MasterCopyContract.asProvider.attach(
erc721LinearVotingContractAddress,
);
return erc721LinearVotingContract.isProposer(user.address);
} else {
return false;
}
}
return false;
},
[
safe,
type,
user,
ozLinearVotingContractAddress,
erc721LinearVotingContractAddress,
lookupModules,
safeAPI,
signerOrProvider,
baseContracts,
],
);
useEffect(() => {
const loadCanUserCreateProposal = async () => {
setCanUserCreateProposal(await getCanUserCreateProposal());
};
loadCanUserCreateProposal();
}, [getCanUserCreateProposal]);

const submitMultisigProposal = useCallback(
async ({
pendingToastMessage,
Expand Down Expand Up @@ -455,5 +366,5 @@ export default function useSubmitProposal() {
],
);

return { submitProposal, pendingCreateTx, canUserCreateProposal, getCanUserCreateProposal };
return { submitProposal, pendingCreateTx };
}
4 changes: 3 additions & 1 deletion src/hooks/DAO/useClawBack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useSafeAPI } from '../../providers/App/hooks/useSafeAPI';
import { useEthersProvider } from '../../providers/Ethers/hooks/useEthersProvider';
import { FractalModuleType, FractalNode } from '../../types';
import { useCanUserCreateProposal } from '../utils/useCanUserSubmitProposal';
import useSubmitProposal from './proposal/useSubmitProposal';

interface IUseClawBack {
Expand All @@ -16,7 +17,8 @@ export default function useClawBack({ childSafeInfo, parentAddress }: IUseClawBa
const { t } = useTranslation(['proposal', 'proposalMetadata']);
const provider = useEthersProvider();
const safeAPI = useSafeAPI();
const { submitProposal, canUserCreateProposal } = useSubmitProposal();
const { submitProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();

const handleClawBack = useCallback(async () => {
if (childSafeInfo && childSafeInfo.daoAddress && parentAddress && safeAPI && provider) {
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/DAO/useCreateSubDAOProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import { useTranslation } from 'react-i18next';
import { useFractal } from '../../providers/App/AppProvider';
import { SafeMultisigDAO, AzoriusGovernance, AzoriusERC20DAO, AzoriusERC721DAO } from '../../types';
import { ProposalExecuteData } from '../../types/daoProposal';
import { useCanUserCreateProposal } from '../utils/useCanUserSubmitProposal';
import useSubmitProposal from './proposal/useSubmitProposal';
import useBuildDAOTx from './useBuildDAOTx';

export const useCreateSubDAOProposal = () => {
const { baseContracts } = useFractal();
const { t } = useTranslation(['daoCreate', 'proposal', 'proposalMetadata']);

const { submitProposal, pendingCreateTx, canUserCreateProposal } = useSubmitProposal();
const { submitProposal, pendingCreateTx } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const [build] = useBuildDAOTx();
const {
node: { daoAddress },
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/DAO/useDeployAzorius.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
AzoriusERC20DAO,
AzoriusERC721DAO,
} from '../../types';
import { useCanUserCreateProposal } from '../utils/useCanUserSubmitProposal';
import useSignerOrProvider from '../utils/useSignerOrProvider';
import useSubmitProposal from './proposal/useSubmitProposal';

Expand All @@ -29,8 +30,8 @@ const useDeployAzorius = () => {
} = useFractal();

const { t } = useTranslation(['transaction', 'proposalMetadata']);
const { submitProposal, canUserCreateProposal } = useSubmitProposal();

const { submitProposal } = useSubmitProposal();
const { canUserCreateProposal } = useCanUserCreateProposal();
const deployAzorius = useCallback(
async (
daoData: AzoriusERC20DAO | AzoriusERC721DAO,
Expand Down
Loading

0 comments on commit 1cbe52b

Please sign in to comment.