From 2695af33ea83d7176ad46bdd7ab016da62514d22 Mon Sep 17 00:00:00 2001 From: emmdim Date: Thu, 14 Dec 2023 16:10:07 +0100 Subject: [PATCH 1/7] Temporarily fixes liniting issues coming from develop (but not throw in develop :-| ) Signed-off-by: emmdim --- src/pages/proposal.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/proposal.tsx b/src/pages/proposal.tsx index e26f412d0..5d1c1f03e 100644 --- a/src/pages/proposal.tsx +++ b/src/pages/proposal.tsx @@ -434,6 +434,8 @@ export const Proposal: React.FC = () => { provider, fetchToken, t, + daoAddress, + proposal?.actions, ]); // caches the status for breadcrumb From ae0270d5b62b2bbc5613075694b122c45e81b709 Mon Sep 17 00:00:00 2001 From: selankon Date: Wed, 17 Jan 2024 20:48:14 +0100 Subject: [PATCH 2/7] Fix end dates differ Gasless elections and onchain elections had different end dates. Now they have the same --- src/context/createGaslessProposal.tsx | 17 ++++---- src/context/createProposal.tsx | 59 ++++++++++++++------------- src/utils/types.ts | 9 ++++ 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/context/createGaslessProposal.tsx b/src/context/createGaslessProposal.tsx index b8af202b8..3c2a24885 100644 --- a/src/context/createGaslessProposal.tsx +++ b/src/context/createGaslessProposal.tsx @@ -1,5 +1,4 @@ import { - CreateMajorityVotingProposalParams, Erc20TokenDetails, Erc20WrapperTokenDetails, VoteValues, @@ -24,8 +23,9 @@ import { StepsMap, StepStatus, useFunctionStepper, -} from 'hooks/useFunctionStepper'; -import {useCensus3Client, useCensus3CreateToken} from 'hooks/useCensus3'; +} from '../hooks/useFunctionStepper'; +import {useCensus3Client, useCensus3CreateToken} from '../hooks/useCensus3'; +import {PartialGaslessParams} from '../utils/types'; export enum GaslessProposalStepId { REGISTER_VOCDONI_ACCOUNT = 'REGISTER_VOCDONI_ACCOUNT', @@ -57,7 +57,7 @@ export type UseCreateElectionProps = Omit< interface IProposalToElectionProps { metadata: ProposalMetadata; - data: CreateMajorityVotingProposalParams; + data: PartialGaslessParams; census: Census; } @@ -71,7 +71,7 @@ const proposalToElection = ({ description: metadata.description, question: metadata.summary, startDate: data.startDate, - endDate: data.endDate!, + endDate: data.endDate, meta: data, // Store all DAO metadata to retrieve it easily census: census, }; @@ -221,10 +221,11 @@ const useCreateGaslessProposal = ({ const createProposal = useCallback( async ( metadata: ProposalMetadata, - data: CreateMajorityVotingProposalParams, + data: PartialGaslessParams, handleOnchainProposal: ( electionId?: string, - vochainCensus?: TokenCensus + vochainCensus?: TokenCensus, + gaslessParams?: PartialGaslessParams ) => Promise ) => { if (globalState === StepStatus.ERROR) { @@ -261,7 +262,7 @@ const useCreateGaslessProposal = ({ // 3. Register the proposal onchain await doStep( GaslessProposalStepId.CREATE_ONCHAIN_PROPOSAL, - async () => await handleOnchainProposal(electionId, census) + async () => await handleOnchainProposal(electionId, census, data) ); // 4. All ready diff --git a/src/context/createProposal.tsx b/src/context/createProposal.tsx index d30a23589..8b123b356 100644 --- a/src/context/createProposal.tsx +++ b/src/context/createProposal.tsx @@ -91,7 +91,12 @@ import {proposalStorage} from 'utils/localStorage/proposalStorage'; import {Proposal} from 'utils/paths'; import {getNonEmptyActions} from 'utils/proposals'; import {isNativeToken} from 'utils/tokens'; -import {ProposalFormData, ProposalId, ProposalResource} from 'utils/types'; +import { + PartialGaslessParams, + ProposalFormData, + ProposalId, + ProposalResource, +} from 'utils/types'; import GaslessProposalModal from '../containers/transactionModals/gaslessProposalModal'; import {StepStatus} from '../hooks/useFunctionStepper'; import {useCreateGaslessProposal} from './createGaslessProposal'; @@ -105,13 +110,6 @@ type Props = { children: ReactNode; }; -// This omitted Gasless params are added after Vocdoni election created -// This type is used to store information needed before creating the proposal in the vochain -type PartialGaslessParams = Omit< - CreateGasslessProposalParams, - 'vochainProposalId' | 'censusURI' | 'censusRoot' | 'totalVotingPower' ->; - const CreateProposalWrapper: React.FC = ({ showTxModal, setShowTxModal, @@ -521,6 +519,8 @@ const CreateProposalWrapper: React.FC = ({ ); } + console.log('xxsaodhsad', startDateTime); + // Minimum allowed end date (if endDate is lower than that SC call fails) const minEndDateTimeMills = startDateTime.valueOf() + @@ -553,10 +553,13 @@ const CreateProposalWrapper: React.FC = ({ // In case the endDate is close to being minimum durable, (and we starting immediately) // to avoid passing late-date possibly, we just rely on SDK to set proper Date if ( + // If is Gasless, undefined is not allowed on vocdoni SDK election creation, and is not suposed to happen + // since SC not allow durations lower than 1 hour + !gasless && endDateTime.valueOf() <= minEndDateTimeMills && startSwitch === 'now' ) { - /* Pass enddate as undefined to SDK to auto-calculate min endDate */ + /* Pass end date as undefined to SDK to auto-calculate min endDate */ endDateTime = undefined; } } else { @@ -625,7 +628,7 @@ const CreateProposalWrapper: React.FC = ({ // We could define a different expiration date for this proposal but is not designed // to do this at ux level. (kon) tallyEndDate: undefined, - startDate: params.startDate, + // We ensure that the endate is not undefined, during the calculation of the CreateMajorityVotingProposalParams endDate: params.endDate!, }; }, @@ -821,7 +824,11 @@ const CreateProposalWrapper: React.FC = ({ }, [pluginAddress, pluginType, queryClient]); const handlePublishProposal = useCallback( - async (vochainProposalId?: string, vochainCensus?: TokenCensus) => { + async ( + vochainProposalId?: string, + vochainCensus?: TokenCensus, + gaslessParams?: CreateMajorityVotingProposalParams + ) => { if (!pluginClient) { return new Error('ERC20 SDK client is not initialized correctly'); } @@ -842,17 +849,15 @@ const CreateProposalWrapper: React.FC = ({ }); let proposalIterator: AsyncGenerator; - if (gasless && vochainProposalId && vochainCensus) { + if (gasless && vochainProposalId && vochainCensus && gaslessParams) { // This is the last step of a gasless proposal creation // If some of the previous steps failed, and the user press the try again button, the end date is the same as when // the user opened the modal. So I get fresh calculated params, to check if the start date is on 6 minutes (for // example), the end date will be updated from now to 6 minutes more. - const updatedParams = getOffChainProposalParams( - (await getProposalCreationParams()).params - ); const params: CreateGasslessProposalParams = { - ...(updatedParams as PartialGaslessParams), + // ...(gaslessParams as PartialGaslessParams), + ...getOffChainProposalParams(gaslessParams), censusRoot: vochainCensus.censusId!, censusURI: vochainCensus.censusURI!, totalVotingPower: vochainCensus.weight!, @@ -966,25 +971,21 @@ const CreateProposalWrapper: React.FC = ({ } const {params, metadata} = await getProposalCreationParams(); - if (!params.endDate) { - const startDate = params.startDate || new Date(); - params.endDate = new Date( - startDate.valueOf() + - daysToMills(minDays || 0) + - hoursToMills(minHours || 0) + - minutesToMills(minMinutes || 0) - ); - } - await createProposal(metadata, params, handlePublishProposal); + + console.log('AAAaa', params); + // return; + await createProposal( + metadata, + getOffChainProposalParams(params), + handlePublishProposal + ); }, [ pluginClient, daoToken, getProposalCreationParams, createProposal, + getOffChainProposalParams, handlePublishProposal, - minDays, - minHours, - minMinutes, ]); /************************************************* diff --git a/src/utils/types.ts b/src/utils/types.ts index 93c82ec47..517d48c28 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -16,6 +16,7 @@ import { VersionTag, } from '@aragon/sdk-client-common'; import { + CreateGasslessProposalParams, GaslessPluginVotingSettings, GaslessVotingProposal, GaslessVotingProposalListItem, @@ -193,6 +194,14 @@ export type DetailedProposal = | MultisigProposal | TokenVotingProposal | GaslessVotingProposal; + +// This omitted Gasless params are added after Vocdoni election created +// This type is used to store information needed before creating the proposal in the vochain +export type PartialGaslessParams = Omit< + CreateGasslessProposalParams, + 'vochainProposalId' | 'censusURI' | 'censusRoot' | 'totalVotingPower' +>; + export type ProposalListItem = | TokenVotingProposalListItem | MultisigProposalListItem From 241a441efcebe1ce050320325109e68fa5ff767a Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 18 Jan 2024 13:24:23 +0100 Subject: [PATCH 3/7] Implement gasless election time offset --- src/context/createGaslessProposal.tsx | 12 ++++++------ src/context/createProposal.tsx | 20 ++++++++++++++------ src/utils/types.ts | 7 +++++-- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/context/createGaslessProposal.tsx b/src/context/createGaslessProposal.tsx index 3c2a24885..09b785ee6 100644 --- a/src/context/createGaslessProposal.tsx +++ b/src/context/createGaslessProposal.tsx @@ -25,7 +25,7 @@ import { useFunctionStepper, } from '../hooks/useFunctionStepper'; import {useCensus3Client, useCensus3CreateToken} from '../hooks/useCensus3'; -import {PartialGaslessParams} from '../utils/types'; +import {GaslessProposalCreationParams} from '../utils/types'; export enum GaslessProposalStepId { REGISTER_VOCDONI_ACCOUNT = 'REGISTER_VOCDONI_ACCOUNT', @@ -57,7 +57,7 @@ export type UseCreateElectionProps = Omit< interface IProposalToElectionProps { metadata: ProposalMetadata; - data: PartialGaslessParams; + data: GaslessProposalCreationParams; census: Census; } @@ -70,8 +70,8 @@ const proposalToElection = ({ title: metadata.title, description: metadata.description, question: metadata.summary, - startDate: data.startDate, - endDate: data.endDate, + startDate: data.gaslessStartDate, + endDate: data.gaslessEndDate, meta: data, // Store all DAO metadata to retrieve it easily census: census, }; @@ -221,11 +221,11 @@ const useCreateGaslessProposal = ({ const createProposal = useCallback( async ( metadata: ProposalMetadata, - data: PartialGaslessParams, + data: GaslessProposalCreationParams, handleOnchainProposal: ( electionId?: string, vochainCensus?: TokenCensus, - gaslessParams?: PartialGaslessParams + gaslessParams?: GaslessProposalCreationParams ) => Promise ) => { if (globalState === StepStatus.ERROR) { diff --git a/src/context/createProposal.tsx b/src/context/createProposal.tsx index 8b123b356..a6f60f833 100644 --- a/src/context/createProposal.tsx +++ b/src/context/createProposal.tsx @@ -92,7 +92,7 @@ import {Proposal} from 'utils/paths'; import {getNonEmptyActions} from 'utils/proposals'; import {isNativeToken} from 'utils/tokens'; import { - PartialGaslessParams, + GaslessProposalCreationParams, ProposalFormData, ProposalId, ProposalResource, @@ -155,7 +155,7 @@ const CreateProposalWrapper: React.FC = ({ const [proposalId, setProposalId] = useState(); const [proposalCreationData, setProposalCreationData] = useState< - CreateMajorityVotingProposalParams | PartialGaslessParams + CreateMajorityVotingProposalParams | GaslessProposalCreationParams >(); const [creationProcessState, setCreationProcessState] = useState(TransactionState.WAITING); @@ -620,7 +620,13 @@ const CreateProposalWrapper: React.FC = ({ ]); const getOffChainProposalParams = useCallback( - (params: CreateMajorityVotingProposalParams): PartialGaslessParams => { + ( + params: CreateMajorityVotingProposalParams + ): GaslessProposalCreationParams => { + let gaslessStartDate; + if (params.startDate) { + gaslessStartDate = new Date(params.startDate.setMinutes(-1)); + } return { ...params, // If the value is undefined will take the expiration time defined at DAO creation level. @@ -628,8 +634,12 @@ const CreateProposalWrapper: React.FC = ({ // We could define a different expiration date for this proposal but is not designed // to do this at ux level. (kon) tallyEndDate: undefined, - // We ensure that the endate is not undefined, during the calculation of the CreateMajorityVotingProposalParams + // We ensure that the onchain endate is not undefined, during the calculation of the CreateMajorityVotingProposalParams endDate: params.endDate!, + // Add offset to the end date to avoid onchain proposal finish before the offchain proposal + gaslessEndDate: new Date(params.endDate!.setMinutes(1)), + // Add offset to ensure offchain is started when proposal starts + gaslessStartDate, }; }, [] @@ -972,8 +982,6 @@ const CreateProposalWrapper: React.FC = ({ const {params, metadata} = await getProposalCreationParams(); - console.log('AAAaa', params); - // return; await createProposal( metadata, getOffChainProposalParams(params), diff --git a/src/utils/types.ts b/src/utils/types.ts index 517d48c28..1fdbb9ed4 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -197,10 +197,13 @@ export type DetailedProposal = // This omitted Gasless params are added after Vocdoni election created // This type is used to store information needed before creating the proposal in the vochain -export type PartialGaslessParams = Omit< +export type GaslessProposalCreationParams = Omit< CreateGasslessProposalParams, 'vochainProposalId' | 'censusURI' | 'censusRoot' | 'totalVotingPower' ->; +> & { + gaslessStartDate: Date | undefined; + gaslessEndDate: Date; +}; export type ProposalListItem = | TokenVotingProposalListItem From 95df238d4c57b473d1452d8f6212c2e151d480bf Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 18 Jan 2024 13:29:24 +0100 Subject: [PATCH 4/7] Lintfix --- src/context/createProposal.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/context/createProposal.tsx b/src/context/createProposal.tsx index a6f60f833..dbeafa9de 100644 --- a/src/context/createProposal.tsx +++ b/src/context/createProposal.tsx @@ -519,8 +519,6 @@ const CreateProposalWrapper: React.FC = ({ ); } - console.log('xxsaodhsad', startDateTime); - // Minimum allowed end date (if endDate is lower than that SC call fails) const minEndDateTimeMills = startDateTime.valueOf() + @@ -964,7 +962,6 @@ const CreateProposalWrapper: React.FC = ({ gasless, isOnWrongNetwork, getOffChainProposalParams, - getProposalCreationParams, handleCloseModal, open, network, From b18d639d800679d6697975514f93c30e2fc8c9a8 Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 18 Jan 2024 14:39:26 +0100 Subject: [PATCH 5/7] Fix estimation --- src/context/createProposal.tsx | 41 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/context/createProposal.tsx b/src/context/createProposal.tsx index dbeafa9de..438431757 100644 --- a/src/context/createProposal.tsx +++ b/src/context/createProposal.tsx @@ -621,9 +621,12 @@ const CreateProposalWrapper: React.FC = ({ ( params: CreateMajorityVotingProposalParams ): GaslessProposalCreationParams => { + const gaslessEndDate = new Date(params.endDate!); + gaslessEndDate.setMinutes(params.endDate!.getMinutes() + 1); let gaslessStartDate; if (params.startDate) { - gaslessStartDate = new Date(params.startDate.setMinutes(-1)); + gaslessStartDate = new Date(params.startDate); + gaslessStartDate.setMinutes(params.startDate.getMinutes() - 1); } return { ...params, @@ -635,7 +638,7 @@ const CreateProposalWrapper: React.FC = ({ // We ensure that the onchain endate is not undefined, during the calculation of the CreateMajorityVotingProposalParams endDate: params.endDate!, // Add offset to the end date to avoid onchain proposal finish before the offchain proposal - gaslessEndDate: new Date(params.endDate!.setMinutes(1)), + gaslessEndDate, // Add offset to ensure offchain is started when proposal starts gaslessStartDate, }; @@ -651,15 +654,16 @@ const CreateProposalWrapper: React.FC = ({ } if (!proposalCreationData) return; - return gasless - ? (pluginClient as GaslessVotingClient).estimation.createProposal( - proposalCreationData as CreateGasslessProposalParams - ) - : ( - pluginClient as TokenVotingClient | MultisigClient - ).estimation.createProposal( - proposalCreationData as CreateMajorityVotingProposalParams - ); + if (gasless) { + return (pluginClient as GaslessVotingClient).estimation.createProposal( + proposalCreationData as CreateGasslessProposalParams + ); + } + return ( + pluginClient as TokenVotingClient | MultisigClient + ).estimation.createProposal( + proposalCreationData as CreateMajorityVotingProposalParams + ); }, [gasless, pluginClient, proposalCreationData]); const { @@ -864,7 +868,6 @@ const CreateProposalWrapper: React.FC = ({ // example), the end date will be updated from now to 6 minutes more. const params: CreateGasslessProposalParams = { - // ...(gaslessParams as PartialGaslessParams), ...getOffChainProposalParams(gaslessParams), censusRoot: vochainCensus.censusId!, censusURI: vochainCensus.censusURI!, @@ -1001,8 +1004,18 @@ const CreateProposalWrapper: React.FC = ({ async function setProposalData() { if (showTxModal && creationProcessState === TransactionState.WAITING) { if (gasless) { - const {params: gaslessParams} = await getProposalCreationParams(); - setProposalCreationData(getOffChainProposalParams(gaslessParams)); + // const {params} = await getProposalCreationParams(); + // // console.log( + // // 'XXXXXXXXXXXXXXXXX', + // // (await getProposalCreationParams()).params.endDate, + // // gaslessParamsxx.endDate, + // // getOffChainProposalParams(gaslessParamsxx).endDate + // // ); + setProposalCreationData( + getOffChainProposalParams( + (await getProposalCreationParams()).params + ) + ); } else { const {params} = await getProposalCreationParams(); setProposalCreationData(params); From f56fe1f84650b44b27b1e03c770cb8cd3c88d4ea Mon Sep 17 00:00:00 2001 From: selankon Date: Mon, 29 Jan 2024 16:21:43 +0100 Subject: [PATCH 6/7] Lintfix --- src/pages/proposal.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/proposal.tsx b/src/pages/proposal.tsx index 5d1c1f03e..e26f412d0 100644 --- a/src/pages/proposal.tsx +++ b/src/pages/proposal.tsx @@ -434,8 +434,6 @@ export const Proposal: React.FC = () => { provider, fetchToken, t, - daoAddress, - proposal?.actions, ]); // caches the status for breadcrumb From bdbc1b5f745d7eada54818c41375c827c6deec48 Mon Sep 17 00:00:00 2001 From: selankon Date: Thu, 8 Feb 2024 15:06:14 +0100 Subject: [PATCH 7/7] Fix gasless endate --- src/context/createProposal.tsx | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/context/createProposal.tsx b/src/context/createProposal.tsx index 438431757..e85b1f23c 100644 --- a/src/context/createProposal.tsx +++ b/src/context/createProposal.tsx @@ -548,17 +548,26 @@ const CreateProposalWrapper: React.FC = ({ endDateTime = new Date(endDateTimeMill); - // In case the endDate is close to being minimum durable, (and we starting immediately) + // In case the endDate is close to being minimum durable, (and starting immediately) // to avoid passing late-date possibly, we just rely on SDK to set proper Date if ( - // If is Gasless, undefined is not allowed on vocdoni SDK election creation, and is not suposed to happen - // since SC not allow durations lower than 1 hour + // If is Gasless, undefined is not allowed on vocdoni SDK election creation, and end date need to be specified + // to be synced with the offchain proposal !gasless && endDateTime.valueOf() <= minEndDateTimeMills && startSwitch === 'now' ) { /* Pass end date as undefined to SDK to auto-calculate min endDate */ endDateTime = undefined; + } else if ( + // In order to have a concordance between onchain and offchain endates, we add an offset to the end date to avoid + // transaction fail due the end date is before the min end date + gasless && + endDateTime.valueOf() <= minEndDateTimeMills && + startSwitch === 'now' + ) { + const endDateOffset = 5; // Minutes + endDateTime.setMinutes(endDateTime.getMinutes() + endDateOffset); } } else { // In case exact time specified by user @@ -621,12 +630,18 @@ const CreateProposalWrapper: React.FC = ({ ( params: CreateMajorityVotingProposalParams ): GaslessProposalCreationParams => { + // The offchain offset is used to ensure that the offchain proposal is enough long to don't overlap the onchain proposal + // limits. As both chains don't use the same clock, and we are calculating the times using blocks, we ensure that + // the times will be properly set to let the voters vote between the onchain proposal limits. + const offchainOffsets = 1; // Minutes const gaslessEndDate = new Date(params.endDate!); - gaslessEndDate.setMinutes(params.endDate!.getMinutes() + 1); + gaslessEndDate.setMinutes(params.endDate!.getMinutes() + offchainOffsets); let gaslessStartDate; if (params.startDate) { gaslessStartDate = new Date(params.startDate); - gaslessStartDate.setMinutes(params.startDate.getMinutes() - 1); + gaslessStartDate.setMinutes( + params.startDate.getMinutes() - offchainOffsets + ); } return { ...params, @@ -1004,13 +1019,6 @@ const CreateProposalWrapper: React.FC = ({ async function setProposalData() { if (showTxModal && creationProcessState === TransactionState.WAITING) { if (gasless) { - // const {params} = await getProposalCreationParams(); - // // console.log( - // // 'XXXXXXXXXXXXXXXXX', - // // (await getProposalCreationParams()).params.endDate, - // // gaslessParamsxx.endDate, - // // getOffChainProposalParams(gaslessParamsxx).endDate - // // ); setProposalCreationData( getOffChainProposalParams( (await getProposalCreationParams()).params