cardano_serialization_lib/builders/
withdrawals_builder.rs1use std::collections::BTreeMap;
2use crate::*;
3
4#[wasm_bindgen]
5#[derive(Clone, Debug)]
6pub struct WithdrawalsBuilder {
7 withdrawals: BTreeMap<RewardAddress, (Coin, Option<ScriptWitnessType>)>,
8}
9
10#[wasm_bindgen]
11impl WithdrawalsBuilder {
12 pub fn new() -> Self {
13 Self {
14 withdrawals: BTreeMap::new(),
15 }
16 }
17
18 pub fn add(&mut self, address: &RewardAddress, coin: &Coin) -> Result<(), JsError> {
19 if address.payment_cred().has_script_hash() {
20 return Err(JsError::from_str(
21 "Your address has a required script witness.\
22 Please use .add_with_plutus_witness or .add_with_native_script instead.",
23 ));
24 }
25
26 self.withdrawals
27 .insert(address.clone(), (coin.clone(), None));
28
29 Ok(())
30 }
31
32 pub fn add_with_plutus_witness(
33 &mut self,
34 address: &RewardAddress,
35 coin: &Coin,
36 witness: &PlutusWitness,
37 ) -> Result<(), JsError> {
38 if !address.payment_cred().has_script_hash() {
39 return Err(JsError::from_str(
40 "Your address does not have a required script witness.\
41 Please use .add instead.",
42 ));
43 }
44
45 self.withdrawals.insert(
46 address.clone(),
47 (
48 coin.clone(),
49 Some(ScriptWitnessType::PlutusScriptWitness(witness.clone())),
50 ),
51 );
52 Ok(())
53 }
54
55 pub fn add_with_native_script(
56 &mut self,
57 address: &RewardAddress,
58 coin: &Coin,
59 native_script_source: &NativeScriptSource,
60 ) -> Result<(), JsError> {
61 if !address.payment_cred().has_script_hash() {
62 return Err(JsError::from_str(
63 "Your address does not have a required script witness.\
64 Please use .add instead.",
65 ));
66 }
67
68 self.withdrawals.insert(
69 address.clone(),
70 (
71 coin.clone(),
72 Some(ScriptWitnessType::NativeScriptWitness(
73 native_script_source.0.clone(),
74 )),
75 ),
76 );
77 Ok(())
78 }
79
80 pub(crate) fn get_required_signers(&self) -> Ed25519KeyHashes {
81 let mut set = Ed25519KeyHashes::new();
82 for (address, (_, script_wit)) in &self.withdrawals {
83 let req_signature = address.payment_cred().to_keyhash();
84 if let Some(req_signature) = req_signature {
85 set.add_move(req_signature);
86 }
87
88 if let Some(script_wit) = script_wit {
89 if let Some(script_wit) = script_wit.get_required_signers() {
90 set.extend_move(script_wit);
91 }
92 }
93 }
94 set
95 }
96
97 pub fn get_plutus_witnesses(&self) -> PlutusWitnesses {
98 let tag = RedeemerTag::new_reward();
99 let mut scripts = PlutusWitnesses::new();
100 for (i, (_, (_, script_wit))) in self.withdrawals.iter().enumerate() {
101 if let Some(ScriptWitnessType::PlutusScriptWitness(s)) = script_wit {
102 let index = BigNum::from(i);
103 scripts.add(&s.clone_with_redeemer_index_and_tag(&index, &tag));
104 }
105 }
106 scripts
107 }
108
109 pub fn get_ref_inputs(&self) -> TransactionInputs {
110 let mut inputs = Vec::new();
111 for (_, (_, script_wit)) in self.withdrawals.iter() {
112 match script_wit {
113 Some(script_witness) => {
114 if let Some(input) = script_witness.get_script_ref_input() {
115 inputs.push(input);
116 }
117 if let Some(input) = script_witness.get_datum_ref_input() {
118 inputs.push(input);
119 }
120 }
121 None => {}
122 }
123 }
124 TransactionInputs::from_vec(inputs)
125 }
126
127 pub fn get_native_scripts(&self) -> NativeScripts {
128 let mut scripts = NativeScripts::new();
129 for (_, (_, script_wit)) in self.withdrawals.iter() {
130 if let Some(ScriptWitnessType::NativeScriptWitness(
131 NativeScriptSourceEnum::NativeScript(script, _),
132 )) = script_wit
133 {
134 scripts.add(script);
135 }
136 }
137 scripts
138 }
139
140 pub(crate) fn get_used_plutus_lang_versions(&self) -> BTreeSet<Language> {
141 let mut used_langs = BTreeSet::new();
142 for (_, (_, script_wit)) in &self.withdrawals {
143 if let Some(ScriptWitnessType::PlutusScriptWitness(s)) = script_wit {
144 used_langs.insert(s.script.language());
145 }
146 }
147 used_langs
148 }
149
150 pub fn get_total_withdrawals(&self) -> Result<Value, JsError> {
151 let mut total = Coin::zero();
152 for (_, (coin, _)) in &self.withdrawals {
153 total = total.checked_add(coin)?;
154 }
155 Ok(Value::new(&total))
156 }
157
158 pub fn has_plutus_scripts(&self) -> bool {
159 for (_, (_, script_wit)) in &self.withdrawals {
160 if let Some(ScriptWitnessType::PlutusScriptWitness(_)) = script_wit {
161 return true;
162 }
163 }
164 false
165 }
166
167 pub(crate) fn get_script_ref_inputs_with_size(
171 &self,
172 ) -> impl Iterator<Item = (&TransactionInput, usize)> {
173 self.withdrawals.iter()
174 .filter_map(|(_, (_, script_wit))| script_wit.as_ref())
175 .filter_map(|script_wit| script_wit.get_script_ref_input_with_size())
176 }
177
178 pub fn build(&self) -> Withdrawals {
179 let map = self
180 .withdrawals
181 .iter()
182 .map(|(k, (v, _))| (k.clone(), v.clone()))
183 .collect();
184 Withdrawals(map)
185 }
186}