whisky/builder/
tx_in.rs

1use super::{TxBuilder, WData, WRedeemer};
2
3use crate::*;
4
5impl TxBuilder {
6    /// ## Transaction building method
7    ///
8    /// Indicate that the transaction is spending a Plutus script in the TxBuilder instance
9    ///
10    /// ### Arguments
11    ///
12    /// * `language_version` - The language version of the script
13    ///
14    /// ### Returns
15    ///
16    /// * `Self` - The TxBuilder instance
17    pub fn spending_plutus_script(&mut self, language_version: &LanguageVersion) -> &mut Self {
18        match language_version {
19            LanguageVersion::V1 => self.spending_plutus_script_v1(),
20            LanguageVersion::V2 => self.spending_plutus_script_v2(),
21            LanguageVersion::V3 => self.spending_plutus_script_v3(),
22        }
23    }
24
25    /// ## Transaction building method
26    ///
27    /// Indicate that the transaction is spending a Plutus script v1 in the TxBuilder instance
28    ///
29    /// ### Returns
30    ///
31    /// * `Self` - The TxBuilder instance
32    pub fn spending_plutus_script_v1(&mut self) -> &mut Self {
33        self.adding_script_input = Some(LanguageVersion::V1);
34        self
35    }
36    /// ## Transaction building method
37    ///
38    /// Indicate that the transaction is spending a Plutus script v2 in the TxBuilder instance
39    ///
40    /// ### Returns
41    ///
42    /// * `Self` - The TxBuilder instance
43    pub fn spending_plutus_script_v2(&mut self) -> &mut Self {
44        self.adding_script_input = Some(LanguageVersion::V2);
45        self
46    }
47    /// ## Transaction building method
48    ///
49    /// Indicate that the transaction is spending a Plutus script v3 in the TxBuilder instance
50    ///
51    /// ### Returns
52    ///
53    /// * `Self` - The TxBuilder instance
54    pub fn spending_plutus_script_v3(&mut self) -> &mut Self {
55        self.adding_script_input = Some(LanguageVersion::V3);
56        self
57    }
58
59    /// ## Transaction building method
60    ///
61    /// Add a transaction input to the TxBuilder instance
62    ///
63    /// ### Arguments
64    ///
65    /// * `tx_hash` - The transaction hash
66    /// * `tx_index` - The transaction index
67    /// * `amount` - The amount of assets
68    /// * `address` - The address
69    ///
70    /// ### Returns
71    ///
72    /// * `Self` - The TxBuilder instance
73    pub fn tx_in(
74        &mut self,
75        tx_hash: &str,
76        tx_index: u32,
77        amount: &[Asset],
78        address: &str,
79    ) -> &mut Self {
80        if self.tx_in_item.is_some() {
81            self.queue_input();
82        }
83        match self.adding_script_input {
84            Some(_) => {
85                let item = TxIn::ScriptTxIn(ScriptTxIn {
86                    tx_in: TxInParameter {
87                        tx_hash: tx_hash.to_string(),
88                        tx_index,
89                        amount: Some(amount.to_vec()),
90                        address: Some(address.to_string()),
91                    },
92                    script_tx_in: ScriptTxInParameter {
93                        script_source: None,
94                        datum_source: None,
95                        redeemer: None,
96                    },
97                });
98                self.tx_in_item = Some(item);
99            }
100            None => {
101                let item = TxIn::PubKeyTxIn(PubKeyTxIn {
102                    tx_in: TxInParameter {
103                        tx_hash: tx_hash.to_string(),
104                        tx_index,
105                        amount: Some(amount.to_vec()),
106                        address: Some(address.to_string()),
107                    },
108                });
109                self.tx_in_item = Some(item);
110            }
111        }
112        self
113    }
114
115    /// ## Transaction building method
116    ///
117    /// Add a transaction input script to the TxBuilder instance
118    ///
119    /// ### Arguments
120    ///
121    /// * `script_cbor` - The script in CBOR format
122    /// * `version` - The language version, leave as None for Native scripts
123    ///
124    /// ### Returns
125    ///
126    /// * `Self` - The TxBuilder instance
127    pub fn tx_in_script(&mut self, script_cbor: &str) -> &mut Self {
128        let tx_in_item = self.tx_in_item.take();
129        if tx_in_item.is_none() {
130            panic!("Undefined input")
131        }
132        let tx_in_item = tx_in_item.unwrap();
133        match tx_in_item {
134            TxIn::PubKeyTxIn(input) => {
135                self.tx_in_item = Some(TxIn::SimpleScriptTxIn(SimpleScriptTxIn {
136                    tx_in: input.tx_in,
137                    simple_script_tx_in: SimpleScriptTxInParameter::ProvidedSimpleScriptSource(
138                        ProvidedSimpleScriptSource {
139                            script_cbor: script_cbor.to_string(),
140                        },
141                    ),
142                }))
143            }
144            TxIn::ScriptTxIn(mut input) => {
145                input.script_tx_in.script_source =
146                    Some(ScriptSource::ProvidedScriptSource(ProvidedScriptSource {
147                        script_cbor: script_cbor.to_string(),
148                        language_version: self
149                            .adding_script_input
150                            .clone()
151                            .expect("Plutus script must have version specified"),
152                    }));
153                self.adding_script_input = None;
154                self.tx_in_item = Some(TxIn::ScriptTxIn(input));
155            }
156
157            // Technically this should be unreachable, but it's here for completeness
158            TxIn::SimpleScriptTxIn(mut input) => {
159                input.simple_script_tx_in = SimpleScriptTxInParameter::ProvidedSimpleScriptSource(
160                    ProvidedSimpleScriptSource {
161                        script_cbor: script_cbor.to_string(),
162                    },
163                );
164                self.tx_in_item = Some(TxIn::SimpleScriptTxIn(input));
165            }
166        }
167        self
168    }
169
170    /// ## Transaction building method
171    ///
172    /// Set the transaction input datum value in the TxBuilder instance
173    ///
174    /// ### Arguments
175    ///
176    /// * `data` - The datum value
177    ///
178    /// ### Returns
179    ///
180    /// * `Self` - The TxBuilder instance
181    pub fn tx_in_datum_value(&mut self, data: &WData) -> &mut Self {
182        let tx_in_item = self.tx_in_item.take();
183        if tx_in_item.is_none() {
184            panic!("Undefined input")
185        }
186        let tx_in_item = tx_in_item.unwrap();
187        match tx_in_item {
188            TxIn::PubKeyTxIn(_) => panic!("Datum cannot be defined for a pubkey tx in"),
189            TxIn::SimpleScriptTxIn(_) => {
190                panic!("Datum cannot be defined for a simple script tx in")
191            }
192            TxIn::ScriptTxIn(mut input) => match data.to_cbor() {
193                Ok(raw_data) => {
194                    input.script_tx_in.datum_source =
195                        Some(DatumSource::ProvidedDatumSource(ProvidedDatumSource {
196                            data: raw_data.to_string(),
197                        }));
198                    self.tx_in_item = Some(TxIn::ScriptTxIn(input));
199                }
200                Err(_) => {
201                    panic!("Error converting datum to CBOR");
202                }
203            },
204        }
205        self
206    }
207
208    /// ## Transaction building method
209    ///
210    /// Indicate that the transaction input has an inline datum in the TxBuilder instance
211    ///
212    /// ### Returns
213    ///
214    /// * `Self` - The TxBuilder instance
215    pub fn tx_in_inline_datum_present(&mut self) -> &mut Self {
216        let tx_in_item = self.tx_in_item.take();
217        if tx_in_item.is_none() {
218            panic!("Undefined input")
219        }
220        let tx_in_item = tx_in_item.unwrap();
221        match tx_in_item {
222            TxIn::PubKeyTxIn(_) => panic!("Datum cannot be defined for a pubkey tx in"),
223            TxIn::SimpleScriptTxIn(_) => {
224                panic!("Datum cannot be defined for a simple script tx in")
225            }
226            TxIn::ScriptTxIn(mut input) => {
227                input.script_tx_in.datum_source =
228                    Some(DatumSource::InlineDatumSource(InlineDatumSource {
229                        tx_hash: input.tx_in.tx_hash.clone(),
230                        tx_index: input.tx_in.tx_index,
231                    }));
232                self.tx_in_item = Some(TxIn::ScriptTxIn(input));
233            }
234        }
235        self
236    }
237
238    /// ## Transaction building method
239    ///
240    /// Set the transaction input redeemer value in the TxBuilder instance
241    ///
242    /// ### Arguments
243    ///
244    /// * `redeemer` - The redeemer value
245    ///
246    /// ### Returns
247    ///
248    /// * `Self` - The TxBuilder instance
249    pub fn tx_in_redeemer_value(&mut self, redeemer: &WRedeemer) -> &mut Self {
250        let tx_in_item = self.tx_in_item.take();
251        if tx_in_item.is_none() {
252            panic!("Undefined input")
253        }
254        let tx_in_item = tx_in_item.unwrap();
255        match tx_in_item {
256            TxIn::PubKeyTxIn(_) => panic!("Redeemer cannot be defined for a pubkey tx in"),
257            TxIn::SimpleScriptTxIn(_) => {
258                panic!("Redeemer cannot be defined for a simple script tx in")
259            }
260            TxIn::ScriptTxIn(mut input) => match redeemer.data.to_cbor() {
261                Ok(raw_redeemer) => {
262                    input.script_tx_in.redeemer = Some(Redeemer {
263                        data: raw_redeemer,
264                        ex_units: redeemer.clone().ex_units,
265                    });
266                    self.tx_in_item = Some(TxIn::ScriptTxIn(input));
267                }
268                Err(_) => {
269                    panic!("Error converting redeemer to CBOR");
270                }
271            },
272        }
273        self
274    }
275
276    /// ## Transaction building method
277    ///
278    /// Add a spending transaction input reference to the TxBuilder instance
279    ///
280    /// ### Arguments
281    ///
282    /// * `tx_hash` - The transaction hash
283    /// * `tx_index` - The transaction index
284    /// * `script_hash` - The spending script hash
285    /// * `script_size` - Size of the script
286    ///
287    /// ### Returns
288    ///
289    /// * `Self` - The TxBuilder instance
290    pub fn spending_tx_in_reference(
291        &mut self,
292        tx_hash: &str,
293        tx_index: u32,
294        script_hash: &str,
295        script_size: usize,
296    ) -> &mut Self {
297        let tx_in_item = self.tx_in_item.take();
298        if tx_in_item.is_none() {
299            panic!("Undefined output")
300        }
301        let tx_in_item = tx_in_item.unwrap();
302        match tx_in_item {
303            TxIn::PubKeyTxIn(_) => panic!("Script reference cannot be defined for a pubkey tx in"),
304            TxIn::SimpleScriptTxIn(_) => {
305                panic!("Script reference cannot be defined for a simple script tx in")
306            }
307            TxIn::ScriptTxIn(mut input) => {
308                input.script_tx_in.script_source =
309                    Some(ScriptSource::InlineScriptSource(InlineScriptSource {
310                        ref_tx_in: RefTxIn {
311                            tx_hash: tx_hash.to_string(),
312                            tx_index,
313                            // Script size is already accounted for in script source
314                            script_size: None,
315                        },
316                        script_hash: script_hash.to_string(),
317                        language_version: self
318                            .adding_script_input
319                            .clone()
320                            .expect("Plutus script must have version specified"),
321                        script_size,
322                    }));
323                self.tx_in_item = Some(TxIn::ScriptTxIn(input));
324            }
325        }
326        self
327    }
328
329    /// ## Transaction building method
330    ///
331    /// Indicate that the spending reference transaction input has an inline datum in the TxBuilder instance
332    ///
333    /// ### Returns
334    ///
335    /// * `Self` - The TxBuilder instance
336    pub fn spending_reference_tx_in_inline_datum_present(&mut self) -> &mut Self {
337        self.tx_in_inline_datum_present()
338    }
339
340    /// ## Transaction building method
341    ///
342    /// Set the spending reference transaction input redeemer value in the TxBuilder instance
343    ///
344    /// ### Arguments
345    ///
346    /// * `redeemer` - The redeemer value
347    ///
348    /// ### Returns
349    ///
350    /// * `Self` - The TxBuilder instance
351    pub fn spending_reference_tx_in_redeemer_value(&mut self, redeemer: &WRedeemer) -> &mut Self {
352        self.tx_in_redeemer_value(redeemer)
353    }
354
355    /// ## Transaction building method
356    ///
357    /// Add a read-only transaction input reference to the TxBuilder instance
358    ///
359    /// ### Arguments
360    ///
361    /// * `tx_hash` - The transaction hash
362    /// * `tx_index` - The transaction index
363    /// * `script_size` - The size of the script contained at the reference input (None if it doesn't contain a script)
364    ///
365    /// ### Returns
366    ///
367    /// * `Self` - The TxBuilder instance
368    pub fn read_only_tx_in_reference(
369        &mut self,
370        tx_hash: &str,
371        tx_index: u32,
372        script_size: Option<usize>,
373    ) -> &mut Self {
374        self.tx_builder_body.reference_inputs.push(RefTxIn {
375            tx_hash: tx_hash.to_string(),
376            tx_index,
377            script_size,
378        });
379        self
380    }
381
382    /// ## Transaction building method
383    ///
384    /// Add a transaction input collateral to the TxBuilder instance
385    ///
386    /// ### Arguments
387    ///
388    /// * `tx_hash` - The transaction hash
389    /// * `tx_index` - The transaction index
390    /// * `amount` - The amount of assets
391    /// * `address` - The address
392    ///
393    /// ### Returns
394    ///
395    /// * `Self` - The TxBuilder instance
396    pub fn tx_in_collateral(
397        &mut self,
398        tx_hash: &str,
399        tx_index: u32,
400        amount: &[Asset],
401        address: &str,
402    ) -> &mut Self {
403        let collateral_item = self.collateral_item.take();
404        if let Some(collateral_item) = collateral_item {
405            self.tx_builder_body.collaterals.push(collateral_item);
406        }
407        self.collateral_item = Some(PubKeyTxIn {
408            tx_in: TxInParameter {
409                tx_hash: tx_hash.to_string(),
410                tx_index,
411                amount: Some(amount.to_vec()),
412                address: Some(address.to_string()),
413            },
414        });
415        self
416    }
417}