1use cosmwasm_schema::cw_serde;
2use cosmwasm_std::{to_json_binary, Empty, StdResult, Storage, SubMsg, WasmMsg};
3use cw_hooks::Hooks;
4use dao_voting::{
5    pre_propose::ProposalCreationPolicy,
6    reply::{failed_pre_propose_module_hook_id, mask_proposal_hook_index},
7    status::Status,
8};
9
10#[cw_serde]
14pub enum ProposalHookMsg {
15    NewProposal {
16        id: u64,
17        proposer: String,
18    },
19    ProposalStatusChanged {
20        id: u64,
21        old_status: String,
22        new_status: String,
23    },
24}
25
26pub fn new_proposal_hooks(
30    hooks: Hooks,
31    storage: &dyn Storage,
32    id: u64,
33    proposer: &str,
34) -> StdResult<Vec<SubMsg>> {
35    let msg = to_json_binary(&ProposalHookExecuteMsg::ProposalHook(
36        ProposalHookMsg::NewProposal {
37            id,
38            proposer: proposer.to_string(),
39        },
40    ))?;
41
42    let mut index: u64 = 0;
43    let messages = hooks.prepare_hooks(storage, |a| {
44        let execute = WasmMsg::Execute {
45            contract_addr: a.to_string(),
46            msg: msg.clone(),
47            funds: vec![],
48        };
49        let masked_index = mask_proposal_hook_index(index);
50        let tmp = SubMsg::reply_on_error(execute, masked_index);
51        index += 1;
52        Ok(tmp)
53    })?;
54
55    Ok(messages)
56}
57
58pub fn proposal_status_changed_hooks(
62    hooks: Hooks,
63    storage: &dyn Storage,
64    id: u64,
65    old_status: String,
66    new_status: String,
67) -> StdResult<Vec<SubMsg>> {
68    if old_status == new_status {
69        return Ok(vec![]);
70    }
71
72    let msg = to_json_binary(&ProposalHookExecuteMsg::ProposalHook(
73        ProposalHookMsg::ProposalStatusChanged {
74            id,
75            old_status,
76            new_status,
77        },
78    ))?;
79    let mut index: u64 = 0;
80    let messages = hooks.prepare_hooks(storage, |a| {
81        let execute = WasmMsg::Execute {
82            contract_addr: a.to_string(),
83            msg: msg.clone(),
84            funds: vec![],
85        };
86        let masked_index = mask_proposal_hook_index(index);
87        let tmp = SubMsg::reply_on_error(execute, masked_index);
88        index += 1;
89        Ok(tmp)
90    })?;
91
92    Ok(messages)
93}
94
95pub type PreProposeHookMsg = dao_pre_propose_base::msg::ExecuteMsg<Empty, Empty>;
98
99pub fn proposal_completed_hooks(
101    proposal_creation_policy: ProposalCreationPolicy,
102    proposal_id: u64,
103    new_status: Status,
104) -> StdResult<Vec<SubMsg>> {
105    let mut hooks: Vec<SubMsg> = vec![];
106    match proposal_creation_policy {
107        ProposalCreationPolicy::Anyone {} => (),
108        ProposalCreationPolicy::Module { addr } => {
109            let msg = to_json_binary(&PreProposeHookMsg::ProposalCompletedHook {
110                proposal_id,
111                new_status,
112            })?;
113            hooks.push(SubMsg::reply_on_error(
114                WasmMsg::Execute {
115                    contract_addr: addr.into_string(),
116                    msg,
117                    funds: vec![],
118                },
119                failed_pre_propose_module_hook_id(),
120            ));
121        }
122    };
123    Ok(hooks)
124}
125
126#[cw_serde]
127pub enum ProposalHookExecuteMsg {
128    ProposalHook(ProposalHookMsg),
129}