plutus_ledger_api/v2/
datum.rs

1//! Types related to Plutus Datums
2
3use cardano_serialization_lib as csl;
4#[cfg(feature = "lbf")]
5use lbr_prelude::json::{self, Error, Json};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate as plutus_ledger_api;
11pub use crate::v1::datum::{Datum, DatumHash};
12use crate::{
13    csl::{
14        csl_to_pla::{FromCSL, TryFromCSL, TryFromCSLError, TryToPLA},
15        pla_to_csl::{TryFromPLA, TryFromPLAError, TryToCSL},
16    },
17    plutus_data::IsPlutusData,
18};
19
20// use crate as plutus_data/
21/////////////////
22// OutputDatum //
23/////////////////
24
25/// Optional datum of a transaction
26///
27/// In case an inline datum is used, the data is embedded inside the transaction body, so it can be
28/// directly retrieved. In case of a datum hash, an off-chain indexer is required to find the
29/// associated datum by its hash.
30#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, IsPlutusData)]
31#[is_plutus_data_derive_strategy = "Constr"]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33pub enum OutputDatum {
34    None,
35    DatumHash(DatumHash),
36    InlineDatum(Datum),
37}
38
39#[cfg(feature = "lbf")]
40impl Json for OutputDatum {
41    fn to_json(&self) -> serde_json::Value {
42        match self {
43            OutputDatum::None => json::json_constructor("NoOutputDatum", Vec::with_capacity(0)),
44            OutputDatum::DatumHash(dat_hash) => {
45                json::json_constructor("OutputDatumHash", vec![dat_hash.to_json()])
46            }
47            OutputDatum::InlineDatum(datum) => {
48                json::json_constructor("OutputDatum", vec![datum.to_json()])
49            }
50        }
51    }
52
53    fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
54        json::case_json_constructor(
55            "Plutus.V2.OutputDatum",
56            vec![
57                (
58                    "NoOutputDatum",
59                    Box::new(|ctor_fields| match &ctor_fields[..] {
60                        [] => Ok(OutputDatum::None),
61                        _ => Err(Error::UnexpectedArrayLength {
62                            wanted: 0,
63                            got: ctor_fields.len(),
64                            parser: "Plutus.V2.OutputDatum".to_owned(),
65                        }),
66                    }),
67                ),
68                (
69                    "OutputDatumHash",
70                    Box::new(|ctor_fields| match &ctor_fields[..] {
71                        [dat_hash] => Ok(OutputDatum::DatumHash(Json::from_json(dat_hash)?)),
72                        _ => Err(Error::UnexpectedArrayLength {
73                            wanted: 1,
74                            got: ctor_fields.len(),
75                            parser: "Plutus.V2.OutputDatum".to_owned(),
76                        }),
77                    }),
78                ),
79                (
80                    "OutputDatum",
81                    Box::new(|ctor_fields| match &ctor_fields[..] {
82                        [datum] => Ok(OutputDatum::InlineDatum(Json::from_json(datum)?)),
83                        _ => Err(Error::UnexpectedArrayLength {
84                            wanted: 1,
85                            got: ctor_fields.len(),
86                            parser: "Plutus.V2.OutputDatum".to_owned(),
87                        }),
88                    }),
89                ),
90            ],
91            value,
92        )
93    }
94}
95
96impl TryFromCSL<csl::OutputDatum> for OutputDatum {
97    fn try_from_csl(value: &csl::OutputDatum) -> Result<Self, TryFromCSLError> {
98        Ok(if let Some(d) = value.data() {
99            OutputDatum::InlineDatum(Datum(d.try_to_pla()?))
100        } else if let Some(h) = value.data_hash() {
101            OutputDatum::DatumHash(DatumHash::from_csl(&h))
102        } else {
103            OutputDatum::None
104        })
105    }
106}
107
108impl TryFromPLA<OutputDatum> for Option<csl::OutputDatum> {
109    fn try_from_pla(
110        pla_output_datum: &OutputDatum,
111    ) -> Result<Option<csl::OutputDatum>, TryFromPLAError> {
112        Ok(match pla_output_datum {
113            OutputDatum::None => None,
114            OutputDatum::InlineDatum(Datum(d)) => {
115                Some(csl::OutputDatum::new_data(&d.try_to_csl()?))
116            }
117            OutputDatum::DatumHash(dh) => Some(csl::OutputDatum::new_data_hash(&dh.try_to_csl()?)),
118        })
119    }
120}