Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support instant vote on proposal creation #1827

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading