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