whisky_csl/tx_builder/whisky_csl.rs
1use super::CoreCSL;
2use whisky_common::*;
3
4#[derive(Clone, Debug)]
5pub struct WhiskyCSL {
6 pub core: CoreCSL,
7 pub tx_builder_body: TxBuilderBody,
8 pub tx_evaluation_multiplier_percentage: u64,
9 pub tx_hex: String,
10}
11
12impl WhiskyCSL {
13 /// ## Transaction building method
14 ///
15 /// Create a new TxBuilder instance
16 ///
17 /// ### Returns
18 ///
19 /// * `Self` - A new TxBuilder instance
20 ///
21 pub fn new(params: Option<Protocol>) -> Result<Self, WError> {
22 let whisky = WhiskyCSL {
23 core: CoreCSL::new(params)?,
24 tx_builder_body: TxBuilderBody::new(),
25 tx_evaluation_multiplier_percentage: 110,
26 tx_hex: String::new(),
27 };
28
29 Ok(whisky)
30 }
31
32 /// ## Internal method
33 ///
34 /// Add multiple signing keys to the TxBuilder instance
35 ///
36 /// ### Arguments
37 ///
38 /// * `signing_keys` - A vector of signing keys in hexadecimal
39 pub fn add_all_signing_keys(&mut self, signing_keys: &[&str]) -> Result<(), WError> {
40 if !signing_keys.is_empty() {
41 self.core.add_signing_keys(signing_keys)?;
42 }
43 Ok(())
44 }
45
46 /// ## Internal method
47 ///
48 /// Add multiple inputs to the TxBuilder instance
49 ///
50 pub fn add_all_inputs(&mut self) -> Result<&mut Self, WError> {
51 let inputs = self.tx_builder_body.inputs.clone();
52 for input in inputs {
53 match input {
54 TxIn::PubKeyTxIn(pub_key_tx_in) => self.core.add_tx_in(pub_key_tx_in)?,
55 TxIn::SimpleScriptTxIn(simple_script_tx_in) => {
56 self.core.add_simple_script_tx_in(simple_script_tx_in)?
57 }
58 TxIn::ScriptTxIn(script_tx_in) => self.core.add_script_tx_in(script_tx_in)?,
59 };
60 }
61 self.core
62 .tx_builder
63 .set_inputs(&self.core.tx_inputs_builder);
64 Ok(self)
65 }
66
67 /// ## Internal method
68 ///
69 /// Add multiple outputs to the TxBuilder instance
70 pub fn add_all_outputs(&mut self) -> Result<&mut Self, WError> {
71 let outputs = self.tx_builder_body.outputs.clone();
72 for output in outputs {
73 self.core.add_output(output)?;
74 }
75 Ok(self)
76 }
77
78 /// ## Internal method
79 ///
80 /// Add multiple collaterals to the TxBuilder instance
81 pub fn add_all_collaterals(&mut self) -> Result<&mut Self, WError> {
82 let collaterals = self.tx_builder_body.collaterals.clone();
83 for collateral in collaterals {
84 self.core.add_collateral(collateral)?
85 }
86 self.core
87 .tx_builder
88 .set_collateral(&self.core.collateral_builder);
89 Ok(self)
90 }
91
92 /// ## Internal method
93 ///
94 /// Add multiple reference inputs to the TxBuilder instance
95 pub fn add_all_reference_inputs(&mut self) -> Result<&mut Self, WError> {
96 let ref_inputs = self.tx_builder_body.reference_inputs.clone();
97 for ref_input in ref_inputs {
98 self.core.add_reference_input(ref_input)?;
99 }
100 Ok(self)
101 }
102
103 /// ## Internal method
104 ///
105 /// Add multiple withdrawals to the TxBuilder instance
106 pub fn add_all_withdrawals(&mut self) -> Result<&mut Self, WError> {
107 let withdrawals = self.tx_builder_body.withdrawals.clone();
108 for withdrawal in withdrawals {
109 match withdrawal {
110 Withdrawal::PubKeyWithdrawal(pub_key_withdrawal) => {
111 self.core.add_pub_key_withdrawal(pub_key_withdrawal)?
112 }
113 Withdrawal::PlutusScriptWithdrawal(plutus_script_withdrawal) => {
114 self.core.add_plutus_withdrawal(plutus_script_withdrawal)?
115 }
116 Withdrawal::SimpleScriptWithdrawal(simple_script_withdrawal) => self
117 .core
118 .add_simple_script_withdrawal(simple_script_withdrawal)?,
119 }
120 }
121 self.core
122 .tx_builder
123 .set_withdrawals_builder(&self.core.tx_withdrawals_builder);
124 Ok(self)
125 }
126
127 /// ## Internal method
128 ///
129 /// Add multiple mints to the TxBuilder instance
130 pub fn add_all_mints(&mut self) -> Result<&mut Self, WError> {
131 let mints = self.tx_builder_body.mints.clone();
132 for (index, mint) in mints.into_iter().enumerate() {
133 match mint {
134 MintItem::ScriptMint(script_mint) => {
135 self.core.add_plutus_mint(script_mint, index as u64)?
136 }
137 MintItem::SimpleScriptMint(simple_script_mint) => {
138 self.core.add_native_mint(simple_script_mint)?
139 }
140 };
141 }
142 self.core
143 .tx_builder
144 .set_mint_builder(&self.core.mint_builder);
145 Ok(self)
146 }
147
148 /// ## Internal method
149 ///
150 /// Add multiple certificates to the TxBuilder instance
151 pub fn add_all_certificates(&mut self) -> Result<&mut Self, WError> {
152 let certificates = self.tx_builder_body.certificates.clone();
153 for (index, cert) in certificates.into_iter().enumerate() {
154 self.core.add_cert(cert, index as u64)?
155 }
156 self.core
157 .tx_builder
158 .set_certs_builder(&self.core.certificates_builder);
159 Ok(self)
160 }
161
162 /// ## Internal method
163 ///
164 /// Add multiple votes to the TxBuilder instance
165 pub fn add_all_votes(&mut self) -> Result<&mut Self, WError> {
166 let votes = self.tx_builder_body.votes.clone();
167 for (index, vote) in votes.into_iter().enumerate() {
168 self.core.add_vote(vote, index as u64)?
169 }
170 self.core
171 .tx_builder
172 .set_voting_builder(&self.core.vote_builder);
173 Ok(self)
174 }
175
176 /// ## Internal method
177 ///
178 /// Add a validity range to the TxBuilder instance
179 pub fn add_validity_range(&mut self) -> Result<&mut Self, WError> {
180 let validity_range = self.tx_builder_body.validity_range.clone();
181 if validity_range.invalid_before.is_some() {
182 self.core
183 .add_invalid_before(validity_range.invalid_before.unwrap())?;
184 };
185 if validity_range.invalid_hereafter.is_some() {
186 self.core
187 .add_invalid_hereafter(validity_range.invalid_hereafter.unwrap())?;
188 };
189 Ok(self)
190 }
191
192 /// ## Internal method
193 ///
194 /// Add multiple required signatures to the TxBuilder instance
195 pub fn add_all_required_signature(&mut self) -> Result<&mut Self, WError> {
196 let required_signatures = self
197 .tx_builder_body
198 .required_signatures
199 .iter()
200 .map(|s| s.as_str())
201 .collect::<Vec<&str>>();
202 for pub_key_hash in required_signatures {
203 self.core
204 .add_required_signature(pub_key_hash)
205 .map_err(WError::from_err("add_all_required_signature"))?;
206 }
207 Ok(self)
208 }
209
210 /// ## Internal method
211 ///
212 /// Add multiple metadata to the TxBuilder instance
213 pub fn add_all_metadata(&mut self) -> Result<&mut Self, WError> {
214 let all_metadata = self.tx_builder_body.metadata.clone();
215 for metadata in all_metadata {
216 self.core
217 .add_metadata(metadata)
218 .map_err(WError::from_err("add_all_metadata"))?;
219 }
220 Ok(self)
221 }
222
223 /// ## Internal method
224 ///
225 /// Add a script hash to the TxBuilder instance
226 pub fn add_script_hash(&mut self) -> Result<&mut Self, WError> {
227 match self.tx_builder_body.network.clone() {
228 Some(current_network) => self.core.add_script_hash(current_network)?,
229 None => self.core.add_script_hash(Network::Mainnet)?,
230 };
231 Ok(self)
232 }
233
234 /// ## Internal method
235 ///
236 /// Set the fee if needed
237 pub fn set_fee_if_needed(&mut self) -> Result<&mut Self, WError> {
238 if self.tx_builder_body.fee.is_some() {
239 self.set_fee(self.tx_builder_body.fee.clone().unwrap());
240 }
241 Ok(self)
242 }
243
244 pub fn add_change_utxo(&mut self) -> Result<&mut Self, WError> {
245 self.core.add_change(
246 self.tx_builder_body.change_address.clone(),
247 self.tx_builder_body.change_datum.clone(),
248 )?;
249 Ok(self)
250 }
251
252 // fn add_collateral_return(&mut self, change_address: String) {
253 // let current_fee = self
254 // .tx_builder
255 // .get_fee_if_set()
256 // .unwrap()
257 // .to_string()
258 // .parse::<u64>()
259 // .unwrap();
260
261 // let collateral_amount = 150 * ((current_fee / 100) + 1);
262 // let _ = self
263 // .tx_builder
264 // .set_total_collateral_and_return(
265 // &to_bignum(collateral_amount),
266 // &csl::address::Address::from_bech32(&change_address).unwrap(),
267 // )
268 // .unwrap();
269 // }
270
271 pub fn set_fee(&mut self, fee: String) {
272 self.core.set_fee(fee);
273 }
274}
275
276// if self.tx_builder_body.change_address != "" {
277// let collateral_inputs = self.tx_builder_body.collaterals.clone();
278// let collateral_vec: Vec<u64> = collateral_inputs
279// .into_iter()
280// .map(|pub_key_tx_in| {
281// let assets = pub_key_tx_in.tx_in.amount.unwrap();
282// let lovelace = assets
283// .into_iter()
284// .find(|asset| asset.unit == "lovelace")
285// .unwrap();
286// lovelace.quantity.parse::<u64>().unwrap()
287// })
288// .collect();
289// let total_collateral: u64 = collateral_vec.into_iter().sum();
290
291// let collateral_estimate: u64 = (150
292// * self
293// .tx_builder
294// .min_fee()
295// .unwrap()
296// .checked_add(&to_bignum(10000))
297// .unwrap()
298// .to_string()
299// .parse::<u64>()
300// .unwrap())
301// / 100;
302
303// let mut collateral_return_needed = false;
304// if (total_collateral - collateral_estimate) > 0 {
305// let collateral_estimate_output = csl::TransactionOutput::new(
306// &csl::address::Address::from_bech32(&self.tx_builder_body.change_address)
307// .unwrap(),
308// &csl::utils::Value::new(&to_bignum(collateral_estimate)),
309// );
310
311// let min_ada = csl::utils::min_ada_for_output(
312// &collateral_estimate_output,
313// &csl::DataCost::new_coins_per_byte(&to_bignum(4310)),
314// )
315// .unwrap()
316// .to_string()
317// .parse::<u64>()
318// .unwrap();
319
320// if total_collateral - collateral_estimate > min_ada {
321// self.tx_builder
322// .set_collateral_return(&csl::TransactionOutput::new(
323// &csl::address::Address::from_bech32(
324// &self.tx_builder_body.change_address,
325// )
326// .unwrap(),
327// &csl::utils::Value::new(&to_bignum(total_collateral)),
328// ));
329
330// self.tx_builder
331// .set_total_collateral(&to_bignum(total_collateral));
332
333// collateral_return_needed = true;
334// }
335// }
336// self.add_change(self.tx_builder_body.change_address.clone());
337// if collateral_return_needed {
338// self.add_collateral_return(self.tx_builder_body.change_address.clone());
339// }
340// }