whisky_pallas/wrapper/auxiliary_data/
auxiliary_data.rs1use std::{collections::BTreeMap, str::FromStr};
2
3use crate::wrapper::witness_set::{native_script::NativeScript, plutus_script::PlutusScript};
4
5use pallas::{
6 codec::utils::{Bytes, Int},
7 ledger::primitives::{
8 alonzo::{
9 PostAlonzoAuxiliaryData as PallasPostAlonzoAuxiliaryData,
10 ShelleyMaAuxiliaryData as PallasShelleyMaAuxiliaryData,
11 },
12 conway::{
13 AuxiliaryData as PallasAuxiliaryData, Metadata as PallasMetadata,
14 Metadatum as PallasMetadum,
15 },
16 Fragment, KeyValuePairs,
17 },
18};
19
20pub type MetadatumLabel = u64;
21
22pub type Metadata = BTreeMap<MetadatumLabel, Metadatum>;
23
24#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
25pub enum Metadatum {
26 Int(i64),
27 Bytes(String),
28 Text(String),
29 Array(Vec<Metadatum>),
30 Map(Vec<(Metadatum, Metadatum)>),
31}
32
33#[derive(Debug, PartialEq, Clone, Eq)]
34pub struct PostAlonzoAuxiliaryData {
35 pub metadata: Option<Metadata>,
36 pub native_scripts: Option<Vec<NativeScript>>,
37 pub plutus_scripts: Option<Vec<PlutusScript<1>>>,
38}
39
40#[derive(Debug, PartialEq, Clone, Eq)]
41pub struct ShelleyMaAuxiliaryData {
42 pub transaction_metadata: Metadata,
43 pub auxiliary_scripts: Option<Vec<NativeScript>>,
44}
45
46#[derive(Debug, PartialEq, Clone, Eq)]
47pub enum AuxiliaryDataKind {
48 Shelley(Metadata),
49 ShelleyMa(ShelleyMaAuxiliaryData),
50 PostAlonzo(PostAlonzoAuxiliaryData),
51}
52
53#[derive(Debug, PartialEq, Clone, Eq)]
54pub struct AuxiliaryData {
55 pub inner: PallasAuxiliaryData,
56}
57
58impl AuxiliaryData {
59 pub fn new(kind: AuxiliaryDataKind) -> Result<Self, String> {
60 let inner: PallasAuxiliaryData = match kind {
61 AuxiliaryDataKind::Shelley(metadata) => {
62 PallasAuxiliaryData::Shelley(Self::to_pallas_metadatum_map(metadata)?)
63 }
64 AuxiliaryDataKind::ShelleyMa(shelley_ma_aux_data) => {
65 PallasAuxiliaryData::ShelleyMa(PallasShelleyMaAuxiliaryData {
66 transaction_metadata: Self::to_pallas_metadatum_map(
67 shelley_ma_aux_data.transaction_metadata,
68 )?,
69 auxiliary_scripts: match shelley_ma_aux_data.auxiliary_scripts {
70 Some(scripts) => Some(scripts.into_iter().map(|s| s.inner).collect()),
71 None => None,
72 },
73 })
74 }
75 AuxiliaryDataKind::PostAlonzo(post_alonzo_aux_data) => {
76 PallasAuxiliaryData::PostAlonzo(PallasPostAlonzoAuxiliaryData {
77 metadata: match post_alonzo_aux_data.metadata {
78 Some(meta) => Some(Self::to_pallas_metadatum_map(meta)?),
79 None => None,
80 },
81 native_scripts: match post_alonzo_aux_data.native_scripts {
82 Some(scripts) => Some(scripts.into_iter().map(|s| s.inner).collect()),
83 None => None,
84 },
85 plutus_scripts: match post_alonzo_aux_data.plutus_scripts {
86 Some(scripts) => Some(scripts.into_iter().map(|s| s.inner).collect()),
87 None => None,
88 },
89 })
90 }
91 };
92
93 Ok(Self { inner })
94 }
95
96 fn to_pallas_metadatum_map(metadata: Metadata) -> Result<PallasMetadata, String> {
97 let mut pallas_metadata_map: BTreeMap<u64, PallasMetadum> = BTreeMap::new();
98 for (key, value) in metadata {
99 let pallas_value = Self::to_pallas_metadatum(value)
100 .map_err(|e| format!("Invalid metadatum during serialization: {}", e))?;
101 pallas_metadata_map.insert(key, pallas_value);
102 }
103 Ok(PallasMetadata::from(pallas_metadata_map))
104 }
105
106 fn to_pallas_metadatum(metadatum: Metadatum) -> Result<PallasMetadum, String> {
107 match metadatum {
108 Metadatum::Int(i) => Ok(PallasMetadum::Int(Int::from(i))),
109 Metadatum::Bytes(b) => {
110 Ok(PallasMetadum::Bytes(Bytes::from_str(&b).map_err(|e| {
111 format!("Invalid bytes in metadatum: {}", e)
112 })?))
113 }
114 Metadatum::Text(t) => Ok(PallasMetadum::Text(t)),
115 Metadatum::Array(arr) => {
116 let mut pallas_array = Vec::new();
117 for item in arr {
118 pallas_array.push(Self::to_pallas_metadatum(item)?);
119 }
120 Ok(PallasMetadum::Array(pallas_array))
121 }
122 Metadatum::Map(map) => {
123 let mut pallas_key_values = Vec::new();
124 for (key, value) in map {
125 let pallas_key = Self::to_pallas_metadatum(key)?;
126 let pallas_value = Self::to_pallas_metadatum(value)?;
127 pallas_key_values.push((pallas_key, pallas_value));
128 }
129 Ok(PallasMetadum::Map(KeyValuePairs::from(pallas_key_values)))
130 }
131 }
132 }
133
134 pub fn encode(&self) -> String {
135 hex::encode(
136 self.inner
137 .encode_fragment()
138 .expect("encoding failed at AuxiliaryData"),
139 )
140 }
141
142 pub fn decode_bytes(bytes: &[u8]) -> Result<Self, String> {
143 let inner = PallasAuxiliaryData::decode_fragment(&bytes)
144 .map_err(|e| format!("Fragment decode error: {}", e.to_string()))?;
145 Ok(Self { inner })
146 }
147}