penumbra_sdk_governance/proposal_withdraw/
action.rs1use serde::{Deserialize, Serialize};
2
3use penumbra_sdk_asset::{Balance, Value};
4use penumbra_sdk_num::Amount;
5use penumbra_sdk_proto::{penumbra::core::component::governance::v1 as pb, DomainType};
6use penumbra_sdk_txhash::{EffectHash, EffectingData};
7
8use crate::ProposalNft;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(try_from = "pb::ProposalWithdraw", into = "pb::ProposalWithdraw")]
13pub struct ProposalWithdraw {
14 pub proposal: u64,
16 pub reason: String,
18}
19
20impl EffectingData for ProposalWithdraw {
21 fn effect_hash(&self) -> EffectHash {
22 EffectHash::from_proto_effecting_data(&self.to_proto())
23 }
24}
25
26impl From<ProposalWithdraw> for pb::ProposalWithdraw {
27 fn from(value: ProposalWithdraw) -> pb::ProposalWithdraw {
28 pb::ProposalWithdraw {
29 proposal: value.proposal,
30 reason: value.reason,
31 }
32 }
33}
34
35impl ProposalWithdraw {
36 pub fn balance(&self) -> Balance {
38 let voting_proposal_nft = self.voting_proposal_nft_value();
39 let withdrawn_proposal_nft = self.withdrawn_proposal_nft();
40
41 Balance::from(withdrawn_proposal_nft) - Balance::from(voting_proposal_nft)
43 }
44
45 fn voting_proposal_nft_value(&self) -> Value {
47 Value {
48 amount: Amount::from(1u64),
49 asset_id: ProposalNft::deposit(self.proposal).denom().into(),
50 }
51 }
52
53 fn withdrawn_proposal_nft(&self) -> Value {
55 Value {
56 amount: Amount::from(1u64),
57 asset_id: ProposalNft::unbonding_deposit(self.proposal).denom().into(),
58 }
59 }
60}
61
62impl TryFrom<pb::ProposalWithdraw> for ProposalWithdraw {
63 type Error = anyhow::Error;
64
65 fn try_from(msg: pb::ProposalWithdraw) -> Result<Self, Self::Error> {
66 Ok(ProposalWithdraw {
67 proposal: msg.proposal,
68 reason: msg.reason,
69 })
70 }
71}
72
73impl DomainType for ProposalWithdraw {
74 type Proto = pb::ProposalWithdraw;
75}