cml_chain_wasm/auxdata/
metadata.rs

1#![allow(
2    clippy::len_without_is_empty,
3    clippy::too_many_arguments,
4    clippy::new_without_default
5)]
6
7use wasm_bindgen::{
8    prelude::{wasm_bindgen, JsValue},
9    JsError,
10};
11
12use cml_core::serialization::{Deserialize, Serialize};
13
14use cml_core_wasm::{impl_wasm_conversions, impl_wasm_list, Int};
15
16pub use cml_chain::auxdata::TransactionMetadatumLabel;
17
18impl_wasm_conversions!(cml_chain::auxdata::MetadatumMap, MetadatumMap);
19
20#[wasm_bindgen]
21#[derive(Clone, Debug)]
22pub struct MetadatumList(Vec<cml_chain::auxdata::TransactionMetadatum>);
23
24#[wasm_bindgen]
25impl MetadatumList {
26    pub fn new() -> Self {
27        Self(Vec::new())
28    }
29
30    pub fn len(&self) -> usize {
31        self.0.len()
32    }
33
34    pub fn get(&self, index: usize) -> TransactionMetadatum {
35        self.0[index].clone().into()
36    }
37
38    pub fn add(&mut self, elem: &TransactionMetadatum) {
39        self.0.push(elem.clone().into());
40    }
41}
42
43impl From<Vec<cml_chain::auxdata::TransactionMetadatum>> for MetadatumList {
44    fn from(native: Vec<cml_chain::auxdata::TransactionMetadatum>) -> Self {
45        Self(native)
46    }
47}
48
49impl From<MetadatumList> for Vec<cml_chain::auxdata::TransactionMetadatum> {
50    fn from(wrapper: MetadatumList) -> Self {
51        wrapper.0
52    }
53}
54
55#[wasm_bindgen]
56#[derive(Clone, Debug)]
57pub struct TransactionMetadatumLabels(Vec<TransactionMetadatumLabel>);
58
59#[wasm_bindgen]
60impl TransactionMetadatumLabels {
61    pub fn new() -> Self {
62        Self(Vec::new())
63    }
64
65    pub fn len(&self) -> usize {
66        self.0.len()
67    }
68
69    pub fn get(&self, index: usize) -> TransactionMetadatumLabel {
70        self.0[index]
71    }
72
73    pub fn add(&mut self, elem: TransactionMetadatumLabel) {
74        self.0.push(elem);
75    }
76}
77
78impl From<Vec<TransactionMetadatumLabel>> for TransactionMetadatumLabels {
79    fn from(native: Vec<TransactionMetadatumLabel>) -> Self {
80        Self(native)
81    }
82}
83
84impl From<TransactionMetadatumLabels> for Vec<TransactionMetadatumLabel> {
85    fn from(wrapper: TransactionMetadatumLabels) -> Self {
86        wrapper.0
87    }
88}
89
90#[wasm_bindgen]
91#[derive(Clone, Debug)]
92pub struct MetadatumMap(cml_chain::auxdata::MetadatumMap);
93
94#[wasm_bindgen]
95impl MetadatumMap {
96    pub fn new() -> Self {
97        Self(cml_chain::auxdata::MetadatumMap::new())
98    }
99
100    pub fn len(&self) -> usize {
101        self.0.len()
102    }
103
104    /// Replaces all metadatums of a given key, if any exist.
105    pub fn set(&mut self, key: &TransactionMetadatum, value: &TransactionMetadatum) {
106        self.0.set(key.clone().into(), value.clone().into())
107    }
108
109    /// Gets the Metadatum corresponding to a given key, if it exists.
110    /// Note: In the case of duplicate keys this only returns the first metadatum.
111    /// This is an extremely rare occurence (2 total on mainnet) on-chain but can happen.
112    pub fn get(&self, key: &TransactionMetadatum) -> Option<TransactionMetadatum> {
113        self.0.get(&key.0).map(|v| v.clone().into())
114    }
115
116    /// In the extremely unlikely situation there are duplicate keys, this gets all of a single key
117    pub fn get_all(&self, key: &TransactionMetadatum) -> Option<TransactionMetadatumList> {
118        self.0
119            .get_all(key.as_ref())
120            .map(|datums| datums.into_iter().cloned().collect::<Vec<_>>().into())
121    }
122
123    pub fn keys(&self) -> MetadatumList {
124        MetadatumList(
125            self.0
126                .entries
127                .iter()
128                .map(|(k, _v)| k.clone())
129                .collect::<Vec<_>>(),
130        )
131    }
132}
133
134impl_wasm_list!(
135    cml_chain::auxdata::TransactionMetadatum,
136    TransactionMetadatum,
137    TransactionMetadatumList
138);
139
140#[wasm_bindgen]
141#[derive(Clone, Debug)]
142pub struct Metadata(cml_chain::auxdata::Metadata);
143
144impl_wasm_conversions!(cml_chain::auxdata::Metadata, Metadata);
145
146#[wasm_bindgen]
147impl Metadata {
148    pub fn new() -> Self {
149        Self(cml_chain::auxdata::Metadata::new())
150    }
151
152    /// How many metadatum labels there are.
153    pub fn len(&self) -> usize {
154        self.0.entries.len()
155    }
156
157    /// Replaces all metadatums of a given label, if any exist.
158    pub fn set(&mut self, key: TransactionMetadatumLabel, value: &TransactionMetadatum) {
159        self.0.set(key, value.clone().into())
160    }
161
162    /// Gets the Metadatum corresponding to a given label, if it exists.
163    /// Note: In the case of duplicate labels this only returns the first metadatum.
164    /// This is an extremely rare occurence on-chain but can happen.
165    pub fn get(&self, label: TransactionMetadatumLabel) -> Option<TransactionMetadatum> {
166        self.0.get(label).map(|x| x.clone().into())
167    }
168
169    /// In the extremely unlikely situation there are duplicate labels, this gets all of a single label
170    pub fn get_all(&self, label: TransactionMetadatumLabel) -> Option<TransactionMetadatumList> {
171        self.0
172            .get_all(label)
173            .map(|mds| mds.into_iter().cloned().collect::<Vec<_>>().into())
174    }
175
176    pub fn labels(&self) -> TransactionMetadatumLabels {
177        TransactionMetadatumLabels(self.0.entries.iter().map(|(k, _v)| *k).collect::<Vec<_>>())
178    }
179}
180
181impl AsMut<cml_chain::auxdata::Metadata> for Metadata {
182    fn as_mut(&mut self) -> &mut cml_chain::auxdata::Metadata {
183        &mut self.0
184    }
185}
186
187#[wasm_bindgen]
188pub enum TransactionMetadatumKind {
189    Map,
190    List,
191    Int,
192    Bytes,
193    Text,
194}
195
196#[wasm_bindgen]
197#[derive(Clone, Debug)]
198pub struct TransactionMetadatum(cml_chain::auxdata::TransactionMetadatum);
199
200#[wasm_bindgen]
201impl TransactionMetadatum {
202    pub fn to_cbor_bytes(&self) -> Vec<u8> {
203        Serialize::to_cbor_bytes(&self.0)
204    }
205
206    pub fn from_cbor_bytes(cbor_bytes: &[u8]) -> Result<TransactionMetadatum, JsValue> {
207        Deserialize::from_cbor_bytes(cbor_bytes)
208            .map(Self)
209            .map_err(|e| JsValue::from_str(&format!("from_bytes: {e}")))
210    }
211
212    pub fn to_json(&self) -> Result<String, JsValue> {
213        serde_json::to_string_pretty(&self.0)
214            .map_err(|e| JsValue::from_str(&format!("to_json: {e}")))
215    }
216
217    pub fn to_json_value(&self) -> Result<JsValue, JsValue> {
218        serde_wasm_bindgen::to_value(&self.0)
219            .map_err(|e| JsValue::from_str(&format!("to_js_value: {e}")))
220    }
221
222    pub fn from_json(json: &str) -> Result<TransactionMetadatum, JsValue> {
223        serde_json::from_str(json)
224            .map(Self)
225            .map_err(|e| JsValue::from_str(&format!("from_json: {e}")))
226    }
227
228    pub fn new_map(map: &MetadatumMap) -> Self {
229        Self(cml_chain::auxdata::TransactionMetadatum::new_map(
230            map.clone().into(),
231        ))
232    }
233
234    pub fn new_list(elements: &MetadatumList) -> Self {
235        Self(cml_chain::auxdata::TransactionMetadatum::new_list(
236            elements.clone().into(),
237        ))
238    }
239
240    pub fn new_int(int: &Int) -> Self {
241        Self(cml_chain::auxdata::TransactionMetadatum::new_int(
242            int.clone().into(),
243        ))
244    }
245
246    pub fn new_bytes(bytes: Vec<u8>) -> Result<TransactionMetadatum, JsError> {
247        cml_chain::auxdata::TransactionMetadatum::new_bytes(bytes)
248            .map(Into::into)
249            .map_err(Into::into)
250    }
251
252    pub fn new_text(text: String) -> Result<TransactionMetadatum, JsError> {
253        cml_chain::auxdata::TransactionMetadatum::new_text(text)
254            .map(Into::into)
255            .map_err(Into::into)
256    }
257
258    pub fn kind(&self) -> TransactionMetadatumKind {
259        match &self.0 {
260            cml_chain::auxdata::TransactionMetadatum::Map { .. } => TransactionMetadatumKind::Map,
261            cml_chain::auxdata::TransactionMetadatum::List { .. } => TransactionMetadatumKind::List,
262            cml_chain::auxdata::TransactionMetadatum::Int(_) => TransactionMetadatumKind::Int,
263            cml_chain::auxdata::TransactionMetadatum::Bytes { .. } => {
264                TransactionMetadatumKind::Bytes
265            }
266            cml_chain::auxdata::TransactionMetadatum::Text { .. } => TransactionMetadatumKind::Text,
267        }
268    }
269
270    pub fn as_map(&self) -> Option<MetadatumMap> {
271        match &self.0 {
272            cml_chain::auxdata::TransactionMetadatum::Map(map) => Some(map.clone().into()),
273            _ => None,
274        }
275    }
276
277    pub fn as_list(&self) -> Option<MetadatumList> {
278        match &self.0 {
279            cml_chain::auxdata::TransactionMetadatum::List { elements, .. } => {
280                Some(elements.clone().into())
281            }
282            _ => None,
283        }
284    }
285
286    pub fn as_int(&self) -> Option<Int> {
287        match &self.0 {
288            cml_chain::auxdata::TransactionMetadatum::Int(int) => Some(int.clone().into()),
289            _ => None,
290        }
291    }
292
293    pub fn as_bytes(&self) -> Option<Vec<u8>> {
294        match &self.0 {
295            cml_chain::auxdata::TransactionMetadatum::Bytes { bytes, .. } => Some(bytes.clone()),
296            _ => None,
297        }
298    }
299
300    pub fn as_text(&self) -> Option<String> {
301        match &self.0 {
302            cml_chain::auxdata::TransactionMetadatum::Text { text, .. } => Some(text.clone()),
303            _ => None,
304        }
305    }
306}
307
308impl From<cml_chain::auxdata::TransactionMetadatum> for TransactionMetadatum {
309    fn from(native: cml_chain::auxdata::TransactionMetadatum) -> Self {
310        Self(native)
311    }
312}
313
314impl From<TransactionMetadatum> for cml_chain::auxdata::TransactionMetadatum {
315    fn from(wasm: TransactionMetadatum) -> Self {
316        wasm.0
317    }
318}
319
320impl AsRef<cml_chain::auxdata::TransactionMetadatum> for TransactionMetadatum {
321    fn as_ref(&self) -> &cml_chain::auxdata::TransactionMetadatum {
322        &self.0
323    }
324}
325
326/// encodes arbitrary bytes into chunks of 64 bytes (the limit for bytes) as a list to be valid Metadata
327#[wasm_bindgen]
328pub fn encode_arbitrary_bytes_as_metadatum(bytes: &[u8]) -> TransactionMetadatum {
329    cml_chain::auxdata::encode_arbitrary_bytes_as_metadatum(bytes).into()
330}
331
332/// decodes from chunks of bytes in a list to a byte vector if that is the metadata format, otherwise returns None
333#[wasm_bindgen]
334pub fn decode_arbitrary_bytes_from_metadatum(metadata: &TransactionMetadatum) -> Option<Vec<u8>> {
335    cml_chain::auxdata::decode_arbitrary_bytes_from_metadatum(metadata.as_ref())
336}