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
845impl serde::Serialize for Withdrawals {
846    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
847    where
848        S: serde::Serializer,
849    {
850        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
851        map.serialize(serializer)
852    }
853}
854
855impl<'de> serde::de::Deserialize<'de> for Withdrawals {
856    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
857    where
858        D: serde::de::Deserializer<'de>,
859    {
860        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
861            deserializer,
862        )?;
863        Ok(Self(map.into_iter().collect()))
864    }
865}
866
867impl JsonSchema for Withdrawals {
868    fn schema_name() -> String {
869        String::from("Withdrawals")
870    }
871    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
872        std::collections::BTreeMap::<RewardAddress, Coin>::json_schema(gen)
873    }
874    fn is_referenceable() -> bool {
875        std::collections::BTreeMap::<RewardAddress, Coin>::is_referenceable()
876    }
877}
878
879#[derive(
880    Debug, Clone, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
881)]
882pub enum DataOption {
883    DataHash(DataHash),
884    Data(PlutusData),
885}
886
887#[wasm_bindgen]
888#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
889pub struct OutputDatum(pub(crate) DataOption);
890
891#[wasm_bindgen]
892impl OutputDatum {
893    pub fn new_data_hash(data_hash: &DataHash) -> Self {
894        Self(DataOption::DataHash(data_hash.clone()))
895    }
896
897    pub fn new_data(data: &PlutusData) -> Self {
898        Self(DataOption::Data(data.clone()))
899    }
900
901    pub fn data_hash(&self) -> Option<DataHash> {
902        match &self.0 {
903            DataOption::DataHash(data_hash) => Some(data_hash.clone()),
904            _ => None,
905        }
906    }
907
908    pub fn data(&self) -> Option<PlutusData> {
909        match &self.0 {
910            DataOption::Data(data) => Some(data.clone()),
911            _ => None,
912        }
913    }
914}
915
916/// Each new language uses a different namespace for hashing its script
917/// This is because you could have a language where the same bytes have different semantics
918/// So this avoids scripts in different languages mapping to the same hash
919/// Note that the enum value here is different than the enum value for deciding the cost model of a script
920#[wasm_bindgen]
921#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
922pub enum ScriptHashNamespace {
923    NativeScript = 0,
924    PlutusScript = 1,
925    PlutusScriptV2 = 2,
926    PlutusScriptV3 = 3,
927}
928
929#[wasm_bindgen]
930#[derive(
931    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
932)]
933pub struct Update {
934    proposed_protocol_parameter_updates: ProposedProtocolParameterUpdates,
935    epoch: Epoch,
936}
937
938impl_to_from!(Update);
939
940#[wasm_bindgen]
941impl Update {
942    pub fn proposed_protocol_parameter_updates(&self) -> ProposedProtocolParameterUpdates {
943        self.proposed_protocol_parameter_updates.clone()
944    }
945
946    pub fn epoch(&self) -> Epoch {
947        self.epoch.clone()
948    }
949
950    pub fn new(
951        proposed_protocol_parameter_updates: &ProposedProtocolParameterUpdates,
952        epoch: Epoch,
953    ) -> Self {
954        Self {
955            proposed_protocol_parameter_updates: proposed_protocol_parameter_updates.clone(),
956            epoch: epoch.clone(),
957        }
958    }
959}
960
961#[wasm_bindgen]
962#[derive(
963    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
964)]
965pub struct GenesisHashes(Vec<GenesisHash>);
966
967impl_to_from!(GenesisHashes);
968
969#[wasm_bindgen]
970impl GenesisHashes {
971    pub fn new() -> Self {
972        Self(Vec::new())
973    }
974
975    pub fn len(&self) -> usize {
976        self.0.len()
977    }
978
979    pub fn get(&self, index: usize) -> GenesisHash {
980        self.0[index].clone()
981    }
982
983    pub fn add(&mut self, elem: &GenesisHash) {
984        self.0.push(elem.clone());
985    }
986}
987
988#[wasm_bindgen]
989#[derive(
990    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
991)]
992pub struct ScriptHashes(pub(crate) Vec<ScriptHash>);
993
994impl_to_from!(ScriptHashes);
995
996#[wasm_bindgen]
997impl ScriptHashes {
998    pub fn new() -> Self {
999        Self(Vec::new())
1000    }
1001
1002    pub fn len(&self) -> usize {
1003        self.0.len()
1004    }
1005
1006    pub fn get(&self, index: usize) -> ScriptHash {
1007        self.0[index].clone()
1008    }
1009
1010    pub fn add(&mut self, elem: &ScriptHash) {
1011        self.0.push(elem.clone());
1012    }
1013}
1014
1015#[wasm_bindgen]
1016#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1017pub struct ProposedProtocolParameterUpdates(
1018    LinkedHashMap<GenesisHash, ProtocolParamUpdate>,
1019);
1020
1021impl serde::Serialize for ProposedProtocolParameterUpdates {
1022    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1023    where
1024        S: serde::Serializer,
1025    {
1026        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
1027        map.serialize(serializer)
1028    }
1029}
1030
1031impl<'de> serde::de::Deserialize<'de> for ProposedProtocolParameterUpdates {
1032    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1033    where
1034        D: serde::de::Deserializer<'de>,
1035    {
1036        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
1037            deserializer,
1038        )?;
1039        Ok(Self(map.into_iter().collect()))
1040    }
1041}
1042
1043impl JsonSchema for ProposedProtocolParameterUpdates {
1044    fn schema_name() -> String {
1045        String::from("ProposedProtocolParameterUpdates")
1046    }
1047    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1048        std::collections::BTreeMap::<GenesisHash, ProtocolParamUpdate>::json_schema(gen)
1049    }
1050    fn is_referenceable() -> bool {
1051        std::collections::BTreeMap::<GenesisHash, ProtocolParamUpdate>::is_referenceable()
1052    }
1053}
1054
1055impl_to_from!(ProposedProtocolParameterUpdates);
1056
1057#[wasm_bindgen]
1058impl ProposedProtocolParameterUpdates {
1059    pub fn new() -> Self {
1060        Self(LinkedHashMap::new())
1061    }
1062
1063    pub fn len(&self) -> usize {
1064        self.0.len()
1065    }
1066
1067    pub fn insert(
1068        &mut self,
1069        key: &GenesisHash,
1070        value: &ProtocolParamUpdate,
1071    ) -> Option<ProtocolParamUpdate> {
1072        self.0.insert(key.clone(), value.clone())
1073    }
1074
1075    pub fn get(&self, key: &GenesisHash) -> Option<ProtocolParamUpdate> {
1076        self.0.get(key).map(|v| v.clone())
1077    }
1078
1079    pub fn keys(&self) -> GenesisHashes {
1080        GenesisHashes(
1081            self.0
1082                .iter()
1083                .map(|(k, _v)| k.clone())
1084                .collect::<Vec<GenesisHash>>(),
1085        )
1086    }
1087}
1088
1089#[wasm_bindgen]
1090#[derive(
1091    Clone,
1092    Debug,
1093    Hash,
1094    Eq,
1095    Ord,
1096    PartialEq,
1097    PartialOrd,
1098    serde::Serialize,
1099    serde::Deserialize,
1100    JsonSchema,
1101)]
1102pub struct ProtocolVersion {
1103    major: u32,
1104    minor: u32,
1105}
1106
1107impl_to_from!(ProtocolVersion);
1108
1109#[wasm_bindgen]
1110impl ProtocolVersion {
1111    pub fn major(&self) -> u32 {
1112        self.major
1113    }
1114
1115    pub fn minor(&self) -> u32 {
1116        self.minor
1117    }
1118
1119    pub fn new(major: u32, minor: u32) -> Self {
1120        Self { major, minor }
1121    }
1122}
1123
1124#[wasm_bindgen]
1125#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1126pub struct AuxiliaryDataSet(LinkedHashMap<TransactionIndex, AuxiliaryData>);
1127
1128#[wasm_bindgen]
1129impl AuxiliaryDataSet {
1130    pub fn new() -> Self {
1131        Self(LinkedHashMap::new())
1132    }
1133
1134    pub fn len(&self) -> usize {
1135        self.0.len()
1136    }
1137
1138    pub fn insert(
1139        &mut self,
1140        tx_index: TransactionIndex,
1141        data: &AuxiliaryData,
1142    ) -> Option<AuxiliaryData> {
1143        self.0.insert(tx_index, data.clone())
1144    }
1145
1146    pub fn get(&self, tx_index: TransactionIndex) -> Option<AuxiliaryData> {
1147        self.0.get(&tx_index).map(|v| v.clone())
1148    }
1149
1150    pub fn indices(&self) -> TransactionIndexes {
1151        self.0
1152            .iter()
1153            .map(|(k, _v)| k.clone())
1154            .collect::<Vec<TransactionIndex>>()
1155    }
1156}
1157
1158impl serde::Serialize for AuxiliaryDataSet {
1159    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1160    where
1161        S: serde::Serializer,
1162    {
1163        let map = self.0.iter().collect::<std::collections::BTreeMap<_, _>>();
1164        map.serialize(serializer)
1165    }
1166}
1167
1168impl<'de> serde::de::Deserialize<'de> for AuxiliaryDataSet {
1169    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1170    where
1171        D: serde::de::Deserializer<'de>,
1172    {
1173        let map = <std::collections::BTreeMap<_, _> as serde::de::Deserialize>::deserialize(
1174            deserializer,
1175        )?;
1176        Ok(Self(map.into_iter().collect()))
1177    }
1178}
1179
1180impl JsonSchema for AuxiliaryDataSet {
1181    fn schema_name() -> String {
1182        String::from("AuxiliaryDataSet")
1183    }
1184    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1185        std::collections::BTreeMap::<TransactionIndex, AuxiliaryData>::json_schema(gen)
1186    }
1187    fn is_referenceable() -> bool {
1188        std::collections::BTreeMap::<TransactionIndex, AuxiliaryData>::is_referenceable()
1189    }
1190}
1191
1192#[wasm_bindgen]
1193#[derive(Clone, Debug, Eq, PartialEq, Hash)]
1194pub struct AssetName(Vec<u8>);
1195
1196impl Display for AssetName {
1197    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1198        write!(f, "{}", hex::encode(&self.0))
1199    }
1200}
1201
1202impl Ord for AssetName {
1203    fn cmp(&self, other: &Self) -> Ordering {
1204        // Implementing canonical CBOR order for asset names,
1205        // as they might be of different length.
1206        return match self.0.len().cmp(&other.0.len()) {
1207            Ordering::Equal => self.0.cmp(&other.0),
1208            x => x,
1209        };
1210    }
1211}
1212
1213impl PartialOrd for AssetName {
1214    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1215        Some(self.cmp(other))
1216    }
1217}
1218
1219impl_to_from!(AssetName);
1220
1221#[wasm_bindgen]
1222impl AssetName {
1223    pub fn new(name: Vec<u8>) -> Result<AssetName, JsError> {
1224        Self::new_impl(name).map_err(|e| JsError::from_str(&e.to_string()))
1225    }
1226
1227    pub(crate) fn new_impl(name: Vec<u8>) -> Result<AssetName, DeserializeError> {
1228        if name.len() <= 32 {
1229            Ok(Self(name))
1230        } else {
1231            Err(DeserializeError::new(
1232                "AssetName",
1233                DeserializeFailure::OutOfRange {
1234                    min: 0,
1235                    max: 32,
1236                    found: name.len(),
1237                },
1238            ))
1239        }
1240    }
1241
1242    pub fn name(&self) -> Vec<u8> {
1243        self.0.clone()
1244    }
1245}
1246
1247impl serde::Serialize for AssetName {
1248    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1249    where
1250        S: serde::Serializer,
1251    {
1252        serializer.serialize_str(&hex::encode(&self.0))
1253    }
1254}
1255
1256impl<'de> serde::de::Deserialize<'de> for AssetName {
1257    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1258    where
1259        D: serde::de::Deserializer<'de>,
1260    {
1261        let s = <String as serde::de::Deserialize>::deserialize(deserializer)?;
1262        if let Ok(bytes) = hex::decode(&s) {
1263            if let Ok(asset_name) = AssetName::new(bytes) {
1264                return Ok(asset_name);
1265            }
1266        }
1267        Err(serde::de::Error::invalid_value(
1268            serde::de::Unexpected::Str(&s),
1269            &"AssetName as hex string e.g. F8AB28C2",
1270        ))
1271    }
1272}
1273
1274impl JsonSchema for AssetName {
1275    fn schema_name() -> String {
1276        String::from("AssetName")
1277    }
1278    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
1279        String::json_schema(gen)
1280    }
1281    fn is_referenceable() -> bool {
1282        String::is_referenceable()
1283    }
1284}
1285
1286#[wasm_bindgen]
1287#[derive(
1288    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1289)]
1290pub struct AssetNames(Vec<AssetName>);
1291
1292impl_to_from!(AssetNames);
1293
1294#[wasm_bindgen]
1295impl AssetNames {
1296    pub fn new() -> Self {
1297        Self(Vec::new())
1298    }
1299
1300    pub fn len(&self) -> usize {
1301        self.0.len()
1302    }
1303
1304    pub fn get(&self, index: usize) -> AssetName {
1305        self.0[index].clone()
1306    }
1307
1308    pub fn add(&mut self, elem: &AssetName) {
1309        self.0.push(elem.clone());
1310    }
1311}
1312
1313pub type PolicyID = ScriptHash;
1314pub type PolicyIDs = ScriptHashes;
1315
1316#[wasm_bindgen]
1317#[derive(
1318    Clone,
1319    Debug,
1320    Default,
1321    Eq,
1322    Ord,
1323    PartialEq,
1324    PartialOrd,
1325    serde::Serialize,
1326    serde::Deserialize,
1327    JsonSchema,
1328)]
1329pub struct Assets(pub(crate) std::collections::BTreeMap<AssetName, BigNum>);
1330
1331impl_to_from!(Assets);
1332
1333#[wasm_bindgen]
1334impl Assets {
1335    pub fn new() -> Self {
1336        Self(std::collections::BTreeMap::new())
1337    }
1338
1339    pub fn len(&self) -> usize {
1340        self.0.len()
1341    }
1342
1343    pub fn insert(&mut self, key: &AssetName, value: &BigNum) -> Option<BigNum> {
1344        self.0.insert(key.clone(), value.clone())
1345    }
1346
1347    pub fn get(&self, key: &AssetName) -> Option<BigNum> {
1348        self.0.get(key).map(|v| v.clone())
1349    }
1350
1351    pub fn keys(&self) -> AssetNames {
1352        AssetNames(
1353            self.0
1354                .iter()
1355                .map(|(k, _v)| k.clone())
1356                .collect::<Vec<AssetName>>(),
1357        )
1358    }
1359}
1360
1361#[wasm_bindgen]
1362#[derive(Clone, Debug, Eq, Ord, PartialEq, serde::Serialize, serde::Deserialize, JsonSchema)]
1363pub struct MultiAsset(pub(crate) std::collections::BTreeMap<PolicyID, Assets>);
1364
1365impl_to_from!(MultiAsset);
1366
1367#[wasm_bindgen]
1368impl MultiAsset {
1369    pub fn new() -> Self {
1370        Self(std::collections::BTreeMap::new())
1371    }
1372
1373    /// the number of unique policy IDs in the multiasset
1374    pub fn len(&self) -> usize {
1375        self.0.len()
1376    }
1377
1378    /// set (and replace if it exists) all assets with policy {policy_id} to a copy of {assets}
1379    pub fn insert(&mut self, policy_id: &PolicyID, assets: &Assets) -> Option<Assets> {
1380        self.0.insert(policy_id.clone(), assets.clone())
1381    }
1382
1383    /// all assets under {policy_id}, if any exist, or else None (undefined in JS)
1384    pub fn get(&self, policy_id: &PolicyID) -> Option<Assets> {
1385        self.0.get(policy_id).map(|v| v.clone())
1386    }
1387
1388    /// sets the asset {asset_name} to {value} under policy {policy_id}
1389    /// returns the previous amount if it was set, or else None (undefined in JS)
1390    pub fn set_asset(
1391        &mut self,
1392        policy_id: &PolicyID,
1393        asset_name: &AssetName,
1394        value: &BigNum,
1395    ) -> Option<BigNum> {
1396        self.0
1397            .entry(policy_id.clone())
1398            .or_default()
1399            .insert(asset_name, value)
1400    }
1401
1402    /// returns the amount of asset {asset_name} under policy {policy_id}
1403    /// If such an asset does not exist, 0 is returned.
1404    pub fn get_asset(&self, policy_id: &PolicyID, asset_name: &AssetName) -> BigNum {
1405        (|| self.0.get(policy_id)?.get(asset_name))().unwrap_or(BigNum::zero())
1406    }
1407
1408    /// returns all policy IDs used by assets in this multiasset
1409    pub fn keys(&self) -> PolicyIDs {
1410        ScriptHashes(
1411            self.0
1412                .iter()
1413                .map(|(k, _v)| k.clone())
1414                .collect::<Vec<PolicyID>>(),
1415        )
1416    }
1417
1418    /// removes an asset from the list if the result is 0 or less
1419    /// does not modify this object, instead the result is returned
1420    pub fn sub(&self, rhs_ma: &MultiAsset) -> MultiAsset {
1421        let mut lhs_ma = self.clone();
1422        for (policy, assets) in &rhs_ma.0 {
1423            for (asset_name, amount) in &assets.0 {
1424                match lhs_ma.0.get_mut(policy) {
1425                    Some(assets) => match assets.0.get_mut(asset_name) {
1426                        Some(current) => match current.checked_sub(&amount) {
1427                            Ok(new) => match new.compare(&BigNum(0)) {
1428                                0 => {
1429                                    assets.0.remove(asset_name);
1430                                    match assets.0.len() {
1431                                        0 => {
1432                                            lhs_ma.0.remove(policy);
1433                                        }
1434                                        _ => {}
1435                                    }
1436                                }
1437                                _ => *current = new,
1438                            },
1439                            Err(_) => {
1440                                assets.0.remove(asset_name);
1441                                match assets.0.len() {
1442                                    0 => {
1443                                        lhs_ma.0.remove(policy);
1444                                    }
1445                                    _ => {}
1446                                }
1447                            }
1448                        },
1449                        None => {
1450                            // asset name is missing from left hand side
1451                        }
1452                    },
1453                    None => {
1454                        // policy id missing from left hand side
1455                    }
1456                }
1457            }
1458        }
1459        lhs_ma
1460    }
1461
1462    pub(crate) fn reduce_empty_to_none(&self) -> Option<&MultiAsset> {
1463        for (_policy, assets) in self.0.iter() {
1464            if assets.len() > 0 {
1465                return Some(self);
1466            }
1467        }
1468
1469        None
1470    }
1471}
1472
1473// deriving PartialOrd doesn't work in a way that's useful , as the
1474// implementation of PartialOrd for BTreeMap compares keys by their order,
1475// i.e, is equivalent to comparing the iterators of (pid, Assets).
1476// that would mean that: v1 < v2 if the min_pid(v1) < min_pid(v2)
1477// this function instead compares amounts, assuming that if a pair (pid, aname)
1478// is not in the MultiAsset then it has an amount of 0
1479impl PartialOrd for MultiAsset {
1480    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1481        fn amount_or_zero(ma: &MultiAsset, pid: &PolicyID, aname: &AssetName) -> Coin {
1482            ma.get(&pid)
1483                .and_then(|assets| assets.get(aname))
1484                .unwrap_or(BigNum(0u64)) // assume 0 if asset not present
1485        }
1486
1487        // idea: if (a-b) > 0 for some asset, then a > b for at least some asset
1488        fn is_all_zeros(lhs: &MultiAsset, rhs: &MultiAsset) -> bool {
1489            for (pid, assets) in lhs.0.iter() {
1490                for (aname, amount) in assets.0.iter() {
1491                    match amount
1492                        .clamped_sub(&amount_or_zero(&rhs, pid, aname))
1493                        .cmp(&BigNum::zero())
1494                    {
1495                        std::cmp::Ordering::Equal => (),
1496                        _ => return false,
1497                    }
1498                }
1499            }
1500            true
1501        }
1502
1503        match (is_all_zeros(self, other), is_all_zeros(other, self)) {
1504            (true, true) => Some(std::cmp::Ordering::Equal),
1505            (true, false) => Some(std::cmp::Ordering::Less),
1506            (false, true) => Some(std::cmp::Ordering::Greater),
1507            (false, false) => None,
1508        }
1509    }
1510}
1511
1512#[wasm_bindgen]
1513#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema)]
1514pub struct MintsAssets(Vec<MintAssets>);
1515
1516to_from_json!(MintsAssets);
1517
1518#[wasm_bindgen]
1519impl MintsAssets {
1520    pub fn new() -> Self {
1521        Self(Vec::new())
1522    }
1523
1524    pub fn add(&mut self, mint_assets: &MintAssets) {
1525        self.0.push(mint_assets.clone())
1526    }
1527
1528    pub fn get(&self, index: usize) -> Option<MintAssets> {
1529        self.0.get(index).map(|v| v.clone())
1530    }
1531
1532    pub fn len(&self) -> usize {
1533        self.0.len()
1534    }
1535}
1536
1537#[wasm_bindgen]
1538#[derive(
1539    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1540)]
1541pub struct MintAssets(std::collections::BTreeMap<AssetName, Int>);
1542
1543#[wasm_bindgen]
1544impl MintAssets {
1545    pub fn new() -> Self {
1546        Self(std::collections::BTreeMap::new())
1547    }
1548
1549    pub fn new_from_entry(key: &AssetName, value: &Int) -> Result<MintAssets, JsError> {
1550        if value.0 == 0 {
1551            return Err(JsError::from_str("MintAssets cannot be created with 0 value"));
1552        }
1553        let mut ma = MintAssets::new();
1554        ma.insert(key, value)?;
1555        Ok(ma)
1556    }
1557
1558    pub fn len(&self) -> usize {
1559        self.0.len()
1560    }
1561
1562    pub fn insert(&mut self, key: &AssetName, value: &Int) -> Result<Option<Int>, JsError> {
1563        if value.0 == 0 {
1564            return Err(JsError::from_str("MintAssets cannot be created with 0 value"));
1565        }
1566        Ok(self.0.insert(key.clone(), value.clone()))
1567    }
1568
1569    pub(crate) fn insert_unchecked(&mut self, key: &AssetName, value: Int) -> Option<Int> {
1570        self.0.insert(key.clone(), value)
1571    }
1572
1573    pub fn get(&self, key: &AssetName) -> Option<Int> {
1574        self.0.get(key).map(|v| v.clone())
1575    }
1576
1577    pub fn keys(&self) -> AssetNames {
1578        AssetNames(
1579            self.0
1580                .iter()
1581                .map(|(k, _v)| k.clone())
1582                .collect::<Vec<AssetName>>(),
1583        )
1584    }
1585}
1586
1587#[wasm_bindgen]
1588#[derive(
1589    Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize, JsonSchema,
1590)]
1591pub struct Mint(Vec<(PolicyID, MintAssets)>);
1592
1593impl_to_from!(Mint);
1594
1595impl NoneOrEmpty for Mint {
1596    fn is_none_or_empty(&self) -> bool {
1597        self.0.is_empty()
1598    }
1599}
1600
1601#[wasm_bindgen]
1602impl Mint {
1603    pub fn new() -> Self {
1604        Self(Vec::new())
1605    }
1606
1607    pub fn new_from_entry(key: &PolicyID, value: &MintAssets) -> Self {
1608        let mut m = Mint::new();
1609        m.insert(key, value);
1610        m
1611    }
1612
1613    pub fn len(&self) -> usize {
1614        self.0.len()
1615    }
1616
1617    //always returns None, because insert doesn't replace an old value
1618    pub fn insert(&mut self, key: &PolicyID, value: &MintAssets) -> Option<MintAssets> {
1619        self.0.push((key.clone(), value.clone()));
1620        None
1621    }
1622
1623    pub fn get(&self, key: &PolicyID) -> Option<MintsAssets> {
1624        let mints: Vec<MintAssets> = self
1625            .0
1626            .iter()
1627            .filter(|(k, _)| k.eq(key))
1628            .map(|(_k, v)| v.clone())
1629            .collect();
1630        if mints.is_empty() {
1631            None
1632        } else {
1633            Some(MintsAssets(mints))
1634        }
1635    }
1636
1637    pub fn keys(&self) -> PolicyIDs {
1638        ScriptHashes(
1639            self.0
1640                .iter()
1641                .map(|(k, _)| k.clone())
1642                .collect::<Vec<ScriptHash>>(),
1643        )
1644    }
1645
1646    fn as_multiasset(&self, is_positive: bool) -> MultiAsset {
1647        self.0
1648            .iter()
1649            .fold(MultiAsset::new(), |res, e: &(PolicyID, MintAssets)| {
1650                let assets: Assets = (e.1).0.iter().fold(Assets::new(), |res, e| {
1651                    let mut assets = res;
1652                    if e.1.is_positive() == is_positive {
1653                        let amount = match is_positive {
1654                            true => e.1.as_positive(),
1655                            false => e.1.as_negative(),
1656                        };
1657                        assets.insert(&e.0, &amount.unwrap());
1658                    }
1659                    assets
1660                });
1661                let mut ma = res;
1662                if !assets.0.is_empty() {
1663                    ma.insert(&e.0, &assets);
1664                }
1665                ma
1666            })
1667    }
1668
1669    /// Returns the multiasset where only positive (minting) entries are present
1670    pub fn as_positive_multiasset(&self) -> MultiAsset {
1671        self.as_multiasset(true)
1672    }
1673
1674    /// Returns the multiasset where only negative (burning) entries are present
1675    pub fn as_negative_multiasset(&self) -> MultiAsset {
1676        self.as_multiasset(false)
1677    }
1678}
1679
1680#[wasm_bindgen]
1681#[derive(
1682    Clone,
1683    Copy,
1684    Debug,
1685    Eq,
1686    Ord,
1687    PartialEq,
1688    PartialOrd,
1689    serde::Serialize,
1690    serde::Deserialize,
1691    JsonSchema,
1692)]
1693pub enum NetworkIdKind {
1694    Testnet,
1695    Mainnet,
1696}
1697
1698#[wasm_bindgen]
1699#[derive(
1700    Clone,
1701    Copy,
1702    Debug,
1703    Eq,
1704    Ord,
1705    PartialEq,
1706    PartialOrd,
1707    serde::Serialize,
1708    serde::Deserialize,
1709    JsonSchema,
1710)]
1711pub struct NetworkId(NetworkIdKind);
1712
1713impl_to_from!(NetworkId);
1714
1715#[wasm_bindgen]
1716impl NetworkId {
1717    pub fn testnet() -> Self {
1718        Self(NetworkIdKind::Testnet)
1719    }
1720
1721    pub fn mainnet() -> Self {
1722        Self(NetworkIdKind::Mainnet)
1723    }
1724
1725    pub fn kind(&self) -> NetworkIdKind {
1726        self.0
1727    }
1728}
1729
1730impl From<&NativeScript> for Ed25519KeyHashes {
1731    fn from(script: &NativeScript) -> Self {
1732        match &script.0 {
1733            NativeScriptEnum::ScriptPubkey(spk) => {
1734                let mut set = Ed25519KeyHashes::new();
1735                set.add_move(spk.addr_keyhash());
1736                set
1737            }
1738            NativeScriptEnum::ScriptAll(all) => Ed25519KeyHashes::from(&all.native_scripts),
1739            NativeScriptEnum::ScriptAny(any) => Ed25519KeyHashes::from(&any.native_scripts),
1740            NativeScriptEnum::ScriptNOfK(ofk) => Ed25519KeyHashes::from(&ofk.native_scripts),
1741            _ => Ed25519KeyHashes::new(),
1742        }
1743    }
1744}