whisky/builder/
complete.rs

1use crate::*;
2use uplc::tx::SlotConfig;
3
4use super::{TxBuilder, TxEvaluation};
5
6impl TxBuilder {
7    /// ## Transaction building method
8    ///  
9    /// Complete the transaction building process with fetching missing information & tx evaluation
10    ///
11    /// ### Arguments
12    ///
13    /// * `customized_tx` - An optional customized transaction body
14    ///
15    /// ### Returns
16    ///
17    /// * `Self` - The TxBuilder instance
18    pub async fn complete(
19        &mut self,
20        customized_tx: Option<TxBuilderBody>,
21    ) -> Result<&mut Self, WError> {
22        self.complete_sync(customized_tx)?;
23        match &self.evaluator {
24            Some(evaluator) => {
25                let network = match &self.tx_builder_body.network {
26                    Some(builder_network) => builder_network,
27                    None => &Network::Mainnet,
28                };
29                let inputs_for_evaluation: Vec<_> =
30                    self.inputs_for_evaluation.values().cloned().collect();
31                let tx_evaluation_result = evaluator
32                    .evaluate_tx(
33                        &self.serializer.tx_hex,
34                        &inputs_for_evaluation,
35                        &self.chained_txs.clone(),
36                        network,
37                        &SlotConfig::default(), // TODO: accept slot config as argument for evaluator
38                    )
39                    .await;
40                match tx_evaluation_result {
41                    Ok(actions) => self.update_redeemer(actions),
42                    Err(err) => {
43                        return Err(WError::new(
44                            "TxBuilder - complete",
45                            &format!(
46                        "Error evaluating transaction - tx_hex: [ {} ] , Error message: [ {:?} ]",
47                        self.tx_hex(),
48                        err
49                    ),
50                        ))
51                    }
52                }
53            }
54            None => self,
55        };
56        self.complete_sync(None)
57    }
58
59    /// ## Transaction building method
60    ///
61    /// Complete the transaction building process synchronously
62    ///
63    /// ### Arguments
64    ///
65    /// * `customized_tx` - An optional customized transaction body
66    ///
67    /// ### Returns
68    ///
69    /// * `Self` - The TxBuilder instance
70    pub fn complete_sync(
71        &mut self,
72        customized_tx: Option<TxBuilderBody>,
73    ) -> Result<&mut Self, WError> {
74        if customized_tx.is_some() {
75            self.tx_builder_body = customized_tx.unwrap();
76        } else {
77            self.queue_all_last_item();
78            if !self.extra_inputs.is_empty() {
79                self.add_utxos_from(self.extra_inputs.clone(), self.selection_threshold)?;
80            }
81        }
82
83        self.tx_builder_body.mints.sort_by(|a, b| {
84            let a_mint = match a {
85                MintItem::ScriptMint(a_script_mint) => &a_script_mint.mint,
86                MintItem::SimpleScriptMint(a_simple_script_mint) => &a_simple_script_mint.mint,
87            };
88            let b_mint = match b {
89                MintItem::ScriptMint(b_script_mint) => &b_script_mint.mint,
90                MintItem::SimpleScriptMint(b_simple_script_mint) => &b_simple_script_mint.mint,
91            };
92            a_mint.policy_id.cmp(&b_mint.policy_id)
93        });
94
95        self.tx_builder_body.inputs.sort_by(|a, b| {
96            let tx_in_data_a: &TxInParameter = match a {
97                TxIn::PubKeyTxIn(pub_key_tx_in) => &pub_key_tx_in.tx_in,
98                TxIn::SimpleScriptTxIn(simple_script_tx_in) => &simple_script_tx_in.tx_in,
99                TxIn::ScriptTxIn(script_tx_in) => &script_tx_in.tx_in,
100            };
101
102            let tx_in_data_b: &TxInParameter = match b {
103                TxIn::PubKeyTxIn(pub_key_tx_in) => &pub_key_tx_in.tx_in,
104                TxIn::SimpleScriptTxIn(simple_script_tx_in) => &simple_script_tx_in.tx_in,
105                TxIn::ScriptTxIn(script_tx_in) => &script_tx_in.tx_in,
106            };
107
108            tx_in_data_a
109                .tx_hash
110                .cmp(&tx_in_data_b.tx_hash)
111                .then_with(|| tx_in_data_a.tx_index.cmp(&tx_in_data_b.tx_index))
112        });
113
114        let tx_hex = self
115            .serializer
116            .set_protocol_params(self.protocol_params.clone().unwrap_or_default())
117            .set_tx_builder_body(self.tx_builder_body.clone())
118            .serialize_tx_body()?;
119        self.serializer.reset_builder();
120        self.serializer.tx_hex = tx_hex;
121        Ok(self)
122    }
123
124    /// ## Transaction building method
125    ///
126    /// Complete the signing process
127    ///
128    /// ### Returns
129    ///
130    /// * `String` - The signed transaction in hex
131    pub fn complete_signing(&mut self) -> Result<String, WError> {
132        self.serializer.complete_signing()
133    }
134
135    /// ## Transaction building method
136    ///
137    /// Obtain the transaction hex
138    ///
139    /// ### Returns
140    ///
141    /// * tx_hex - The current transaction hex from build
142    pub fn tx_hex(&mut self) -> String {
143        self.serializer.tx_hex()
144    }
145}