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