Skip to content

Commit

Permalink
feat: detailed timeline (#1932)
Browse files Browse the repository at this point in the history
  • Loading branch information
JoaquinBattilana authored Mar 8, 2024
1 parent 1030737 commit d44f8ed
Show file tree
Hide file tree
Showing 22 changed files with 828 additions and 521 deletions.
33 changes: 25 additions & 8 deletions pages/governance/ipfs-preview.governance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { ContentContainer } from 'src/components/ContentContainer';
import { Meta } from 'src/components/Meta';
import { EnhancedProposal } from 'src/hooks/governance/useProposal';
import { Proposal } from 'src/hooks/governance/useProposals';
import { MainLayout } from 'src/layouts/MainLayout';
import { ProposalOverview } from 'src/modules/governance/proposal/ProposalOverview';
import { ProposalTopPanel } from 'src/modules/governance/proposal/ProposalTopPanel';
import { ProposalBadgeState } from 'src/modules/governance/StateBadge';
import { ProposalLifecycleStep } from 'src/modules/governance/utils/formatProposal';
import { getProposalMetadata } from 'src/modules/governance/utils/getProposalMetadata';
import { ipfsGateway } from 'src/ui-config/governanceConfig';

// proposal metadata is fetched using the ipfs hash,
// but all other data is mocked so the page can be rendered
const mockProposal: EnhancedProposal = {
proposal: {
const mockProposal: Proposal = {
subgraphProposal: {
id: '',
creator: '',
accessLevel: '',
Expand Down Expand Up @@ -103,13 +105,28 @@ const mockProposal: EnhancedProposal = {
},
state: 0,
},
payloadsData: [],
lifecycleState: ProposalLifecycleStep.Created,
badgeState: ProposalBadgeState.Created,
votingInfo: {
forVotes: 0,
againstVotes: 0,
forPercent: 0,
againstPercent: 0,
quorum: '80000',
quorumReached: false,
currentDifferential: '0',
requiredDifferential: '320000',
differentialReached: false,
isPassing: false,
},
};

export default function IpfsPreview() {
const router = useRouter();
const ipfsHash = router.query.ipfsHash as string;
const [loading, setLoading] = useState(true);
const [proposal, setProposal] = useState<EnhancedProposal>(mockProposal);
const [proposal, setProposal] = useState<Proposal>(mockProposal);
const [error, setError] = useState(false);

async function fetchIpfs() {
Expand All @@ -119,8 +136,8 @@ export default function IpfsPreview() {
setProposal((prev) => {
return {
...prev,
proposal: {
...prev.proposal,
subgraphProposalb: {
...prev.subgraphProposal,
proposalMetadata,
},
};
Expand All @@ -144,8 +161,8 @@ export default function IpfsPreview() {
{!loading && (
<Meta
imageUrl="https://app.aave.com/aaveMetaLogo-min.jpg"
title={proposal.proposal.proposalMetadata.title}
description={proposal.proposal.proposalMetadata.shortDescription}
title={proposal.subgraphProposal.proposalMetadata.title}
description={proposal.subgraphProposal.proposalMetadata.shortDescription}
/>
)}
<ProposalTopPanel />
Expand Down
34 changes: 13 additions & 21 deletions pages/governance/v3/proposal/index.governance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Grid } from '@mui/material';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import { Meta } from 'src/components/Meta';
import { usePayloadsData } from 'src/hooks/governance/usePayloadsData';
import { useProposal } from 'src/hooks/governance/useProposal';
import { useProposalVotes } from 'src/hooks/governance/useProposalVotes';
import { MainLayout } from 'src/layouts/MainLayout';
Expand All @@ -25,35 +24,24 @@ export default function ProposalPage() {
const proposalId = Number(query.proposalId);
const {
data: proposal,
isLoading: newProposalLoading,
isLoading: proposalLoading,
error: newProposalError,
} = useProposal(proposalId);

const payloadParams =
proposal?.proposal.payloads.map((p) => {
return {
payloadControllerAddress: p.payloadsController,
payloadId: +p.id,
chainId: +p.chainId,
};
}) || [];

const { data: payloadData } = usePayloadsData(payloadParams);

const proposalVotes = useProposalVotes({
proposalId,
votingChainId: proposal ? +proposal.proposal.votingPortal.votingMachineChainId : undefined,
votingChainId: proposal
? +proposal.subgraphProposal.votingPortal.votingMachineChainId
: undefined,
});

const loading = newProposalLoading;

return (
<>
{proposal && (
<Meta
imageUrl="https://app.aave.com/aaveMetaLogo-min.jpg"
title={proposal.proposal.proposalMetadata.title}
description={proposal.proposal.proposalMetadata.shortDescription}
title={proposal.subgraphProposal.proposalMetadata.title}
description={proposal.subgraphProposal.proposalMetadata.shortDescription}
/>
)}
<ProposalTopPanel />
Expand All @@ -64,13 +52,17 @@ export default function ProposalPage() {
<ProposalOverview
proposal={proposal}
error={!!newProposalError}
loading={newProposalLoading}
loading={proposalLoading}
/>
</Grid>
<Grid item xs={12} md={4}>
{proposal && <VoteInfo proposal={proposal} />}
<VotingResults proposal={proposal} proposalVotes={proposalVotes} loading={loading} />
<ProposalLifecycle proposal={proposal} payloads={payloadData} />
<VotingResults
proposal={proposal}
proposalVotes={proposalVotes}
loading={proposalLoading}
/>
<ProposalLifecycle proposal={proposal} />
</Grid>
</Grid>
</ContentContainer>
Expand Down
10 changes: 5 additions & 5 deletions src/components/transactions/GovVote/GovVoteActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AbiCoder, keccak256, RLP } from 'ethers/lib/utils';
import { useState } from 'react';
import { MOCK_SIGNED_HASH } from 'src/helpers/useTransactionHandler';
import { useGovernanceTokensAndPowers } from 'src/hooks/governance/useGovernanceTokensAndPowers';
import { EnhancedProposal } from 'src/hooks/governance/useProposal';
import { Proposal } from 'src/hooks/governance/useProposals';
import { useModalContext } from 'src/hooks/useModal';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { useRootStore } from 'src/store/root';
Expand All @@ -31,7 +31,7 @@ interface GetProofResponse {
export type GovVoteActionsProps = {
isWrongNetwork: boolean;
blocked: boolean;
proposal: EnhancedProposal;
proposal: Proposal;
support: boolean;
};

Expand Down Expand Up @@ -157,9 +157,9 @@ export const GovVoteActions = ({
const { sendTx, signTxData } = useWeb3Context();
const tokenPowers = useGovernanceTokensAndPowers();
const [signature, setSignature] = useState<string | undefined>(undefined);
const proposalId = +proposal.proposal.id;
const blockHash = proposal.proposal.snapshotBlockHash;
const votingChainId = +proposal.proposal.votingPortal.votingMachineChainId;
const proposalId = +proposal.subgraphProposal.id;
const blockHash = proposal.subgraphProposal.snapshotBlockHash;
const votingChainId = +proposal.subgraphProposal.votingPortal.votingMachineChainId;
const votingMachineAddress =
governanceV3Config.votingChainConfig[votingChainId].votingMachineAddress;

Expand Down
6 changes: 3 additions & 3 deletions src/components/transactions/GovVote/GovVoteModalContent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Trans } from '@lingui/macro';
import { Box, Button, Typography, useTheme } from '@mui/material';
import { EnhancedProposal } from 'src/hooks/governance/useProposal';
import { Proposal } from 'src/hooks/governance/useProposals';
import { useModalContext } from 'src/hooks/useModal';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import { useRootStore } from 'src/store/root';
Expand All @@ -17,7 +17,7 @@ import { ChangeNetworkWarning } from '../Warnings/ChangeNetworkWarning';
import { GovVoteActions } from './GovVoteActions';

export type GovVoteModalContentProps = {
proposal: EnhancedProposal;
proposal: Proposal;
support: boolean;
power: string;
};
Expand Down Expand Up @@ -63,7 +63,7 @@ export const GovVoteModalContent = ({
}
};

const proposalVotingChain = +proposal.proposal.votingPortal.votingMachineChainId;
const proposalVotingChain = +proposal.subgraphProposal.votingPortal.votingMachineChainId;

const isWrongNetwork = connectedChainId !== proposalVotingChain;

Expand Down
46 changes: 2 additions & 44 deletions src/hooks/governance/usePayloadsData.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,13 @@
import { ChainId, Payload } from '@aave/contract-helpers';
import { useQuery } from '@tanstack/react-query';
import { GovernanceV3Service } from 'src/services/GovernanceV3Service';
import { PayloadParams } from 'src/services/GovernanceV3Service';
import { useSharedDependencies } from 'src/ui-config/SharedDependenciesProvider';

type PayloadParams = {
payloadControllerAddress: string;
payloadId: number;
chainId: ChainId;
};

type PayloadData = {
[key in ChainId]: {
[payloadsControllerAddres: string]: number[];
};
};

export const usePayloadsData = (params: PayloadParams[]) => {
const { governanceV3Service } = useSharedDependencies();
return useQuery({
queryFn: () => fetchPayloadsData(params, governanceV3Service),
queryFn: () => governanceV3Service.getMultiChainPayloadsData(params),
queryKey: ['payloadsData'],
cacheTime: 0,
enabled: params.length > 0,
});
};

async function fetchPayloadsData(params: PayloadParams[], service: GovernanceV3Service) {
const payloadsByChainId: PayloadData = params.reduce(
(acc, { chainId, payloadControllerAddress, payloadId }) => {
if (!acc[chainId]) {
acc[chainId] = {};
}

if (!acc[chainId][payloadControllerAddress]) {
acc[chainId][payloadControllerAddress] = [];
}

acc[chainId][payloadControllerAddress].push(payloadId);
return acc;
},
{} as PayloadData
);

const promises: Promise<Payload[]>[] = [];
Object.entries(payloadsByChainId).forEach(([chainId, payloads]) => {
const chainIdKey = +chainId;
Object.entries(payloads).forEach(([payloadControllerAddress, payloadIds]) => {
promises.push(service.getPayloadsData(payloadControllerAddress, payloadIds, chainIdKey));
});
});

const data = await Promise.all(promises);
return data.flat();
}
70 changes: 41 additions & 29 deletions src/hooks/governance/useProposal.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { VotingMachineProposal } from '@aave/contract-helpers';
import { useQuery } from '@tanstack/react-query';
import { constants } from 'ethers';
import request, { gql } from 'graphql-request';
import { lifecycleToBadge } from 'src/modules/governance/StateBadge';
import {
getLifecycleState,
getProposalVoteInfo,
} from 'src/modules/governance/utils/formatProposal';
import { GovernanceV3Service } from 'src/services/GovernanceV3Service';
import { VotingMachineService } from 'src/services/VotingMachineService';
import { useRootStore } from 'src/store/root';
import { governanceV3Config } from 'src/ui-config/governanceConfig';
import { useSharedDependencies } from 'src/ui-config/SharedDependenciesProvider';

import {
enhanceProposalWithMetadata,
getSubgraphProposalMetadata,
Proposal,
proposalQueryFields,
SubgraphProposal,
} from './useProposals';

export interface EnhancedProposal {
proposal: Proposal;
votingMachineData: VotingMachineProposal;
}

const getProposalQuery = gql`
query getProposal($id: Int!) {
proposal(id: $id) {
Expand All @@ -41,46 +41,58 @@ export const getProposal = async (proposalId: number) => {
async function fetchProposal(
proposalId: number,
votingMachineService: VotingMachineService,
governanceV3Service: GovernanceV3Service,
user?: string
): Promise<EnhancedProposal> {
console.log('getting proposal', proposalId);
): Promise<Proposal> {
const proposal = await getProposal(proposalId);

const proposalWithMetadata = await enhanceProposalWithMetadata(proposal);

const votingMachineData = (
await votingMachineService.getProposalsData(
[
{
id: +proposal.id,
snapshotBlockHash: proposal.snapshotBlockHash || constants.HashZero,
chainId: +proposal.votingPortal.votingMachineChainId,
votingMachineAddress: proposal.votingPortal.votingMachine,
},
],
user
)
)[0];
const votingMachineParams = {
id: +proposal.id,
snapshotBlockHash: proposal.snapshotBlockHash || constants.HashZero,
chainId: +proposal.votingPortal.votingMachineChainId,
votingMachineAddress: proposal.votingPortal.votingMachine,
};
const payloadParams = proposal.payloads.map((p) => {
return {
payloadControllerAddress: p.payloadsController,
payloadId: +p.id.split('_')[1],
chainId: +p.chainId,
};
});
const [proposalMetadata, votingMachineData, payloadsData] = await Promise.all([
getSubgraphProposalMetadata(proposal),
votingMachineService.getProposalsData([votingMachineParams], user).then((data) => data[0]),
governanceV3Service.getMultiChainPayloadsData(payloadParams),
]);

const proposalsWithVotes = {
...proposalWithMetadata,
const enhancedSubgraphProposal = {
...proposal,
votes: {
forVotes: votingMachineData.proposalData.forVotes,
againstVotes: votingMachineData.proposalData.againstVotes,
},
proposalMetadata,
};

const lifecycleState = getLifecycleState(proposal, votingMachineData, payloadsData);
const votingInfo = getProposalVoteInfo(enhancedSubgraphProposal);
const badgeState = lifecycleToBadge(lifecycleState, votingInfo);

return {
proposal: proposalsWithVotes,
subgraphProposal: enhancedSubgraphProposal,
votingMachineData,
payloadsData,
lifecycleState,
badgeState,
votingInfo,
};
}

export const useProposal = (proposalId: number) => {
const { votingMachineSerivce } = useSharedDependencies();
const { votingMachineSerivce, governanceV3Service } = useSharedDependencies();
const user = useRootStore((store) => store.account);
return useQuery({
queryFn: () => fetchProposal(proposalId, votingMachineSerivce, user),
queryFn: () => fetchProposal(proposalId, votingMachineSerivce, governanceV3Service, user),
queryKey: ['governance_proposal', proposalId, user],
refetchOnMount: false,
refetchOnReconnect: false,
Expand Down
Loading

2 comments on commit d44f8ed

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit was deployed on ipfs

Please sign in to comment.