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// }