whisky_pallas/wrapper/transaction_body/
datum.rs

1use pallas::{
2    codec::utils::{CborWrap, KeepRaw},
3    ledger::{
4        primitives::{conway::DatumOption, Fragment, PlutusData as PallasPlutusData},
5        traverse::ComputeHash,
6    },
7};
8use whisky_common::WError;
9
10#[derive(Debug, PartialEq, Clone)]
11pub enum DatumKind {
12    Hash { datum_hash: String },
13    Data { plutus_data_hex: String },
14}
15
16#[derive(Debug, PartialEq, Clone)]
17pub struct Datum<'a> {
18    pub inner: DatumOption<'a>,
19}
20
21impl<'a> Datum<'a> {
22    pub fn new(datum_option_kind: DatumKind) -> Result<Self, WError> {
23        let pallas_datum_option = match datum_option_kind {
24            DatumKind::Hash { datum_hash } => {
25                let datum_hash = datum_hash.parse().map_err(|e| {
26                    WError::new(
27                        "WhiskyPallas - Creating datum:",
28                        &format!("Invalid datum hash length: {}", e),
29                    )
30                })?;
31                DatumOption::Hash(datum_hash)
32            }
33
34            DatumKind::Data { plutus_data_hex } => {
35                let bytes = hex::decode(plutus_data_hex).map_err(|e| {
36                    WError::new(
37                        "WhiskyPallas - Creating datum:",
38                        &format!("Hex decode error: {}", e),
39                    )
40                })?;
41                let plutus_data = PallasPlutusData::decode_fragment(&bytes).map_err(|e| {
42                    WError::new(
43                        "WhiskyPallas - Creating datum:",
44                        &format!("Fragment decode error: {}", e),
45                    )
46                })?;
47                DatumOption::Data(CborWrap(KeepRaw::from(plutus_data)))
48            }
49        };
50
51        Ok(Self {
52            inner: pallas_datum_option,
53        })
54    }
55
56    pub fn hash(&self) -> Result<String, WError> {
57        Ok(DatumOption::compute_hash(&self.inner).to_string())
58    }
59
60    pub fn encode(&self) -> Result<String, WError> {
61        self.inner
62            .encode_fragment()
63            .map(|bytes| hex::encode(bytes))
64            .map_err(|_| {
65                WError::new(
66                    "WhiskyPallas - Encoding datum:",
67                    "Failed to encode fragment",
68                )
69            })
70    }
71
72    pub fn decode(bytes: &'a [u8]) -> Result<Self, WError> {
73        let pallas_datum_option = DatumOption::decode_fragment(&bytes).map_err(|e| {
74            WError::new(
75                "WhiskyPallas - Decoding datum:",
76                &format!("Fragment decode error: {}", e),
77            )
78        })?;
79
80        Ok(Self {
81            inner: pallas_datum_option,
82        })
83    }
84}