cardano_serialization_lib/
lib.rs

1#![cfg_attr(feature = "with-bench", feature(test))]
2#![allow(deprecated)]
3
4#[macro_use]
5extern crate cfg_if;
6
7#[cfg(test)]
8#[cfg(feature = "with-bench")]
9extern crate test;
10
11#[cfg(test)]
12extern crate quickcheck;
13#[cfg(test)]
14#[macro_use(quickcheck)]
15extern crate quickcheck_macros;
16extern crate hex;
17
18#[cfg(test)]
19mod tests;
20
21#[macro_use]
22extern crate num_derive;
23
24use std::convert::TryInto;
25use std::io::{BufRead, Seek, Write};
26
27#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
28use noop_proc_macro::wasm_bindgen;
29
30#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
31use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
32
33// This file was code-generated using an experimental CDDL to rust tool:
34// https://github.com/Emurgo/cddl-codegen
35
36use cbor_event::{Len, Special as CBORSpecial};
37use cbor_event::Type as CBORType;
38use cbor_event::{
39    self,
40    de::Deserializer,
41    se::{Serialize, Serializer},
42};
43
44mod builders;
45pub use builders::*;
46pub mod chain_core;
47pub mod chain_crypto;
48mod crypto;
49pub(crate) use crypto::*;
50mod emip3;
51pub use emip3::*;
52mod error;
53pub use error::*;
54mod fees;
55pub use fees::*;
56pub mod impl_mockchain;
57pub mod legacy_address;
58pub mod traits;
59mod protocol_types;
60pub use protocol_types::*;
61pub mod typed_bytes;
62#[macro_use]
63mod utils;
64pub use utils::*;
65mod serialization;
66mod rational;
67
68pub use serialization::*;
69
70use crate::traits::NoneOrEmpty;
71use schemars::JsonSchema;
72use std::cmp::Ordering;
73use std::collections::BTreeSet;
74use std::fmt;
75use std::fmt::Display;
76use hashlink::LinkedHashMap;
77
78type DeltaCoin = Int;
79
80#[wasm_bindgen]
81#[derive(
82    Clone,
83    Debug,
84    Hash,
85    Eq,
86    Ord,
87    PartialEq,
88    PartialOrd,
89    Default,
90    serde::Serialize,
91    serde::Deserialize,
92    JsonSchema,
93)]
94pub struct UnitInterval {
95    numerator: BigNum,
96    denominator: BigNum,
97}
98
99impl_to_from!(UnitInterval);
100
101#[wasm_bindgen]
102impl UnitInterval {
103    pub fn numerator(&self) -> BigNum {
104        self.numerator.clone()
105    }
106
107    pub fn denominator(&self) -> BigNum {
108        self.denominator.clone()
109    }
110
111    pub fn new(numerator: &BigNum, denominator: &BigNum) -> Self {
112        Self {
113            numerator: numerator.clone(),
114            denominator: denominator.clone(),
115        }
116    }
117}
118
119type SubCoin = UnitInterval;
120type Epoch = u32;
121type Slot32 = u32;
122type SlotBigNum = BigNum;
123
124#[wasm_bindgen]
125#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, JsonSchema)]
126pub struct Transaction {
127    body: TransactionBody,
128    witness_set: TransactionWitnessSet,
129    is_valid: bool,
130    auxiliary_data: Option<AuxiliaryData>,
131}
132
133impl_to_from!(Transaction);
134
135#[wasm_bindgen]
136impl Transaction {
137    pub fn body(&self) -> TransactionBody {
138        self.body.clone()
139    }
140
141    pub fn witness_set(&self) -> TransactionWitnessSet {
142        self.witness_set.clone()
143    }
144
145    pub fn is_valid(&self) -> bool {
146        self.is_valid.clone()
147    }
148
149    pub fn auxiliary_data(&self) -> Option<AuxiliaryData> {
150        self.auxiliary_data.clone()
151    }
152
153    pub fn set_is_valid(&mut self, valid: bool) {
154        self.is_valid = valid
155    }
156
157    pub fn new(
158        body: &TransactionBody,
159        witness_set: &TransactionWitnessSet,
160        auxiliary_data: Option<AuxiliaryData>,
161    ) -> Self {
162        Self {
163            body: body.clone(),
164            witness_set: witness_set.clone(),
165            is_valid: true,
166            auxiliary_data: auxiliary_data.clone(),
167        }
168    }
169}
170
171// index of a tx within a block
172type TransactionIndex = u32;
173// index of a cert within a tx
174type CertificateIndex = u32;
175type GovernanceActionIndex = u32;
176
177#[wasm_bindgen]
178#[derive(Clone, Eq, PartialEq, Debug, serde::Serialize, serde::Deserialize, JsonSchema)]
179pub struct TransactionOutputs(Vec<TransactionOutput>);
180
181impl_to_from!(TransactionOutputs);
182
183#[wasm_bindgen]
184impl TransactionOutputs {
185    pub fn new() -> Self {
186        Self(Vec::new())
187    }
188
189    pub fn len(&self) -> usize {
190        self.0.len()
191    }
192
193    pub fn get(&self, index: usize) -> TransactionOutput {
194        self.0[index].clone()
195    }
196
197    pub fn add(&mut self, elem: &TransactionOutput) {
198        self.0.push(elem.clone());
199    }
200}
201
202impl<'a> IntoIterator for &'a TransactionOutputs {
203    type Item = &'a TransactionOutput;
204    type IntoIter = std::slice::Iter<'a, TransactionOutput>;
205
206    fn into_iter(self) -> std::slice::Iter<'a, TransactionOutput> {
207        self.0.iter()
208    }
209}
210
211#[wasm_bindgen]
212#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
213pub struct DataCost{
214    coins_per_byte: Coin
215}
216
217#[wasm_bindgen]
218impl DataCost {
219    pub fn new_coins_per_byte(coins_per_byte: &Coin) -> DataCost {
220        DataCost {
221            coins_per_byte: coins_per_byte.clone()
222        }
223    }
224
225    pub fn coins_per_byte(&self) -> Coin {
226        self.coins_per_byte.clone()
227    }
228}
229
230#[wasm_bindgen]
231#[derive(Debug, Clone, Eq, Ord, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema)]
232pub struct TransactionOutput {
233    address: Address,
234    amount: Value,
235    plutus_data: Option<DataOption>,
236    script_ref: Option<ScriptRef>,
237
238    #[serde(skip)]
239    serialization_format: Option<CborContainerType>,
240}
241
242impl_to_from!(TransactionOutput);
243
244#[wasm_bindgen]
245impl TransactionOutput {
246    pub fn address(&self) -> Address {
247        self.address.clone()
248    }
249
250    pub fn amount(&self) -> Value {
251        self.amount.clone()
252    }
253
254    pub fn data_hash(&self) -> Option<DataHash> {
255        match &self.plutus_data {
256            Some(DataOption::DataHash(data_hash)) => Some(data_hash.clone()),
257            _ => None,
258        }
259    }
260
261    pub fn plutus_data(&self) -> Option<PlutusData> {
262        match &self.plutus_data {
263            Some(DataOption::Data(plutus_data)) => Some(plutus_data.clone()),
264            _ => None,
265        }
266    }
267
268    pub fn script_ref(&self) -> Option<ScriptRef> {
269        self.script_ref.clone()
270    }
271
272    pub fn set_script_ref(&mut self, script_ref: &ScriptRef) {
273        self.script_ref = Some(script_ref.clone());
274    }
275
276    pub fn set_plutus_data(&mut self, data: &PlutusData) {
277        self.plutus_data = Some(DataOption::Data(data.clone()));
278    }
279
280    pub fn set_data_hash(&mut self, data_hash: &DataHash) {
281        self.plutus_data = Some(DataOption::DataHash(data_hash.clone()));
282    }
283
284    pub fn has_plutus_data(&self) -> bool {
285        match &self.plutus_data {
286            Some(DataOption::Data(_)) => true,
287            _ => false,
288        }
289    }
290
291    pub fn has_data_hash(&self) -> bool {
292        match &self.plutus_data {
293            Some(DataOption::DataHash(_)) => true,
294            _ => false,
295        }
296    }
297
298    pub fn has_script_ref(&self) -> bool {
299        self.script_ref.is_some()
300    }
301
302    pub fn new(address: &Address, amount: &Value) -> Self {
303        Self {
304            address: address.clone(),
305            amount: amount.clone(),
306            plutus_data: None,
307            script_ref: None,
308            serialization_format: None,
309        }
310    }
311
312    pub fn serialization_format(&self) -> Option<CborContainerType> {
313        self.serialization_format.clone()
314    }
315}
316
317impl PartialEq for TransactionOutput {
318    fn eq(&self, other: &Self) -> bool {
319        self.address == other.address
320            && self.amount == other.amount
321            && self.plutus_data == other.plutus_data
322            && self.script_ref == other.script_ref
323    }
324}
325
326type Port = u16;
327
328#[wasm_bindgen]
329#[derive(
330    Clone,
331    Debug,
332    Hash,
333    Eq,
334    Ord,
335    PartialEq,
336    PartialOrd,
337    serde::Serialize,
338    serde::Deserialize,
339    JsonSchema,
340)]
341pub struct Ipv4([u8; 4]);
342
343impl_to_from!(Ipv4);
344
345#[wasm_bindgen]
346impl Ipv4 {
347    pub fn new(data: Vec<u8>) -> Result<Ipv4, JsError> {
348        Self::new_impl(data).map_err(|e| JsError::from_str(&e.to_string()))
349    }
350
351    pub(crate) fn new_impl(data: Vec<u8>) -> Result<Ipv4, DeserializeError> {
352        data.as_slice().try_into().map(Self).map_err(|_e| {
353            let cbor_error = cbor_event::Error::WrongLen(
354                4,
355                cbor_event::Len::Len(data.len() as u64),
356                "Ipv4 address length",
357            );
358            DeserializeError::new("Ipv4", DeserializeFailure::CBOR(cbor_error))
359        })
360    }
361
362    pub fn ip(&self) -> Vec<u8> {
363        self.0.to_vec()
364    }
365}
366
367#[wasm_bindgen]
368#[derive(
369    Clone,
370    Debug,
371    Hash,
372    Eq,
373    Ord,
374    PartialEq,
375    PartialOrd,
376    serde::Serialize,
377    serde::Deserialize,
378    JsonSchema,
379)]
380pub struct Ipv6([u8; 16]);
381
382impl_to_from!(Ipv6);
383
384#[wasm_bindgen]
385impl Ipv6 {
386    pub fn new(data: Vec<u8>) -> Result<Ipv6, JsError> {
387        Self::new_impl(data).map_err(|e| JsError::from_str(&e.to_string()))
388    }
389
390    pub(crate) fn new_impl(data: Vec<u8>) -> Result<Ipv6, DeserializeError> {
391        data.as_slice().try_into().map(Self).map_err(|_e| {
392            let cbor_error = cbor_event::Error::WrongLen(
393                16,
394                cbor_event::Len::Len(data.len() as u64),
395                "Ipv6 address length",
396            );
397            DeserializeError::new("Ipv6", DeserializeFailure::CBOR(cbor_error))
398        })
399    }
400
401    pub fn ip(&self) -> Vec<u8> {
402        self.0.to_vec()
403    }
404}
405
406static URL_MAX_LEN: usize = 128;
407
408#[wasm_bindgen]
409#[derive(
410    Clone,
411    Debug,
412    Hash,
413    Eq,
414    Ord,
415    PartialEq,
416    PartialOrd,
417    serde::Serialize,
418    serde::Deserialize,
419    JsonSchema,
420)]
421pub struct URL(String);
422
423impl_to_from!(URL);
424
425#[wasm_bindgen]
426impl URL {
427    pub fn new(url: String) -> Result<URL, JsError> {
428        Self::new_impl(url).map_err(|e| JsError::from_str(&e.to_string()))
429    }
430
431    pub(crate) fn new_impl(url: String) -> Result<URL, DeserializeError> {
432        if url.len() <= URL_MAX_LEN {
433            Ok(Self(url))
434        } else {
435            Err(DeserializeError::new(
436                "URL",
437                DeserializeFailure::OutOfRange {
438                    min: 0,
439                    max: URL_MAX_LEN,
440                    found: url.len(),
441                },
442            ))
443        }
444    }
445
446    pub fn url(&self) -> String {
447        self.0.clone()
448    }
449}
450
451static DNS_NAME_MAX_LEN: usize = 128;
452
453#[wasm_bindgen]
454#[derive(
455    Clone,
456    Debug,
457    Hash,
458    Eq,
459    Ord,
460    PartialEq,
461    PartialOrd,
462    serde::Serialize,
463    serde::Deserialize,
464    JsonSchema,
465)]
466pub struct DNSRecordAorAAAA(String);
467
468impl_to_from!(DNSRecordAorAAAA);
469
470#[wasm_bindgen]
471impl DNSRecordAorAAAA {
472    pub fn new(dns_name: String) -> Result<DNSRecordAorAAAA, JsError> {
473        Self::new_impl(dns_name).map_err(|e| JsError::from_str(&e.to_string()))
474    }
475
476    pub(crate) fn new_impl(dns_name: String) -> Result<DNSRecordAorAAAA, DeserializeError> {
477        if dns_name.len() <= DNS_NAME_MAX_LEN {
478            Ok(Self(dns_name))
479        } else {
480            Err(DeserializeError::new(
481                "DNSRecordAorAAAA",
482                DeserializeFailure::OutOfRange {
483                    min: 0,
484                    max: DNS_NAME_MAX_LEN,
485                    found: dns_name.len(),
486                },
487            ))
488        }
489    }
490
491    pub fn record(&self) -> String {
492        self.0.clone()
493    }
494}
495
496#[wasm_bindgen]
497#[derive(
498    Clone,
499    Debug,
500    Hash,
501    Eq,
502    Ord,
503    PartialEq,
504    PartialOrd,
505    serde::Serialize,
506    serde::Deserialize,
507    JsonSchema,
508)]
509pub struct DNSRecordSRV(String);
510
511impl_to_from!(DNSRecordSRV);
512
513#[wasm_bindgen]
514impl DNSRecordSRV {
515    pub fn new(dns_name: String) -> Result<DNSRecordSRV, JsError> {
516        Self::new_impl(dns_name).map_err(|e| JsError::from_str(&e.to_string()))
517    }
518
519    pub(crate) fn new_impl(dns_name: String) -> Result<DNSRecordSRV, DeserializeError> {
520        if dns_name.len() <= DNS_NAME_MAX_LEN {
521            Ok(Self(dns_name))
522        } else {
523            Err(DeserializeError::new(
524                "DNSRecordSRV",
525                DeserializeFailure::OutOfRange {
526                    min: 0,
527                    max: DNS_NAME_MAX_LEN,
528                    found: dns_name.len(),
529                },
530            ))
531        }
532    }
533
534    pub fn record(&self) -> String {
535        self.0.clone()
536    }
537}
538
539#[wasm_bindgen]
540#[derive(
541    Clone,
542    Debug,
543    Hash,
544    Eq,
545    Ord,
546    PartialEq,
547    PartialOrd,
548    serde::Serialize,
549    serde::Deserialize,
550    JsonSchema,
551)]
552pub struct SingleHostAddr {
553    port: Option<Port>,
554    ipv4: Option<Ipv4>,
555    ipv6: Option<Ipv6>,
556}
557
558impl_to_from!(SingleHostAddr);
559
560#[wasm_bindgen]
561impl SingleHostAddr {
562    pub fn port(&self) -> Option<Port> {
563        self.port.clone()
564    }
565
566    pub fn ipv4(&self) -> Option<Ipv4> {
567        self.ipv4.clone()
568    }
569
570    pub fn ipv6(&self) -> Option<Ipv6> {
571        self.ipv6.clone()
572    }
573
574    pub fn new(port: Option<Port>, ipv4: Option<Ipv4>, ipv6: Option<Ipv6>) -> Self {
575        Self {
576            port: port,
577            ipv4: ipv4.clone(),
578            ipv6: ipv6.clone(),
579        }
580    }
581}
582
583#[wasm_bindgen]
584#[derive(
585    Clone,
586    Debug,
587    Hash,
588    Eq,
589    Ord,
590    PartialEq,
591    PartialOrd,
592    serde::Serialize,
593    serde::Deserialize,
594    JsonSchema,
595)]
596pub struct SingleHostName {
597    port: Option<Port>,
598    dns_name: DNSRecordAorAAAA,
599}
600
601impl_to_from!(SingleHostName);
602
603#[wasm_bindgen]
604impl SingleHostName {
605    pub fn port(&self) -> Option<Port> {
606        self.port.clone()
607    }
608
609    pub fn dns_name(&self) -> DNSRecordAorAAAA {
610        self.dns_name.clone()
611    }
612
613    pub fn new(port: Option<Port>, dns_name: &DNSRecordAorAAAA) -> Self {
614        Self {
615            port: port,
616            dns_name: dns_name.clone(),
617        }
618    }
619}
620
621#[wasm_bindgen]
622#[derive(
623    Clone,
624    Debug,
625    Hash,
626    Eq,
627    Ord,
628    PartialEq,
629    PartialOrd,
630    serde::Serialize,
631    serde::Deserialize,
632    JsonSchema,
633)]
634pub struct MultiHostName {
635    dns_name: DNSRecordSRV,
636}
637
638impl_to_from!(MultiHostName);
639
640#[wasm_bindgen]
641impl MultiHostName {
642    pub fn dns_name(&self) -> DNSRecordSRV {
643        self.dns_name.clone()
644    }
645
646    pub fn new(dns_name: &DNSRecordSRV) -> Self {
647        Self {
648            dns_name: dns_name.clone(),
649        }
650    }
651}
652
653#[wasm_bindgen]
654#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
655pub enum RelayKind {
656    SingleHostAddr,
657    SingleHostName,
658    MultiHostName,
659}
660
661#[derive(
662    Clone,
663    Debug,
664    Hash,
665    Eq,
666    Ord,
667    PartialEq,
668    PartialOrd,
669    serde::Serialize,
670    serde::Deserialize,
671    JsonSchema,
672)]
673pub enum RelayEnum {
674    SingleHostAddr(SingleHostAddr),
675    SingleHostName(SingleHostName),
676    MultiHostName(MultiHostName),
677}
678
679#[wasm_bindgen]
680#[derive(
681    Clone,
682    Debug,
683    Hash,
684    Eq,
685    Ord,
686    PartialEq,
687    PartialOrd,
688    serde::Serialize,
689    serde::Deserialize,
690    JsonSchema,
691)]
692pub struct Relay(RelayEnum);
693
694impl_to_from!(Relay);
695
696#[wasm_bindgen]
697impl Relay {
698    pub fn new_single_host_addr(single_host_addr: &SingleHostAddr) -> Self {
699        Self(RelayEnum::SingleHostAddr(single_host_addr.clone()))
700    }
701
702    pub fn new_single_host_name(single_host_name: &SingleHostName) -> Self {
703        Self(RelayEnum::SingleHostName(single_host_name.clone()))
704    }
705
706    pub fn new_multi_host_name(multi_host_name: &MultiHostName) -> Self {
707        Self(RelayEnum::MultiHostName(multi_host_name.clone()))
708    }
709
710    pub fn kind(&self) -> RelayKind {
711        match &self.0 {
712            RelayEnum::SingleHostAddr(_) => RelayKind::SingleHostAddr,
713            RelayEnum::SingleHostName(_) => RelayKind::SingleHostName,
714            RelayEnum::MultiHostName(_) => RelayKind::MultiHostName,
715        }
716    }
717
718    pub fn as_single_host_addr(&self) -> Option<SingleHostAddr> {
719        match &self.0 {
720            RelayEnum::SingleHostAddr(x) => Some(x.clone()),
721            _ => None,
722        }
723    }
724
725    pub fn as_single_host_name(&self) -> Option<SingleHostName> {
726        match &self.0 {
727            RelayEnum::SingleHostName(x) => Some(x.clone()),
728            _ => None,
729        }
730    }
731
732    pub fn as_multi_host_name(&self) -> Option<MultiHostName> {
733        match &self.0 {
734            RelayEnum::MultiHostName(x) => Some(x.clone()),
735            _ => None,
736        }
737    }
738}
739
740#[wasm_bindgen]
741#[derive(
742    Clone,
743    Debug,
744    Hash,
745    Eq,
746    Ord,
747    PartialEq,
748    PartialOrd,
749    serde::Serialize,
750    serde::Deserialize,
751    JsonSchema,
752)]
753pub struct PoolMetadata {
754    url: URL,
755    pool_metadata_hash: PoolMetadataHash,
756}
757
758impl_to_from!(PoolMetadata);
759
760#[wasm_bindgen]
761impl PoolMetadata {
762    pub fn url(&self) -> URL {
763        self.url.clone()
764    }
765
766    pub fn pool_metadata_hash(&self) -> PoolMetadataHash {
767        self.pool_metadata_hash.clone()
768    }
769
770    pub fn new(url: &URL, pool_metadata_hash: &PoolMetadataHash) -> Self {
771        Self {
772            url: url.clone(),
773            pool_metadata_hash: pool_metadata_hash.clone(),
774        }
775    }
776}
777
778#[wasm_bindgen]
779#[derive(
780    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
781)]
782pub struct RewardAddresses(pub(crate) Vec<RewardAddress>);
783
784impl_to_from!(RewardAddresses);
785
786#[wasm_bindgen]
787impl RewardAddresses {
788    pub fn new() -> Self {
789        Self(Vec::new())
790    }
791
792    pub fn len(&self) -> usize {
793        self.0.len()
794    }
795
796    pub fn get(&self, index: usize) -> RewardAddress {
797        self.0[index].clone()
798    }
799
800    pub fn add(&mut self, elem: &RewardAddress) {
801        self.0.push(elem.clone());
802    }
803}
804
805#[wasm_bindgen]
806#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
807pub struct Withdrawals(LinkedHashMap<RewardAddress, Coin>);
808
809impl_to_from!(Withdrawals);
810
811impl NoneOrEmpty for Withdrawals {
812    fn is_none_or_empty(&self) -> bool {
813        self.0.is_empty()
814    }
815}
816
817#[wasm_bindgen]
818impl Withdrawals {
819    pub fn new() -> Self {
820        Self(LinkedHashMap::new())
821    }
822
823    pub fn len(&self) -> usize {
824        self.0.len()
825    }
826
827    pub fn insert(&mut self, key: &RewardAddress, value: &Coin) -> Option<Coin> {
828        self.0.insert(key.clone(), value.clone())
829    }
830
831    pub fn get(&self, key: &RewardAddress) -> Option<Coin> {
832        self.0.get(key).map(|v| v.clone())
833    }
834
835    pub fn keys(&self) -> RewardAddresses {
836        RewardAddresses(
837            self.0
838                .iter()
839                .map(|(k, _v)| k.clone())
840                .collect::<Vec<RewardAddress>>(),
841        )
842    }
843
844    #[allow(dead_code)]
845    pub(crate) fn as_vec(&self) -> Vec<(&RewardAddress, &Coin)> {
846        self.0.iter().collect()
847    }
848}
849
850impl serde::Serialize for Withdrawals {
851    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
852    where
853        S: serde::Serializer,
854    {
855        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
856        map.serialize(serializer)
857    }
858}
859
860impl<'de> serde::de::Deserialize<'de> for Withdrawals {
861    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
862    where
863        D: serde::de::Deserializer<'de>,
864    {
865        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
866            deserializer,
867        )?;
868        Ok(Self(map.into_iter().collect()))
869    }
870}
871
872impl JsonSchema for Withdrawals {
873    fn schema_name() -> String {
874        String::from("Withdrawals")
875    }
876    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
877        std::collections::BTreeMap::<RewardAddress, Coin>::json_schema(gen)
878    }
879    fn is_referenceable() -> bool {
880        std::collections::BTreeMap::<RewardAddress, Coin>::is_referenceable()
881    }
882}
883
884#[derive(
885    Debug, Clone, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
886)]
887pub enum DataOption {
888    DataHash(DataHash),
889    Data(PlutusData),
890}
891
892#[wasm_bindgen]
893#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
894pub struct OutputDatum(pub(crate) DataOption);
895
896#[wasm_bindgen]
897impl OutputDatum {
898    pub fn new_data_hash(data_hash: &DataHash) -> Self {
899        Self(DataOption::DataHash(data_hash.clone()))
900    }
901
902    pub fn new_data(data: &PlutusData) -> Self {
903        Self(DataOption::Data(data.clone()))
904    }
905
906    pub fn data_hash(&self) -> Option<DataHash> {
907        match &self.0 {
908            DataOption::DataHash(data_hash) => Some(data_hash.clone()),
909            _ => None,
910        }
911    }
912
913    pub fn data(&self) -> Option<PlutusData> {
914        match &self.0 {
915            DataOption::Data(data) => Some(data.clone()),
916            _ => None,
917        }
918    }
919}
920
921/// Each new language uses a different namespace for hashing its script
922/// This is because you could have a language where the same bytes have different semantics
923/// So this avoids scripts in different languages mapping to the same hash
924/// Note that the enum value here is different than the enum value for deciding the cost model of a script
925#[wasm_bindgen]
926#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
927pub enum ScriptHashNamespace {
928    NativeScript = 0,
929    PlutusScript = 1,
930    PlutusScriptV2 = 2,
931    PlutusScriptV3 = 3,
932}
933
934#[wasm_bindgen]
935#[derive(
936    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
937)]
938pub struct Update {
939    proposed_protocol_parameter_updates: ProposedProtocolParameterUpdates,
940    epoch: Epoch,
941}
942
943impl_to_from!(Update);
944
945#[wasm_bindgen]
946impl Update {
947    pub fn proposed_protocol_parameter_updates(&self) -> ProposedProtocolParameterUpdates {
948        self.proposed_protocol_parameter_updates.clone()
949    }
950
951    pub fn epoch(&self) -> Epoch {
952        self.epoch.clone()
953    }
954
955    pub fn new(
956        proposed_protocol_parameter_updates: &ProposedProtocolParameterUpdates,
957        epoch: Epoch,
958    ) -> Self {
959        Self {
960            proposed_protocol_parameter_updates: proposed_protocol_parameter_updates.clone(),
961            epoch: epoch.clone(),
962        }
963    }
964}
965
966#[wasm_bindgen]
967#[derive(
968    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
969)]
970pub struct GenesisHashes(Vec<GenesisHash>);
971
972impl_to_from!(GenesisHashes);
973
974#[wasm_bindgen]
975impl GenesisHashes {
976    pub fn new() -> Self {
977        Self(Vec::new())
978    }
979
980    pub fn len(&self) -> usize {
981        self.0.len()
982    }
983
984    pub fn get(&self, index: usize) -> GenesisHash {
985        self.0[index].clone()
986    }
987
988    pub fn add(&mut self, elem: &GenesisHash) {
989        self.0.push(elem.clone());
990    }
991}
992
993#[wasm_bindgen]
994#[derive(
995    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
996)]
997pub struct ScriptHashes(pub(crate) Vec<ScriptHash>);
998
999impl_to_from!(ScriptHashes);
1000
1001#[wasm_bindgen]
1002impl ScriptHashes {
1003    pub fn new() -> Self {
1004        Self(Vec::new())
1005    }
1006
1007    pub fn len(&self) -> usize {
1008        self.0.len()
1009    }
1010
1011    pub fn get(&self, index: usize) -> ScriptHash {
1012        self.0[index].clone()
1013    }
1014
1015    pub fn add(&mut self, elem: &ScriptHash) {
1016        self.0.push(elem.clone());
1017    }
1018}
1019
1020#[wasm_bindgen]
1021#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1022pub struct ProposedProtocolParameterUpdates(
1023    LinkedHashMap<GenesisHash, ProtocolParamUpdate>,
1024);
1025
1026impl serde::Serialize for ProposedProtocolParameterUpdates {
1027    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1028    where
1029        S: serde::Serializer,
1030    {
1031        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
1032        map.serialize(serializer)
1033    }
1034}
1035
1036impl<'de> serde::de::Deserialize<'de> for ProposedProtocolParameterUpdates {
1037    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1038    where
1039        D: serde::de::Deserializer<'de>,
1040    {
1041        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
1042            deserializer,
1043        )?;
1044        Ok(Self(map.into_iter().collect()))
1045    }
1046}
1047
1048impl JsonSchema for ProposedProtocolParameterUpdates {
1049    fn schema_name() -> String {
1050        String::from("ProposedProtocolParameterUpdates")
1051    }
1052    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1053        std::collections::BTreeMap::<GenesisHash, ProtocolParamUpdate>::json_schema(gen)
1054    }
1055    fn is_referenceable() -> bool {
1056        std::collections::BTreeMap::<GenesisHash, ProtocolParamUpdate>::is_referenceable()
1057    }
1058}
1059
1060impl_to_from!(ProposedProtocolParameterUpdates);
1061
1062#[wasm_bindgen]
1063impl ProposedProtocolParameterUpdates {
1064    pub fn new() -> Self {
1065        Self(LinkedHashMap::new())
1066    }
1067
1068    pub fn len(&self) -> usize {
1069        self.0.len()
1070    }
1071
1072    pub fn insert(
1073        &mut self,
1074        key: &GenesisHash,
1075        value: &ProtocolParamUpdate,
1076    ) -> Option<ProtocolParamUpdate> {
1077        self.0.insert(key.clone(), value.clone())
1078    }
1079
1080    pub fn get(&self, key: &GenesisHash) -> Option<ProtocolParamUpdate> {
1081        self.0.get(key).map(|v| v.clone())
1082    }
1083
1084    pub fn keys(&self) -> GenesisHashes {
1085        GenesisHashes(
1086            self.0
1087                .iter()
1088                .map(|(k, _v)| k.clone())
1089                .collect::<Vec<GenesisHash>>(),
1090        )
1091    }
1092}
1093
1094#[wasm_bindgen]
1095#[derive(
1096    Clone,
1097    Debug,
1098    Hash,
1099    Eq,
1100    Ord,
1101    PartialEq,
1102    PartialOrd,
1103    serde::Serialize,
1104    serde::Deserialize,
1105    JsonSchema,
1106)]
1107pub struct ProtocolVersion {
1108    major: u32,
1109    minor: u32,
1110}
1111
1112impl_to_from!(ProtocolVersion);
1113
1114#[wasm_bindgen]
1115impl ProtocolVersion {
1116    pub fn major(&self) -> u32 {
1117        self.major
1118    }
1119
1120    pub fn minor(&self) -> u32 {
1121        self.minor
1122    }
1123
1124    pub fn new(major: u32, minor: u32) -> Self {
1125        Self { major, minor }
1126    }
1127}
1128
1129#[wasm_bindgen]
1130#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1131pub struct AuxiliaryDataSet(LinkedHashMap<TransactionIndex, AuxiliaryData>);
1132
1133#[wasm_bindgen]
1134impl AuxiliaryDataSet {
1135    pub fn new() -> Self {
1136        Self(LinkedHashMap::new())
1137    }
1138
1139    pub fn len(&self) -> usize {
1140        self.0.len()
1141    }
1142
1143    pub fn insert(
1144        &mut self,
1145        tx_index: TransactionIndex,
1146        data: &AuxiliaryData,
1147    ) -> Option<AuxiliaryData> {
1148        self.0.insert(tx_index, data.clone())
1149    }
1150
1151    pub fn get(&self, tx_index: TransactionIndex) -> Option<AuxiliaryData> {
1152        self.0.get(&tx_index).map(|v| v.clone())
1153    }
1154
1155    pub fn indices(&self) -> TransactionIndexes {
1156        self.0
1157            .iter()
1158            .map(|(k, _v)| k.clone())
1159            .collect::<Vec<TransactionIndex>>()
1160    }
1161}
1162
1163impl serde::Serialize for AuxiliaryDataSet {
1164    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1165    where
1166        S: serde::Serializer,
1167    {
1168        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
1169        map.serialize(serializer)
1170    }
1171}
1172
1173impl<'de> serde::de::Deserialize<'de> for AuxiliaryDataSet {
1174    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1175    where
1176        D: serde::de::Deserializer<'de>,
1177    {
1178        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
1179            deserializer,
1180        )?;
1181        Ok(Self(map.into_iter().collect()))
1182    }
1183}
1184
1185impl JsonSchema for AuxiliaryDataSet {
1186    fn schema_name() -> String {
1187        String::from("AuxiliaryDataSet")
1188    }
1189    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1190        std::collections::BTreeMap::<TransactionIndex, AuxiliaryData>::json_schema(gen)
1191    }
1192    fn is_referenceable() -> bool {
1193        std::collections::BTreeMap::<TransactionIndex, AuxiliaryData>::is_referenceable()
1194    }
1195}
1196
1197#[wasm_bindgen]
1198#[derive(Clone, Debug, Eq, PartialEq, Hash)]
1199pub struct AssetName(Vec<u8>);
1200
1201impl Display for AssetName {
1202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1203        write!(f, "{}", hex::encode(&self.0))
1204    }
1205}
1206
1207impl Ord for AssetName {
1208    fn cmp(&self, other: &Self) -> Ordering {
1209        // Implementing canonical CBOR order for asset names,
1210        // as they might be of different length.
1211        return match self.0.len().cmp(&other.0.len()) {
1212            Ordering::Equal => self.0.cmp(&other.0),
1213            x => x,
1214        };
1215    }
1216}
1217
1218impl PartialOrd for AssetName {
1219    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1220        Some(self.cmp(other))
1221    }
1222}
1223
1224impl_to_from!(AssetName);
1225
1226#[wasm_bindgen]
1227impl AssetName {
1228    pub fn new(name: Vec<u8>) -> Result<AssetName, JsError> {
1229        Self::new_impl(name).map_err(|e| JsError::from_str(&e.to_string()))
1230    }
1231
1232    pub(crate) fn new_impl(name: Vec<u8>) -> Result<AssetName, DeserializeError> {
1233        if name.len() <= 32 {
1234            Ok(Self(name))
1235        } else {
1236            Err(DeserializeError::new(
1237                "AssetName",
1238                DeserializeFailure::OutOfRange {
1239                    min: 0,
1240                    max: 32,
1241                    found: name.len(),
1242                },
1243            ))
1244        }
1245    }
1246
1247    pub fn name(&self) -> Vec<u8> {
1248        self.0.clone()
1249    }
1250}
1251
1252impl serde::Serialize for AssetName {
1253    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1254    where
1255        S: serde::Serializer,
1256    {
1257        serializer.serialize_str(&hex::encode(&self.0))
1258    }
1259}
1260
1261impl<'de> serde::de::Deserialize<'de> for AssetName {
1262    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1263    where
1264        D: serde::de::Deserializer<'de>,
1265    {
1266        let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
1267        if let Ok(bytes) = hex::decode(&s) {
1268            if let Ok(asset_name) = AssetName::new(bytes) {
1269                return Ok(asset_name);
1270            }
1271        }
1272        Err(serde::de::Error::invalid_value(
1273            serde::de::Unexpected::Str(&s),
1274            &"AssetName as hex string e.g. F8AB28C2",
1275        ))
1276    }
1277}
1278
1279impl JsonSchema for AssetName {
1280    fn schema_name() -> String {
1281        String::from("AssetName")
1282    }
1283    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1284        String::json_schema(gen)
1285    }
1286    fn is_referenceable() -> bool {
1287        String::is_referenceable()
1288    }
1289}
1290
1291#[wasm_bindgen]
1292#[derive(
1293    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1294)]
1295pub struct AssetNames(Vec<AssetName>);
1296
1297impl_to_from!(AssetNames);
1298
1299#[wasm_bindgen]
1300impl AssetNames {
1301    pub fn new() -> Self {
1302        Self(Vec::new())
1303    }
1304
1305    pub fn len(&self) -> usize {
1306        self.0.len()
1307    }
1308
1309    pub fn get(&self, index: usize) -> AssetName {
1310        self.0[index].clone()
1311    }
1312
1313    pub fn add(&mut self, elem: &AssetName) {
1314        self.0.push(elem.clone());
1315    }
1316}
1317
1318pub type PolicyID = ScriptHash;
1319pub type PolicyIDs = ScriptHashes;
1320
1321#[wasm_bindgen]
1322#[derive(
1323    Clone,
1324    Debug,
1325    Default,
1326    Eq,
1327    Ord,
1328    PartialEq,
1329    PartialOrd,
1330    serde::Serialize,
1331    serde::Deserialize,
1332    JsonSchema,
1333)]
1334pub struct Assets(pub(crate) std::collections::BTreeMap<AssetName, BigNum>);
1335
1336impl_to_from!(Assets);
1337
1338#[wasm_bindgen]
1339impl Assets {
1340    pub fn new() -> Self {
1341        Self(std::collections::BTreeMap::new())
1342    }
1343
1344    pub fn len(&self) -> usize {
1345        self.0.len()
1346    }
1347
1348    pub fn insert(&mut self, key: &AssetName, value: &BigNum) -> Option<BigNum> {
1349        self.0.insert(key.clone(), value.clone())
1350    }
1351
1352    pub fn get(&self, key: &AssetName) -> Option<BigNum> {
1353        self.0.get(key).map(|v| v.clone())
1354    }
1355
1356    pub fn keys(&self) -> AssetNames {
1357        AssetNames(
1358            self.0
1359                .iter()
1360                .map(|(k, _v)| k.clone())
1361                .collect::<Vec<AssetName>>(),
1362        )
1363    }
1364}
1365
1366#[wasm_bindgen]
1367#[derive(Clone, Debug, Eq, Ord, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
1368pub struct MultiAsset(pub(crate) std::collections::BTreeMap<PolicyID, Assets>);
1369
1370impl_to_from!(MultiAsset);
1371
1372#[wasm_bindgen]
1373impl MultiAsset {
1374    pub fn new() -> Self {
1375        Self(std::collections::BTreeMap::new())
1376    }
1377
1378    /// the number of unique policy IDs in the multiasset
1379    pub fn len(&self) -> usize {
1380        self.0.len()
1381    }
1382
1383    /// set (and replace if it exists) all assets with policy {policy_id} to a copy of {assets}
1384    pub fn insert(&mut self, policy_id: &PolicyID, assets: &Assets) -> Option<Assets> {
1385        self.0.insert(policy_id.clone(), assets.clone())
1386    }
1387
1388    /// all assets under {policy_id}, if any exist, or else None (undefined in JS)
1389    pub fn get(&self, policy_id: &PolicyID) -> Option<Assets> {
1390        self.0.get(policy_id).map(|v| v.clone())
1391    }
1392
1393    /// sets the asset {asset_name} to {value} under policy {policy_id}
1394    /// returns the previous amount if it was set, or else None (undefined in JS)
1395    pub fn set_asset(
1396        &mut self,
1397        policy_id: &PolicyID,
1398        asset_name: &AssetName,
1399        value: &BigNum,
1400    ) -> Option<BigNum> {
1401        self.0
1402            .entry(policy_id.clone())
1403            .or_default()
1404            .insert(asset_name, value)
1405    }
1406
1407    /// returns the amount of asset {asset_name} under policy {policy_id}
1408    /// If such an asset does not exist, 0 is returned.
1409    pub fn get_asset(&self, policy_id: &PolicyID, asset_name: &AssetName) -> BigNum {
1410        (|| self.0.get(policy_id)?.get(asset_name))().unwrap_or(BigNum::zero())
1411    }
1412
1413    /// returns all policy IDs used by assets in this multiasset
1414    pub fn keys(&self) -> PolicyIDs {
1415        ScriptHashes(
1416            self.0
1417                .iter()
1418                .map(|(k, _v)| k.clone())
1419                .collect::<Vec<PolicyID>>(),
1420        )
1421    }
1422
1423    /// removes an asset from the list if the result is 0 or less
1424    /// does not modify this object, instead the result is returned
1425    pub fn sub(&self, rhs_ma: &MultiAsset) -> MultiAsset {
1426        let mut lhs_ma = self.clone();
1427        for (policy, assets) in &rhs_ma.0 {
1428            for (asset_name, amount) in &assets.0 {
1429                match lhs_ma.0.get_mut(policy) {
1430                    Some(assets) => match assets.0.get_mut(asset_name) {
1431                        Some(current) => match current.checked_sub(&amount) {
1432                            Ok(new) => match new.compare(&BigNum(0)) {
1433                                0 => {
1434                                    assets.0.remove(asset_name);
1435                                    match assets.0.len() {
1436                                        0 => {
1437                                            lhs_ma.0.remove(policy);
1438                                        }
1439                                        _ => {}
1440                                    }
1441                                }
1442                                _ => *current = new,
1443                            },
1444                            Err(_) => {
1445                                assets.0.remove(asset_name);
1446                                match assets.0.len() {
1447                                    0 => {
1448                                        lhs_ma.0.remove(policy);
1449                                    }
1450                                    _ => {}
1451                                }
1452                            }
1453                        },
1454                        None => {
1455                            // asset name is missing from left hand side
1456                        }
1457                    },
1458                    None => {
1459                        // policy id missing from left hand side
1460                    }
1461                }
1462            }
1463        }
1464        lhs_ma
1465    }
1466
1467    pub(crate) fn reduce_empty_to_none(&self) -> Option<&MultiAsset> {
1468        for (_policy, assets) in self.0.iter() {
1469            if assets.len() > 0 {
1470                return Some(self);
1471            }
1472        }
1473
1474        None
1475    }
1476}
1477
1478// deriving PartialOrd doesn't work in a way that's useful , as the
1479// implementation of PartialOrd for BTreeMap compares keys by their order,
1480// i.e, is equivalent to comparing the iterators of (pid, Assets).
1481// that would mean that: v1 < v2 if the min_pid(v1) < min_pid(v2)
1482// this function instead compares amounts, assuming that if a pair (pid, aname)
1483// is not in the MultiAsset then it has an amount of 0
1484impl PartialOrd for MultiAsset {
1485    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1486        fn amount_or_zero(ma: &MultiAsset, pid: &PolicyID, aname: &AssetName) -> Coin {
1487            ma.get(&pid)
1488                .and_then(|assets| assets.get(aname))
1489                .unwrap_or(BigNum(0u64)) // assume 0 if asset not present
1490        }
1491
1492        // idea: if (a-b) > 0 for some asset, then a > b for at least some asset
1493        fn is_all_zeros(lhs: &MultiAsset, rhs: &MultiAsset) -> bool {
1494            for (pid, assets) in lhs.0.iter() {
1495                for (aname, amount) in assets.0.iter() {
1496                    match amount
1497                        .clamped_sub(&amount_or_zero(&rhs, pid, aname))
1498                        .cmp(&BigNum::zero())
1499                    {
1500                        std::cmp::Ordering::Equal => (),
1501                        _ => return false,
1502                    }
1503                }
1504            }
1505            true
1506        }
1507
1508        match (is_all_zeros(self, other), is_all_zeros(other, self)) {
1509            (true, true) => Some(std::cmp::Ordering::Equal),
1510            (true, false) => Some(std::cmp::Ordering::Less),
1511            (false, true) => Some(std::cmp::Ordering::Greater),
1512            (false, false) => None,
1513        }
1514    }
1515}
1516
1517#[wasm_bindgen]
1518#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema)]
1519pub struct MintsAssets(Vec<MintAssets>);
1520
1521to_from_json!(MintsAssets);
1522
1523#[wasm_bindgen]
1524impl MintsAssets {
1525    pub fn new() -> Self {
1526        Self(Vec::new())
1527    }
1528
1529    pub fn add(&mut self, mint_assets: &MintAssets) {
1530        self.0.push(mint_assets.clone())
1531    }
1532
1533    pub fn get(&self, index: usize) -> Option<MintAssets> {
1534        self.0.get(index).map(|v| v.clone())
1535    }
1536
1537    pub fn len(&self) -> usize {
1538        self.0.len()
1539    }
1540}
1541
1542#[wasm_bindgen]
1543#[derive(
1544    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1545)]
1546pub struct MintAssets(std::collections::BTreeMap<AssetName, Int>);
1547
1548#[wasm_bindgen]
1549impl MintAssets {
1550    pub fn new() -> Self {
1551        Self(std::collections::BTreeMap::new())
1552    }
1553
1554    pub fn new_from_entry(key: &AssetName, value: &Int) -> Result<MintAssets, JsError> {
1555        if value.0 == 0 {
1556            return Err(JsError::from_str("MintAssets cannot be created with 0 value"));
1557        }
1558        let mut ma = MintAssets::new();
1559        ma.insert(key, value)?;
1560        Ok(ma)
1561    }
1562
1563    pub fn len(&self) -> usize {
1564        self.0.len()
1565    }
1566
1567    pub fn insert(&mut self, key: &AssetName, value: &Int) -> Result<Option<Int>, JsError> {
1568        if value.0 == 0 {
1569            return Err(JsError::from_str("MintAssets cannot be created with 0 value"));
1570        }
1571        Ok(self.0.insert(key.clone(), value.clone()))
1572    }
1573
1574    pub(crate) fn insert_unchecked(&mut self, key: &AssetName, value: Int) -> Option<Int> {
1575        self.0.insert(key.clone(), value)
1576    }
1577
1578    pub fn get(&self, key: &AssetName) -> Option<Int> {
1579        self.0.get(key).map(|v| v.clone())
1580    }
1581
1582    pub fn keys(&self) -> AssetNames {
1583        AssetNames(
1584            self.0
1585                .iter()
1586                .map(|(k, _v)| k.clone())
1587                .collect::<Vec<AssetName>>(),
1588        )
1589    }
1590}
1591
1592#[wasm_bindgen]
1593#[derive(
1594    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1595)]
1596pub struct Mint(Vec<(PolicyID, MintAssets)>);
1597
1598impl_to_from!(Mint);
1599
1600impl NoneOrEmpty for Mint {
1601    fn is_none_or_empty(&self) -> bool {
1602        self.0.is_empty()
1603    }
1604}
1605
1606#[wasm_bindgen]
1607impl Mint {
1608    pub fn new() -> Self {
1609        Self(Vec::new())
1610    }
1611
1612    pub fn new_from_entry(key: &PolicyID, value: &MintAssets) -> Self {
1613        let mut m = Mint::new();
1614        m.insert(key, value);
1615        m
1616    }
1617
1618    pub fn len(&self) -> usize {
1619        self.0.len()
1620    }
1621
1622    //always returns None, because insert doesn't replace an old value
1623    pub fn insert(&mut self, key: &PolicyID, value: &MintAssets) -> Option<MintAssets> {
1624        self.0.push((key.clone(), value.clone()));
1625        None
1626    }
1627
1628    pub fn get(&self, key: &PolicyID) -> Option<MintsAssets> {
1629        let mints: Vec<MintAssets> = self
1630            .0
1631            .iter()
1632            .filter(|(k, _)| k.eq(key))
1633            .map(|(_k, v)| v.clone())
1634            .collect();
1635        if mints.is_empty() {
1636            None
1637        } else {
1638            Some(MintsAssets(mints))
1639        }
1640    }
1641
1642    pub fn keys(&self) -> PolicyIDs {
1643        ScriptHashes(
1644            self.0
1645                .iter()
1646                .map(|(k, _)| k.clone())
1647                .collect::<Vec<ScriptHash>>(),
1648        )
1649    }
1650
1651    fn as_multiasset(&self, is_positive: bool) -> MultiAsset {
1652        self.0
1653            .iter()
1654            .fold(MultiAsset::new(), |res, e: &(PolicyID, MintAssets)| {
1655                let assets: Assets = (e.1).0.iter().fold(Assets::new(), |res, e| {
1656                    let mut assets = res;
1657                    if e.1.is_positive() == is_positive {
1658                        let amount = match is_positive {
1659                            true => e.1.as_positive(),
1660                            false => e.1.as_negative(),
1661                        };
1662                        assets.insert(&e.0, &amount.unwrap());
1663                    }
1664                    assets
1665                });
1666                let mut ma = res;
1667                if !assets.0.is_empty() {
1668                    ma.insert(&e.0, &assets);
1669                }
1670                ma
1671            })
1672    }
1673
1674    /// Returns the multiasset where only positive (minting) entries are present
1675    pub fn as_positive_multiasset(&self) -> MultiAsset {
1676        self.as_multiasset(true)
1677    }
1678
1679    /// Returns the multiasset where only negative (burning) entries are present
1680    pub fn as_negative_multiasset(&self) -> MultiAsset {
1681        self.as_multiasset(false)
1682    }
1683}
1684
1685#[wasm_bindgen]
1686#[derive(
1687    Clone,
1688    Copy,
1689    Debug,
1690    Eq,
1691    Ord,
1692    PartialEq,
1693    PartialOrd,
1694    serde::Serialize,
1695    serde::Deserialize,
1696    JsonSchema,
1697)]
1698pub enum NetworkIdKind {
1699    Testnet,
1700    Mainnet,
1701}
1702
1703#[wasm_bindgen]
1704#[derive(
1705    Clone,
1706    Copy,
1707    Debug,
1708    Eq,
1709    Ord,
1710    PartialEq,
1711    PartialOrd,
1712    serde::Serialize,
1713    serde::Deserialize,
1714    JsonSchema,
1715)]
1716pub struct NetworkId(NetworkIdKind);
1717
1718impl_to_from!(NetworkId);
1719
1720#[wasm_bindgen]
1721impl NetworkId {
1722    pub fn testnet() -> Self {
1723        Self(NetworkIdKind::Testnet)
1724    }
1725
1726    pub fn mainnet() -> Self {
1727        Self(NetworkIdKind::Mainnet)
1728    }
1729
1730    pub fn kind(&self) -> NetworkIdKind {
1731        self.0
1732    }
1733}
1734
1735impl From<&NativeScript> for Ed25519KeyHashes {
1736    fn from(script: &NativeScript) -> Self {
1737        match &script.0 {
1738            NativeScriptEnum::ScriptPubkey(spk) => {
1739                let mut set = Ed25519KeyHashes::new();
1740                set.add_move(spk.addr_keyhash());
1741                set
1742            }
1743            NativeScriptEnum::ScriptAll(all) => Ed25519KeyHashes::from(&all.native_scripts),
1744            NativeScriptEnum::ScriptAny(any) => Ed25519KeyHashes::from(&any.native_scripts),
1745            NativeScriptEnum::ScriptNOfK(ofk) => Ed25519KeyHashes::from(&ofk.native_scripts),
1746            _ => Ed25519KeyHashes::new(),
1747        }
1748    }
1749}