1use std::collections::BTreeMap;
4
5use anyhow::anyhow;
6use plutus_ledger_api::csl::{lib as csl, pla_to_csl::TryToCSL};
7
8use crate::error::Error;
9
10#[derive(Debug, Clone)]
12pub struct TransactionMetadata(pub BTreeMap<u64, Metadata>);
13
14impl TryFrom<&TransactionMetadata> for csl::GeneralTransactionMetadata {
15 type Error = Error;
16
17 fn try_from(tx_metadata: &TransactionMetadata) -> Result<Self, Self::Error> {
18 let mut csl_tx_metadata = csl::GeneralTransactionMetadata::new();
19
20 tx_metadata.0.iter().try_for_each(|(key, value)| {
21 let _ = csl_tx_metadata.insert(&csl::BigNum::from(*key), &value.try_into()?);
22 Ok::<(), Self::Error>(())
23 })?;
24
25 Ok(csl_tx_metadata)
26 }
27}
28
29impl<const N: usize> From<[(u64, Metadata); N]> for TransactionMetadata {
30 fn from(arr: [(u64, Metadata); N]) -> Self {
31 TransactionMetadata(BTreeMap::from(arr))
32 }
33}
34
35#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)]
37pub enum Metadata {
38 Map(BTreeMap<Metadata, Metadata>),
39 List(Vec<Metadata>),
40 Int(i64),
41 Bytes(Vec<u8>),
42 Text(String),
43}
44
45impl TryFrom<&Metadata> for csl::TransactionMetadatum {
46 type Error = Error;
47
48 fn try_from(metadata: &Metadata) -> Result<Self, Self::Error> {
49 match metadata {
50 Metadata::Map(metadata_map) => {
51 let mut csl_metadata_map = csl::MetadataMap::new();
52
53 metadata_map.iter().try_for_each(|(key, value)| {
54 let _ = csl_metadata_map.insert(&key.try_into()?, &value.try_into()?);
55 Ok::<(), Self::Error>(())
56 })?;
57
58 Ok(csl::TransactionMetadatum::new_map(&csl_metadata_map))
59 }
60
61 Metadata::List(metadata_list) => {
62 let mut csl_metadata_list = csl::MetadataList::new();
63
64 metadata_list.iter().try_for_each(|elem| {
65 csl_metadata_list.add(&elem.try_into()?);
66 Ok::<(), Self::Error>(())
67 })?;
68
69 Ok(csl::TransactionMetadatum::new_list(&csl_metadata_list))
70 }
71
72 Metadata::Int(int) => Ok(csl::TransactionMetadatum::new_int(&int.try_to_csl()?)),
73
74 Metadata::Bytes(bytes) => csl::TransactionMetadatum::new_bytes(bytes.to_owned())
75 .map_err(|source| {
76 Error::ConversionError(anyhow!(
77 "Metadata::Bytes could not be converted: {}",
78 source
79 ))
80 }),
81
82 Metadata::Text(str) => {
83 csl::TransactionMetadatum::new_text(str.to_owned()).map_err(|source| {
84 Error::ConversionError(anyhow!(
85 "Metadata::Text could not be converted: {}",
86 source
87 ))
88 })
89 }
90 }
91 }
92}