diff --git a/Cargo.lock b/Cargo.lock index fa6f574f..8f19ec41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1281,6 +1281,7 @@ dependencies = [ name = "cwd-voting" version = "0.2.0" dependencies = [ + "cosmwasm-schema", "cosmwasm-std", "cw-denom", "cw-storage-plus 1.2.0", diff --git a/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/cwd-pre-propose-multiple.json b/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/cwd-pre-propose-multiple.json index 1df1299a..bf2953bb 100644 --- a/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/cwd-pre-propose-multiple.json +++ b/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/cwd-pre-propose-multiple.json @@ -1495,7 +1495,8 @@ "description": "Unchecked multiple choice option", "type": "object", "required": [ - "description" + "description", + "title" ], "properties": { "description": { @@ -1509,6 +1510,9 @@ "items": { "$ref": "#/definitions/CosmosMsg_for_NeutronMsg" } + }, + "title": { + "type": "string" } } }, diff --git a/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/raw/execute.json b/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/raw/execute.json index 544362a9..336e0aa7 100644 --- a/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/raw/execute.json +++ b/contracts/dao/pre-propose/cwd-pre-propose-multiple/schema/raw/execute.json @@ -1330,7 +1330,8 @@ "description": "Unchecked multiple choice option", "type": "object", "required": [ - "description" + "description", + "title" ], "properties": { "description": { @@ -1344,6 +1345,9 @@ "items": { "$ref": "#/definitions/CosmosMsg_for_NeutronMsg" } + }, + "title": { + "type": "string" } } }, diff --git a/contracts/dao/proposal/cwd-proposal-multiple/schema/cwd-proposal-multiple.json b/contracts/dao/proposal/cwd-proposal-multiple/schema/cwd-proposal-multiple.json index fa637634..32b4e854 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/schema/cwd-proposal-multiple.json +++ b/contracts/dao/proposal/cwd-proposal-multiple/schema/cwd-proposal-multiple.json @@ -1836,7 +1836,8 @@ "description": "Unchecked multiple choice option", "type": "object", "required": [ - "description" + "description", + "title" ], "properties": { "description": { @@ -1850,6 +1851,9 @@ "items": { "$ref": "#/definitions/CosmosMsg_for_NeutronMsg" } + }, + "title": { + "type": "string" } } }, @@ -4197,6 +4201,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -4220,6 +4225,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } @@ -6987,6 +6995,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -7010,6 +7019,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } @@ -9754,6 +9766,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -9777,6 +9790,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } diff --git a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/execute.json b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/execute.json index 9cebc591..6f439e90 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/execute.json +++ b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/execute.json @@ -1552,7 +1552,8 @@ "description": "Unchecked multiple choice option", "type": "object", "required": [ - "description" + "description", + "title" ], "properties": { "description": { @@ -1566,6 +1567,9 @@ "items": { "$ref": "#/definitions/CosmosMsg_for_NeutronMsg" } + }, + "title": { + "type": "string" } } }, diff --git a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_list_proposals.json b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_list_proposals.json index 0ebb8edb..623f7bfc 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_list_proposals.json +++ b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_list_proposals.json @@ -261,6 +261,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -284,6 +285,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } diff --git a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_proposal.json b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_proposal.json index 7b9d7d71..05bd4197 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_proposal.json +++ b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_proposal.json @@ -265,6 +265,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -288,6 +289,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } diff --git a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_reverse_proposals.json b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_reverse_proposals.json index 0ebb8edb..623f7bfc 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_reverse_proposals.json +++ b/contracts/dao/proposal/cwd-proposal-multiple/schema/raw/response_to_reverse_proposals.json @@ -261,6 +261,7 @@ "description", "index", "option_type", + "title", "vote_count" ], "properties": { @@ -284,6 +285,9 @@ "option_type": { "$ref": "#/definitions/MultipleChoiceOptionType" }, + "title": { + "type": "string" + }, "vote_count": { "$ref": "#/definitions/Uint128" } diff --git a/contracts/dao/proposal/cwd-proposal-multiple/src/contract.rs b/contracts/dao/proposal/cwd-proposal-multiple/src/contract.rs index d4aa3b4e..80b10a58 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/src/contract.rs +++ b/contracts/dao/proposal/cwd-proposal-multiple/src/contract.rs @@ -6,7 +6,7 @@ use cosmwasm_std::{ }; use cw2::set_contract_version; -use cw_storage_plus::Bound; +use cw_storage_plus::{Bound, Map}; use cw_utils::{parse_reply_instantiate_data, Duration}; use cwd_hooks::Hooks; use cwd_interface::voting::IsActiveResponse; @@ -15,7 +15,8 @@ use cwd_proposal_hooks::{new_proposal_hooks, proposal_status_changed_hooks}; use cwd_vote_hooks::new_vote_hooks; use cwd_voting::{ multiple_choice::{ - MultipleChoiceOptions, MultipleChoiceVote, MultipleChoiceVotes, VotingStrategy, + CheckedMultipleChoiceOption, MultipleChoiceOptions, MultipleChoiceVote, + MultipleChoiceVotes, VotingStrategy, }, pre_propose::{PreProposeInfo, ProposalCreationPolicy}, proposal::{DEFAULT_LIMIT, MAX_PROPOSAL_SIZE}, @@ -30,7 +31,7 @@ use crate::state::PROPOSAL_EXECUTION_ERRORS; use crate::{msg::MigrateMsg, state::CREATION_POLICY}; use crate::{ msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, - proposal::{MultipleChoiceProposal, VoteResult}, + proposal::{MultipleChoiceProposal, OldMultipleChoiceProposal, VoteResult}, query::{ProposalListResponse, ProposalResponse, VoteInfo, VoteListResponse, VoteResponse}, state::{ Ballot, Config, BALLOTS, CONFIG, PROPOSALS, PROPOSAL_COUNT, PROPOSAL_HOOKS, VOTE_HOOKS, @@ -918,5 +919,50 @@ pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result Result { set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; - Ok(Response::default()) + + let mut migrated_proposal_ids: Vec = vec![]; + + // This constant is needed to access the old proposals without "title" field inside "choices". + const OLD_PROPOSALS: Map = Map::new("proposals"); + OLD_PROPOSALS + .range(deps.storage, None, None, cosmwasm_std::Order::Ascending) + .collect::>>()? + .into_iter() + .try_for_each(|(id, prop)| { + migrated_proposal_ids.push(id.to_string()); + + PROPOSALS.save( + deps.storage, + id, + &MultipleChoiceProposal { + title: prop.title, + description: prop.description, + proposer: prop.proposer, + start_height: prop.start_height, + min_voting_period: prop.min_voting_period, + expiration: prop.expiration, + choices: prop + .choices + .into_iter() + .map(|choice| CheckedMultipleChoiceOption { + index: choice.index, + option_type: choice.option_type, + title: "".to_string(), + description: choice.description, + msgs: choice.msgs, + vote_count: choice.vote_count, + }) + .collect(), + status: prop.status, + voting_strategy: prop.voting_strategy, + total_power: prop.total_power, + votes: prop.votes, + allow_revoting: prop.allow_revoting, + }, + ) + })?; + + Ok(Response::default() + .add_attribute("action", "migrate") + .add_attribute("migrated_proposal_ids", migrated_proposal_ids.join(","))) } diff --git a/contracts/dao/proposal/cwd-proposal-multiple/src/proposal.rs b/contracts/dao/proposal/cwd-proposal-multiple/src/proposal.rs index e1e48fef..17a519ea 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/src/proposal.rs +++ b/contracts/dao/proposal/cwd-proposal-multiple/src/proposal.rs @@ -3,7 +3,8 @@ use cosmwasm_std::{Addr, BlockInfo, StdError, StdResult, Uint128}; use cw_utils::Expiration; use cwd_voting::{ multiple_choice::{ - CheckedMultipleChoiceOption, MultipleChoiceOptionType, MultipleChoiceVotes, VotingStrategy, + CheckedMultipleChoiceOption, MultipleChoiceOptionType, MultipleChoiceVotes, + OldCheckedMultipleChoiceOption, VotingStrategy, }, proposal::Proposal, status::Status, @@ -46,6 +47,24 @@ pub struct MultipleChoiceProposal { pub allow_revoting: bool, } +/// Deprecated. +/// This is the old proposal version without "title" field inside "choices". +#[cw_serde] +pub struct OldMultipleChoiceProposal { + pub title: String, + pub description: String, + pub proposer: Addr, + pub start_height: u64, + pub min_voting_period: Option, + pub expiration: Expiration, + pub choices: Vec, + pub status: Status, + pub voting_strategy: VotingStrategy, + pub total_power: Uint128, + pub votes: MultipleChoiceVotes, + pub allow_revoting: bool, +} + pub enum VoteResult { SingleWinner(CheckedMultipleChoiceOption), Tie, @@ -284,10 +303,12 @@ mod tests { // The last option that gets added in into_checked is always the none of the above option let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, diff --git a/contracts/dao/proposal/cwd-proposal-multiple/src/testing/do_votes.rs b/contracts/dao/proposal/cwd-proposal-multiple/src/testing/do_votes.rs index d9e34160..8e1a956a 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/src/testing/do_votes.rs +++ b/contracts/dao/proposal/cwd-proposal-multiple/src/testing/do_votes.rs @@ -156,10 +156,12 @@ where let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, diff --git a/contracts/dao/proposal/cwd-proposal-multiple/src/testing/tests.rs b/contracts/dao/proposal/cwd-proposal-multiple/src/testing/tests.rs index d331f91c..060e56be 100644 --- a/contracts/dao/proposal/cwd-proposal-multiple/src/testing/tests.rs +++ b/contracts/dao/proposal/cwd-proposal-multiple/src/testing/tests.rs @@ -17,8 +17,8 @@ use cwd_voting::{ deposit::{CheckedDepositInfo, DepositRefundPolicy, DepositToken, UncheckedDepositInfo}, multiple_choice::{ CheckedMultipleChoiceOption, MultipleChoiceOption, MultipleChoiceOptionType, - MultipleChoiceOptions, MultipleChoiceVote, MultipleChoiceVotes, VotingStrategy, - MAX_NUM_CHOICES, + MultipleChoiceOptions, MultipleChoiceVote, MultipleChoiceVotes, + OldCheckedMultipleChoiceOption, VotingStrategy, MAX_NUM_CHOICES, }, pre_propose::PreProposeInfo, status::Status, @@ -28,8 +28,8 @@ use neutron_sdk::bindings::msg::NeutronMsg; use std::panic; use crate::{ - msg::{ExecuteMsg, InstantiateMsg, QueryMsg}, - proposal::MultipleChoiceProposal, + msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}, + proposal::{MultipleChoiceProposal, OldMultipleChoiceProposal}, query::{ProposalListResponse, ProposalResponse}, state::Config, testing::{ @@ -149,11 +149,13 @@ fn test_propose() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { - description: "multiple choice option 1".to_string(), + title: "title".to_string(), + description: "multiple choice option 2".to_string(), msgs: None, }, ]; @@ -243,6 +245,7 @@ fn test_propose_wrong_num_choices() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }; @@ -343,10 +346,12 @@ fn test_no_early_pass_with_min_duration() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -452,10 +457,12 @@ fn test_propose_with_messages() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: Some(vec![CosmosMsg::Wasm(wasm_msg)]), }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -613,10 +620,12 @@ fn test_min_duration_same_as_proposal_duration() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -786,10 +795,12 @@ fn test_native_proposal_deposit() { let mc_options = MultipleChoiceOptions { options: vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -919,10 +930,12 @@ fn test_cant_propose_zero_power() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1016,10 +1029,12 @@ fn test_open_proposal_submission() { MultipleChoiceOptions { options: vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1044,6 +1059,7 @@ fn test_open_proposal_submission() { }, choices: vec![ CheckedMultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, option_type: MultipleChoiceOptionType::Standard, @@ -1051,6 +1067,7 @@ fn test_open_proposal_submission() { index: 0, }, CheckedMultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, option_type: MultipleChoiceOptionType::Standard, @@ -1058,6 +1075,7 @@ fn test_open_proposal_submission() { index: 1, }, CheckedMultipleChoiceOption { + title: "None of the above".to_string(), description: "None of the above".to_string(), msgs: None, option_type: MultipleChoiceOptionType::None, @@ -1117,10 +1135,12 @@ fn test_execute_expired_proposal() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1236,10 +1256,12 @@ fn test_query_list_proposals() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1485,10 +1507,12 @@ fn test_revoting() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1612,10 +1636,12 @@ fn test_allow_revoting_config_changes() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1757,10 +1783,12 @@ fn test_revoting_same_vote_twice() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1847,10 +1875,12 @@ fn test_invalid_revote_does_not_invalidate_initial_vote() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -1967,6 +1997,7 @@ fn test_close_failed_proposal() { let options = vec![ MultipleChoiceOption { + title: "title".to_string(), description: "Burn or burn".to_string(), msgs: Some(vec![WasmMsg::Execute { contract_addr: "token_contract".to_string(), @@ -1976,6 +2007,7 @@ fn test_close_failed_proposal() { .into()]), }, MultipleChoiceOption { + title: "title".to_string(), description: "Don't burn".to_string(), msgs: None, }, @@ -2039,6 +2071,7 @@ fn test_close_failed_proposal() { choices: MultipleChoiceOptions { options: vec![ MultipleChoiceOption { + title: "title".to_string(), description: "Disable closing failed proposals".to_string(), msgs: Some(vec![WasmMsg::Execute { contract_addr: govmod.to_string(), @@ -2057,6 +2090,7 @@ fn test_close_failed_proposal() { .into()]), }, MultipleChoiceOption { + title: "title".to_string(), description: "Don't disable".to_string(), msgs: None, }, @@ -2188,3 +2222,117 @@ fn test_reply_proposal_mock() { let error: Option = from_json(query_res).unwrap(); assert_eq!(error, Some("error".to_string())); } + +#[test] +fn test_migrate_mock() { + use crate::contract::migrate; + use crate::state::PROPOSALS; + use cw_storage_plus::Map; + + let mut deps = mock_dependencies(); + let env = mock_env(); + let max_voting_period = cw_utils::Duration::Height(6); + + let old_proposals: Map = Map::new("proposals"); + old_proposals + .save( + deps.as_mut().storage, + 0, + &OldMultipleChoiceProposal { + title: "A simple text proposal".to_string(), + description: "This is a simple text proposal".to_string(), + proposer: Addr::unchecked(CREATOR_ADDR), + start_height: env.block.height, + min_voting_period: None, + expiration: max_voting_period.after(&env.block), + choices: vec![ + OldCheckedMultipleChoiceOption { + description: "multiple choice option 1".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::Standard, + vote_count: Uint128::zero(), + index: 0, + }, + OldCheckedMultipleChoiceOption { + description: "multiple choice option 2".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::Standard, + vote_count: Uint128::zero(), + index: 1, + }, + OldCheckedMultipleChoiceOption { + description: "None of the above".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::None, + vote_count: Uint128::zero(), + index: 2, + }, + ], + status: Status::Open, + voting_strategy: VotingStrategy::SingleChoice { + quorum: cwd_voting::threshold::PercentageThreshold::Majority {}, + }, + total_power: Uint128::new(100), + votes: MultipleChoiceVotes { + vote_weights: vec![Uint128::zero(); 3], + }, + allow_revoting: false, + }, + ) + .unwrap(); + + let msg = MigrateMsg::FromV1 { + close_proposal_on_execution_failure: true, + pre_propose_info: PreProposeInfo::AnyoneMayPropose {}, + }; + + migrate(deps.as_mut(), env.clone(), msg.clone()).unwrap(); + + let migrated_proposal = PROPOSALS.load(deps.as_mut().storage, 0).unwrap(); + + let expected = MultipleChoiceProposal { + title: "A simple text proposal".to_string(), + description: "This is a simple text proposal".to_string(), + proposer: Addr::unchecked(CREATOR_ADDR), + start_height: env.block.height, + min_voting_period: None, + expiration: max_voting_period.after(&env.block), + choices: vec![ + CheckedMultipleChoiceOption { + title: "".to_string(), + description: "multiple choice option 1".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::Standard, + vote_count: Uint128::zero(), + index: 0, + }, + CheckedMultipleChoiceOption { + title: "".to_string(), + description: "multiple choice option 2".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::Standard, + vote_count: Uint128::zero(), + index: 1, + }, + CheckedMultipleChoiceOption { + title: "".to_string(), + description: "None of the above".to_string(), + msgs: None, + option_type: MultipleChoiceOptionType::None, + vote_count: Uint128::zero(), + index: 2, + }, + ], + status: Status::Open, + voting_strategy: VotingStrategy::SingleChoice { + quorum: cwd_voting::threshold::PercentageThreshold::Majority {}, + }, + total_power: Uint128::new(100), + votes: MultipleChoiceVotes { + vote_weights: vec![Uint128::zero(); 3], + }, + allow_revoting: false, + }; + + assert_eq!(migrated_proposal, expected); +} diff --git a/packages/cwd-voting/Cargo.toml b/packages/cwd-voting/Cargo.toml index 68e47f50..80119fec 100644 --- a/packages/cwd-voting/Cargo.toml +++ b/packages/cwd-voting/Cargo.toml @@ -8,6 +8,7 @@ description = "Types and methods for CosmWasm DAO voting." [dependencies] neutron-sdk = "0.10.0" +cosmwasm-schema = { version = "1.3.0" } cosmwasm-std = { version = "1.3.0" } schemars = "0.8.8" serde = { version = "1.0.175", default-features = false, features = ["derive"] } diff --git a/packages/cwd-voting/src/multiple_choice.rs b/packages/cwd-voting/src/multiple_choice.rs index b269bd4f..d400a2b6 100644 --- a/packages/cwd-voting/src/multiple_choice.rs +++ b/packages/cwd-voting/src/multiple_choice.rs @@ -1,3 +1,4 @@ +use cosmwasm_schema::cw_serde; use cosmwasm_std::{CosmosMsg, StdError, StdResult, Uint128}; use neutron_sdk::bindings::msg::NeutronMsg; use schemars::JsonSchema; @@ -100,6 +101,7 @@ pub struct MultipleChoiceOptions { /// Unchecked multiple choice option #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] pub struct MultipleChoiceOption { + pub title: String, pub description: String, pub msgs: Option>>, } @@ -116,6 +118,18 @@ pub struct CheckedMultipleChoiceOptions { pub struct CheckedMultipleChoiceOption { // This is the index of the option in both the vote_weights and proposal.choices vectors. // Workaround due to not being able to use HashMaps in Cosmwasm. + pub index: u32, + pub option_type: MultipleChoiceOptionType, + pub title: String, + pub description: String, + pub msgs: Option>>, + pub vote_count: Uint128, +} + +/// Deprecated. +/// This is the old choice option version without "title" field. +#[cw_serde] +pub struct OldCheckedMultipleChoiceOption { pub index: u32, pub option_type: MultipleChoiceOptionType, pub description: String, @@ -142,6 +156,7 @@ impl MultipleChoiceOptions { let checked_option = CheckedMultipleChoiceOption { index: idx as u32, option_type: MultipleChoiceOptionType::Standard, + title: choice.title, description: choice.description, msgs: choice.msgs, vote_count: Uint128::zero(), @@ -153,6 +168,7 @@ impl MultipleChoiceOptions { let none_option = CheckedMultipleChoiceOption { index: (checked_options.capacity() - 1) as u32, option_type: MultipleChoiceOptionType::None, + title: NONE_OPTION_DESCRIPTION.to_string(), description: NONE_OPTION_DESCRIPTION.to_string(), msgs: None, vote_count: Uint128::zero(), @@ -205,10 +221,12 @@ mod test { fn test_into_checked() { let options = vec![ super::MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }, super::MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 2".to_string(), msgs: None, }, @@ -248,6 +266,7 @@ mod test { #[test] fn test_into_checked_wrong_num_choices() { let options = vec![super::MultipleChoiceOption { + title: "title".to_string(), description: "multiple choice option 1".to_string(), msgs: None, }];