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 Ok(Some(
60 script_ref
61 .native_script()
62 .ok_or_else(WError::from_opt("resolve_script", "script_ref"))?
63 .to_hex(),
64 ))
65 }
66 ScriptVersion::Plutusv1 => {
67 let script_hex = &ref_script.bytes;
68 let normalized = normalize_plutus_script(script_hex)
69 .map_err(WError::from_err("normalize_plutus_script"))?;
70 let script: PlutusScript = PlutusScript::from_hex_with_version(
71 &normalized,
72 &csl::Language::new_plutus_v1(),
73 )
74 .map_err(WError::from_err("from_hex_with_version"))?;
75 let script_ref = to_script_ref(&ScriptType::Plutus(script));
76 Ok(Some(
77 script_ref
78 .plutus_script()
79 .ok_or_else(WError::from_opt("resolve_script", "script_ref"))?
80 .to_hex(),
81 ))
82 }
83 ScriptVersion::Plutusv2 => {
84 let script_hex = &ref_script.bytes;
85 let normalized = normalize_plutus_script(script_hex)
86 .map_err(WError::from_err("normalize_plutus_script"))?;
87 let script: PlutusScript = PlutusScript::from_hex_with_version(
88 &normalized,
89 &csl::Language::new_plutus_v2(),
90 )
91 .map_err(WError::from_err("from_hex_with_version"))?;
92 let script_ref = to_script_ref(&ScriptType::Plutus(script));
93 Ok(Some(
94 script_ref
95 .plutus_script()
96 .ok_or_else(WError::from_opt("resolve_script", "script_ref"))?
97 .to_hex(),
98 ))
99 }
100 ScriptVersion::Plutusv3 => {
101 let script_hex = &ref_script.bytes;
102 let normalized = normalize_plutus_script(script_hex)
103 .map_err(WError::from_err("normalize_plutus_script"))?;
104 let script: PlutusScript = PlutusScript::from_hex_with_version(
105 &normalized,
106 &csl::Language::new_plutus_v3(),
107 )
108 .map_err(WError::from_err("from_hex_with_version"))?;
109 let script_ref = to_script_ref(&ScriptType::Plutus(script));
110 Ok(Some(
111 script_ref
112 .plutus_script()
113 .ok_or_else(WError::from_opt("resolve_script", "script_ref"))?
114 .to_hex(),
115 ))
116 }
117 }
118 } else {
119 Ok(None)
120 }
122}
123
124pub fn normalize_plutus_script(script_hex: &str) -> Result<String, WError> {
125 apply_double_cbor_encoding(script_hex)
126}
127
128pub fn to_script_ref(script: &ScriptType) -> ScriptRef {
129 match script {
130 ScriptType::Plutus(plutus) => ScriptRef::new_plutus_script(plutus),
131 ScriptType::Native(native) => ScriptRef::new_native_script(native),
132 }
133}