1use std::collections::HashMap;
8
9use async_trait::async_trait;
10
11use crate::primitives::public_key::PublicKey;
12use crate::wallet::error::WalletError;
13use crate::wallet::types::{
14 BasketStringUnder300Bytes, BooleanDefaultFalse, BooleanDefaultTrue, Counterparty,
15 DescriptionString5to50Bytes, LabelStringUnder300Bytes, OutpointString,
16 OutputTagStringUnder300Bytes, PositiveIntegerDefault10Max10000, PositiveIntegerOrZero,
17 Protocol, SatoshiValue, TXIDHexString,
18};
19
20#[cfg(feature = "serde")]
27pub(crate) mod serde_helpers {
28 use crate::primitives::public_key::PublicKey;
29
30 pub mod public_key_hex {
32 use super::PublicKey;
33 use serde::{self, Deserialize, Deserializer, Serializer};
34
35 pub fn serialize<S>(pk: &PublicKey, serializer: S) -> Result<S::Ok, S::Error>
36 where
37 S: Serializer,
38 {
39 serializer.serialize_str(&pk.to_der_hex())
40 }
41
42 pub fn deserialize<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
43 where
44 D: Deserializer<'de>,
45 {
46 let s = String::deserialize(deserializer)?;
47 PublicKey::from_string(&s).map_err(serde::de::Error::custom)
48 }
49 }
50
51 #[allow(dead_code)]
53 pub mod option_public_key_hex {
54 use super::PublicKey;
55 use serde::{self, Deserialize, Deserializer, Serializer};
56
57 pub fn serialize<S>(pk: &Option<PublicKey>, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: Serializer,
60 {
61 match pk {
62 Some(pk) => serializer.serialize_str(&pk.to_der_hex()),
63 None => serializer.serialize_none(),
64 }
65 }
66
67 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<PublicKey>, D::Error>
68 where
69 D: Deserializer<'de>,
70 {
71 let opt: Option<String> = Option::deserialize(deserializer)?;
72 match opt {
73 Some(s) if !s.is_empty() => PublicKey::from_string(&s)
74 .map(Some)
75 .map_err(serde::de::Error::custom),
76 _ => Ok(None),
77 }
78 }
79 }
80
81 pub mod vec_public_key_hex {
83 use super::PublicKey;
84 use serde::ser::SerializeSeq;
85 use serde::{self, Deserialize, Deserializer, Serializer};
86
87 pub fn serialize<S>(pks: &[PublicKey], serializer: S) -> Result<S::Ok, S::Error>
88 where
89 S: Serializer,
90 {
91 let mut seq = serializer.serialize_seq(Some(pks.len()))?;
92 for pk in pks {
93 seq.serialize_element(&pk.to_der_hex())?;
94 }
95 seq.end()
96 }
97
98 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<PublicKey>, D::Error>
99 where
100 D: Deserializer<'de>,
101 {
102 let strs: Vec<String> = Vec::deserialize(deserializer)?;
103 strs.iter()
104 .map(|s| PublicKey::from_string(s).map_err(serde::de::Error::custom))
105 .collect()
106 }
107 }
108
109 pub mod bytes32_base64 {
111 use serde::{self, Deserialize, Deserializer, Serializer};
112
113 pub fn serialize<S>(bytes: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
114 where
115 S: Serializer,
116 {
117 serializer.serialize_str(&base64_encode(bytes))
118 }
119
120 pub fn deserialize<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
121 where
122 D: Deserializer<'de>,
123 {
124 let s = String::deserialize(deserializer)?;
125 let decoded = base64_decode(&s).map_err(serde::de::Error::custom)?;
126 if decoded.len() > 32 {
127 return Err(serde::de::Error::custom(
128 "base64 decoded value exceeds 32 bytes",
129 ));
130 }
131 let mut buf = [0u8; 32];
132 buf[..decoded.len()].copy_from_slice(&decoded);
133 Ok(buf)
134 }
135
136 pub(super) fn base64_encode_vec(data: &[u8]) -> String {
138 base64_encode(data)
139 }
140
141 pub(super) fn base64_decode_vec(s: &str) -> Result<Vec<u8>, String> {
143 base64_decode(s)
144 }
145
146 fn base64_encode(data: &[u8]) -> String {
147 const CHARS: &[u8] =
148 b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
149 let mut result = String::new();
150 let chunks = data.chunks(3);
151 for chunk in chunks {
152 let b0 = chunk[0] as u32;
153 let b1 = if chunk.len() > 1 { chunk[1] as u32 } else { 0 };
154 let b2 = if chunk.len() > 2 { chunk[2] as u32 } else { 0 };
155 let triple = (b0 << 16) | (b1 << 8) | b2;
156 result.push(CHARS[((triple >> 18) & 0x3F) as usize] as char);
157 result.push(CHARS[((triple >> 12) & 0x3F) as usize] as char);
158 if chunk.len() > 1 {
159 result.push(CHARS[((triple >> 6) & 0x3F) as usize] as char);
160 } else {
161 result.push('=');
162 }
163 if chunk.len() > 2 {
164 result.push(CHARS[(triple & 0x3F) as usize] as char);
165 } else {
166 result.push('=');
167 }
168 }
169 result
170 }
171
172 fn base64_decode(s: &str) -> Result<Vec<u8>, String> {
173 fn char_to_val(c: u8) -> Result<u8, String> {
174 match c {
175 b'A'..=b'Z' => Ok(c - b'A'),
176 b'a'..=b'z' => Ok(c - b'a' + 26),
177 b'0'..=b'9' => Ok(c - b'0' + 52),
178 b'+' => Ok(62),
179 b'/' => Ok(63),
180 _ => Err(format!("invalid base64 character: {}", c as char)),
181 }
182 }
183 let bytes = s.as_bytes();
184 let mut result = Vec::new();
185 let mut i = 0;
186 while i < bytes.len() {
187 if bytes[i] == b'=' {
188 break;
189 }
190 let a = char_to_val(bytes[i])?;
191 let b = if i + 1 < bytes.len() && bytes[i + 1] != b'=' {
192 char_to_val(bytes[i + 1])?
193 } else {
194 0
195 };
196 let c = if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
197 char_to_val(bytes[i + 2])?
198 } else {
199 0
200 };
201 let d = if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
202 char_to_val(bytes[i + 3])?
203 } else {
204 0
205 };
206 let triple =
207 ((a as u32) << 18) | ((b as u32) << 12) | ((c as u32) << 6) | (d as u32);
208 result.push(((triple >> 16) & 0xFF) as u8);
209 if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
210 result.push(((triple >> 8) & 0xFF) as u8);
211 }
212 if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
213 result.push((triple & 0xFF) as u8);
214 }
215 i += 4;
216 }
217 Ok(result)
218 }
219 }
220
221 pub mod bytes_as_base64 {
226 use serde::{self, Deserialize, Deserializer, Serializer};
227
228 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
229 where
230 S: Serializer,
231 {
232 serializer.serialize_str(&super::bytes32_base64::base64_encode_vec(bytes))
233 }
234
235 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
236 where
237 D: Deserializer<'de>,
238 {
239 let s = String::deserialize(deserializer)?;
240 super::bytes32_base64::base64_decode_vec(&s).map_err(serde::de::Error::custom)
241 }
242 }
243
244 pub mod bytes_as_array {
246 use serde::{Deserialize, Deserializer, Serializer};
247
248 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
249 where
250 S: Serializer,
251 {
252 serializer.collect_seq(bytes.iter())
253 }
254
255 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
256 where
257 D: Deserializer<'de>,
258 {
259 Vec::<u8>::deserialize(deserializer)
260 }
261 }
262
263 pub mod option_bytes_as_array {
265 use serde::{Deserialize, Deserializer, Serializer};
266
267 pub fn serialize<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
268 where
269 S: Serializer,
270 {
271 match bytes {
272 Some(b) => serializer.collect_seq(b.iter()),
273 None => serializer.serialize_none(),
274 }
275 }
276
277 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
278 where
279 D: Deserializer<'de>,
280 {
281 Option::<Vec<u8>>::deserialize(deserializer)
282 }
283 }
284
285 pub mod bytes_as_hex {
287 use serde::{self, Deserialize, Deserializer, Serializer};
288
289 pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
290 where
291 S: Serializer,
292 {
293 serializer.serialize_str(&to_hex(bytes))
294 }
295
296 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
297 where
298 D: Deserializer<'de>,
299 {
300 let s = String::deserialize(deserializer)?;
301 from_hex(&s).map_err(serde::de::Error::custom)
302 }
303
304 fn to_hex(bytes: &[u8]) -> String {
305 const HEX: &[u8; 16] = b"0123456789abcdef";
306 let mut s = String::with_capacity(bytes.len() * 2);
307 for &b in bytes {
308 s.push(HEX[(b >> 4) as usize] as char);
309 s.push(HEX[(b & 0xf) as usize] as char);
310 }
311 s
312 }
313
314 pub(crate) fn from_hex(s: &str) -> Result<Vec<u8>, String> {
315 if !s.len().is_multiple_of(2) {
316 return Err("hex string has odd length".to_string());
317 }
318 let bytes = s.as_bytes();
319 let mut result = Vec::with_capacity(bytes.len() / 2);
320 for chunk in bytes.chunks(2) {
321 let hi = hex_val(chunk[0])?;
322 let lo = hex_val(chunk[1])?;
323 result.push((hi << 4) | lo);
324 }
325 Ok(result)
326 }
327
328 fn hex_val(b: u8) -> Result<u8, String> {
329 match b {
330 b'0'..=b'9' => Ok(b - b'0'),
331 b'a'..=b'f' => Ok(b - b'a' + 10),
332 b'A'..=b'F' => Ok(b - b'A' + 10),
333 _ => Err(format!("invalid hex character: {}", b as char)),
334 }
335 }
336 }
337
338 pub mod option_bytes_as_hex {
340 use serde::{self, Deserialize, Deserializer, Serializer};
341
342 pub fn serialize<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
343 where
344 S: Serializer,
345 {
346 match bytes {
347 Some(b) => super::bytes_as_hex::serialize(b, serializer),
348 None => serializer.serialize_none(),
349 }
350 }
351
352 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
353 where
354 D: Deserializer<'de>,
355 {
356 let opt: Option<String> = Option::deserialize(deserializer)?;
357 match opt {
358 Some(s) if !s.is_empty() => super::bytes_as_hex::from_hex(&s)
359 .map(Some)
360 .map_err(serde::de::Error::custom),
361 _ => Ok(None),
362 }
363 }
364 }
365}
366
367#[cfg(feature = "serde")]
373fn is_false(b: &bool) -> bool {
374 !*b
375}
376
377#[derive(Clone, Debug, PartialEq, Eq)]
383#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
384#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
385pub enum ActionStatus {
386 Completed,
387 Unprocessed,
388 Sending,
389 Unproven,
390 Unsigned,
391 #[cfg_attr(feature = "serde", serde(rename = "nosend"))]
392 NoSend,
393 #[cfg_attr(feature = "serde", serde(rename = "nonfinal"))]
394 NonFinal,
395 Failed,
396}
397
398impl ActionStatus {
399 pub fn as_str(&self) -> &'static str {
400 match self {
401 ActionStatus::Completed => "completed",
402 ActionStatus::Unprocessed => "unprocessed",
403 ActionStatus::Sending => "sending",
404 ActionStatus::Unproven => "unproven",
405 ActionStatus::Unsigned => "unsigned",
406 ActionStatus::NoSend => "nosend",
407 ActionStatus::NonFinal => "nonfinal",
408 ActionStatus::Failed => "failed",
409 }
410 }
411}
412
413#[derive(Clone, Debug, PartialEq, Eq)]
415#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
416#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
417pub enum ActionResultStatus {
418 Unproven,
419 Sending,
420 Failed,
421}
422
423impl ActionResultStatus {
424 pub fn as_str(&self) -> &'static str {
425 match self {
426 ActionResultStatus::Unproven => "unproven",
427 ActionResultStatus::Sending => "sending",
428 ActionResultStatus::Failed => "failed",
429 }
430 }
431}
432
433#[derive(Clone, Debug, PartialEq, Eq)]
435#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
436#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
437pub enum QueryMode {
438 Any,
439 All,
440}
441
442impl QueryMode {
443 pub fn as_str(&self) -> &'static str {
444 match self {
445 QueryMode::Any => "any",
446 QueryMode::All => "all",
447 }
448 }
449}
450
451#[derive(Clone, Debug, PartialEq, Eq)]
453#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
454pub enum OutputInclude {
455 #[cfg_attr(feature = "serde", serde(rename = "locking scripts"))]
456 LockingScripts,
457 #[cfg_attr(feature = "serde", serde(rename = "entire transactions"))]
458 EntireTransactions,
459}
460
461impl OutputInclude {
462 pub fn as_str(&self) -> &'static str {
463 match self {
464 OutputInclude::LockingScripts => "locking scripts",
465 OutputInclude::EntireTransactions => "entire transactions",
466 }
467 }
468}
469
470#[derive(Clone, Debug, PartialEq, Eq)]
472#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
473pub enum InternalizeProtocol {
474 #[cfg_attr(feature = "serde", serde(rename = "wallet payment"))]
475 WalletPayment,
476 #[cfg_attr(feature = "serde", serde(rename = "basket insertion"))]
477 BasketInsertion,
478}
479
480impl InternalizeProtocol {
481 pub fn as_str(&self) -> &'static str {
482 match self {
483 InternalizeProtocol::WalletPayment => "wallet payment",
484 InternalizeProtocol::BasketInsertion => "basket insertion",
485 }
486 }
487}
488
489#[derive(Clone, Debug, PartialEq, Eq)]
491#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
492#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
493pub enum AcquisitionProtocol {
494 Direct,
495 Issuance,
496}
497
498impl AcquisitionProtocol {
499 pub fn as_str(&self) -> &'static str {
500 match self {
501 AcquisitionProtocol::Direct => "direct",
502 AcquisitionProtocol::Issuance => "issuance",
503 }
504 }
505}
506
507#[derive(Clone, Debug, PartialEq, Eq)]
509#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
510#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
511pub enum Network {
512 Mainnet,
513 Testnet,
514}
515
516impl Network {
517 pub fn as_str(&self) -> &'static str {
518 match self {
519 Network::Mainnet => "mainnet",
520 Network::Testnet => "testnet",
521 }
522 }
523}
524
525#[derive(Clone, Debug, PartialEq, Eq)]
527#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
528#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
529pub enum TrustSelf {
530 Known,
531}
532
533impl TrustSelf {
534 pub fn as_str(&self) -> &'static str {
535 match self {
536 TrustSelf::Known => "known",
537 }
538 }
539}
540
541#[derive(Clone, Debug, PartialEq, Eq, Hash)]
548pub struct CertificateType(pub [u8; 32]);
549
550#[cfg(feature = "serde")]
551impl serde::Serialize for CertificateType {
552 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
553 serde_helpers::bytes32_base64::serialize(&self.0, serializer)
554 }
555}
556
557#[cfg(feature = "serde")]
558impl<'de> serde::Deserialize<'de> for CertificateType {
559 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
560 serde_helpers::bytes32_base64::deserialize(deserializer).map(CertificateType)
561 }
562}
563
564impl CertificateType {
565 pub fn from_string(s: &str) -> Result<Self, WalletError> {
570 let bytes = if s.len() == 44 || (!s.is_empty() && s.ends_with('=')) {
571 SerialNumber::base64_decode_sn(s)?
572 } else if s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) {
573 crate::primitives::utils::from_hex(s)
574 .map_err(|e| WalletError::InvalidParameter(format!("hex: {e}")))?
575 } else if s.len() <= 32 {
576 let mut buf = [0u8; 32];
577 buf[..s.len()].copy_from_slice(s.as_bytes());
578 return Ok(CertificateType(buf));
579 } else {
580 return Err(WalletError::InvalidParameter(format!(
581 "CertificateType: unsupported string length {}",
582 s.len()
583 )));
584 };
585 if bytes.len() != 32 {
586 return Err(WalletError::InvalidParameter(format!(
587 "CertificateType must decode to 32 bytes, got {}",
588 bytes.len()
589 )));
590 }
591 let mut buf = [0u8; 32];
592 buf.copy_from_slice(&bytes);
593 Ok(CertificateType(buf))
594 }
595
596 pub fn bytes(&self) -> &[u8; 32] {
597 &self.0
598 }
599}
600
601#[derive(Clone, Debug, PartialEq, Eq, Hash)]
604pub struct SerialNumber(pub [u8; 32]);
605
606#[cfg(feature = "serde")]
607impl serde::Serialize for SerialNumber {
608 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
609 serde_helpers::bytes32_base64::serialize(&self.0, serializer)
610 }
611}
612
613#[cfg(feature = "serde")]
614impl<'de> serde::Deserialize<'de> for SerialNumber {
615 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
616 serde_helpers::bytes32_base64::deserialize(deserializer).map(SerialNumber)
617 }
618}
619
620impl SerialNumber {
621 pub fn from_string(s: &str) -> Result<Self, WalletError> {
629 let bytes = if s.len() == 44 || (!s.is_empty() && s.ends_with('=')) {
630 Self::base64_decode_sn(s)?
632 } else if s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) {
633 crate::primitives::utils::from_hex(s)
635 .map_err(|e| WalletError::InvalidParameter(format!("hex: {e}")))?
636 } else {
637 return Err(WalletError::InvalidParameter(format!(
638 "SerialNumber string must be 44 (base64) or 64 (hex) chars, got {}",
639 s.len()
640 )));
641 };
642 if bytes.len() != 32 {
643 return Err(WalletError::InvalidParameter(
644 "SerialNumber must decode to 32 bytes".into(),
645 ));
646 }
647 let mut buf = [0u8; 32];
648 buf.copy_from_slice(&bytes);
649 Ok(SerialNumber(buf))
650 }
651
652 pub(crate) fn base64_decode_sn(s: &str) -> Result<Vec<u8>, WalletError> {
654 fn b64_val(c: u8) -> Result<u8, WalletError> {
655 match c {
656 b'A'..=b'Z' => Ok(c - b'A'),
657 b'a'..=b'z' => Ok(c - b'a' + 26),
658 b'0'..=b'9' => Ok(c - b'0' + 52),
659 b'+' => Ok(62),
660 b'/' => Ok(63),
661 _ => Err(WalletError::InvalidParameter(format!(
662 "invalid base64 character: {}",
663 c as char
664 ))),
665 }
666 }
667 let bytes = s.as_bytes();
668 let mut result = Vec::new();
669 let mut i = 0;
670 while i < bytes.len() {
671 if bytes[i] == b'=' {
672 break;
673 }
674 let a = b64_val(bytes[i])?;
675 let b = if i + 1 < bytes.len() && bytes[i + 1] != b'=' {
676 b64_val(bytes[i + 1])?
677 } else {
678 0
679 };
680 let c = if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
681 b64_val(bytes[i + 2])?
682 } else {
683 0
684 };
685 let d = if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
686 b64_val(bytes[i + 3])?
687 } else {
688 0
689 };
690 let n = (a as u32) << 18 | (b as u32) << 12 | (c as u32) << 6 | (d as u32);
691 result.push((n >> 16) as u8);
692 if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
693 result.push((n >> 8) as u8);
694 }
695 if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
696 result.push(n as u8);
697 }
698 i += 4;
699 }
700 Ok(result)
701 }
702
703 pub fn bytes(&self) -> &[u8; 32] {
704 &self.0
705 }
706}
707
708#[derive(Clone, Debug)]
710#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
711#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
712pub struct Certificate {
713 #[cfg_attr(feature = "serde", serde(rename = "type"))]
714 pub cert_type: CertificateType,
715 pub serial_number: SerialNumber,
716 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
717 pub subject: PublicKey,
718 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
719 pub certifier: PublicKey,
720 #[cfg_attr(
727 feature = "serde",
728 serde(default, skip_serializing_if = "Option::is_none")
729 )]
730 pub revocation_outpoint: Option<String>,
731 #[cfg_attr(
732 feature = "serde",
733 serde(default, skip_serializing_if = "Option::is_none")
734 )]
735 pub fields: Option<HashMap<String, String>>,
736 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
737 #[cfg_attr(
738 feature = "serde",
739 serde(default, skip_serializing_if = "Option::is_none")
740 )]
741 pub signature: Option<Vec<u8>>,
742}
743
744#[derive(Clone, Debug)]
747#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
748#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
749pub struct PartialCertificate {
750 #[cfg_attr(feature = "serde", serde(rename = "type"))]
751 #[cfg_attr(
752 feature = "serde",
753 serde(default, skip_serializing_if = "Option::is_none")
754 )]
755 pub cert_type: Option<CertificateType>,
756 #[cfg_attr(
757 feature = "serde",
758 serde(default, skip_serializing_if = "Option::is_none")
759 )]
760 pub serial_number: Option<SerialNumber>,
761 #[cfg_attr(
762 feature = "serde",
763 serde(with = "serde_helpers::option_public_key_hex")
764 )]
765 #[cfg_attr(feature = "serde", serde(default))]
766 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
767 pub subject: Option<PublicKey>,
768 #[cfg_attr(
769 feature = "serde",
770 serde(with = "serde_helpers::option_public_key_hex")
771 )]
772 #[cfg_attr(feature = "serde", serde(default))]
773 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
774 pub certifier: Option<PublicKey>,
775 #[cfg_attr(
776 feature = "serde",
777 serde(default, skip_serializing_if = "Option::is_none")
778 )]
779 pub revocation_outpoint: Option<String>,
780 #[cfg_attr(
781 feature = "serde",
782 serde(default, skip_serializing_if = "Option::is_none")
783 )]
784 pub fields: Option<HashMap<String, String>>,
785 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
786 #[cfg_attr(feature = "serde", serde(default))]
787 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
788 pub signature: Option<Vec<u8>>,
789}
790
791impl From<Certificate> for PartialCertificate {
792 fn from(c: Certificate) -> Self {
793 PartialCertificate {
794 cert_type: Some(c.cert_type),
795 serial_number: Some(c.serial_number),
796 subject: Some(c.subject),
797 certifier: Some(c.certifier),
798 revocation_outpoint: c.revocation_outpoint,
799 fields: c.fields,
800 signature: c.signature,
801 }
802 }
803}
804
805#[derive(Clone, Debug)]
807pub enum KeyringRevealer {
808 Certifier,
810 PubKey(PublicKey),
812}
813
814#[cfg(feature = "serde")]
815impl serde::Serialize for KeyringRevealer {
816 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
817 match self {
818 KeyringRevealer::Certifier => serializer.serialize_str("certifier"),
819 KeyringRevealer::PubKey(pk) => serializer.serialize_str(&pk.to_der_hex()),
820 }
821 }
822}
823
824#[cfg(feature = "serde")]
825impl<'de> serde::Deserialize<'de> for KeyringRevealer {
826 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
827 let s = String::deserialize(deserializer)?;
828 if s == "certifier" || s.is_empty() {
829 Ok(KeyringRevealer::Certifier)
830 } else {
831 PublicKey::from_string(&s)
832 .map(KeyringRevealer::PubKey)
833 .map_err(serde::de::Error::custom)
834 }
835 }
836}
837
838#[derive(Clone, Debug)]
844#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
845#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
846pub struct CreateActionInput {
847 pub outpoint: OutpointString,
848 pub input_description: String,
849 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
850 #[cfg_attr(
851 feature = "serde",
852 serde(skip_serializing_if = "Option::is_none", default)
853 )]
854 pub unlocking_script: Option<Vec<u8>>,
855 #[cfg_attr(
856 feature = "serde",
857 serde(default, skip_serializing_if = "Option::is_none")
858 )]
859 pub unlocking_script_length: Option<u32>,
860 #[cfg_attr(
861 feature = "serde",
862 serde(default, skip_serializing_if = "Option::is_none")
863 )]
864 pub sequence_number: Option<u32>,
865}
866
867#[derive(Clone, Debug)]
869#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
870#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
871pub struct CreateActionOutput {
872 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
873 #[cfg_attr(
874 feature = "serde",
875 serde(skip_serializing_if = "Option::is_none", default)
876 )]
877 pub locking_script: Option<Vec<u8>>,
878 pub satoshis: SatoshiValue,
879 pub output_description: String,
880 #[cfg_attr(
881 feature = "serde",
882 serde(default, skip_serializing_if = "Option::is_none")
883 )]
884 pub basket: Option<BasketStringUnder300Bytes>,
885 #[cfg_attr(
886 feature = "serde",
887 serde(default, skip_serializing_if = "Option::is_none")
888 )]
889 pub custom_instructions: Option<String>,
890 #[cfg_attr(
891 feature = "serde",
892 serde(skip_serializing_if = "Vec::is_empty", default)
893 )]
894 pub tags: Vec<OutputTagStringUnder300Bytes>,
895}
896
897#[derive(Clone, Debug, Default)]
899#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
900#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
901pub struct CreateActionOptions {
902 #[cfg_attr(
903 feature = "serde",
904 serde(
905 default = "BooleanDefaultTrue::none",
906 skip_serializing_if = "BooleanDefaultTrue::is_none"
907 )
908 )]
909 pub sign_and_process: BooleanDefaultTrue,
910 #[cfg_attr(
911 feature = "serde",
912 serde(
913 default = "BooleanDefaultTrue::none",
914 skip_serializing_if = "BooleanDefaultTrue::is_none"
915 )
916 )]
917 pub accept_delayed_broadcast: BooleanDefaultTrue,
918 #[cfg_attr(
919 feature = "serde",
920 serde(default, skip_serializing_if = "Option::is_none")
921 )]
922 pub trust_self: Option<TrustSelf>,
923 #[cfg_attr(
924 feature = "serde",
925 serde(skip_serializing_if = "Vec::is_empty", default)
926 )]
927 pub known_txids: Vec<TXIDHexString>,
928 #[cfg_attr(
929 feature = "serde",
930 serde(
931 default = "BooleanDefaultFalse::none",
932 skip_serializing_if = "BooleanDefaultFalse::is_none"
933 )
934 )]
935 pub return_txid_only: BooleanDefaultFalse,
936 #[cfg_attr(
937 feature = "serde",
938 serde(
939 default = "BooleanDefaultFalse::none",
940 skip_serializing_if = "BooleanDefaultFalse::is_none"
941 )
942 )]
943 pub no_send: BooleanDefaultFalse,
944 #[cfg_attr(
945 feature = "serde",
946 serde(skip_serializing_if = "Vec::is_empty", default)
947 )]
948 pub no_send_change: Vec<OutpointString>,
949 #[cfg_attr(
950 feature = "serde",
951 serde(skip_serializing_if = "Vec::is_empty", default)
952 )]
953 pub send_with: Vec<TXIDHexString>,
954 #[cfg_attr(
955 feature = "serde",
956 serde(
957 default = "BooleanDefaultTrue::none",
958 skip_serializing_if = "BooleanDefaultTrue::is_none"
959 )
960 )]
961 pub randomize_outputs: BooleanDefaultTrue,
962}
963
964#[derive(Clone, Debug)]
966#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
967#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
968pub struct CreateActionArgs {
969 pub description: DescriptionString5to50Bytes,
970 #[cfg_attr(
971 feature = "serde",
972 serde(with = "serde_helpers::option_bytes_as_array")
973 )]
974 #[cfg_attr(
975 feature = "serde",
976 serde(skip_serializing_if = "Option::is_none", default)
977 )]
978 #[cfg_attr(feature = "serde", serde(rename = "inputBEEF"))]
979 pub input_beef: Option<Vec<u8>>,
980 #[cfg_attr(
981 feature = "serde",
982 serde(skip_serializing_if = "Vec::is_empty", default)
983 )]
984 pub inputs: Vec<CreateActionInput>,
985 #[cfg_attr(
986 feature = "serde",
987 serde(skip_serializing_if = "Vec::is_empty", default)
988 )]
989 pub outputs: Vec<CreateActionOutput>,
990 #[cfg_attr(
991 feature = "serde",
992 serde(default, skip_serializing_if = "Option::is_none")
993 )]
994 pub lock_time: Option<u32>,
995 #[cfg_attr(
996 feature = "serde",
997 serde(default, skip_serializing_if = "Option::is_none")
998 )]
999 pub version: Option<u32>,
1000 #[cfg_attr(
1001 feature = "serde",
1002 serde(skip_serializing_if = "Vec::is_empty", default)
1003 )]
1004 pub labels: Vec<LabelStringUnder300Bytes>,
1005 #[cfg_attr(
1006 feature = "serde",
1007 serde(default, skip_serializing_if = "Option::is_none")
1008 )]
1009 pub options: Option<CreateActionOptions>,
1010 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1011 pub reference: Option<String>,
1012}
1013
1014#[derive(Clone, Debug)]
1016#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1017#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1018pub struct SignableTransaction {
1019 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1021 pub tx: Vec<u8>,
1022 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_base64"))]
1025 pub reference: Vec<u8>,
1026}
1027
1028#[derive(Clone, Debug)]
1030#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1031#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1032pub struct SendWithResult {
1033 pub txid: TXIDHexString,
1034 pub status: ActionResultStatus,
1035}
1036
1037#[derive(Clone, Debug, PartialEq, Eq)]
1039#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1040#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1041pub enum ReviewActionResultStatus {
1042 Success,
1043 DoubleSpend,
1044 ServiceError,
1045 InvalidTx,
1046}
1047
1048impl ReviewActionResultStatus {
1049 pub fn as_str(&self) -> &'static str {
1050 match self {
1051 ReviewActionResultStatus::Success => "success",
1052 ReviewActionResultStatus::DoubleSpend => "doubleSpend",
1053 ReviewActionResultStatus::ServiceError => "serviceError",
1054 ReviewActionResultStatus::InvalidTx => "invalidTx",
1055 }
1056 }
1057}
1058
1059#[derive(Clone, Debug)]
1061#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1062#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1063pub struct ReviewActionResult {
1064 pub txid: TXIDHexString,
1065 pub status: ReviewActionResultStatus,
1066 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1067 pub competing_txs: Option<Vec<String>>,
1068 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1069 pub competing_beef: Option<Vec<u8>>,
1070}
1071
1072#[derive(Clone, Debug)]
1074#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1075#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1076pub struct CreateActionResult {
1077 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1078 pub txid: Option<TXIDHexString>,
1079 #[cfg_attr(
1080 feature = "serde",
1081 serde(with = "serde_helpers::option_bytes_as_array")
1082 )]
1083 #[cfg_attr(
1084 feature = "serde",
1085 serde(skip_serializing_if = "Option::is_none", default)
1086 )]
1087 pub tx: Option<Vec<u8>>,
1088 #[cfg_attr(
1089 feature = "serde",
1090 serde(skip_serializing_if = "Vec::is_empty", default)
1091 )]
1092 pub no_send_change: Vec<OutpointString>,
1093 #[cfg_attr(
1094 feature = "serde",
1095 serde(skip_serializing_if = "Vec::is_empty", default)
1096 )]
1097 pub send_with_results: Vec<SendWithResult>,
1098 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1099 pub signable_transaction: Option<SignableTransaction>,
1100}
1101
1102#[derive(Clone, Debug)]
1104#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1105#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1106pub struct SignActionSpend {
1107 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_hex"))]
1108 pub unlocking_script: Vec<u8>,
1109 #[cfg_attr(
1110 feature = "serde",
1111 serde(default, skip_serializing_if = "Option::is_none")
1112 )]
1113 pub sequence_number: Option<u32>,
1114}
1115
1116#[derive(Clone, Debug, Default)]
1118#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1119#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1120pub struct SignActionOptions {
1121 #[cfg_attr(
1122 feature = "serde",
1123 serde(
1124 default = "BooleanDefaultTrue::none",
1125 skip_serializing_if = "BooleanDefaultTrue::is_none"
1126 )
1127 )]
1128 pub accept_delayed_broadcast: BooleanDefaultTrue,
1129 #[cfg_attr(
1130 feature = "serde",
1131 serde(
1132 default = "BooleanDefaultFalse::none",
1133 skip_serializing_if = "BooleanDefaultFalse::is_none"
1134 )
1135 )]
1136 pub return_txid_only: BooleanDefaultFalse,
1137 #[cfg_attr(
1138 feature = "serde",
1139 serde(
1140 default = "BooleanDefaultFalse::none",
1141 skip_serializing_if = "BooleanDefaultFalse::is_none"
1142 )
1143 )]
1144 pub no_send: BooleanDefaultFalse,
1145 #[cfg_attr(
1146 feature = "serde",
1147 serde(skip_serializing_if = "Vec::is_empty", default)
1148 )]
1149 pub send_with: Vec<TXIDHexString>,
1150}
1151
1152#[derive(Clone, Debug)]
1154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1155#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1156pub struct SignActionArgs {
1157 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_base64"))]
1159 pub reference: Vec<u8>,
1160 pub spends: HashMap<u32, SignActionSpend>,
1161 #[cfg_attr(
1162 feature = "serde",
1163 serde(default, skip_serializing_if = "Option::is_none")
1164 )]
1165 pub options: Option<SignActionOptions>,
1166}
1167
1168#[derive(Clone, Debug)]
1170#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1171#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1172pub struct SignActionResult {
1173 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1174 pub txid: Option<TXIDHexString>,
1175 #[cfg_attr(
1176 feature = "serde",
1177 serde(with = "serde_helpers::option_bytes_as_array")
1178 )]
1179 #[cfg_attr(
1180 feature = "serde",
1181 serde(skip_serializing_if = "Option::is_none", default)
1182 )]
1183 pub tx: Option<Vec<u8>>,
1184 #[cfg_attr(
1185 feature = "serde",
1186 serde(skip_serializing_if = "Vec::is_empty", default)
1187 )]
1188 pub send_with_results: Vec<SendWithResult>,
1189}
1190
1191#[derive(Clone, Debug)]
1193#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1194#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1195pub struct AbortActionArgs {
1196 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_base64"))]
1198 pub reference: Vec<u8>,
1199}
1200
1201#[derive(Clone, Debug)]
1203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1204#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1205pub struct AbortActionResult {
1206 pub aborted: bool,
1207}
1208
1209#[derive(Clone, Debug)]
1215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1216#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1217pub struct ActionInput {
1218 pub source_outpoint: OutpointString,
1219 pub source_satoshis: SatoshiValue,
1220 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
1221 #[cfg_attr(
1222 feature = "serde",
1223 serde(skip_serializing_if = "Option::is_none", default)
1224 )]
1225 pub source_locking_script: Option<Vec<u8>>,
1226 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
1227 #[cfg_attr(
1228 feature = "serde",
1229 serde(skip_serializing_if = "Option::is_none", default)
1230 )]
1231 pub unlocking_script: Option<Vec<u8>>,
1232 pub input_description: String,
1233 pub sequence_number: u32,
1234}
1235
1236#[derive(Clone, Debug)]
1238#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1239#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1240pub struct ActionOutput {
1241 pub satoshis: SatoshiValue,
1242 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
1243 #[cfg_attr(
1244 feature = "serde",
1245 serde(skip_serializing_if = "Option::is_none", default)
1246 )]
1247 pub locking_script: Option<Vec<u8>>,
1248 pub spendable: bool,
1249 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1250 pub custom_instructions: Option<String>,
1251 pub tags: Vec<String>,
1252 pub output_index: u32,
1253 pub output_description: String,
1254 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1255 pub basket: Option<String>,
1256}
1257
1258#[derive(Clone, Debug)]
1260#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1261#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1262pub struct Action {
1263 pub txid: TXIDHexString,
1264 pub satoshis: i64,
1265 pub status: ActionStatus,
1266 pub is_outgoing: bool,
1267 pub description: String,
1268 #[cfg_attr(
1269 feature = "serde",
1270 serde(skip_serializing_if = "Vec::is_empty", default)
1271 )]
1272 pub labels: Vec<String>,
1273 pub version: u32,
1274 pub lock_time: u32,
1275 #[cfg_attr(
1276 feature = "serde",
1277 serde(skip_serializing_if = "Vec::is_empty", default)
1278 )]
1279 pub inputs: Vec<ActionInput>,
1280 #[cfg_attr(
1281 feature = "serde",
1282 serde(skip_serializing_if = "Vec::is_empty", default)
1283 )]
1284 pub outputs: Vec<ActionOutput>,
1285}
1286
1287pub const MAX_ACTIONS_LIMIT: u32 = 10000;
1289
1290#[derive(Clone, Debug)]
1296#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1297#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1298pub struct ListActionsArgs {
1299 #[cfg_attr(
1300 feature = "serde",
1301 serde(skip_serializing_if = "Vec::is_empty", default)
1302 )]
1303 pub labels: Vec<LabelStringUnder300Bytes>,
1304 #[cfg_attr(
1305 feature = "serde",
1306 serde(default, skip_serializing_if = "Option::is_none")
1307 )]
1308 pub label_query_mode: Option<QueryMode>,
1309 #[cfg_attr(
1310 feature = "serde",
1311 serde(
1312 default = "BooleanDefaultFalse::none",
1313 skip_serializing_if = "BooleanDefaultFalse::is_none"
1314 )
1315 )]
1316 pub include_labels: BooleanDefaultFalse,
1317 #[cfg_attr(
1318 feature = "serde",
1319 serde(
1320 default = "BooleanDefaultFalse::none",
1321 skip_serializing_if = "BooleanDefaultFalse::is_none"
1322 )
1323 )]
1324 pub include_inputs: BooleanDefaultFalse,
1325 #[cfg_attr(
1326 feature = "serde",
1327 serde(
1328 default = "BooleanDefaultFalse::none",
1329 skip_serializing_if = "BooleanDefaultFalse::is_none"
1330 )
1331 )]
1332 pub include_input_source_locking_scripts: BooleanDefaultFalse,
1333 #[cfg_attr(
1334 feature = "serde",
1335 serde(
1336 default = "BooleanDefaultFalse::none",
1337 skip_serializing_if = "BooleanDefaultFalse::is_none"
1338 )
1339 )]
1340 pub include_input_unlocking_scripts: BooleanDefaultFalse,
1341 #[cfg_attr(
1342 feature = "serde",
1343 serde(
1344 default = "BooleanDefaultFalse::none",
1345 skip_serializing_if = "BooleanDefaultFalse::is_none"
1346 )
1347 )]
1348 pub include_outputs: BooleanDefaultFalse,
1349 #[cfg_attr(
1350 feature = "serde",
1351 serde(
1352 default = "BooleanDefaultFalse::none",
1353 skip_serializing_if = "BooleanDefaultFalse::is_none"
1354 )
1355 )]
1356 pub include_output_locking_scripts: BooleanDefaultFalse,
1357 #[cfg_attr(feature = "serde", serde(default))]
1358 pub limit: PositiveIntegerDefault10Max10000,
1359 #[cfg_attr(
1360 feature = "serde",
1361 serde(default, skip_serializing_if = "Option::is_none")
1362 )]
1363 pub offset: Option<PositiveIntegerOrZero>,
1364 #[cfg_attr(
1365 feature = "serde",
1366 serde(
1367 default = "BooleanDefaultTrue::none",
1368 skip_serializing_if = "BooleanDefaultTrue::is_none"
1369 )
1370 )]
1371 pub seek_permission: BooleanDefaultTrue,
1372}
1373
1374#[derive(Clone, Debug)]
1376#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1377#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1378pub struct ListActionsResult {
1379 pub total_actions: u32,
1380 pub actions: Vec<Action>,
1381}
1382
1383#[derive(Clone, Debug)]
1389#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1390#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1391pub struct Payment {
1392 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_base64"))]
1395 pub derivation_prefix: Vec<u8>,
1396 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_base64"))]
1397 pub derivation_suffix: Vec<u8>,
1398 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
1399 pub sender_identity_key: PublicKey,
1400}
1401
1402#[derive(Clone, Debug)]
1404#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1405#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1406pub struct BasketInsertion {
1407 pub basket: BasketStringUnder300Bytes,
1408 #[cfg_attr(
1409 feature = "serde",
1410 serde(default, skip_serializing_if = "Option::is_none")
1411 )]
1412 pub custom_instructions: Option<String>,
1413 #[cfg_attr(
1414 feature = "serde",
1415 serde(skip_serializing_if = "Vec::is_empty", default)
1416 )]
1417 pub tags: Vec<OutputTagStringUnder300Bytes>,
1418}
1419
1420#[derive(Clone, Debug)]
1426#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1427#[cfg_attr(feature = "serde", serde(tag = "protocol", rename_all = "camelCase"))]
1428pub enum InternalizeOutput {
1429 #[cfg_attr(feature = "serde", serde(rename = "wallet payment"))]
1430 WalletPayment {
1431 #[cfg_attr(feature = "serde", serde(rename = "outputIndex"))]
1432 output_index: u32,
1433 #[cfg_attr(feature = "serde", serde(rename = "paymentRemittance"))]
1434 payment: Payment,
1435 },
1436 #[cfg_attr(feature = "serde", serde(rename = "basket insertion"))]
1437 BasketInsertion {
1438 #[cfg_attr(feature = "serde", serde(rename = "outputIndex"))]
1439 output_index: u32,
1440 #[cfg_attr(feature = "serde", serde(rename = "insertionRemittance"))]
1441 insertion: BasketInsertion,
1442 },
1443}
1444
1445#[derive(Clone, Debug)]
1447#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1448#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1449pub struct InternalizeActionArgs {
1450 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1451 pub tx: Vec<u8>,
1452 pub description: String,
1453 #[cfg_attr(
1454 feature = "serde",
1455 serde(skip_serializing_if = "Vec::is_empty", default)
1456 )]
1457 pub labels: Vec<LabelStringUnder300Bytes>,
1458 #[cfg_attr(
1459 feature = "serde",
1460 serde(
1461 default = "BooleanDefaultTrue::none",
1462 skip_serializing_if = "BooleanDefaultTrue::is_none"
1463 )
1464 )]
1465 pub seek_permission: BooleanDefaultTrue,
1466 pub outputs: Vec<InternalizeOutput>,
1467}
1468
1469#[derive(Clone, Debug)]
1471#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1472#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1473pub struct InternalizeActionResult {
1474 pub accepted: bool,
1475}
1476
1477#[derive(Clone, Debug)]
1483#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1484#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1485pub struct ListOutputsArgs {
1486 pub basket: BasketStringUnder300Bytes,
1487 #[cfg_attr(
1488 feature = "serde",
1489 serde(skip_serializing_if = "Vec::is_empty", default)
1490 )]
1491 pub tags: Vec<OutputTagStringUnder300Bytes>,
1492 #[cfg_attr(
1493 feature = "serde",
1494 serde(default, skip_serializing_if = "Option::is_none")
1495 )]
1496 pub tag_query_mode: Option<QueryMode>,
1497 #[cfg_attr(
1498 feature = "serde",
1499 serde(default, skip_serializing_if = "Option::is_none")
1500 )]
1501 pub include: Option<OutputInclude>,
1502 #[cfg_attr(
1503 feature = "serde",
1504 serde(
1505 default = "BooleanDefaultFalse::none",
1506 skip_serializing_if = "BooleanDefaultFalse::is_none"
1507 )
1508 )]
1509 pub include_custom_instructions: BooleanDefaultFalse,
1510 #[cfg_attr(
1511 feature = "serde",
1512 serde(
1513 default = "BooleanDefaultFalse::none",
1514 skip_serializing_if = "BooleanDefaultFalse::is_none"
1515 )
1516 )]
1517 pub include_tags: BooleanDefaultFalse,
1518 #[cfg_attr(
1519 feature = "serde",
1520 serde(
1521 default = "BooleanDefaultFalse::none",
1522 skip_serializing_if = "BooleanDefaultFalse::is_none"
1523 )
1524 )]
1525 pub include_labels: BooleanDefaultFalse,
1526 #[cfg_attr(
1527 feature = "serde",
1528 serde(skip_serializing_if = "Option::is_none", default)
1529 )]
1530 pub limit: PositiveIntegerDefault10Max10000,
1531 #[cfg_attr(
1532 feature = "serde",
1533 serde(default, skip_serializing_if = "Option::is_none")
1534 )]
1535 pub offset: Option<PositiveIntegerOrZero>,
1536 #[cfg_attr(
1537 feature = "serde",
1538 serde(
1539 default = "BooleanDefaultTrue::none",
1540 skip_serializing_if = "BooleanDefaultTrue::is_none"
1541 )
1542 )]
1543 pub seek_permission: BooleanDefaultTrue,
1544}
1545
1546#[derive(Clone, Debug)]
1548#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1549#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1550pub struct Output {
1551 pub satoshis: SatoshiValue,
1552 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
1553 #[cfg_attr(
1554 feature = "serde",
1555 serde(skip_serializing_if = "Option::is_none", default)
1556 )]
1557 pub locking_script: Option<Vec<u8>>,
1558 pub spendable: bool,
1559 #[cfg_attr(
1560 feature = "serde",
1561 serde(default, skip_serializing_if = "Option::is_none")
1562 )]
1563 pub custom_instructions: Option<String>,
1564 #[cfg_attr(
1565 feature = "serde",
1566 serde(skip_serializing_if = "Vec::is_empty", default)
1567 )]
1568 pub tags: Vec<String>,
1569 pub outpoint: OutpointString,
1570 #[cfg_attr(
1571 feature = "serde",
1572 serde(skip_serializing_if = "Vec::is_empty", default)
1573 )]
1574 pub labels: Vec<String>,
1575}
1576
1577#[derive(Clone, Debug)]
1579#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1580#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1581pub struct ListOutputsResult {
1582 pub total_outputs: u32,
1583 #[cfg_attr(
1584 feature = "serde",
1585 serde(with = "serde_helpers::option_bytes_as_array")
1586 )]
1587 #[cfg_attr(
1588 feature = "serde",
1589 serde(skip_serializing_if = "Option::is_none", default)
1590 )]
1591 #[cfg_attr(feature = "serde", serde(rename = "BEEF"))]
1592 pub beef: Option<Vec<u8>>,
1593 pub outputs: Vec<Output>,
1594}
1595
1596#[derive(Clone, Debug)]
1602#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1603#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1604pub struct RelinquishOutputArgs {
1605 pub basket: BasketStringUnder300Bytes,
1606 pub output: OutpointString,
1607}
1608
1609#[derive(Clone, Debug)]
1611#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1612#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1613pub struct RelinquishOutputResult {
1614 pub relinquished: bool,
1615}
1616
1617#[derive(Clone, Debug)]
1623#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1624#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1625pub struct GetPublicKeyArgs {
1626 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "is_false"))]
1630 pub identity_key: bool,
1631 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1632 #[cfg_attr(
1633 feature = "serde",
1634 serde(default, skip_serializing_if = "Option::is_none")
1635 )]
1636 pub protocol_id: Option<Protocol>,
1637 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1638 #[cfg_attr(
1639 feature = "serde",
1640 serde(default, skip_serializing_if = "Option::is_none")
1641 )]
1642 pub key_id: Option<String>,
1643 #[cfg_attr(
1644 feature = "serde",
1645 serde(skip_serializing_if = "Option::is_none", default)
1646 )]
1647 pub counterparty: Option<Counterparty>,
1648 #[cfg_attr(feature = "serde", serde(default))]
1649 pub privileged: bool,
1650 #[cfg_attr(
1651 feature = "serde",
1652 serde(default, skip_serializing_if = "Option::is_none")
1653 )]
1654 pub privileged_reason: Option<String>,
1655 #[cfg_attr(
1656 feature = "serde",
1657 serde(skip_serializing_if = "Option::is_none", default)
1658 )]
1659 pub for_self: Option<bool>,
1660 #[cfg_attr(
1661 feature = "serde",
1662 serde(skip_serializing_if = "Option::is_none", default)
1663 )]
1664 pub seek_permission: Option<bool>,
1665}
1666
1667#[derive(Clone, Debug)]
1669#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1670#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1671pub struct GetPublicKeyResult {
1672 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
1673 pub public_key: PublicKey,
1674}
1675
1676#[derive(Clone, Debug)]
1678#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1679#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1680pub struct EncryptArgs {
1681 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1682 pub protocol_id: Protocol,
1683 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1684 pub key_id: String,
1685 #[cfg_attr(feature = "serde", serde(default))]
1686 pub counterparty: Counterparty,
1687 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1688 pub plaintext: Vec<u8>,
1689 #[cfg_attr(feature = "serde", serde(default))]
1690 pub privileged: bool,
1691 #[cfg_attr(
1692 feature = "serde",
1693 serde(default, skip_serializing_if = "Option::is_none")
1694 )]
1695 pub privileged_reason: Option<String>,
1696 #[cfg_attr(
1697 feature = "serde",
1698 serde(default, skip_serializing_if = "Option::is_none")
1699 )]
1700 pub seek_permission: Option<bool>,
1701}
1702
1703#[derive(Clone, Debug)]
1705#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1706#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1707pub struct EncryptResult {
1708 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1709 pub ciphertext: Vec<u8>,
1710}
1711
1712#[derive(Clone, Debug)]
1714#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1715#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1716pub struct DecryptArgs {
1717 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1718 pub protocol_id: Protocol,
1719 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1720 pub key_id: String,
1721 #[cfg_attr(feature = "serde", serde(default))]
1722 pub counterparty: Counterparty,
1723 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1724 pub ciphertext: Vec<u8>,
1725 #[cfg_attr(feature = "serde", serde(default))]
1726 pub privileged: bool,
1727 #[cfg_attr(
1728 feature = "serde",
1729 serde(default, skip_serializing_if = "Option::is_none")
1730 )]
1731 pub privileged_reason: Option<String>,
1732 #[cfg_attr(
1733 feature = "serde",
1734 serde(default, skip_serializing_if = "Option::is_none")
1735 )]
1736 pub seek_permission: Option<bool>,
1737}
1738
1739#[derive(Clone, Debug)]
1741#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1742#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1743pub struct DecryptResult {
1744 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1745 pub plaintext: Vec<u8>,
1746}
1747
1748#[derive(Clone, Debug)]
1750#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1751#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1752pub struct CreateHmacArgs {
1753 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1754 pub protocol_id: Protocol,
1755 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1756 pub key_id: String,
1757 #[cfg_attr(feature = "serde", serde(default))]
1758 pub counterparty: Counterparty,
1759 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1760 pub data: Vec<u8>,
1761 #[cfg_attr(feature = "serde", serde(default))]
1762 pub privileged: bool,
1763 #[cfg_attr(
1764 feature = "serde",
1765 serde(default, skip_serializing_if = "Option::is_none")
1766 )]
1767 pub privileged_reason: Option<String>,
1768 #[cfg_attr(
1769 feature = "serde",
1770 serde(default, skip_serializing_if = "Option::is_none")
1771 )]
1772 pub seek_permission: Option<bool>,
1773}
1774
1775#[derive(Clone, Debug)]
1777#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1778#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1779pub struct CreateHmacResult {
1780 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1781 pub hmac: Vec<u8>,
1782}
1783
1784#[derive(Clone, Debug)]
1786#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1787#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1788pub struct VerifyHmacArgs {
1789 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1790 pub protocol_id: Protocol,
1791 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1792 pub key_id: String,
1793 #[cfg_attr(feature = "serde", serde(default))]
1794 pub counterparty: Counterparty,
1795 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1796 pub data: Vec<u8>,
1797 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1798 pub hmac: Vec<u8>,
1799 #[cfg_attr(feature = "serde", serde(default))]
1800 pub privileged: bool,
1801 #[cfg_attr(
1802 feature = "serde",
1803 serde(default, skip_serializing_if = "Option::is_none")
1804 )]
1805 pub privileged_reason: Option<String>,
1806 #[cfg_attr(
1807 feature = "serde",
1808 serde(default, skip_serializing_if = "Option::is_none")
1809 )]
1810 pub seek_permission: Option<bool>,
1811}
1812
1813#[derive(Clone, Debug)]
1815#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1816#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1817pub struct VerifyHmacResult {
1818 pub valid: bool,
1819}
1820
1821#[derive(Clone, Debug)]
1823#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1824#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1825pub struct CreateSignatureArgs {
1826 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1827 pub protocol_id: Protocol,
1828 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1829 pub key_id: String,
1830 #[cfg_attr(feature = "serde", serde(default))]
1831 pub counterparty: Counterparty,
1832 #[cfg_attr(
1833 feature = "serde",
1834 serde(with = "serde_helpers::option_bytes_as_array")
1835 )]
1836 #[cfg_attr(
1837 feature = "serde",
1838 serde(skip_serializing_if = "Option::is_none", default)
1839 )]
1840 pub data: Option<Vec<u8>>,
1841 #[cfg_attr(
1842 feature = "serde",
1843 serde(with = "serde_helpers::option_bytes_as_array")
1844 )]
1845 #[cfg_attr(
1846 feature = "serde",
1847 serde(skip_serializing_if = "Option::is_none", default)
1848 )]
1849 pub hash_to_directly_sign: Option<Vec<u8>>,
1850 #[cfg_attr(feature = "serde", serde(default))]
1851 pub privileged: bool,
1852 #[cfg_attr(
1853 feature = "serde",
1854 serde(default, skip_serializing_if = "Option::is_none")
1855 )]
1856 pub privileged_reason: Option<String>,
1857 #[cfg_attr(
1858 feature = "serde",
1859 serde(default, skip_serializing_if = "Option::is_none")
1860 )]
1861 pub seek_permission: Option<bool>,
1862}
1863
1864#[derive(Clone, Debug)]
1866#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1867#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1868pub struct CreateSignatureResult {
1869 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1872 pub signature: Vec<u8>,
1873}
1874
1875#[derive(Clone, Debug)]
1877#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1878#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1879pub struct VerifySignatureArgs {
1880 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
1881 pub protocol_id: Protocol,
1882 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
1883 pub key_id: String,
1884 #[cfg_attr(feature = "serde", serde(default))]
1885 pub counterparty: Counterparty,
1886 #[cfg_attr(
1887 feature = "serde",
1888 serde(with = "serde_helpers::option_bytes_as_array")
1889 )]
1890 #[cfg_attr(
1891 feature = "serde",
1892 serde(skip_serializing_if = "Option::is_none", default)
1893 )]
1894 pub data: Option<Vec<u8>>,
1895 #[cfg_attr(
1896 feature = "serde",
1897 serde(with = "serde_helpers::option_bytes_as_array")
1898 )]
1899 #[cfg_attr(
1900 feature = "serde",
1901 serde(skip_serializing_if = "Option::is_none", default)
1902 )]
1903 pub hash_to_directly_verify: Option<Vec<u8>>,
1904 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
1906 pub signature: Vec<u8>,
1907 #[cfg_attr(
1908 feature = "serde",
1909 serde(default, skip_serializing_if = "Option::is_none")
1910 )]
1911 pub for_self: Option<bool>,
1912 #[cfg_attr(feature = "serde", serde(default))]
1913 pub privileged: bool,
1914 #[cfg_attr(
1915 feature = "serde",
1916 serde(default, skip_serializing_if = "Option::is_none")
1917 )]
1918 pub privileged_reason: Option<String>,
1919 #[cfg_attr(
1920 feature = "serde",
1921 serde(default, skip_serializing_if = "Option::is_none")
1922 )]
1923 pub seek_permission: Option<bool>,
1924}
1925
1926#[derive(Clone, Debug)]
1928#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1929#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1930pub struct VerifySignatureResult {
1931 pub valid: bool,
1932}
1933
1934#[derive(Clone, Debug)]
1940#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1941#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1942pub struct AcquireCertificateArgs {
1943 #[cfg_attr(feature = "serde", serde(rename = "type"))]
1944 pub cert_type: CertificateType,
1945 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
1946 pub certifier: PublicKey,
1947 pub acquisition_protocol: AcquisitionProtocol,
1948 #[cfg_attr(
1949 feature = "serde",
1950 serde(skip_serializing_if = "HashMap::is_empty", default)
1951 )]
1952 pub fields: HashMap<String, String>,
1953 #[cfg_attr(
1954 feature = "serde",
1955 serde(default, skip_serializing_if = "Option::is_none")
1956 )]
1957 pub serial_number: Option<SerialNumber>,
1958 #[cfg_attr(
1959 feature = "serde",
1960 serde(default, skip_serializing_if = "Option::is_none")
1961 )]
1962 pub revocation_outpoint: Option<String>,
1963 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
1964 #[cfg_attr(
1965 feature = "serde",
1966 serde(skip_serializing_if = "Option::is_none", default)
1967 )]
1968 pub signature: Option<Vec<u8>>,
1969 #[cfg_attr(
1970 feature = "serde",
1971 serde(default, skip_serializing_if = "Option::is_none")
1972 )]
1973 pub certifier_url: Option<String>,
1974 #[cfg_attr(
1975 feature = "serde",
1976 serde(default, skip_serializing_if = "Option::is_none")
1977 )]
1978 pub keyring_revealer: Option<KeyringRevealer>,
1979 #[cfg_attr(
1980 feature = "serde",
1981 serde(default, skip_serializing_if = "Option::is_none")
1982 )]
1983 pub keyring_for_subject: Option<HashMap<String, String>>,
1984 #[cfg_attr(feature = "serde", serde(default))]
1985 pub privileged: bool,
1986 #[cfg_attr(
1987 feature = "serde",
1988 serde(default, skip_serializing_if = "Option::is_none")
1989 )]
1990 pub privileged_reason: Option<String>,
1991}
1992
1993#[derive(Clone, Debug)]
1995#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1996#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1997pub struct ListCertificatesArgs {
1998 #[cfg_attr(
1999 feature = "serde",
2000 serde(with = "serde_helpers::vec_public_key_hex", default)
2001 )]
2002 pub certifiers: Vec<PublicKey>,
2003 #[cfg_attr(
2004 feature = "serde",
2005 serde(skip_serializing_if = "Vec::is_empty", default)
2006 )]
2007 pub types: Vec<CertificateType>,
2008 #[cfg_attr(feature = "serde", serde(default))]
2009 pub limit: PositiveIntegerDefault10Max10000,
2010 #[cfg_attr(
2011 feature = "serde",
2012 serde(default, skip_serializing_if = "Option::is_none")
2013 )]
2014 pub offset: Option<PositiveIntegerOrZero>,
2015 #[cfg_attr(
2016 feature = "serde",
2017 serde(
2018 default = "BooleanDefaultFalse::none",
2019 skip_serializing_if = "BooleanDefaultFalse::is_none"
2020 )
2021 )]
2022 pub privileged: BooleanDefaultFalse,
2023 #[cfg_attr(
2024 feature = "serde",
2025 serde(default, skip_serializing_if = "Option::is_none")
2026 )]
2027 pub privileged_reason: Option<String>,
2028 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2031 pub partial: Option<PartialCertificate>,
2032}
2033
2034#[derive(Clone, Debug)]
2036#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2037#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2038pub struct CertificateResult {
2039 #[cfg_attr(feature = "serde", serde(flatten))]
2040 pub certificate: Certificate,
2041 #[cfg_attr(
2042 feature = "serde",
2043 serde(default, skip_serializing_if = "Option::is_none")
2044 )]
2045 pub keyring: Option<HashMap<String, String>>,
2046 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::option_bytes_as_hex"))]
2047 #[cfg_attr(
2048 feature = "serde",
2049 serde(skip_serializing_if = "Option::is_none", default)
2050 )]
2051 pub verifier: Option<Vec<u8>>,
2052}
2053
2054#[derive(Clone, Debug)]
2056#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2057#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2058pub struct ListCertificatesResult {
2059 pub total_certificates: u32,
2060 pub certificates: Vec<CertificateResult>,
2061}
2062
2063#[derive(Clone, Debug)]
2065#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2066#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2067pub struct ProveCertificateArgs {
2068 pub certificate: PartialCertificate,
2069 pub fields_to_reveal: Vec<String>,
2070 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2071 pub verifier: PublicKey,
2072 #[cfg_attr(
2073 feature = "serde",
2074 serde(
2075 default = "BooleanDefaultFalse::none",
2076 skip_serializing_if = "BooleanDefaultFalse::is_none"
2077 )
2078 )]
2079 pub privileged: BooleanDefaultFalse,
2080 #[cfg_attr(
2081 feature = "serde",
2082 serde(default, skip_serializing_if = "Option::is_none")
2083 )]
2084 pub privileged_reason: Option<String>,
2085}
2086
2087#[derive(Clone, Debug)]
2089#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2090#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2091pub struct ProveCertificateResult {
2092 pub keyring_for_verifier: HashMap<String, String>,
2093 #[cfg_attr(
2094 feature = "serde",
2095 serde(default, skip_serializing_if = "Option::is_none")
2096 )]
2097 pub certificate: Option<Certificate>,
2098 #[cfg_attr(
2099 feature = "serde",
2100 serde(with = "serde_helpers::option_public_key_hex")
2101 )]
2102 #[cfg_attr(feature = "serde", serde(default))]
2103 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2104 pub verifier: Option<PublicKey>,
2105}
2106
2107#[derive(Clone, Debug)]
2109#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2110#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2111pub struct RelinquishCertificateArgs {
2112 #[cfg_attr(feature = "serde", serde(rename = "type"))]
2113 pub cert_type: CertificateType,
2114 pub serial_number: SerialNumber,
2115 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2116 pub certifier: PublicKey,
2117}
2118
2119#[derive(Clone, Debug)]
2121#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2122#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2123pub struct RelinquishCertificateResult {
2124 pub relinquished: bool,
2125}
2126
2127#[derive(Clone, Debug)]
2133#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2134#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2135pub struct IdentityCertifier {
2136 pub name: String,
2137 pub icon_url: String,
2138 pub description: String,
2139 pub trust: u8,
2140}
2141
2142#[derive(Clone, Debug)]
2144#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2145#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2146pub struct IdentityCertificate {
2147 #[cfg_attr(feature = "serde", serde(flatten))]
2148 pub certificate: Certificate,
2149 pub certifier_info: IdentityCertifier,
2150 pub publicly_revealed_keyring: HashMap<String, String>,
2151 pub decrypted_fields: HashMap<String, String>,
2152}
2153
2154#[derive(Clone, Debug)]
2156#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2157#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2158pub struct DiscoverByIdentityKeyArgs {
2159 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2160 pub identity_key: PublicKey,
2161 #[cfg_attr(
2162 feature = "serde",
2163 serde(default, skip_serializing_if = "Option::is_none")
2164 )]
2165 pub limit: Option<u32>,
2166 #[cfg_attr(
2167 feature = "serde",
2168 serde(default, skip_serializing_if = "Option::is_none")
2169 )]
2170 pub offset: Option<u32>,
2171 #[cfg_attr(
2172 feature = "serde",
2173 serde(default, skip_serializing_if = "Option::is_none")
2174 )]
2175 pub seek_permission: Option<bool>,
2176}
2177
2178#[derive(Clone, Debug)]
2180#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2181#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2182pub struct DiscoverByAttributesArgs {
2183 pub attributes: HashMap<String, String>,
2184 #[cfg_attr(
2185 feature = "serde",
2186 serde(default, skip_serializing_if = "Option::is_none")
2187 )]
2188 pub limit: Option<u32>,
2189 #[cfg_attr(
2190 feature = "serde",
2191 serde(default, skip_serializing_if = "Option::is_none")
2192 )]
2193 pub offset: Option<u32>,
2194 #[cfg_attr(
2195 feature = "serde",
2196 serde(default, skip_serializing_if = "Option::is_none")
2197 )]
2198 pub seek_permission: Option<bool>,
2199}
2200
2201#[derive(Clone, Debug)]
2203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2204#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2205pub struct DiscoverCertificatesResult {
2206 pub total_certificates: u32,
2207 pub certificates: Vec<IdentityCertificate>,
2208}
2209
2210#[derive(Clone, Debug)]
2216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2217#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2218pub struct RevealCounterpartyKeyLinkageArgs {
2219 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2220 pub counterparty: PublicKey,
2221 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2222 pub verifier: PublicKey,
2223 #[cfg_attr(
2224 feature = "serde",
2225 serde(default, skip_serializing_if = "Option::is_none")
2226 )]
2227 pub privileged: Option<bool>,
2228 #[cfg_attr(
2229 feature = "serde",
2230 serde(default, skip_serializing_if = "Option::is_none")
2231 )]
2232 pub privileged_reason: Option<String>,
2233}
2234
2235#[derive(Clone, Debug)]
2237#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2238#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2239pub struct RevealCounterpartyKeyLinkageResult {
2240 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2241 pub prover: PublicKey,
2242 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2243 pub counterparty: PublicKey,
2244 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2245 pub verifier: PublicKey,
2246 pub revelation_time: String,
2247 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
2248 pub encrypted_linkage: Vec<u8>,
2249 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
2250 pub encrypted_linkage_proof: Vec<u8>,
2251}
2252
2253#[derive(Clone, Debug)]
2255#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2256#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2257pub struct RevealSpecificKeyLinkageArgs {
2258 pub counterparty: Counterparty,
2259 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2260 pub verifier: PublicKey,
2261 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
2262 pub protocol_id: Protocol,
2263 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
2264 pub key_id: String,
2265 #[cfg_attr(
2266 feature = "serde",
2267 serde(default, skip_serializing_if = "Option::is_none")
2268 )]
2269 pub privileged: Option<bool>,
2270 #[cfg_attr(
2271 feature = "serde",
2272 serde(default, skip_serializing_if = "Option::is_none")
2273 )]
2274 pub privileged_reason: Option<String>,
2275}
2276
2277#[derive(Clone, Debug)]
2279#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2280#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2281pub struct RevealSpecificKeyLinkageResult {
2282 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
2283 pub encrypted_linkage: Vec<u8>,
2284 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_array"))]
2285 pub encrypted_linkage_proof: Vec<u8>,
2286 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2287 pub prover: PublicKey,
2288 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2289 pub verifier: PublicKey,
2290 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::public_key_hex"))]
2291 pub counterparty: PublicKey,
2292 #[cfg_attr(feature = "serde", serde(rename = "protocolID"))]
2293 pub protocol_id: Protocol,
2294 #[cfg_attr(feature = "serde", serde(rename = "keyID"))]
2295 pub key_id: String,
2296 pub proof_type: u8,
2297}
2298
2299#[derive(Clone, Debug)]
2305#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2306#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2307pub struct AuthenticatedResult {
2308 pub authenticated: bool,
2309}
2310
2311#[derive(Clone, Debug)]
2313#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2314#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2315pub struct GetHeightResult {
2316 pub height: u32,
2317}
2318
2319#[derive(Clone, Debug)]
2321#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2322#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2323pub struct GetHeaderArgs {
2324 pub height: u32,
2325}
2326
2327#[derive(Clone, Debug)]
2329#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2330#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2331pub struct GetHeaderResult {
2332 #[cfg_attr(feature = "serde", serde(with = "serde_helpers::bytes_as_hex"))]
2333 pub header: Vec<u8>,
2334}
2335
2336#[derive(Clone, Debug)]
2338#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2339#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2340pub struct GetNetworkResult {
2341 pub network: Network,
2342}
2343
2344#[derive(Clone, Debug)]
2346#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2347#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2348pub struct GetVersionResult {
2349 pub version: String,
2350}
2351
2352#[async_trait]
2364pub trait WalletInterface: Send + Sync {
2365 async fn create_action(
2368 &self,
2369 args: CreateActionArgs,
2370 originator: Option<&str>,
2371 ) -> Result<CreateActionResult, WalletError>;
2372
2373 async fn sign_action(
2374 &self,
2375 args: SignActionArgs,
2376 originator: Option<&str>,
2377 ) -> Result<SignActionResult, WalletError>;
2378
2379 async fn abort_action(
2380 &self,
2381 args: AbortActionArgs,
2382 originator: Option<&str>,
2383 ) -> Result<AbortActionResult, WalletError>;
2384
2385 async fn list_actions(
2386 &self,
2387 args: ListActionsArgs,
2388 originator: Option<&str>,
2389 ) -> Result<ListActionsResult, WalletError>;
2390
2391 async fn internalize_action(
2392 &self,
2393 args: InternalizeActionArgs,
2394 originator: Option<&str>,
2395 ) -> Result<InternalizeActionResult, WalletError>;
2396
2397 async fn list_outputs(
2400 &self,
2401 args: ListOutputsArgs,
2402 originator: Option<&str>,
2403 ) -> Result<ListOutputsResult, WalletError>;
2404
2405 async fn relinquish_output(
2406 &self,
2407 args: RelinquishOutputArgs,
2408 originator: Option<&str>,
2409 ) -> Result<RelinquishOutputResult, WalletError>;
2410
2411 async fn get_public_key(
2414 &self,
2415 args: GetPublicKeyArgs,
2416 originator: Option<&str>,
2417 ) -> Result<GetPublicKeyResult, WalletError>;
2418
2419 async fn reveal_counterparty_key_linkage(
2420 &self,
2421 args: RevealCounterpartyKeyLinkageArgs,
2422 originator: Option<&str>,
2423 ) -> Result<RevealCounterpartyKeyLinkageResult, WalletError>;
2424
2425 async fn reveal_specific_key_linkage(
2426 &self,
2427 args: RevealSpecificKeyLinkageArgs,
2428 originator: Option<&str>,
2429 ) -> Result<RevealSpecificKeyLinkageResult, WalletError>;
2430
2431 async fn encrypt(
2432 &self,
2433 args: EncryptArgs,
2434 originator: Option<&str>,
2435 ) -> Result<EncryptResult, WalletError>;
2436
2437 async fn decrypt(
2438 &self,
2439 args: DecryptArgs,
2440 originator: Option<&str>,
2441 ) -> Result<DecryptResult, WalletError>;
2442
2443 async fn create_hmac(
2444 &self,
2445 args: CreateHmacArgs,
2446 originator: Option<&str>,
2447 ) -> Result<CreateHmacResult, WalletError>;
2448
2449 async fn verify_hmac(
2450 &self,
2451 args: VerifyHmacArgs,
2452 originator: Option<&str>,
2453 ) -> Result<VerifyHmacResult, WalletError>;
2454
2455 async fn create_signature(
2456 &self,
2457 args: CreateSignatureArgs,
2458 originator: Option<&str>,
2459 ) -> Result<CreateSignatureResult, WalletError>;
2460
2461 async fn verify_signature(
2462 &self,
2463 args: VerifySignatureArgs,
2464 originator: Option<&str>,
2465 ) -> Result<VerifySignatureResult, WalletError>;
2466
2467 async fn acquire_certificate(
2470 &self,
2471 args: AcquireCertificateArgs,
2472 originator: Option<&str>,
2473 ) -> Result<Certificate, WalletError>;
2474
2475 async fn list_certificates(
2476 &self,
2477 args: ListCertificatesArgs,
2478 originator: Option<&str>,
2479 ) -> Result<ListCertificatesResult, WalletError>;
2480
2481 async fn prove_certificate(
2482 &self,
2483 args: ProveCertificateArgs,
2484 originator: Option<&str>,
2485 ) -> Result<ProveCertificateResult, WalletError>;
2486
2487 async fn relinquish_certificate(
2488 &self,
2489 args: RelinquishCertificateArgs,
2490 originator: Option<&str>,
2491 ) -> Result<RelinquishCertificateResult, WalletError>;
2492
2493 async fn discover_by_identity_key(
2496 &self,
2497 args: DiscoverByIdentityKeyArgs,
2498 originator: Option<&str>,
2499 ) -> Result<DiscoverCertificatesResult, WalletError>;
2500
2501 async fn discover_by_attributes(
2502 &self,
2503 args: DiscoverByAttributesArgs,
2504 originator: Option<&str>,
2505 ) -> Result<DiscoverCertificatesResult, WalletError>;
2506
2507 async fn is_authenticated(
2510 &self,
2511 originator: Option<&str>,
2512 ) -> Result<AuthenticatedResult, WalletError>;
2513
2514 async fn wait_for_authentication(
2515 &self,
2516 originator: Option<&str>,
2517 ) -> Result<AuthenticatedResult, WalletError>;
2518
2519 async fn get_height(&self, originator: Option<&str>) -> Result<GetHeightResult, WalletError>;
2520
2521 async fn get_header_for_height(
2522 &self,
2523 args: GetHeaderArgs,
2524 originator: Option<&str>,
2525 ) -> Result<GetHeaderResult, WalletError>;
2526
2527 async fn get_network(&self, originator: Option<&str>) -> Result<GetNetworkResult, WalletError>;
2528
2529 async fn get_version(&self, originator: Option<&str>) -> Result<GetVersionResult, WalletError>;
2530}
2531
2532#[cfg(all(test, feature = "serde"))]
2533mod certificate_serde_tests {
2534 use super::*;
2543 use crate::primitives::private_key::PrivateKey;
2544
2545 fn unsigned_cert() -> Certificate {
2546 Certificate {
2547 cert_type: CertificateType([0x01; 32]),
2548 serial_number: SerialNumber([0x02; 32]),
2549 subject: PrivateKey::from_random().unwrap().to_public_key(),
2550 certifier: PrivateKey::from_random().unwrap().to_public_key(),
2551 revocation_outpoint: None,
2552 fields: None,
2553 signature: None,
2554 }
2555 }
2556
2557 #[test]
2558 fn unsigned_certificate_round_trips() {
2559 let cert = unsigned_cert();
2560 let json = serde_json::to_string(&cert).expect("serialize");
2561 let back: Certificate = serde_json::from_str(&json).expect(
2562 "an unsigned certificate must deserialize from its own serialization — a signer \
2563 cannot be handed a cert body it is unable to parse",
2564 );
2565 assert_eq!(back.cert_type.0, cert.cert_type.0);
2566 assert_eq!(back.serial_number.0, cert.serial_number.0);
2567 assert_eq!(back.subject, cert.subject);
2568 assert_eq!(back.certifier, cert.certifier);
2569 assert!(back.revocation_outpoint.is_none());
2570 assert!(back.fields.is_none());
2571 assert!(back.signature.is_none());
2572 }
2573
2574 #[test]
2575 fn absent_optional_keys_deserialize_as_none() {
2576 let json = serde_json::to_string(&unsigned_cert()).unwrap();
2578 assert!(!json.contains("signature"), "None must be omitted: {json}");
2579 assert!(!json.contains("revocationOutpoint"), "None must be omitted");
2580 assert!(!json.contains("fields"), "None must be omitted");
2581
2582 let back: Certificate = serde_json::from_str(&json).unwrap();
2583 assert!(back.signature.is_none());
2584 }
2585
2586 #[test]
2587 fn a_populated_certificate_still_round_trips() {
2588 let mut fields = HashMap::new();
2590 fields.insert("role".to_string(), "admin".to_string());
2591 let cert = Certificate {
2592 revocation_outpoint: Some("aa".repeat(32) + ".1"),
2593 fields: Some(fields),
2594 signature: Some(vec![0xde, 0xad, 0xbe, 0xef]),
2595 ..unsigned_cert()
2596 };
2597 let json = serde_json::to_string(&cert).unwrap();
2598 let back: Certificate = serde_json::from_str(&json).unwrap();
2599 assert_eq!(back.revocation_outpoint, cert.revocation_outpoint);
2600 assert_eq!(back.fields, cert.fields);
2601 assert_eq!(back.signature, Some(vec![0xde, 0xad, 0xbe, 0xef]));
2602 }
2603}
2604
2605#[cfg(test)]
2606mod tests {
2607 use super::*;
2608
2609 #[test]
2610 fn test_serial_number_from_string_hex_valid() {
2611 let hex = "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2";
2612 let sn = SerialNumber::from_string(hex).unwrap();
2613 assert_eq!(sn.0[0], 0xa1);
2614 assert_eq!(sn.0[31], 0xb2);
2615 }
2616
2617 #[test]
2618 fn test_serial_number_from_string_base64_valid() {
2619 let b64 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
2621 let sn = SerialNumber::from_string(b64).unwrap();
2622 assert_eq!(sn.0, [0u8; 32]);
2623 }
2624
2625 #[test]
2626 fn test_serial_number_from_string_base64_nonzero() {
2627 let b64 = "//////////////////////////////////////////8=";
2629 let sn = SerialNumber::from_string(b64).unwrap();
2630 assert_eq!(sn.0, [0xffu8; 32]);
2631 }
2632
2633 #[test]
2634 fn test_serial_number_from_string_invalid_length() {
2635 assert!(SerialNumber::from_string("abc").is_err());
2636 assert!(SerialNumber::from_string("").is_err());
2637 assert!(SerialNumber::from_string("a1b2c3").is_err());
2638 }
2639
2640 #[test]
2641 fn test_serial_number_from_string_invalid_chars() {
2642 let bad_hex = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
2644 assert!(SerialNumber::from_string(bad_hex).is_err());
2645 }
2646}
2647
2648#[cfg(test)]
2649mod review_action_result_tests {
2650 use super::*;
2651
2652 #[test]
2653 fn test_review_action_result_status_values() {
2654 assert_eq!(ReviewActionResultStatus::Success.as_str(), "success");
2655 assert_eq!(
2656 ReviewActionResultStatus::DoubleSpend.as_str(),
2657 "doubleSpend"
2658 );
2659 assert_eq!(
2660 ReviewActionResultStatus::ServiceError.as_str(),
2661 "serviceError"
2662 );
2663 assert_eq!(ReviewActionResultStatus::InvalidTx.as_str(), "invalidTx");
2664 }
2665
2666 #[cfg(feature = "serde")]
2667 #[test]
2668 fn test_review_action_result_serde_roundtrip() {
2669 let r = ReviewActionResult {
2670 txid: "aabb".to_string(),
2671 status: ReviewActionResultStatus::DoubleSpend,
2672 competing_txs: Some(vec!["ccdd".to_string()]),
2673 competing_beef: None,
2674 };
2675 let json = serde_json::to_string(&r).unwrap();
2676 assert!(json.contains("\"doubleSpend\""));
2677 assert!(json.contains("\"competingTxs\""));
2678 assert!(!json.contains("\"competingBeef\""));
2680 let r2: ReviewActionResult = serde_json::from_str(&json).unwrap();
2681 assert_eq!(r2.status, ReviewActionResultStatus::DoubleSpend);
2682 assert_eq!(r2.competing_txs.unwrap()[0], "ccdd");
2683 }
2684}