whisky_provider/maestro/utils/
utxo_utils.rs1use whisky_common::{
2 models::{Asset, UTxO, UtxoInput, UtxoOutput},
3 WError,
4};
5use whisky_csl::{
6 apply_double_cbor_encoding,
7 csl::{self, NativeScript, PlutusScript, ScriptRef},
8};
9
10use crate::maestro::models::{utxo::Utxo, ScriptVersion};
11
12#[derive(Debug, Clone)]
13pub enum ScriptType {
14 Plutus(PlutusScript),
15 Native(NativeScript),
16}
17
18pub fn to_utxo(utxo: &Utxo) -> Result<UTxO, WError> {
19 let utxo = UTxO {
20 input: UtxoInput {
21 output_index: utxo.index as u32,
22 tx_hash: utxo.tx_hash.clone(),
23 },
24 output: UtxoOutput {
25 address: utxo.address.clone(),
26 amount: utxo
27 .assets
28 .iter()
29 .map(|asset| Asset::new(asset.unit.clone(), asset.amount.to_string()))
30 .collect(),
31 data_hash: utxo.datum.as_ref().and_then(|datum| {
32 datum
33 .get("hash")
34 .and_then(|hash| hash.as_str().map(|s| s.to_string()))
35 }),
36 plutus_data: utxo.datum.as_ref().and_then(|datum| {
37 datum
38 .get("bytes")
39 .and_then(|hash| hash.as_str().map(|s| s.to_string()))
40 }),
41 script_ref: resolve_script(utxo).map_err(WError::from_err("to_utxo - script_ref"))?,
42 script_hash: utxo
43 .reference_script
44 .as_ref()
45 .map(|script| script.hash.clone()),
46 },
47 };
48 Ok(utxo)
49}
50
51pub fn resolve_script(utxo: &Utxo) -> Result<Option<String>, WError> {
52 if let Some(ref_script) = &utxo.reference_script {
53 match ref_script.r#type {
54 ScriptVersion::Native => {
55 let script: NativeScript =
56 NativeScript::from_json(&serde_json::json!(&ref_script.json).to_string())
57 .map_err(WError::from_err("json to string"))?;
58 let script_ref = to_script_ref(&ScriptType::Native(script));
59 let result = Some(hex::encode(script_ref.to_unwrapped_bytes()));
60 Ok(result)
61 }
62 ScriptVersion::Plutusv1 => {
63 let script_hex = &ref_script.bytes;
64 let normalized = normalize_plutus_script(script_hex)
65 .map_err(WError::from_err("normalize_plutus_script"))?;
66 let script: PlutusScript = PlutusScript::from_hex_with_version(
67 &normalized,
68 &csl::Language::new_plutus_v1(),
69 )
70 .map_err(WError::from_err("from_hex_with_version"))?;
71 let script_ref = to_script_ref(&ScriptType::Plutus(script));
72 let result = Some(hex::encode(script_ref.to_unwrapped_bytes()));
73 Ok(result)
74 }
75 ScriptVersion::Plutusv2 => {
76 let script_hex = &ref_script.bytes;
77 let normalized = normalize_plutus_script(script_hex)
78 .map_err(WError::from_err("normalize_plutus_script"))?;
79 let script: PlutusScript = PlutusScript::from_hex_with_version(
80 &normalized,
81 &csl::Language::new_plutus_v2(),
82 )
83 .map_err(WError::from_err("from_hex_with_version"))?;
84 let script_ref = to_script_ref(&ScriptType::Plutus(script));
85 let result = Some(hex::encode(script_ref.to_unwrapped_bytes()));
86 Ok(result)
87 }
88 ScriptVersion::Plutusv3 => {
89 let script_hex = &ref_script.bytes;
90 let normalized = normalize_plutus_script(script_hex)
91 .map_err(WError::from_err("normalize_plutus_script"))?;
92 let script: PlutusScript = PlutusScript::from_hex_with_version(
93 &normalized,
94 &csl::Language::new_plutus_v3(),
95 )
96 .map_err(WError::from_err("from_hex_with_version"))?;
97 let script_ref = to_script_ref(&ScriptType::Plutus(script));
98 let result = Some(hex::encode(script_ref.to_unwrapped_bytes()));
99 Ok(result)
100 }
101 }
102 } else {
103 Ok(None)
104 }
106}
107
108pub fn normalize_plutus_script(script_hex: &str) -> Result<String, WError> {
109 apply_double_cbor_encoding(script_hex)
110}
111
112pub fn to_script_ref(script: &ScriptType) -> ScriptRef {
113 match script {
114 ScriptType::Plutus(plutus) => ScriptRef::new_plutus_script(plutus),
115 ScriptType::Native(native) => ScriptRef::new_native_script(native),
116 }
117}