whisky_csl/tx_parser/
outputs.rs

1use cardano_serialization_lib::{self as csl};
2use whisky_common::*;
3
4use super::TxParser;
5
6impl TxParser {
7    pub fn outputs(&mut self) -> Result<Vec<Output>, WError> {
8        let mut parsed_outputs = vec![];
9        for i in 0..self.csl_tx_body.outputs().len() {
10            let tx_output = self.csl_tx_body.outputs().get(i);
11            parsed_outputs.push(
12                csl_output_to_whisky_output(tx_output)
13                    .map_err(WError::from_err("TxParser - outputs"))?,
14            )
15        }
16        self.tx_body.outputs = parsed_outputs.clone();
17        Ok(parsed_outputs)
18    }
19
20    pub fn get_tx_outs_utxo(&self) -> Result<Vec<UTxO>, WError> {
21        let tx_outs = self.tx_body.outputs.clone();
22        let mut result = vec![];
23        tx_outs.iter().enumerate().for_each(|(i, current_tx_out)| {
24            let (data_hash, plutus_data) = match current_tx_out.clone().datum {
25                Some(Datum::Hash(data)) => {
26                    let data_hash = Some(data);
27                    (data_hash, None)
28                }
29                Some(Datum::Inline(data)) => {
30                    let datum_cbor =
31                        csl::PlutusData::from_json(&data, csl::PlutusDatumSchema::DetailedSchema)
32                            .unwrap() // TODO: Handle unwrap
33                            .to_hex();
34                    let plutus_data = Some(datum_cbor);
35                    (None, plutus_data)
36                }
37                Some(Datum::Embedded(data)) => {
38                    let data_hash = Some(data);
39                    (data_hash, None)
40                }
41                None => (None, None),
42            };
43            let tx_out_utxo: UTxO = UTxO {
44                input: UtxoInput {
45                    output_index: i as u32,
46                    tx_hash: self.tx_hash.clone(),
47                },
48                output: UtxoOutput {
49                    address: current_tx_out.address.clone(),
50                    amount: current_tx_out.amount.clone(),
51                    data_hash,
52                    plutus_data,
53                    script_ref: None,
54                    script_hash: None,
55                },
56            };
57            result.push(tx_out_utxo);
58        });
59        Ok(result)
60    }
61
62    pub fn get_tx_outs_cbor(&self) -> Vec<String> {
63        let tx_outs = self.csl_tx_body.outputs();
64        let mut result = vec![];
65        for i in 0..tx_outs.len() {
66            let tx_out: csl::TransactionOutput = tx_outs.get(i);
67            let tx_out_cbor = tx_out.to_hex();
68            result.push(tx_out_cbor);
69        }
70        result
71    }
72}
73
74fn csl_output_to_whisky_output(output: csl::TransactionOutput) -> Result<Output, WError> {
75    let mut value: Vec<Asset> = vec![];
76    value.push(Asset::new_from_str(
77        "lovelace",
78        &output.amount().coin().to_str(),
79    ));
80    let multi_asset = output.amount().multiasset();
81
82    match multi_asset {
83        None => {}
84        Some(multi_asset) => {
85            for policy_id_index in 0..multi_asset.keys().len() {
86                let policy_id = multi_asset.keys().get(policy_id_index);
87                let assets = multi_asset.get(&policy_id).unwrap();
88                for asset_index in 0..assets.keys().len() {
89                    let asset_name = assets.keys().get(asset_index);
90                    let asset_quantity = assets.get(&asset_name).unwrap();
91                    let concated_name = policy_id.to_hex() + &asset_name.to_string();
92
93                    value.push(Asset::new_from_str(
94                        &concated_name,
95                        &asset_quantity.to_str(),
96                    ))
97                }
98            }
99        }
100    }
101
102    // TODO: Handle datum hash case
103    let datum: Option<Datum> = output.plutus_data().map(|csl_datum| {
104        Datum::Inline(
105            csl_datum
106                .to_json(csl::PlutusDatumSchema::DetailedSchema)
107                .unwrap(),
108        )
109    });
110
111    let reference_script: Option<OutputScriptSource> = match output.script_ref() {
112        Some(csl_script_ref) => {
113            let plutus_script = csl_script_ref.plutus_script().unwrap();
114            let language_version = match plutus_script.language_version().kind() {
115                csl::LanguageKind::PlutusV1 => LanguageVersion::V1,
116                csl::LanguageKind::PlutusV2 => LanguageVersion::V2,
117                csl::LanguageKind::PlutusV3 => LanguageVersion::V3,
118            };
119            Some(OutputScriptSource::ProvidedScriptSource(
120                ProvidedScriptSource {
121                    script_cbor: plutus_script.to_hex(),
122                    language_version,
123                },
124            ))
125        }
126        None => None,
127    };
128    Ok(Output {
129        address: output.address().to_bech32(None).unwrap(),
130        amount: value,
131        datum,
132        reference_script,
133    })
134}