whisky_csl/tx_builder/
mod.rs

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