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