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