1use std::string::ToString;
2use super::*;
3use crate::chain_crypto;
4use cbor_event::{self};
5
6#[derive(Debug)]
10pub enum Key {
11 Str(String),
12 Uint(u64),
13 OptUint(Option<u64>),
14}
15
16impl std::fmt::Display for Key {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 match self {
19 Key::Str(x) => write!(f, "\"{}\"", x),
20 Key::Uint(x) => write!(f, "{}", x),
21 Key::OptUint(Some(x)) => write!(f, "{}", x),
22 Key::OptUint(None) => write!(f, "null"),
23 }
24 }
25}
26
27#[derive(Debug)]
28pub enum DeserializeFailure {
29 BadAddressType(u8),
30 BreakInDefiniteLen,
31 CBOR(cbor_event::Error),
32 DefiniteLenMismatch(u64, Option<u64>),
33 DuplicateKey(Key),
34 EndingBreakMissing,
35 ExpectedNull,
36 ExpectedBool,
37 FixedValueMismatch {
38 found: Key,
39 expected: Key,
40 },
41 FixedValuesMismatch {
42 found: Key,
43 expected: Vec<Key>,
44 },
45 MandatoryFieldMissing(Key),
46 Metadata(JsError),
47 NoVariantMatched,
48 OutOfRange {
49 min: usize,
50 max: usize,
51 found: usize,
52 },
53 PublicKeyError(chain_crypto::PublicKeyError),
54 SignatureError(chain_crypto::SignatureError),
55 TagMismatch {
56 found: u64,
57 expected: u64,
58 },
59 UnknownKey(Key),
60 UnexpectedKeyType(cbor_event::Type),
61 VariableLenNatDecodeFailed,
62 IoError(String),
63 ExpectedType(String, cbor_event::Type),
64 CustomError(String),
65}
66
67#[derive(Debug)]
68pub struct DeserializeError {
69 location: Option<String>,
70 failure: DeserializeFailure,
71}
72
73impl DeserializeError {
74 pub fn new<T: Into<String>>(location: T, failure: DeserializeFailure) -> Self {
75 Self {
76 location: Some(location.into()),
77 failure,
78 }
79 }
80
81 pub fn annotate<T: Into<String>>(self, location: T) -> Self {
82 match self.location {
83 Some(loc) => Self::new(format!("{}.{}", location.into(), loc), self.failure),
84 None => Self::new(location, self.failure),
85 }
86 }
87}
88
89impl std::fmt::Display for DeserializeError {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match &self.location {
92 Some(loc) => write!(f, "Deserialization failed in {} because: ", loc),
93 None => write!(f, "Deserialization: "),
94 }?;
95 match &self.failure {
96 DeserializeFailure::BadAddressType(header) => {
97 write!(f, "Encountered unknown address header {:#08b}", header)
98 }
99 DeserializeFailure::BreakInDefiniteLen => write!(
100 f,
101 "Encountered CBOR Break while reading definite length sequence"
102 ),
103 DeserializeFailure::CBOR(e) => e.fmt(f),
104 DeserializeFailure::DefiniteLenMismatch(found, expected) => {
105 write!(f, "Definite length mismatch: found {}", found)?;
106 if let Some(expected_elems) = expected {
107 write!(f, ", expected: {}", expected_elems)?;
108 }
109 Ok(())
110 }
111 DeserializeFailure::DuplicateKey(key) => write!(f, "Duplicate key: {}", key),
112 DeserializeFailure::EndingBreakMissing => write!(f, "Missing ending CBOR Break"),
113 DeserializeFailure::ExpectedNull => write!(f, "Expected null, found other type"),
114 DeserializeFailure::ExpectedBool => write!(f, "Expected bool, found other type"),
115 DeserializeFailure::FixedValueMismatch { found, expected } => {
116 write!(f, "Expected fixed value {} found {}", expected, found)
117 }
118 DeserializeFailure::FixedValuesMismatch { found, expected } => {
119 write!(f, "Expected fixed value {:?} found {}", expected, found)
120 }
121 DeserializeFailure::MandatoryFieldMissing(key) => {
122 write!(f, "Mandatory field {} not found", key)
123 }
124 DeserializeFailure::Metadata(e) => write!(f, "Metadata error: {:?}", e),
125 DeserializeFailure::NoVariantMatched => write!(f, "No variant matched"),
126 DeserializeFailure::OutOfRange { min, max, found } => write!(
127 f,
128 "Out of range: {} - must be in range {} - {}",
129 found, min, max
130 ),
131 DeserializeFailure::PublicKeyError(e) => write!(f, "PublicKeyError error: {}", e),
132 DeserializeFailure::SignatureError(e) => write!(f, "Signature error: {}", e),
133 DeserializeFailure::TagMismatch { found, expected } => {
134 write!(f, "Expected tag {}, found {}", expected, found)
135 }
136 DeserializeFailure::UnknownKey(key) => write!(f, "Found unexpected key {}", key),
137 DeserializeFailure::UnexpectedKeyType(ty) => {
138 write!(f, "Found unexpected key of CBOR type {:?}", ty)
139 }
140 DeserializeFailure::VariableLenNatDecodeFailed => {
141 write!(f, "Variable length natural number decode failed")
142 }
143 DeserializeFailure::IoError(e) => write!(f, "IO error: {}", e),
144 DeserializeFailure::CustomError(e) => write!(f, "Deserialize error: {}", e),
145 DeserializeFailure::ExpectedType(expected, found) => {
146 write!(f, "Expected type {}, found {:?}", expected, found)
147 }
148 }
149 }
150}
151
152#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
153impl std::error::Error for DeserializeError {}
154
155impl From<DeserializeError> for JsError {
156 fn from(e: DeserializeError) -> JsError {
157 JsError::from_str(&e.to_string())
158 }
159}
160
161impl From<DeserializeFailure> for DeserializeError {
162 fn from(failure: DeserializeFailure) -> DeserializeError {
163 DeserializeError {
164 location: None,
165 failure,
166 }
167 }
168}
169
170impl From<cbor_event::Error> for DeserializeError {
171 fn from(err: cbor_event::Error) -> DeserializeError {
172 DeserializeError {
173 location: None,
174 failure: DeserializeFailure::CBOR(err),
175 }
176 }
177}
178
179impl From<chain_crypto::SignatureError> for DeserializeError {
180 fn from(err: chain_crypto::SignatureError) -> DeserializeError {
181 DeserializeError {
182 location: None,
183 failure: DeserializeFailure::SignatureError(err),
184 }
185 }
186}
187
188impl From<chain_crypto::PublicKeyError> for DeserializeError {
189 fn from(err: chain_crypto::PublicKeyError) -> DeserializeError {
190 DeserializeError {
191 location: None,
192 failure: DeserializeFailure::PublicKeyError(err),
193 }
194 }
195}
196
197#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
201pub type JsError = JsValue;
202
203#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
204#[derive(Debug, Clone)]
205pub struct JsError {
206 msg: String,
207}
208
209#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
210impl JsError {
211 pub fn from_str(s: &str) -> Self {
212 Self { msg: s.to_owned() }
213 }
214
215 pub fn as_string(&self) -> Option<String> {
217 Some(self.msg.clone())
218 }
219}
220
221#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
222impl std::fmt::Display for JsError {
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 write!(f, "{}", self.msg)
225 }
226}
227
228#[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))]
229impl std::error::Error for JsError {}
230
231pub(crate) enum BuilderError {
232 RegularInputIsScript,
233 RegularInputIsFromRewardAddress,
234 MalformedAddress,
235 ScriptAddressTypeMismatch,
236 RegularAddressTypeMismatch,
237 ScriptAddressCredentialMismatch,
238 MintBuilderDifferentScriptType,
239 MintBuilderDifferentRedeemerDataAndExUnits(String, String),
240 MintBuilderDifferentWitnessTypeRef,
241 MintBuilderDifferentWitnessTypeNonRef
242}
243
244impl BuilderError {
245 pub(crate) fn as_str(&self) -> String {
246 match self {
247 BuilderError::RegularInputIsScript => "You can't add a script input to this function. You can use `.add_native_script_utxo` or `.add_plutus_script_utxo` or `.add_native_script_input` or `.add_plutus_script_input` directly to register the input along with the witness.".to_string(),
248 BuilderError::RegularInputIsFromRewardAddress => "You can't use an input from reward address. To spend funds from reward address you to use withdrawal mechanism.".to_string(),
249 BuilderError::MalformedAddress => "The address is malformed.".to_string(),
250 BuilderError::MintBuilderDifferentScriptType => "You can't add a mint to the same policy id but with different script type.".to_string(),
251 BuilderError::MintBuilderDifferentRedeemerDataAndExUnits(redeemer1, redeemer2) => format!("You can't add a mint to the same policy id but with different redeemer data and ex units. Current redeemer {redeemer1}, your redeemer {redeemer2}"),
252 BuilderError::MintBuilderDifferentWitnessTypeRef => "You can't add a mint to the same policy id but with different witness type. Current witness is ref input".to_string(),
253 BuilderError::MintBuilderDifferentWitnessTypeNonRef => "You can't add a mint to the same policy id but with different witness type. Current witness is non ref".to_string(),
254 BuilderError::ScriptAddressTypeMismatch => "The address should be Base or Pointer or Enterprise.".to_string(),
255 BuilderError::RegularAddressTypeMismatch => "The address should be Base or Pointer or Enterprise or Byron.".to_string(),
256 BuilderError::ScriptAddressCredentialMismatch => "The address should have script payment credential.".to_string(),
257 }
258 }
259}