gevulot_rs/
gov_client.rs

1use cosmos_sdk_proto::cosmos::base::v1beta1::Coin;
2use prost::Message;
3use std::sync::Arc;
4use tokio::sync::RwLock;
5
6use crate::{base_client::BaseClient, error::Result};
7
8use cosmos_sdk_proto::cosmos::gov::v1beta1::{
9    MsgDeposit, MsgDepositResponse, MsgSubmitProposal, MsgSubmitProposalResponse, MsgVote,
10    MsgVoteResponse, MsgVoteWeighted, MsgVoteWeightedResponse, QueryDepositRequest,
11    QueryDepositResponse, QueryDepositsRequest, QueryDepositsResponse, QueryParamsRequest,
12    QueryParamsResponse, QueryProposalRequest, QueryProposalResponse, QueryProposalsRequest,
13    QueryProposalsResponse, QueryTallyResultRequest, QueryTallyResultResponse, QueryVoteRequest,
14    QueryVoteResponse, QueryVotesRequest, QueryVotesResponse,
15};
16use cosmos_sdk_proto::cosmos::upgrade::v1beta1::MsgSoftwareUpgrade;
17use cosmos_sdk_proto::Any;
18
19/// Client for interacting with the governance module in the Cosmos SDK.
20#[derive(Debug, Clone)]
21pub struct GovClient {
22    base_client: Arc<RwLock<BaseClient>>,
23}
24
25impl GovClient {
26    /// Creates a new instance of GovClient.
27    ///
28    /// # Arguments
29    ///
30    /// * `base_client` - An Arc-wrapped RwLock of the BaseClient.
31    ///
32    /// # Returns
33    ///
34    /// A new instance of GovClient.
35    pub fn new(base_client: Arc<RwLock<BaseClient>>) -> Self {
36        Self { base_client }
37    }
38
39    /// Queries a proposal based on proposal ID.
40    pub async fn get_proposal(&mut self, proposal_id: u64) -> Result<QueryProposalResponse> {
41        let request = QueryProposalRequest { proposal_id };
42        let response = self
43            .base_client
44            .write()
45            .await
46            .gov_client
47            .proposal(request)
48            .await?;
49        Ok(response.into_inner())
50    }
51
52    /// Queries all proposals based on given status.
53    pub async fn get_proposals(
54        &mut self,
55        proposal_status: i32,
56        voter: String,
57        depositor: String,
58    ) -> Result<QueryProposalsResponse> {
59        let request = QueryProposalsRequest {
60            proposal_status,
61            voter,
62            depositor,
63            pagination: None,
64        };
65        let response = self
66            .base_client
67            .write()
68            .await
69            .gov_client
70            .proposals(request)
71            .await?;
72        Ok(response.into_inner())
73    }
74
75    /// Queries voted information based on proposalID, voter address.
76    pub async fn get_vote(&mut self, proposal_id: u64, voter: String) -> Result<QueryVoteResponse> {
77        let request = QueryVoteRequest { proposal_id, voter };
78        let response = self
79            .base_client
80            .write()
81            .await
82            .gov_client
83            .vote(request)
84            .await?;
85        Ok(response.into_inner())
86    }
87
88    /// Queries votes of a given proposal.
89    pub async fn get_votes(&mut self, proposal_id: u64) -> Result<QueryVotesResponse> {
90        let request = QueryVotesRequest {
91            proposal_id,
92            pagination: None,
93        };
94        let response = self
95            .base_client
96            .write()
97            .await
98            .gov_client
99            .votes(request)
100            .await?;
101        Ok(response.into_inner())
102    }
103
104    /// Queries all parameters of the gov module.
105    pub async fn get_params(&mut self, params_type: String) -> Result<QueryParamsResponse> {
106        let request = QueryParamsRequest { params_type };
107        let response = self
108            .base_client
109            .write()
110            .await
111            .gov_client
112            .params(request)
113            .await?;
114        Ok(response.into_inner())
115    }
116
117    /// Queries single deposit information based on proposalID, depositor address.
118    pub async fn get_deposit(
119        &mut self,
120        proposal_id: u64,
121        depositor: String,
122    ) -> Result<QueryDepositResponse> {
123        let request = QueryDepositRequest {
124            proposal_id,
125            depositor,
126        };
127        let response = self
128            .base_client
129            .write()
130            .await
131            .gov_client
132            .deposit(request)
133            .await?;
134        Ok(response.into_inner())
135    }
136
137    /// Queries all deposits of a single proposal.
138    pub async fn get_deposits(&mut self, proposal_id: u64) -> Result<QueryDepositsResponse> {
139        let request = QueryDepositsRequest {
140            proposal_id,
141            pagination: None,
142        };
143        let response = self
144            .base_client
145            .write()
146            .await
147            .gov_client
148            .deposits(request)
149            .await?;
150        Ok(response.into_inner())
151    }
152
153    /// Queries the tally of a proposal vote.
154    pub async fn get_tally_result(&mut self, proposal_id: u64) -> Result<QueryTallyResultResponse> {
155        let request = QueryTallyResultRequest { proposal_id };
156        let response = self
157            .base_client
158            .write()
159            .await
160            .gov_client
161            .tally_result(request)
162            .await?;
163        Ok(response.into_inner())
164    }
165
166    /// Submits a proposal.
167    pub async fn submit_proposal(
168        &mut self,
169        msg: MsgSubmitProposal,
170    ) -> Result<MsgSubmitProposalResponse> {
171        let resp: MsgSubmitProposalResponse = self
172            .base_client
173            .write()
174            .await
175            .send_msg_sync(msg, "")
176            .await?;
177        Ok(resp)
178    }
179
180    /// Casts a vote.
181    pub async fn vote(&mut self, msg: MsgVote) -> Result<MsgVoteResponse> {
182        let resp: MsgVoteResponse = self
183            .base_client
184            .write()
185            .await
186            .send_msg_sync(msg, "")
187            .await?;
188        Ok(resp)
189    }
190
191    /// Casts a weighted vote.
192    /// @TODO: Doesnt work because of no Name bound on the message type 🤔
193    pub async fn vote_weighted(&mut self, msg: MsgVoteWeighted) -> Result<MsgVoteWeightedResponse> {
194        let resp: MsgVoteWeightedResponse = self
195            .base_client
196            .write()
197            .await
198            .send_msg_sync(msg, "")
199            .await?;
200        Ok(resp)
201    }
202
203    /// Submits a deposit to an existing proposal.
204    pub async fn deposit(&mut self, msg: MsgDeposit) -> Result<MsgDepositResponse> {
205        let resp: MsgDepositResponse = self
206            .base_client
207            .write()
208            .await
209            .send_msg_sync(msg, "")
210            .await?;
211        Ok(resp)
212    }
213
214    /// Submits a software upgrade proposal.
215    pub async fn submit_software_upgrade(
216        &mut self,
217        proposer: &str,
218        upgrade_msg: MsgSoftwareUpgrade,
219        deposit: &str,
220    ) -> Result<MsgSubmitProposalResponse> {
221        let content = Any {
222            type_url: "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade".to_string(),
223            value: upgrade_msg.encode_to_vec(),
224        };
225
226        let deposit = vec![Coin {
227            denom: "ucredit".to_string(),
228            amount: deposit.to_string(),
229        }];
230        let msg = MsgSubmitProposal {
231            content: Some(content),
232            initial_deposit: deposit,
233            proposer: proposer.to_string(),
234        };
235
236        self.submit_proposal(msg).await
237    }
238}