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    // fn add_collateral_return(&mut self, change_address: String) {
250    //     let current_fee = self
251    //         .tx_builder
252    //         .get_fee_if_set()
253    //         .unwrap()
254    //         .to_string()
255    //         .parse::<u64>()
256    //         .unwrap();
257
258    //     let collateral_amount = 150 * ((current_fee / 100) + 1);
259    //     let _ = self
260    //         .tx_builder
261    //         .set_total_collateral_and_return(
262    //             &to_bignum(collateral_amount),
263    //             &csl::address::Address::from_bech32(&change_address).unwrap(),
264    //         )
265    //         .unwrap();
266    // }
267
268    pub fn set_fee(&mut self, fee: String) {
269        self.core.set_fee(fee);
270    }
271}
272
273// if self.tx_builder_body.change_address != "" {
274//     let collateral_inputs = self.tx_builder_body.collaterals.clone();
275//     let collateral_vec: Vec<u64> = collateral_inputs
276//         .into_iter()
277//         .map(|pub_key_tx_in| {
278//             let assets = pub_key_tx_in.tx_in.amount.unwrap();
279//             let lovelace = assets
280//                 .into_iter()
281//                 .find(|asset| asset.unit == "lovelace")
282//                 .unwrap();
283//             lovelace.quantity.parse::<u64>().unwrap()
284//         })
285//         .collect();
286//     let total_collateral: u64 = collateral_vec.into_iter().sum();
287
288//     let collateral_estimate: u64 = (150
289//         * self
290//             .tx_builder
291//             .min_fee()
292//             .unwrap()
293//             .checked_add(&to_bignum(10000))
294//             .unwrap()
295//             .to_string()
296//             .parse::<u64>()
297//             .unwrap())
298//         / 100;
299
300//     let mut collateral_return_needed = false;
301// if (total_collateral - collateral_estimate) > 0 {
302// let collateral_estimate_output = csl::TransactionOutput::new(
303//     &csl::address::Address::from_bech32(&self.tx_builder_body.change_address)
304//         .unwrap(),
305//     &csl::utils::Value::new(&to_bignum(collateral_estimate)),
306// );
307
308// let min_ada = csl::utils::min_ada_for_output(
309//     &collateral_estimate_output,
310//     &csl::DataCost::new_coins_per_byte(&to_bignum(4310)),
311// )
312// .unwrap()
313// .to_string()
314// .parse::<u64>()
315// .unwrap();
316
317// if total_collateral - collateral_estimate > min_ada {
318//     self.tx_builder
319//         .set_collateral_return(&csl::TransactionOutput::new(
320//             &csl::address::Address::from_bech32(
321//                 &self.tx_builder_body.change_address,
322//             )
323//             .unwrap(),
324//             &csl::utils::Value::new(&to_bignum(total_collateral)),
325//         ));
326
327//     self.tx_builder
328//         .set_total_collateral(&to_bignum(total_collateral));
329
330//     collateral_return_needed = true;
331// }
332// }
333// self.add_change(self.tx_builder_body.change_address.clone());
334// if collateral_return_needed {
335//     self.add_collateral_return(self.tx_builder_body.change_address.clone());
336// }
337// }