Skip to content

Commit

Permalink
Support instant vote on proposal creation (#1827)
Browse files Browse the repository at this point in the history
  • Loading branch information
NoahSaso authored Dec 4, 2024
1 parent 6e0b850 commit e1b7f2e
Show file tree
Hide file tree
Showing 43 changed files with 397 additions and 144 deletions.
2 changes: 2 additions & 0 deletions packages/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,7 @@
"inboxEmailTooltip": "Receive inbox notifications in your email.",
"initialRewardsFundsDescription": "Reward distribution starts upon execution if initial funds are added.",
"installKeplrMobileOrScanQrCode": "If you don't have Keplr Mobile installed, <2>click here to install it</2> or scan the QR code at the bottom with another device.",
"instantVoteTooltip": "Cast a vote when submitting this proposal.",
"instantiatePredictableSmartContractActionDescription": "Instantiate a smart contract with a predictable address.",
"instantiateSmartContractActionDescription": "Instantiate a smart contract.",
"instantiatorAccountTooltip": "This is the account that will be instantiating the smart contract. The contract will see this as the `sender`.",
Expand Down Expand Up @@ -1876,6 +1877,7 @@
"importMultisig": "Import Multisig",
"inactiveDaos": "Inactive DAOs",
"initialTokenDistribution": "Initial Token Distribution",
"instantVote": "Instant Vote",
"instantiatePredictableSmartContract": "Instantiate Predictable Smart Contract",
"instantiateSmartContract": "Instantiate Smart Contract",
"lastUpdated": "Last updated",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class BecomeApproverAction extends ActionBase<BecomeApproverData> {
constructor(options: ActionOptions) {
if (
options.context.type !== ActionContextType.Dao ||
!options.context.dao.info.supportedFeatures[Feature.Approval]
!options.context.dao.supports(Feature.Approval)
) {
throw new Error('Invalid context for becoming an approver')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class EnableApproverAction extends ActionBase<EnableApproverData> {
// - approver is already enabled
if (
options.context.type !== ActionContextType.Dao ||
!options.context.dao.info.supportedFeatures[Feature.Approval]
!options.context.dao.supports(Feature.Approval)
) {
throw new Error('Invalid context for enabling approver')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ export class EnableMultipleChoiceAction extends ActionBase<{}> {
// support approval flow right now and that would be confusing.
if (
options.context.type !== ActionContextType.Dao ||
!options.context.dao.info.supportedFeatures[
Feature.MultipleChoiceProposals
] ||
!options.context.dao.supports(Feature.MultipleChoiceProposals) ||
// Neutron fork SubDAOs don't support multiple choice proposals due to the
// timelock/overrule system only being designed for single choice
// proposals.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ export class ManageStorageItemsAction extends ActionBase<ManageStorageItemsData>
matchPriority: -90,
})

this.valueKey = options.context.dao.info.supportedFeatures[
Feature.StorageItemValueKey
]
this.valueKey = options.context.dao.supports(Feature.StorageItemValueKey)
? 'value'
: 'addr'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class ManageSubDaosAction extends ActionBase<ManageSubDaosData> {
throw new Error('Only DAOs can manage their subDAOs.')
}

if (!options.context.dao.info.supportedFeatures[Feature.SubDaos]) {
if (!options.context.dao.supports(Feature.SubDaos)) {
throw new Error("This DAO's version doesn't support subDAOs.")
}

Expand Down
3 changes: 1 addition & 2 deletions packages/stateful/clients/dao/CreatingDaoPlaceholder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TotalPowerAtHeightResponse,
VotingPowerAtHeightResponse,
} from '@dao-dao/types/contracts/DaoDaoCore'
import { getChainForChainId, getSupportedFeatures } from '@dao-dao/utils'
import { getChainForChainId } from '@dao-dao/utils'

import { DaoBase } from './base'

Expand All @@ -44,7 +44,6 @@ export class CreatingDaoPlaceholder extends DaoBase {
chainId: options.chainId,
coreAddress: options.coreAddress,
coreVersion: options.coreVersion,
supportedFeatures: getSupportedFeatures(options.coreVersion),
votingModuleAddress: '',
votingModuleInfo: {
contract: '',
Expand Down
9 changes: 9 additions & 0 deletions packages/stateful/clients/dao/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DaoCardLazyData,
DaoInfo,
DaoSource,
Feature,
IDaoBase,
IProposalModuleBase,
IVotingModuleBase,
Expand All @@ -17,6 +18,7 @@ import {
TotalPowerAtHeightResponse,
VotingPowerAtHeightResponse,
} from '@dao-dao/types/contracts/DaoDaoCore'
import { isFeatureSupportedByVersion } from '@dao-dao/utils'

export abstract class DaoBase implements IDaoBase {
constructor(protected readonly queryClient: QueryClient) {}
Expand Down Expand Up @@ -130,6 +132,13 @@ export abstract class DaoBase implements IDaoBase {
return this.info.items['banner']
}

/**
* Check whether or not the DAO supports a given feature.
*/
supports(feature: Feature): boolean {
return isFeatureSupportedByVersion(feature, this.coreVersion)
}

/**
* Get the proposal module with the given address.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
CheckedDepositInfo,
Coin,
Duration,
Feature,
SecretModuleInstantiateInfo,
} from '@dao-dao/types'
import {
Expand Down Expand Up @@ -138,19 +139,36 @@ export class SecretMultipleChoiceProposalModule extends ProposalModuleBase<
}

async propose({
data,
data: _data,
vote,
getSigningClient,
sender,
funds,
}: {
data: NewProposalData
vote?: MultipleChoiceVote
getSigningClient: () => Promise<SupportedSigningCosmWasmClient>
sender: string
funds?: Coin[]
}): Promise<{
proposalNumber: number
proposalId: string
}> {
if (vote && !this.supports(Feature.CastVoteOnProposalCreation)) {
throw new Error(
`Casting vote on proposal creation is not supported by version ${this.version}`
)
}

const data = {
..._data,
...(vote && {
vote: {
vote,
},
}),
}

const client = await getSigningClient()
const permit = await this.dao.getPermit(sender)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,36 @@ export class MultipleChoiceProposalModule extends ProposalModuleBase<
}

async propose({
data,
data: _data,
vote,
getSigningClient,
sender,
funds,
}: {
data: NewProposalData
vote?: MultipleChoiceVote
getSigningClient: () => Promise<SupportedSigningCosmWasmClient>
sender: string
funds?: Coin[]
}): Promise<{
proposalNumber: number
proposalId: string
}> {
if (vote && !this.supports(Feature.CastVoteOnProposalCreation)) {
throw new Error(
`Casting vote on proposal creation is not supported by version ${this.version}`
)
}

const data = {
..._data,
...(vote && {
vote: {
vote,
},
}),
}

const client = await getSigningClient()

let proposalNumber: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
CheckedDepositInfo,
Coin,
Duration,
Feature,
SecretModuleInstantiateInfo,
} from '@dao-dao/types'
import { InstantiateMsg as SecretDaoPreProposeApprovalSingleInstantiateMsg } from '@dao-dao/types/contracts/SecretDaoPreProposeApprovalSingle'
Expand Down Expand Up @@ -156,19 +157,36 @@ export class SecretSingleChoiceProposalModule extends ProposalModuleBase<
}

async propose({
data,
data: _data,
vote,
getSigningClient,
sender,
funds,
}: {
data: NewProposalData
vote?: Vote
getSigningClient: () => Promise<SupportedSigningCosmWasmClient>
sender: string
funds?: Coin[]
}): Promise<{
proposalNumber: number
proposalId: string
}> {
if (vote && !this.supports(Feature.CastVoteOnProposalCreation)) {
throw new Error(
`Casting vote on proposal creation is not supported by version ${this.version}`
)
}

const data = {
..._data,
...(vote && {
vote: {
vote,
},
}),
}

const client = await getSigningClient()
const permit = await this.dao.getPermit(sender)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,36 @@ export class SingleChoiceProposalModule extends ProposalModuleBase<
}

async propose({
data,
data: _data,
vote,
getSigningClient,
sender,
funds,
}: {
data: NewProposalData
vote?: Vote
getSigningClient: () => Promise<SupportedSigningCosmWasmClient>
sender: string
funds?: Coin[]
}): Promise<{
proposalNumber: number
proposalId: string
}> {
if (vote && !this.supports(Feature.CastVoteOnProposalCreation)) {
throw new Error(
`Casting vote on proposal creation is not supported by version ${this.version}`
)
}

const data = {
..._data,
...(vote && {
vote: {
vote,
},
}),
}

const client = await getSigningClient()

let proposalNumber: number
Expand Down
13 changes: 13 additions & 0 deletions packages/stateful/clients/proposal-module/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
Coin,
ContractVersion,
Duration,
Feature,
IDaoBase,
IProposalModuleBase,
PreProposeModule,
ProposalModuleInfo,
} from '@dao-dao/types'
import { isFeatureSupportedByVersion } from '@dao-dao/utils'

export abstract class ProposalModuleBase<
Dao extends IDaoBase = IDaoBase,
Expand Down Expand Up @@ -85,11 +87,22 @@ export abstract class ProposalModuleBase<
return this.info.prePropose
}

/**
* Check whether or not the proposal module supports a given feature.
*/
supports(feature: Feature): boolean {
return isFeatureSupportedByVersion(feature, this.version)
}

/**
* Make a proposal.
*/
abstract propose(options: {
data: Proposal
/**
* Cast a vote with the proposal.
*/
vote?: Vote
getSigningClient: () => Promise<SigningCosmWasmClient>
sender: string
funds?: Coin[]
Expand Down
8 changes: 3 additions & 5 deletions packages/stateful/command/contexts/generic/dao.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ export const makeGenericDaoContext: CommandModalContextMaker<{
const useSections = () => {
const { t } = useTranslation()
const { getDaoPath, getDaoProposalPath, router } = useDaoNavHelpers()
const {
info: { accounts, supportedFeatures },
} = useDao()
const dao = useDao()
const loadingTabs = useLoadingTabs()

const { isFollowing, setFollowing, setUnfollowing, updatingFollowing } =
Expand Down Expand Up @@ -83,7 +81,7 @@ export const makeGenericDaoContext: CommandModalContextMaker<{
chainId,
coreAddress,
}),
enabled: !!supportedFeatures[Feature.SubDaos],
enabled: dao.supports(Feature.SubDaos),
},
[]
)
Expand Down Expand Up @@ -152,7 +150,7 @@ export const makeGenericDaoContext: CommandModalContextMaker<{
}),
loading: updatingFollowing,
},
...accounts.map(({ chainId, address, type }, accountIndex) => ({
...dao.accounts.map(({ chainId, address, type }, accountIndex) => ({
name:
copied === accountIndex
? t('info.copiedChainAddress', {
Expand Down
2 changes: 0 additions & 2 deletions packages/stateful/components/dao/CreateDaoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -900,8 +900,6 @@ export const InnerCreateDaoForm = ({
description,
imageUrl: imageUrl || getFallbackImage(coreAddress),
parentDao: parentDao || null,
// Unused.
supportedFeatures: {} as any,
created: Date.now(),
votingModuleAddress: '',
votingModuleInfo: {
Expand Down
9 changes: 8 additions & 1 deletion packages/stateful/components/dao/CreateDaoProposal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,14 @@ const InnerCreateDaoProposal = ({
className="my-2"
matchAdapter={matchProposalModuleAdapter}
selected={selectedProposalModule.address}
setSelected={setSelectedProposalModule}
setSelected={(m) => {
// Clear instant vote if switching proposal modules.
if (m.address !== selectedProposalModule.address) {
formMethods.setValue('vote', undefined)
}

setSelectedProposalModule(m)
}}
/>
}
saveDraft={saveDraft}
Expand Down
4 changes: 0 additions & 4 deletions packages/stateful/components/dao/LazyDaoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ export const LazyDaoCard = (props: LazyDaoCardProps) => {
className={clsx('animate-pulse', props.className)}
info={{
...props.info,
// Unused.
supportedFeatures: {} as any,
votingModuleAddress: '',
votingModuleInfo: {
contract: '',
Expand Down Expand Up @@ -54,8 +52,6 @@ export const LazyDaoCard = (props: LazyDaoCardProps) => {
processError(daoInfoQuery.error, {
forceCapture: false,
}),
// Unused.
supportedFeatures: {} as any,
votingModuleAddress: '',
votingModuleInfo: {
contract: '',
Expand Down
Loading

0 comments on commit e1b7f2e

Please sign in to comment.