Skip to content

Commit

Permalink
Adds missing ability to query for completed proposals and view the cr…
Browse files Browse the repository at this point in the history
…eated proposal ID when approved.
  • Loading branch information
NoahSaso committed Nov 15, 2023
1 parent db42d45 commit 671c0c8
Show file tree
Hide file tree
Showing 5 changed files with 451 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,54 @@
},
"additionalProperties": false
},
{
"description": "Return whether or not the proposal is pending",
"type": "object",
"required": [
"is_pending"
],
"properties": {
"is_pending": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "A proposal, pending or completed.",
"type": "object",
"required": [
"proposal"
],
"properties": {
"proposal": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "A pending proposal",
"type": "object",
Expand Down Expand Up @@ -1586,6 +1634,117 @@
}
},
"additionalProperties": false
},
{
"description": "A completed proposal",
"type": "object",
"required": [
"completed_proposal"
],
"properties": {
"completed_proposal": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "List of completed proposals",
"type": "object",
"required": [
"completed_proposals"
],
"properties": {
"completed_proposals": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"reverse_completed_proposals"
],
"properties": {
"reverse_completed_proposals": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_before": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "The completed approval ID for a created proposal ID.",
"type": "object",
"required": [
"completed_proposal_id_for_created_proposal_id"
],
"properties": {
"completed_proposal_id_for_created_proposal_id": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use crate::msg::{
ApproverProposeMessage, ExecuteExt, ExecuteMsg, InstantiateExt, InstantiateMsg, ProposeMessage,
ProposeMessageInternal, QueryExt, QueryMsg,
};
use crate::state::{advance_approval_id, PendingProposal, APPROVER, PENDING_PROPOSALS};
use crate::state::{
advance_approval_id, Proposal, ProposalStatus, APPROVER, COMPLETED_PROPOSALS,
CREATED_PROPOSAL_TO_COMPLETED_PROPOSAL, PENDING_PROPOSALS,
};

pub(crate) const CONTRACT_NAME: &str = "crates.io:dao-pre-propose-approval-single";
pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
Expand Down Expand Up @@ -123,7 +126,8 @@ pub fn execute_propose(
PENDING_PROPOSALS.save(
deps.storage,
approval_id,
&PendingProposal {
&Proposal {
status: ProposalStatus::Pending {},
approval_id,
proposer: info.sender,
msg: propose_msg_internal,
Expand Down Expand Up @@ -164,14 +168,29 @@ pub fn execute_approve(
PrePropose::default().deposits.save(
deps.storage,
proposal_id,
&(proposal.deposit, proposal.proposer),
&(proposal.deposit.clone(), proposal.proposer.clone()),
)?;

let propose_messsage = WasmMsg::Execute {
contract_addr: proposal_module.into_string(),
msg: to_binary(&ProposeMessageInternal::Propose(proposal.msg))?,
msg: to_binary(&ProposeMessageInternal::Propose(proposal.msg.clone()))?,
funds: vec![],
};

COMPLETED_PROPOSALS.save(
deps.storage,
id,
&Proposal {
status: ProposalStatus::Approved {
created_proposal_id: proposal_id,
},
approval_id: proposal.approval_id,
proposer: proposal.proposer,
msg: proposal.msg,
deposit: proposal.deposit,
},
)?;
CREATED_PROPOSAL_TO_COMPLETED_PROPOSAL.save(deps.storage, proposal_id, &id)?;
PENDING_PROPOSALS.remove(deps.storage, id);

Ok(Response::default()
Expand All @@ -195,12 +214,27 @@ pub fn execute_reject(
return Err(PreProposeError::Unauthorized {});
}

let PendingProposal {
deposit, proposer, ..
let Proposal {
approval_id,
proposer,
msg,
deposit,
..
} = PENDING_PROPOSALS
.may_load(deps.storage, id)?
.ok_or(PreProposeError::ProposalNotFound {})?;

COMPLETED_PROPOSALS.save(
deps.storage,
id,
&Proposal {
status: ProposalStatus::Rejected {},
approval_id,
proposer: proposer.clone(),
msg: msg.clone(),
deposit: deposit.clone(),
},
)?;
PENDING_PROPOSALS.remove(deps.storage, id);

let messages = if let Some(ref deposit_info) = deposit {
Expand Down Expand Up @@ -297,6 +331,25 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::QueryExtension { msg } => match msg {
QueryExt::Approver {} => to_binary(&APPROVER.load(deps.storage)?),
QueryExt::IsPending { id } => {
let pending = PENDING_PROPOSALS.may_load(deps.storage, id)?.is_some();
// Force load completed proposal if not pending, throwing error
// if not found.
if !pending {
COMPLETED_PROPOSALS.load(deps.storage, id)?;
}

to_binary(&pending)
}
QueryExt::Proposal { id } => {
if let Some(pending) = PENDING_PROPOSALS.may_load(deps.storage, id)? {
to_binary(&pending)
} else {
// Force load completed proposal if not pending, throwing
// error if not found.
to_binary(&COMPLETED_PROPOSALS.load(deps.storage, id)?)
}
}
QueryExt::PendingProposal { id } => {
to_binary(&PENDING_PROPOSALS.load(deps.storage, id)?)
}
Expand All @@ -317,6 +370,29 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
limit,
Order::Ascending,
)?),
QueryExt::CompletedProposal { id } => {
to_binary(&COMPLETED_PROPOSALS.load(deps.storage, id)?)
}
QueryExt::CompletedProposals { start_after, limit } => to_binary(&paginate_map_values(
deps,
&COMPLETED_PROPOSALS,
start_after,
limit,
Order::Descending,
)?),
QueryExt::ReverseCompletedProposals {
start_before,
limit,
} => to_binary(&paginate_map_values(
deps,
&COMPLETED_PROPOSALS,
start_before,
limit,
Order::Ascending,
)?),
QueryExt::CompletedProposalIdForCreatedProposalId { id } => {
to_binary(&CREATED_PROPOSAL_TO_COMPLETED_PROPOSAL.may_load(deps.storage, id)?)
}
},
_ => PrePropose::default().query(deps, env, msg),
}
Expand Down
29 changes: 26 additions & 3 deletions contracts/pre-propose/dao-pre-propose-approval-single/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,43 @@ pub enum QueryExt {
/// List the approver address
#[returns(cosmwasm_std::Addr)]
Approver {},
/// Return whether or not the proposal is pending
#[returns(bool)]
IsPending { id: u64 },
/// A proposal, pending or completed.
#[returns(crate::state::Proposal)]
Proposal { id: u64 },
/// A pending proposal
#[returns(crate::state::PendingProposal)]
#[returns(crate::state::Proposal)]
PendingProposal { id: u64 },
/// List of proposals awaiting approval
#[returns(Vec<crate::state::PendingProposal>)]
#[returns(Vec<crate::state::Proposal>)]
PendingProposals {
start_after: Option<u64>,
limit: Option<u32>,
},
#[returns(Vec<crate::state::PendingProposal>)]
#[returns(Vec<crate::state::Proposal>)]
ReversePendingProposals {
start_before: Option<u64>,
limit: Option<u32>,
},
/// A completed proposal
#[returns(crate::state::Proposal)]
CompletedProposal { id: u64 },
/// List of completed proposals
#[returns(Vec<crate::state::Proposal>)]
CompletedProposals {
start_after: Option<u64>,
limit: Option<u32>,
},
#[returns(Vec<crate::state::Proposal>)]
ReverseCompletedProposals {
start_before: Option<u64>,
limit: Option<u32>,
},
/// The completed approval ID for a created proposal ID.
#[returns(Option<u64>)]
CompletedProposalIdForCreatedProposalId { id: u64 },
}

pub type InstantiateMsg = InstantiateBase<InstantiateExt>;
Expand Down
22 changes: 20 additions & 2 deletions contracts/pre-propose/dao-pre-propose-approval-single/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,22 @@ use dao_voting::deposit::CheckedDepositInfo;
use dao_voting::proposal::SingleChoiceProposeMsg as ProposeMsg;

#[cw_serde]
pub struct PendingProposal {
pub enum ProposalStatus {
/// The proposal is pending approval.
Pending {},
/// The proposal has been approved.
Approved {
/// The created proposal ID.
created_proposal_id: u64,
},
/// The proposal has been rejected.
Rejected {},
}

#[cw_serde]
pub struct Proposal {
/// The status of a completed proposal.
pub status: ProposalStatus,
/// The approval ID used to identify this pending proposal.
pub approval_id: u64,
/// The address that created the proposal.
Expand All @@ -20,7 +35,10 @@ pub struct PendingProposal {
}

pub const APPROVER: Item<Addr> = Item::new("approver");
pub const PENDING_PROPOSALS: Map<u64, PendingProposal> = Map::new("pending_proposals");
pub const PENDING_PROPOSALS: Map<u64, Proposal> = Map::new("pending_proposals");
pub const COMPLETED_PROPOSALS: Map<u64, Proposal> = Map::new("completed_proposals");
pub const CREATED_PROPOSAL_TO_COMPLETED_PROPOSAL: Map<u64, u64> =
Map::new("created_to_completed_proposal");

/// Used internally to track the current approval_id.
const CURRENT_ID: Item<u64> = Item::new("current_id");
Expand Down
Loading

0 comments on commit 671c0c8

Please sign in to comment.