cardano_serialization_lib/builders/
voting_proposal_builder.rs

1use crate::*;
2use std::collections::BTreeMap;
3
4#[wasm_bindgen]
5#[derive(Clone, Debug)]
6pub struct VotingProposalBuilder {
7    proposals: BTreeMap<VotingProposal, Option<ScriptWitnessType>>,
8}
9
10#[wasm_bindgen]
11impl VotingProposalBuilder {
12    pub fn new() -> Self {
13        Self {
14            proposals: BTreeMap::new(),
15        }
16    }
17
18    pub fn add(&mut self, proposal: &VotingProposal) -> Result<(), JsError> {
19        if proposal.has_script_hash() {
20            return Err(JsError::from_str("Proposal has a script hash. Use add_with_plutus_witness instead."));
21        }
22        self.proposals.insert(proposal.clone(), None);
23        Ok(())
24    }
25
26    pub fn add_with_plutus_witness(
27        &mut self,
28        proposal: &VotingProposal,
29        witness: &PlutusWitness,
30    ) -> Result<(), JsError> {
31        self.proposals.insert(
32            proposal.clone(),
33            Some(ScriptWitnessType::PlutusScriptWitness(witness.clone())),
34        );
35        Ok(())
36    }
37
38    pub fn get_plutus_witnesses(&self) -> PlutusWitnesses {
39        let tag = RedeemerTag::new_voting_proposal();
40        let mut scripts = PlutusWitnesses::new();
41        for (i, (_, script_wit)) in self.proposals.iter().enumerate() {
42            if let Some(ScriptWitnessType::PlutusScriptWitness(s)) = script_wit {
43                let index = BigNum::from(i);
44                scripts.add(&s.clone_with_redeemer_index_and_tag(&index, &tag));
45            }
46        }
47        scripts
48    }
49
50    pub fn get_ref_inputs(&self) -> TransactionInputs {
51        let mut inputs = Vec::new();
52        for (_, script_wit) in &self.proposals {
53            match script_wit {
54                Some(script_witness) => {
55                    if let Some(input) = script_witness.get_script_ref_input() {
56                        inputs.push(input);
57                    }
58                    if let Some(input) = script_witness.get_datum_ref_input() {
59                        inputs.push(input);
60                    }
61                }
62                None => {}
63            }
64        }
65        TransactionInputs::from_vec(inputs)
66    }
67
68    pub(crate) fn get_total_deposit(&self) -> Result<Coin, JsError> {
69        self.proposals.iter().fold(
70            Ok(Coin::zero()),
71            |acc: Result<Coin, JsError>, (proposal, _)| {
72                acc.and_then(|acc| {
73                    acc.checked_add(&proposal.deposit)
74                        .or_else(|_| Err(JsError::from_str("Overflow when calculating total deposit")))
75                })
76            },
77        )
78    }
79
80    pub(crate) fn get_used_plutus_lang_versions(&self) -> BTreeSet<Language> {
81        let mut used_langs = BTreeSet::new();
82        for (_, script_wit) in &self.proposals {
83            if let Some(ScriptWitnessType::PlutusScriptWitness(s)) = script_wit {
84                used_langs.insert(s.script.language());
85            }
86        }
87        used_langs
88    }
89
90    //return only ref inputs that are script refs with added size
91    //used for calculating the fee for the transaction
92    //another ref input and also script ref input without size are filtered out
93    pub(crate) fn get_script_ref_inputs_with_size(
94        &self,
95    ) -> impl Iterator<Item = (&TransactionInput, usize)> {
96        self.proposals.iter()
97            .filter_map(|(_, script_wit)| script_wit.as_ref())
98            .filter_map(|script_wit| script_wit.get_script_ref_input_with_size())
99    }
100
101    pub fn has_plutus_scripts(&self) -> bool {
102        for (_, script_wit) in &self.proposals {
103            if let Some(ScriptWitnessType::PlutusScriptWitness(_)) = script_wit {
104                return true;
105            }
106        }
107        false
108    }
109
110    pub fn build(&self) -> VotingProposals {
111        let mut proposals = Vec::new();
112        for (voter, _) in &self.proposals {
113            proposals.push(voter.clone());
114        }
115        VotingProposals::from_vec(proposals)
116    }
117}