Skip to main content

bsv/wallet/
interfaces.rs

1//! WalletInterface trait and all arg/result structs.
2//!
3//! Defines the contract that all wallet implementations must satisfy.
4//! Translated from Go SDK wallet/interfaces.go and TS SDK Wallet.interfaces.ts.
5//! Uses #[async_trait] for object safety -- enables `dyn WalletInterface`.
6
7use 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// ---------------------------------------------------------------------------
21// Serde helper modules (only compiled with "network" feature)
22// ---------------------------------------------------------------------------
23
24/// Serde helpers for custom JSON serialization of wallet types.
25/// Gated behind the "network" feature since serde is an optional dependency.
26#[cfg(feature = "network")]
27pub(crate) mod serde_helpers {
28    use crate::primitives::public_key::PublicKey;
29
30    /// Serialize/deserialize PublicKey as DER hex string.
31    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    /// Serialize/deserialize `Option<PublicKey>` as optional DER hex string.
52    #[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    /// Serialize/deserialize `Vec<PublicKey>` as array of DER hex strings.
82    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    /// Serialize/deserialize [u8; 32] as base64 string (matches Go SDK Bytes32Base64).
110    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        fn base64_encode(data: &[u8]) -> String {
137            const CHARS: &[u8] =
138                b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
139            let mut result = String::new();
140            let chunks = data.chunks(3);
141            for chunk in chunks {
142                let b0 = chunk[0] as u32;
143                let b1 = if chunk.len() > 1 { chunk[1] as u32 } else { 0 };
144                let b2 = if chunk.len() > 2 { chunk[2] as u32 } else { 0 };
145                let triple = (b0 << 16) | (b1 << 8) | b2;
146                result.push(CHARS[((triple >> 18) & 0x3F) as usize] as char);
147                result.push(CHARS[((triple >> 12) & 0x3F) as usize] as char);
148                if chunk.len() > 1 {
149                    result.push(CHARS[((triple >> 6) & 0x3F) as usize] as char);
150                } else {
151                    result.push('=');
152                }
153                if chunk.len() > 2 {
154                    result.push(CHARS[(triple & 0x3F) as usize] as char);
155                } else {
156                    result.push('=');
157                }
158            }
159            result
160        }
161
162        fn base64_decode(s: &str) -> Result<Vec<u8>, String> {
163            fn char_to_val(c: u8) -> Result<u8, String> {
164                match c {
165                    b'A'..=b'Z' => Ok(c - b'A'),
166                    b'a'..=b'z' => Ok(c - b'a' + 26),
167                    b'0'..=b'9' => Ok(c - b'0' + 52),
168                    b'+' => Ok(62),
169                    b'/' => Ok(63),
170                    _ => Err(format!("invalid base64 character: {}", c as char)),
171                }
172            }
173            let bytes = s.as_bytes();
174            let mut result = Vec::new();
175            let mut i = 0;
176            while i < bytes.len() {
177                if bytes[i] == b'=' {
178                    break;
179                }
180                let a = char_to_val(bytes[i])?;
181                let b = if i + 1 < bytes.len() && bytes[i + 1] != b'=' {
182                    char_to_val(bytes[i + 1])?
183                } else {
184                    0
185                };
186                let c = if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
187                    char_to_val(bytes[i + 2])?
188                } else {
189                    0
190                };
191                let d = if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
192                    char_to_val(bytes[i + 3])?
193                } else {
194                    0
195                };
196                let triple =
197                    ((a as u32) << 18) | ((b as u32) << 12) | ((c as u32) << 6) | (d as u32);
198                result.push(((triple >> 16) & 0xFF) as u8);
199                if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
200                    result.push(((triple >> 8) & 0xFF) as u8);
201                }
202                if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
203                    result.push((triple & 0xFF) as u8);
204                }
205                i += 4;
206            }
207            Ok(result)
208        }
209    }
210
211    /// Serialize/deserialize `Vec<u8>` as JSON array of numbers (matches Go SDK BytesList).
212    pub mod bytes_as_array {
213        use serde::{Deserialize, Deserializer, Serializer};
214
215        pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
216        where
217            S: Serializer,
218        {
219            serializer.collect_seq(bytes.iter())
220        }
221
222        pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
223        where
224            D: Deserializer<'de>,
225        {
226            Vec::<u8>::deserialize(deserializer)
227        }
228    }
229
230    /// Serialize/deserialize `Option<Vec<u8>>` as optional JSON array of numbers.
231    pub mod option_bytes_as_array {
232        use serde::{Deserialize, Deserializer, Serializer};
233
234        pub fn serialize<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
235        where
236            S: Serializer,
237        {
238            match bytes {
239                Some(b) => serializer.collect_seq(b.iter()),
240                None => serializer.serialize_none(),
241            }
242        }
243
244        pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
245        where
246            D: Deserializer<'de>,
247        {
248            Option::<Vec<u8>>::deserialize(deserializer)
249        }
250    }
251
252    /// Serialize/deserialize `Vec<u8>` as hex string (matches Go SDK BytesHex).
253    pub mod bytes_as_hex {
254        use serde::{self, Deserialize, Deserializer, Serializer};
255
256        pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
257        where
258            S: Serializer,
259        {
260            serializer.serialize_str(&to_hex(bytes))
261        }
262
263        pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
264        where
265            D: Deserializer<'de>,
266        {
267            let s = String::deserialize(deserializer)?;
268            from_hex(&s).map_err(serde::de::Error::custom)
269        }
270
271        fn to_hex(bytes: &[u8]) -> String {
272            const HEX: &[u8; 16] = b"0123456789abcdef";
273            let mut s = String::with_capacity(bytes.len() * 2);
274            for &b in bytes {
275                s.push(HEX[(b >> 4) as usize] as char);
276                s.push(HEX[(b & 0xf) as usize] as char);
277            }
278            s
279        }
280
281        pub(crate) fn from_hex(s: &str) -> Result<Vec<u8>, String> {
282            if !s.len().is_multiple_of(2) {
283                return Err("hex string has odd length".to_string());
284            }
285            let bytes = s.as_bytes();
286            let mut result = Vec::with_capacity(bytes.len() / 2);
287            for chunk in bytes.chunks(2) {
288                let hi = hex_val(chunk[0])?;
289                let lo = hex_val(chunk[1])?;
290                result.push((hi << 4) | lo);
291            }
292            Ok(result)
293        }
294
295        fn hex_val(b: u8) -> Result<u8, String> {
296            match b {
297                b'0'..=b'9' => Ok(b - b'0'),
298                b'a'..=b'f' => Ok(b - b'a' + 10),
299                b'A'..=b'F' => Ok(b - b'A' + 10),
300                _ => Err(format!("invalid hex character: {}", b as char)),
301            }
302        }
303    }
304
305    /// Serialize/deserialize `Option<Vec<u8>>` as optional hex string.
306    pub mod option_bytes_as_hex {
307        use serde::{self, Deserialize, Deserializer, Serializer};
308
309        pub fn serialize<S>(bytes: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
310        where
311            S: Serializer,
312        {
313            match bytes {
314                Some(b) => super::bytes_as_hex::serialize(b, serializer),
315                None => serializer.serialize_none(),
316            }
317        }
318
319        pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<u8>>, D::Error>
320        where
321            D: Deserializer<'de>,
322        {
323            let opt: Option<String> = Option::deserialize(deserializer)?;
324            match opt {
325                Some(s) if !s.is_empty() => super::bytes_as_hex::from_hex(&s)
326                    .map(Some)
327                    .map_err(serde::de::Error::custom),
328                _ => Ok(None),
329            }
330        }
331    }
332}
333
334// ---------------------------------------------------------------------------
335// Enums
336// ---------------------------------------------------------------------------
337
338/// Current state of a transaction action.
339#[derive(Clone, Debug, PartialEq, Eq)]
340#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
341#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
342pub enum ActionStatus {
343    Completed,
344    Unprocessed,
345    Sending,
346    Unproven,
347    Unsigned,
348    #[cfg_attr(feature = "network", serde(rename = "nosend"))]
349    NoSend,
350    #[cfg_attr(feature = "network", serde(rename = "nonfinal"))]
351    NonFinal,
352    Failed,
353}
354
355impl ActionStatus {
356    pub fn as_str(&self) -> &'static str {
357        match self {
358            ActionStatus::Completed => "completed",
359            ActionStatus::Unprocessed => "unprocessed",
360            ActionStatus::Sending => "sending",
361            ActionStatus::Unproven => "unproven",
362            ActionStatus::Unsigned => "unsigned",
363            ActionStatus::NoSend => "nosend",
364            ActionStatus::NonFinal => "nonfinal",
365            ActionStatus::Failed => "failed",
366        }
367    }
368}
369
370/// Status of a transaction result (subset of ActionStatus).
371#[derive(Clone, Debug, PartialEq, Eq)]
372#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
373#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
374pub enum ActionResultStatus {
375    Unproven,
376    Sending,
377    Failed,
378}
379
380impl ActionResultStatus {
381    pub fn as_str(&self) -> &'static str {
382        match self {
383            ActionResultStatus::Unproven => "unproven",
384            ActionResultStatus::Sending => "sending",
385            ActionResultStatus::Failed => "failed",
386        }
387    }
388}
389
390/// How multiple criteria are combined in queries.
391#[derive(Clone, Debug, PartialEq, Eq)]
392#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
393#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
394pub enum QueryMode {
395    Any,
396    All,
397}
398
399impl QueryMode {
400    pub fn as_str(&self) -> &'static str {
401        match self {
402            QueryMode::Any => "any",
403            QueryMode::All => "all",
404        }
405    }
406}
407
408/// What additional data to include with output listings.
409#[derive(Clone, Debug, PartialEq, Eq)]
410#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
411pub enum OutputInclude {
412    #[cfg_attr(feature = "network", serde(rename = "locking scripts"))]
413    LockingScripts,
414    #[cfg_attr(feature = "network", serde(rename = "entire transactions"))]
415    EntireTransactions,
416}
417
418impl OutputInclude {
419    pub fn as_str(&self) -> &'static str {
420        match self {
421            OutputInclude::LockingScripts => "locking scripts",
422            OutputInclude::EntireTransactions => "entire transactions",
423        }
424    }
425}
426
427/// Protocol for internalizing transaction outputs.
428#[derive(Clone, Debug, PartialEq, Eq)]
429#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
430pub enum InternalizeProtocol {
431    #[cfg_attr(feature = "network", serde(rename = "wallet payment"))]
432    WalletPayment,
433    #[cfg_attr(feature = "network", serde(rename = "basket insertion"))]
434    BasketInsertion,
435}
436
437impl InternalizeProtocol {
438    pub fn as_str(&self) -> &'static str {
439        match self {
440            InternalizeProtocol::WalletPayment => "wallet payment",
441            InternalizeProtocol::BasketInsertion => "basket insertion",
442        }
443    }
444}
445
446/// Protocol for certificate acquisition.
447#[derive(Clone, Debug, PartialEq, Eq)]
448#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
449#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
450pub enum AcquisitionProtocol {
451    Direct,
452    Issuance,
453}
454
455impl AcquisitionProtocol {
456    pub fn as_str(&self) -> &'static str {
457        match self {
458            AcquisitionProtocol::Direct => "direct",
459            AcquisitionProtocol::Issuance => "issuance",
460        }
461    }
462}
463
464/// Blockchain network type.
465#[derive(Clone, Debug, PartialEq, Eq)]
466#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
467#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
468pub enum Network {
469    Mainnet,
470    Testnet,
471}
472
473impl Network {
474    pub fn as_str(&self) -> &'static str {
475        match self {
476            Network::Mainnet => "mainnet",
477            Network::Testnet => "testnet",
478        }
479    }
480}
481
482/// Trust level for self-referential operations.
483#[derive(Clone, Debug, PartialEq, Eq)]
484#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
485#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
486pub enum TrustSelf {
487    Known,
488}
489
490impl TrustSelf {
491    pub fn as_str(&self) -> &'static str {
492        match self {
493            TrustSelf::Known => "known",
494        }
495    }
496}
497
498// ---------------------------------------------------------------------------
499// Core types: Certificate, CertificateType, SerialNumber, KeyringRevealer
500// ---------------------------------------------------------------------------
501
502/// Newtype wrapper for certificate type identifier (32 bytes).
503/// Serializes as base64 string matching Go SDK Bytes32Base64.
504#[derive(Clone, Debug, PartialEq, Eq, Hash)]
505pub struct CertificateType(pub [u8; 32]);
506
507#[cfg(feature = "network")]
508impl serde::Serialize for CertificateType {
509    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
510        serde_helpers::bytes32_base64::serialize(&self.0, serializer)
511    }
512}
513
514#[cfg(feature = "network")]
515impl<'de> serde::Deserialize<'de> for CertificateType {
516    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
517        serde_helpers::bytes32_base64::deserialize(deserializer).map(CertificateType)
518    }
519}
520
521impl CertificateType {
522    pub fn from_string(s: &str) -> Result<Self, WalletError> {
523        if s.len() > 32 {
524            return Err(WalletError::InvalidParameter(
525                "certificate type string longer than 32 bytes".to_string(),
526            ));
527        }
528        let mut buf = [0u8; 32];
529        buf[..s.len()].copy_from_slice(s.as_bytes());
530        Ok(CertificateType(buf))
531    }
532
533    pub fn bytes(&self) -> &[u8; 32] {
534        &self.0
535    }
536}
537
538/// Newtype wrapper for certificate serial number (32 bytes).
539/// Serializes as base64 string matching Go SDK Bytes32Base64.
540#[derive(Clone, Debug, PartialEq, Eq, Hash)]
541pub struct SerialNumber(pub [u8; 32]);
542
543#[cfg(feature = "network")]
544impl serde::Serialize for SerialNumber {
545    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
546        serde_helpers::bytes32_base64::serialize(&self.0, serializer)
547    }
548}
549
550#[cfg(feature = "network")]
551impl<'de> serde::Deserialize<'de> for SerialNumber {
552    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
553        serde_helpers::bytes32_base64::deserialize(deserializer).map(SerialNumber)
554    }
555}
556
557impl SerialNumber {
558    /// Parse a SerialNumber from a base64 or hex string.
559    ///
560    /// Accepts:
561    /// - 44-character base64 string (with optional padding, decodes to 32 bytes)
562    /// - 64-character hex string (decodes to 32 bytes)
563    ///
564    /// Returns an error for other formats or if the decoded length is not 32 bytes.
565    pub fn from_string(s: &str) -> Result<Self, WalletError> {
566        let bytes = if s.len() == 44 || (!s.is_empty() && s.ends_with('=')) {
567            // Base64 format (32 bytes -> 44 base64 chars with padding)
568            Self::base64_decode_sn(s)?
569        } else if s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit()) {
570            // Hex format (32 bytes -> 64 hex chars)
571            crate::primitives::utils::from_hex(s)
572                .map_err(|e| WalletError::InvalidParameter(format!("hex: {}", e)))?
573        } else {
574            return Err(WalletError::InvalidParameter(format!(
575                "SerialNumber string must be 44 (base64) or 64 (hex) chars, got {}",
576                s.len()
577            )));
578        };
579        if bytes.len() != 32 {
580            return Err(WalletError::InvalidParameter(
581                "SerialNumber must decode to 32 bytes".into(),
582            ));
583        }
584        let mut buf = [0u8; 32];
585        buf.copy_from_slice(&bytes);
586        Ok(SerialNumber(buf))
587    }
588
589    /// Inline base64 decoder for SerialNumber (self-contained, no cross-module dependency).
590    fn base64_decode_sn(s: &str) -> Result<Vec<u8>, WalletError> {
591        fn b64_val(c: u8) -> Result<u8, WalletError> {
592            match c {
593                b'A'..=b'Z' => Ok(c - b'A'),
594                b'a'..=b'z' => Ok(c - b'a' + 26),
595                b'0'..=b'9' => Ok(c - b'0' + 52),
596                b'+' => Ok(62),
597                b'/' => Ok(63),
598                _ => Err(WalletError::InvalidParameter(format!(
599                    "invalid base64 character: {}",
600                    c as char
601                ))),
602            }
603        }
604        let bytes = s.as_bytes();
605        let mut result = Vec::new();
606        let mut i = 0;
607        while i < bytes.len() {
608            if bytes[i] == b'=' {
609                break;
610            }
611            let a = b64_val(bytes[i])?;
612            let b = if i + 1 < bytes.len() && bytes[i + 1] != b'=' {
613                b64_val(bytes[i + 1])?
614            } else {
615                0
616            };
617            let c = if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
618                b64_val(bytes[i + 2])?
619            } else {
620                0
621            };
622            let d = if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
623                b64_val(bytes[i + 3])?
624            } else {
625                0
626            };
627            let n = (a as u32) << 18 | (b as u32) << 12 | (c as u32) << 6 | (d as u32);
628            result.push((n >> 16) as u8);
629            if i + 2 < bytes.len() && bytes[i + 2] != b'=' {
630                result.push((n >> 8) as u8);
631            }
632            if i + 3 < bytes.len() && bytes[i + 3] != b'=' {
633                result.push(n as u8);
634            }
635            i += 4;
636        }
637        Ok(result)
638    }
639
640    pub fn bytes(&self) -> &[u8; 32] {
641        &self.0
642    }
643}
644
645/// A certificate in the wallet.
646#[derive(Clone, Debug)]
647#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
648#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
649pub struct Certificate {
650    #[cfg_attr(feature = "network", serde(rename = "type"))]
651    pub cert_type: CertificateType,
652    pub serial_number: SerialNumber,
653    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
654    pub subject: PublicKey,
655    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
656    pub certifier: PublicKey,
657    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
658    pub revocation_outpoint: Option<String>,
659    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
660    pub fields: Option<HashMap<String, String>>,
661    #[cfg_attr(
662        feature = "network",
663        serde(with = "serde_helpers::option_bytes_as_hex")
664    )]
665    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
666    pub signature: Option<Vec<u8>>,
667}
668
669/// A partial certificate where all fields are optional.
670/// Used for ProveCertificateArgs to match TS SDK's `Partial<WalletCertificate>`.
671#[derive(Clone, Debug)]
672#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
673#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
674pub struct PartialCertificate {
675    #[cfg_attr(feature = "network", serde(rename = "type"))]
676    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
677    pub cert_type: Option<CertificateType>,
678    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
679    pub serial_number: Option<SerialNumber>,
680    #[cfg_attr(
681        feature = "network",
682        serde(with = "serde_helpers::option_public_key_hex")
683    )]
684    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
685    pub subject: Option<PublicKey>,
686    #[cfg_attr(
687        feature = "network",
688        serde(with = "serde_helpers::option_public_key_hex")
689    )]
690    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
691    pub certifier: Option<PublicKey>,
692    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
693    pub revocation_outpoint: Option<String>,
694    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
695    pub fields: Option<HashMap<String, String>>,
696    #[cfg_attr(
697        feature = "network",
698        serde(with = "serde_helpers::option_bytes_as_hex")
699    )]
700    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
701    pub signature: Option<Vec<u8>>,
702}
703
704impl From<Certificate> for PartialCertificate {
705    fn from(c: Certificate) -> Self {
706        PartialCertificate {
707            cert_type: Some(c.cert_type),
708            serial_number: Some(c.serial_number),
709            subject: Some(c.subject),
710            certifier: Some(c.certifier),
711            revocation_outpoint: c.revocation_outpoint,
712            fields: c.fields,
713            signature: c.signature,
714        }
715    }
716}
717
718/// Identifies who reveals a keyring.
719#[derive(Clone, Debug)]
720pub enum KeyringRevealer {
721    /// The certifier reveals the keyring.
722    Certifier,
723    /// A specific public key reveals the keyring.
724    PubKey(PublicKey),
725}
726
727#[cfg(feature = "network")]
728impl serde::Serialize for KeyringRevealer {
729    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
730        match self {
731            KeyringRevealer::Certifier => serializer.serialize_str("certifier"),
732            KeyringRevealer::PubKey(pk) => serializer.serialize_str(&pk.to_der_hex()),
733        }
734    }
735}
736
737#[cfg(feature = "network")]
738impl<'de> serde::Deserialize<'de> for KeyringRevealer {
739    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
740        let s = String::deserialize(deserializer)?;
741        if s == "certifier" || s.is_empty() {
742            Ok(KeyringRevealer::Certifier)
743        } else {
744            PublicKey::from_string(&s)
745                .map(KeyringRevealer::PubKey)
746                .map_err(serde::de::Error::custom)
747        }
748    }
749}
750
751// ---------------------------------------------------------------------------
752// Action types (CreateAction, SignAction, AbortAction)
753// ---------------------------------------------------------------------------
754
755/// An input to be spent in a new transaction.
756#[derive(Clone, Debug)]
757#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
758#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
759pub struct CreateActionInput {
760    pub outpoint: OutpointString,
761    pub input_description: String,
762    #[cfg_attr(
763        feature = "network",
764        serde(with = "serde_helpers::option_bytes_as_hex")
765    )]
766    #[cfg_attr(
767        feature = "network",
768        serde(skip_serializing_if = "Option::is_none", default)
769    )]
770    pub unlocking_script: Option<Vec<u8>>,
771    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
772    pub unlocking_script_length: Option<u32>,
773    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
774    pub sequence_number: Option<u32>,
775}
776
777/// An output to be created in a new transaction.
778#[derive(Clone, Debug)]
779#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
780#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
781pub struct CreateActionOutput {
782    #[cfg_attr(
783        feature = "network",
784        serde(with = "serde_helpers::option_bytes_as_hex")
785    )]
786    #[cfg_attr(
787        feature = "network",
788        serde(skip_serializing_if = "Option::is_none", default)
789    )]
790    pub locking_script: Option<Vec<u8>>,
791    pub satoshis: SatoshiValue,
792    pub output_description: String,
793    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
794    pub basket: Option<BasketStringUnder300Bytes>,
795    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
796    pub custom_instructions: Option<String>,
797    #[cfg_attr(
798        feature = "network",
799        serde(skip_serializing_if = "Vec::is_empty", default)
800    )]
801    pub tags: Vec<OutputTagStringUnder300Bytes>,
802}
803
804/// Optional parameters for creating a new transaction.
805#[derive(Clone, Debug, Default)]
806#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
807#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
808pub struct CreateActionOptions {
809    pub sign_and_process: BooleanDefaultTrue,
810    pub accept_delayed_broadcast: BooleanDefaultTrue,
811    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
812    pub trust_self: Option<TrustSelf>,
813    #[cfg_attr(
814        feature = "network",
815        serde(skip_serializing_if = "Vec::is_empty", default)
816    )]
817    pub known_txids: Vec<TXIDHexString>,
818    pub return_txid_only: BooleanDefaultFalse,
819    pub no_send: BooleanDefaultFalse,
820    #[cfg_attr(
821        feature = "network",
822        serde(skip_serializing_if = "Vec::is_empty", default)
823    )]
824    pub no_send_change: Vec<OutpointString>,
825    #[cfg_attr(
826        feature = "network",
827        serde(skip_serializing_if = "Vec::is_empty", default)
828    )]
829    pub send_with: Vec<TXIDHexString>,
830    pub randomize_outputs: BooleanDefaultTrue,
831}
832
833/// Arguments for creating a new transaction.
834#[derive(Clone, Debug)]
835#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
836#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
837pub struct CreateActionArgs {
838    pub description: DescriptionString5to50Bytes,
839    #[cfg_attr(
840        feature = "network",
841        serde(with = "serde_helpers::option_bytes_as_array")
842    )]
843    #[cfg_attr(
844        feature = "network",
845        serde(skip_serializing_if = "Option::is_none", default)
846    )]
847    #[cfg_attr(feature = "network", serde(rename = "inputBEEF"))]
848    pub input_beef: Option<Vec<u8>>,
849    #[cfg_attr(
850        feature = "network",
851        serde(skip_serializing_if = "Vec::is_empty", default)
852    )]
853    pub inputs: Vec<CreateActionInput>,
854    #[cfg_attr(
855        feature = "network",
856        serde(skip_serializing_if = "Vec::is_empty", default)
857    )]
858    pub outputs: Vec<CreateActionOutput>,
859    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
860    pub lock_time: Option<u32>,
861    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
862    pub version: Option<u32>,
863    #[cfg_attr(
864        feature = "network",
865        serde(skip_serializing_if = "Vec::is_empty", default)
866    )]
867    pub labels: Vec<LabelStringUnder300Bytes>,
868    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
869    pub options: Option<CreateActionOptions>,
870    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
871    pub reference: Option<String>,
872}
873
874/// Data needed to complete signing of a partial transaction.
875#[derive(Clone, Debug)]
876#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
877#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
878pub struct SignableTransaction {
879    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
880    pub tx: Vec<u8>,
881    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
882    pub reference: Vec<u8>,
883}
884
885/// Status of a transaction sent as part of a batch.
886#[derive(Clone, Debug)]
887#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
888#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
889pub struct SendWithResult {
890    pub txid: TXIDHexString,
891    pub status: ActionResultStatus,
892}
893
894/// Result of creating a transaction.
895#[derive(Clone, Debug)]
896#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
897#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
898pub struct CreateActionResult {
899    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
900    pub txid: Option<TXIDHexString>,
901    #[cfg_attr(
902        feature = "network",
903        serde(with = "serde_helpers::option_bytes_as_array")
904    )]
905    #[cfg_attr(
906        feature = "network",
907        serde(skip_serializing_if = "Option::is_none", default)
908    )]
909    pub tx: Option<Vec<u8>>,
910    #[cfg_attr(
911        feature = "network",
912        serde(skip_serializing_if = "Vec::is_empty", default)
913    )]
914    pub no_send_change: Vec<OutpointString>,
915    #[cfg_attr(
916        feature = "network",
917        serde(skip_serializing_if = "Vec::is_empty", default)
918    )]
919    pub send_with_results: Vec<SendWithResult>,
920    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
921    pub signable_transaction: Option<SignableTransaction>,
922}
923
924/// Unlocking script and sequence number for a specific input.
925#[derive(Clone, Debug)]
926#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
927#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
928pub struct SignActionSpend {
929    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_hex"))]
930    pub unlocking_script: Vec<u8>,
931    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
932    pub sequence_number: Option<u32>,
933}
934
935/// Controls signing and broadcasting behavior.
936#[derive(Clone, Debug, Default)]
937#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
938#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
939pub struct SignActionOptions {
940    pub accept_delayed_broadcast: BooleanDefaultTrue,
941    pub return_txid_only: BooleanDefaultFalse,
942    pub no_send: BooleanDefaultFalse,
943    #[cfg_attr(
944        feature = "network",
945        serde(skip_serializing_if = "Vec::is_empty", default)
946    )]
947    pub send_with: Vec<TXIDHexString>,
948}
949
950/// Arguments for signing a previously created transaction.
951#[derive(Clone, Debug)]
952#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
953#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
954pub struct SignActionArgs {
955    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
956    pub reference: Vec<u8>,
957    pub spends: HashMap<u32, SignActionSpend>,
958    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
959    pub options: Option<SignActionOptions>,
960}
961
962/// Result of a successful signing operation.
963#[derive(Clone, Debug)]
964#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
965#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
966pub struct SignActionResult {
967    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
968    pub txid: Option<TXIDHexString>,
969    #[cfg_attr(
970        feature = "network",
971        serde(with = "serde_helpers::option_bytes_as_array")
972    )]
973    #[cfg_attr(
974        feature = "network",
975        serde(skip_serializing_if = "Option::is_none", default)
976    )]
977    pub tx: Option<Vec<u8>>,
978    #[cfg_attr(
979        feature = "network",
980        serde(skip_serializing_if = "Vec::is_empty", default)
981    )]
982    pub send_with_results: Vec<SendWithResult>,
983}
984
985/// Arguments for aborting a transaction.
986#[derive(Clone, Debug)]
987#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
988#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
989pub struct AbortActionArgs {
990    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
991    pub reference: Vec<u8>,
992}
993
994/// Result of aborting a transaction.
995#[derive(Clone, Debug)]
996#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
997#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
998pub struct AbortActionResult {
999    pub aborted: bool,
1000}
1001
1002// ---------------------------------------------------------------------------
1003// Action detail types (for listing)
1004// ---------------------------------------------------------------------------
1005
1006/// A transaction input with full details.
1007#[derive(Clone, Debug)]
1008#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1009#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1010pub struct ActionInput {
1011    pub source_outpoint: OutpointString,
1012    pub source_satoshis: SatoshiValue,
1013    #[cfg_attr(
1014        feature = "network",
1015        serde(with = "serde_helpers::option_bytes_as_hex")
1016    )]
1017    #[cfg_attr(
1018        feature = "network",
1019        serde(skip_serializing_if = "Option::is_none", default)
1020    )]
1021    pub source_locking_script: Option<Vec<u8>>,
1022    #[cfg_attr(
1023        feature = "network",
1024        serde(with = "serde_helpers::option_bytes_as_hex")
1025    )]
1026    #[cfg_attr(
1027        feature = "network",
1028        serde(skip_serializing_if = "Option::is_none", default)
1029    )]
1030    pub unlocking_script: Option<Vec<u8>>,
1031    pub input_description: String,
1032    pub sequence_number: u32,
1033}
1034
1035/// A transaction output with full details.
1036#[derive(Clone, Debug)]
1037#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1038#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1039pub struct ActionOutput {
1040    pub satoshis: SatoshiValue,
1041    #[cfg_attr(
1042        feature = "network",
1043        serde(with = "serde_helpers::option_bytes_as_hex")
1044    )]
1045    #[cfg_attr(
1046        feature = "network",
1047        serde(skip_serializing_if = "Option::is_none", default)
1048    )]
1049    pub locking_script: Option<Vec<u8>>,
1050    pub spendable: bool,
1051    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1052    pub custom_instructions: Option<String>,
1053    pub tags: Vec<String>,
1054    pub output_index: u32,
1055    pub output_description: String,
1056    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1057    pub basket: Option<String>,
1058}
1059
1060/// Full details about a wallet transaction.
1061#[derive(Clone, Debug)]
1062#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1063#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1064pub struct Action {
1065    pub txid: TXIDHexString,
1066    pub satoshis: i64,
1067    pub status: ActionStatus,
1068    pub is_outgoing: bool,
1069    pub description: String,
1070    #[cfg_attr(
1071        feature = "network",
1072        serde(skip_serializing_if = "Vec::is_empty", default)
1073    )]
1074    pub labels: Vec<String>,
1075    pub version: u32,
1076    pub lock_time: u32,
1077    #[cfg_attr(
1078        feature = "network",
1079        serde(skip_serializing_if = "Vec::is_empty", default)
1080    )]
1081    pub inputs: Vec<ActionInput>,
1082    #[cfg_attr(
1083        feature = "network",
1084        serde(skip_serializing_if = "Vec::is_empty", default)
1085    )]
1086    pub outputs: Vec<ActionOutput>,
1087}
1088
1089/// Maximum number of actions or outputs that can be returned.
1090pub const MAX_ACTIONS_LIMIT: u32 = 10000;
1091
1092// ---------------------------------------------------------------------------
1093// ListActions
1094// ---------------------------------------------------------------------------
1095
1096/// Filtering and pagination options for listing wallet transactions.
1097#[derive(Clone, Debug)]
1098#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1099#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1100pub struct ListActionsArgs {
1101    pub labels: Vec<LabelStringUnder300Bytes>,
1102    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1103    pub label_query_mode: Option<QueryMode>,
1104    pub include_labels: BooleanDefaultFalse,
1105    pub include_inputs: BooleanDefaultFalse,
1106    pub include_input_source_locking_scripts: BooleanDefaultFalse,
1107    pub include_input_unlocking_scripts: BooleanDefaultFalse,
1108    pub include_outputs: BooleanDefaultFalse,
1109    pub include_output_locking_scripts: BooleanDefaultFalse,
1110    pub limit: PositiveIntegerDefault10Max10000,
1111    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1112    pub offset: Option<PositiveIntegerOrZero>,
1113    pub seek_permission: BooleanDefaultTrue,
1114}
1115
1116/// Paginated list of wallet transactions.
1117#[derive(Clone, Debug)]
1118#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1119#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1120pub struct ListActionsResult {
1121    pub total_actions: u32,
1122    pub actions: Vec<Action>,
1123}
1124
1125// ---------------------------------------------------------------------------
1126// InternalizeAction
1127// ---------------------------------------------------------------------------
1128
1129/// Derivation and identity data for wallet payment outputs.
1130#[derive(Clone, Debug)]
1131#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1132#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1133pub struct Payment {
1134    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1135    pub derivation_prefix: Vec<u8>,
1136    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1137    pub derivation_suffix: Vec<u8>,
1138    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1139    pub sender_identity_key: PublicKey,
1140}
1141
1142/// Metadata for outputs being inserted into baskets.
1143#[derive(Clone, Debug)]
1144#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1145#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1146pub struct BasketInsertion {
1147    pub basket: BasketStringUnder300Bytes,
1148    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1149    pub custom_instructions: Option<String>,
1150    #[cfg_attr(
1151        feature = "network",
1152        serde(skip_serializing_if = "Vec::is_empty", default)
1153    )]
1154    pub tags: Vec<OutputTagStringUnder300Bytes>,
1155}
1156
1157/// How to process a transaction output -- as payment or basket insertion.
1158///
1159/// An enum with two variants, encoding the protocol in the variant itself.
1160/// This makes impossible states unrepresentable: a WalletPayment always has
1161/// a Payment, and a BasketInsertion always has a BasketInsertion.
1162#[derive(Clone, Debug)]
1163#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1164#[cfg_attr(feature = "network", serde(tag = "protocol", rename_all = "camelCase"))]
1165pub enum InternalizeOutput {
1166    #[cfg_attr(feature = "network", serde(rename = "wallet payment"))]
1167    WalletPayment {
1168        output_index: u32,
1169        #[cfg_attr(feature = "network", serde(rename = "paymentRemittance"))]
1170        payment: Payment,
1171    },
1172    #[cfg_attr(feature = "network", serde(rename = "basket insertion"))]
1173    BasketInsertion {
1174        output_index: u32,
1175        #[cfg_attr(feature = "network", serde(rename = "insertionRemittance"))]
1176        insertion: BasketInsertion,
1177    },
1178}
1179
1180/// Arguments for importing an external transaction into the wallet.
1181#[derive(Clone, Debug)]
1182#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1183#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1184pub struct InternalizeActionArgs {
1185    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1186    pub tx: Vec<u8>,
1187    pub description: String,
1188    #[cfg_attr(
1189        feature = "network",
1190        serde(skip_serializing_if = "Vec::is_empty", default)
1191    )]
1192    pub labels: Vec<LabelStringUnder300Bytes>,
1193    pub seek_permission: BooleanDefaultTrue,
1194    pub outputs: Vec<InternalizeOutput>,
1195}
1196
1197/// Result of internalizing a transaction.
1198#[derive(Clone, Debug)]
1199#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1200#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1201pub struct InternalizeActionResult {
1202    pub accepted: bool,
1203}
1204
1205// ---------------------------------------------------------------------------
1206// ListOutputs
1207// ---------------------------------------------------------------------------
1208
1209/// Filtering and options for listing wallet outputs.
1210#[derive(Clone, Debug)]
1211#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1212#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1213pub struct ListOutputsArgs {
1214    pub basket: BasketStringUnder300Bytes,
1215    #[cfg_attr(
1216        feature = "network",
1217        serde(skip_serializing_if = "Vec::is_empty", default)
1218    )]
1219    pub tags: Vec<OutputTagStringUnder300Bytes>,
1220    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1221    pub tag_query_mode: Option<QueryMode>,
1222    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1223    pub include: Option<OutputInclude>,
1224    #[cfg_attr(
1225        feature = "network",
1226        serde(skip_serializing_if = "BooleanDefaultFalse::is_none")
1227    )]
1228    pub include_custom_instructions: BooleanDefaultFalse,
1229    #[cfg_attr(
1230        feature = "network",
1231        serde(skip_serializing_if = "BooleanDefaultFalse::is_none")
1232    )]
1233    pub include_tags: BooleanDefaultFalse,
1234    #[cfg_attr(
1235        feature = "network",
1236        serde(skip_serializing_if = "BooleanDefaultFalse::is_none")
1237    )]
1238    pub include_labels: BooleanDefaultFalse,
1239    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1240    pub limit: PositiveIntegerDefault10Max10000,
1241    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1242    pub offset: Option<PositiveIntegerOrZero>,
1243    #[cfg_attr(
1244        feature = "network",
1245        serde(skip_serializing_if = "BooleanDefaultTrue::is_none")
1246    )]
1247    pub seek_permission: BooleanDefaultTrue,
1248}
1249
1250/// A wallet UTXO with its metadata.
1251#[derive(Clone, Debug)]
1252#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1253#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1254pub struct Output {
1255    pub satoshis: SatoshiValue,
1256    #[cfg_attr(
1257        feature = "network",
1258        serde(with = "serde_helpers::option_bytes_as_hex")
1259    )]
1260    #[cfg_attr(
1261        feature = "network",
1262        serde(skip_serializing_if = "Option::is_none", default)
1263    )]
1264    pub locking_script: Option<Vec<u8>>,
1265    pub spendable: bool,
1266    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1267    pub custom_instructions: Option<String>,
1268    #[cfg_attr(
1269        feature = "network",
1270        serde(skip_serializing_if = "Vec::is_empty", default)
1271    )]
1272    pub tags: Vec<String>,
1273    pub outpoint: OutpointString,
1274    #[cfg_attr(
1275        feature = "network",
1276        serde(skip_serializing_if = "Vec::is_empty", default)
1277    )]
1278    pub labels: Vec<String>,
1279}
1280
1281/// Paginated list of wallet outputs.
1282#[derive(Clone, Debug)]
1283#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1284#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1285pub struct ListOutputsResult {
1286    pub total_outputs: u32,
1287    #[cfg_attr(
1288        feature = "network",
1289        serde(with = "serde_helpers::option_bytes_as_array")
1290    )]
1291    #[cfg_attr(
1292        feature = "network",
1293        serde(skip_serializing_if = "Option::is_none", default)
1294    )]
1295    #[cfg_attr(feature = "network", serde(rename = "BEEF"))]
1296    pub beef: Option<Vec<u8>>,
1297    pub outputs: Vec<Output>,
1298}
1299
1300// ---------------------------------------------------------------------------
1301// RelinquishOutput
1302// ---------------------------------------------------------------------------
1303
1304/// Arguments for relinquishing ownership of an output.
1305#[derive(Clone, Debug)]
1306#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1307#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1308pub struct RelinquishOutputArgs {
1309    pub basket: BasketStringUnder300Bytes,
1310    pub output: OutpointString,
1311}
1312
1313/// Result of relinquishing an output.
1314#[derive(Clone, Debug)]
1315#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1316#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1317pub struct RelinquishOutputResult {
1318    pub relinquished: bool,
1319}
1320
1321// ---------------------------------------------------------------------------
1322// Key/Crypto types
1323// ---------------------------------------------------------------------------
1324
1325/// Arguments for getting a public key.
1326#[derive(Clone, Debug)]
1327#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1328#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1329pub struct GetPublicKeyArgs {
1330    pub identity_key: bool,
1331    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1332    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1333    pub protocol_id: Option<Protocol>,
1334    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1335    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1336    pub key_id: Option<String>,
1337    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1338    pub counterparty: Option<Counterparty>,
1339    pub privileged: bool,
1340    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1341    pub privileged_reason: Option<String>,
1342    pub for_self: Option<bool>,
1343    pub seek_permission: Option<bool>,
1344}
1345
1346/// Result of getting a public key.
1347#[derive(Clone, Debug)]
1348#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1349#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1350pub struct GetPublicKeyResult {
1351    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1352    pub public_key: PublicKey,
1353}
1354
1355/// Arguments for encryption.
1356#[derive(Clone, Debug)]
1357#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1358#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1359pub struct EncryptArgs {
1360    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1361    pub protocol_id: Protocol,
1362    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1363    pub key_id: String,
1364    pub counterparty: Counterparty,
1365    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1366    pub plaintext: Vec<u8>,
1367    pub privileged: bool,
1368    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1369    pub privileged_reason: Option<String>,
1370    pub seek_permission: Option<bool>,
1371}
1372
1373/// Result of encryption.
1374#[derive(Clone, Debug)]
1375#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1376#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1377pub struct EncryptResult {
1378    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1379    pub ciphertext: Vec<u8>,
1380}
1381
1382/// Arguments for decryption.
1383#[derive(Clone, Debug)]
1384#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1385#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1386pub struct DecryptArgs {
1387    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1388    pub protocol_id: Protocol,
1389    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1390    pub key_id: String,
1391    pub counterparty: Counterparty,
1392    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1393    pub ciphertext: Vec<u8>,
1394    pub privileged: bool,
1395    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1396    pub privileged_reason: Option<String>,
1397    pub seek_permission: Option<bool>,
1398}
1399
1400/// Result of decryption.
1401#[derive(Clone, Debug)]
1402#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1403#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1404pub struct DecryptResult {
1405    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1406    pub plaintext: Vec<u8>,
1407}
1408
1409/// Arguments for creating an HMAC.
1410#[derive(Clone, Debug)]
1411#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1412#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1413pub struct CreateHmacArgs {
1414    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1415    pub protocol_id: Protocol,
1416    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1417    pub key_id: String,
1418    pub counterparty: Counterparty,
1419    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1420    pub data: Vec<u8>,
1421    pub privileged: bool,
1422    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1423    pub privileged_reason: Option<String>,
1424    pub seek_permission: Option<bool>,
1425}
1426
1427/// Result of creating an HMAC.
1428#[derive(Clone, Debug)]
1429#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1430#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1431pub struct CreateHmacResult {
1432    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1433    pub hmac: Vec<u8>,
1434}
1435
1436/// Arguments for verifying an HMAC.
1437#[derive(Clone, Debug)]
1438#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1439#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1440pub struct VerifyHmacArgs {
1441    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1442    pub protocol_id: Protocol,
1443    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1444    pub key_id: String,
1445    pub counterparty: Counterparty,
1446    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1447    pub data: Vec<u8>,
1448    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1449    pub hmac: Vec<u8>,
1450    pub privileged: bool,
1451    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1452    pub privileged_reason: Option<String>,
1453    pub seek_permission: Option<bool>,
1454}
1455
1456/// Result of verifying an HMAC.
1457#[derive(Clone, Debug)]
1458#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1459#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1460pub struct VerifyHmacResult {
1461    pub valid: bool,
1462}
1463
1464/// Arguments for creating a digital signature.
1465#[derive(Clone, Debug)]
1466#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1467#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1468pub struct CreateSignatureArgs {
1469    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1470    pub protocol_id: Protocol,
1471    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1472    pub key_id: String,
1473    pub counterparty: Counterparty,
1474    #[cfg_attr(
1475        feature = "network",
1476        serde(with = "serde_helpers::option_bytes_as_array")
1477    )]
1478    #[cfg_attr(
1479        feature = "network",
1480        serde(skip_serializing_if = "Option::is_none", default)
1481    )]
1482    pub data: Option<Vec<u8>>,
1483    #[cfg_attr(
1484        feature = "network",
1485        serde(with = "serde_helpers::option_bytes_as_array")
1486    )]
1487    #[cfg_attr(
1488        feature = "network",
1489        serde(skip_serializing_if = "Option::is_none", default)
1490    )]
1491    pub hash_to_directly_sign: Option<Vec<u8>>,
1492    pub privileged: bool,
1493    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1494    pub privileged_reason: Option<String>,
1495    pub seek_permission: Option<bool>,
1496}
1497
1498/// Result of creating a digital signature.
1499#[derive(Clone, Debug)]
1500#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1501#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1502pub struct CreateSignatureResult {
1503    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_hex"))]
1504    pub signature: Vec<u8>,
1505}
1506
1507/// Arguments for verifying a digital signature.
1508#[derive(Clone, Debug)]
1509#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1510#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1511pub struct VerifySignatureArgs {
1512    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1513    pub protocol_id: Protocol,
1514    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1515    pub key_id: String,
1516    pub counterparty: Counterparty,
1517    #[cfg_attr(
1518        feature = "network",
1519        serde(with = "serde_helpers::option_bytes_as_array")
1520    )]
1521    #[cfg_attr(
1522        feature = "network",
1523        serde(skip_serializing_if = "Option::is_none", default)
1524    )]
1525    pub data: Option<Vec<u8>>,
1526    #[cfg_attr(
1527        feature = "network",
1528        serde(with = "serde_helpers::option_bytes_as_array")
1529    )]
1530    #[cfg_attr(
1531        feature = "network",
1532        serde(skip_serializing_if = "Option::is_none", default)
1533    )]
1534    pub hash_to_directly_verify: Option<Vec<u8>>,
1535    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_hex"))]
1536    pub signature: Vec<u8>,
1537    pub for_self: Option<bool>,
1538    pub privileged: bool,
1539    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1540    pub privileged_reason: Option<String>,
1541    pub seek_permission: Option<bool>,
1542}
1543
1544/// Result of verifying a digital signature.
1545#[derive(Clone, Debug)]
1546#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1547#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1548pub struct VerifySignatureResult {
1549    pub valid: bool,
1550}
1551
1552// ---------------------------------------------------------------------------
1553// Certificate operations
1554// ---------------------------------------------------------------------------
1555
1556/// Arguments for acquiring a new certificate.
1557#[derive(Clone, Debug)]
1558#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1559#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1560pub struct AcquireCertificateArgs {
1561    #[cfg_attr(feature = "network", serde(rename = "type"))]
1562    pub cert_type: CertificateType,
1563    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1564    pub certifier: PublicKey,
1565    pub acquisition_protocol: AcquisitionProtocol,
1566    #[cfg_attr(
1567        feature = "network",
1568        serde(skip_serializing_if = "HashMap::is_empty", default)
1569    )]
1570    pub fields: HashMap<String, String>,
1571    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1572    pub serial_number: Option<SerialNumber>,
1573    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1574    pub revocation_outpoint: Option<String>,
1575    #[cfg_attr(
1576        feature = "network",
1577        serde(with = "serde_helpers::option_bytes_as_hex")
1578    )]
1579    #[cfg_attr(
1580        feature = "network",
1581        serde(skip_serializing_if = "Option::is_none", default)
1582    )]
1583    pub signature: Option<Vec<u8>>,
1584    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1585    pub certifier_url: Option<String>,
1586    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1587    pub keyring_revealer: Option<KeyringRevealer>,
1588    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1589    pub keyring_for_subject: Option<HashMap<String, String>>,
1590    pub privileged: bool,
1591    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1592    pub privileged_reason: Option<String>,
1593}
1594
1595/// Arguments for listing certificates.
1596#[derive(Clone, Debug)]
1597#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1598#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1599pub struct ListCertificatesArgs {
1600    #[cfg_attr(feature = "network", serde(with = "serde_helpers::vec_public_key_hex"))]
1601    pub certifiers: Vec<PublicKey>,
1602    pub types: Vec<CertificateType>,
1603    pub limit: PositiveIntegerDefault10Max10000,
1604    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1605    pub offset: Option<PositiveIntegerOrZero>,
1606    pub privileged: BooleanDefaultFalse,
1607    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1608    pub privileged_reason: Option<String>,
1609}
1610
1611/// A certificate with its keyring and verifier.
1612#[derive(Clone, Debug)]
1613#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1614#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1615pub struct CertificateResult {
1616    #[cfg_attr(feature = "network", serde(flatten))]
1617    pub certificate: Certificate,
1618    pub keyring: HashMap<String, String>,
1619    #[cfg_attr(
1620        feature = "network",
1621        serde(with = "serde_helpers::option_bytes_as_hex")
1622    )]
1623    #[cfg_attr(
1624        feature = "network",
1625        serde(skip_serializing_if = "Option::is_none", default)
1626    )]
1627    pub verifier: Option<Vec<u8>>,
1628}
1629
1630/// Paginated list of certificates.
1631#[derive(Clone, Debug)]
1632#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1633#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1634pub struct ListCertificatesResult {
1635    pub total_certificates: u32,
1636    pub certificates: Vec<CertificateResult>,
1637}
1638
1639/// Arguments for creating a verifiable certificate.
1640#[derive(Clone, Debug)]
1641#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1642#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1643pub struct ProveCertificateArgs {
1644    pub certificate: PartialCertificate,
1645    pub fields_to_reveal: Vec<String>,
1646    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1647    pub verifier: PublicKey,
1648    pub privileged: BooleanDefaultFalse,
1649    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1650    pub privileged_reason: Option<String>,
1651}
1652
1653/// Result of creating a verifiable certificate.
1654#[derive(Clone, Debug)]
1655#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1656#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1657pub struct ProveCertificateResult {
1658    pub keyring_for_verifier: HashMap<String, String>,
1659    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1660    pub certificate: Option<Certificate>,
1661    #[cfg_attr(
1662        feature = "network",
1663        serde(with = "serde_helpers::option_public_key_hex")
1664    )]
1665    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1666    pub verifier: Option<PublicKey>,
1667}
1668
1669/// Arguments for relinquishing ownership of a certificate.
1670#[derive(Clone, Debug)]
1671#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1672#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1673pub struct RelinquishCertificateArgs {
1674    #[cfg_attr(feature = "network", serde(rename = "type"))]
1675    pub cert_type: CertificateType,
1676    pub serial_number: SerialNumber,
1677    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1678    pub certifier: PublicKey,
1679}
1680
1681/// Result of relinquishing a certificate.
1682#[derive(Clone, Debug)]
1683#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1684#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1685pub struct RelinquishCertificateResult {
1686    pub relinquished: bool,
1687}
1688
1689// ---------------------------------------------------------------------------
1690// Discovery types
1691// ---------------------------------------------------------------------------
1692
1693/// Information about an entity that issues identity certificates.
1694#[derive(Clone, Debug)]
1695#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1696#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1697pub struct IdentityCertifier {
1698    pub name: String,
1699    pub icon_url: String,
1700    pub description: String,
1701    pub trust: u8,
1702}
1703
1704/// An identity certificate with decoded fields and certifier info.
1705#[derive(Clone, Debug)]
1706#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1707#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1708pub struct IdentityCertificate {
1709    #[cfg_attr(feature = "network", serde(flatten))]
1710    pub certificate: Certificate,
1711    pub certifier_info: IdentityCertifier,
1712    pub publicly_revealed_keyring: HashMap<String, String>,
1713    pub decrypted_fields: HashMap<String, String>,
1714}
1715
1716/// Arguments for discovering certificates by identity key.
1717#[derive(Clone, Debug)]
1718#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1719#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1720pub struct DiscoverByIdentityKeyArgs {
1721    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1722    pub identity_key: PublicKey,
1723    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1724    pub limit: Option<u32>,
1725    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1726    pub offset: Option<u32>,
1727    pub seek_permission: Option<bool>,
1728}
1729
1730/// Arguments for discovering certificates by attributes.
1731#[derive(Clone, Debug)]
1732#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1733#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1734pub struct DiscoverByAttributesArgs {
1735    pub attributes: HashMap<String, String>,
1736    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1737    pub limit: Option<u32>,
1738    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1739    pub offset: Option<u32>,
1740    pub seek_permission: Option<bool>,
1741}
1742
1743/// Paginated list of identity certificates found during discovery.
1744#[derive(Clone, Debug)]
1745#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1746#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1747pub struct DiscoverCertificatesResult {
1748    pub total_certificates: u32,
1749    pub certificates: Vec<IdentityCertificate>,
1750}
1751
1752// ---------------------------------------------------------------------------
1753// Key linkage types
1754// ---------------------------------------------------------------------------
1755
1756/// Arguments for revealing key linkage between counterparties.
1757#[derive(Clone, Debug)]
1758#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1759#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1760pub struct RevealCounterpartyKeyLinkageArgs {
1761    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1762    pub counterparty: PublicKey,
1763    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1764    pub verifier: PublicKey,
1765    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1766    pub privileged: Option<bool>,
1767    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1768    pub privileged_reason: Option<String>,
1769}
1770
1771/// Result of revealing counterparty key linkage.
1772#[derive(Clone, Debug)]
1773#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1774#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1775pub struct RevealCounterpartyKeyLinkageResult {
1776    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1777    pub prover: PublicKey,
1778    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1779    pub counterparty: PublicKey,
1780    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1781    pub verifier: PublicKey,
1782    pub revelation_time: String,
1783    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1784    pub encrypted_linkage: Vec<u8>,
1785    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1786    pub encrypted_linkage_proof: Vec<u8>,
1787}
1788
1789/// Arguments for revealing specific key linkage.
1790#[derive(Clone, Debug)]
1791#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1792#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1793pub struct RevealSpecificKeyLinkageArgs {
1794    pub counterparty: Counterparty,
1795    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1796    pub verifier: PublicKey,
1797    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1798    pub protocol_id: Protocol,
1799    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1800    pub key_id: String,
1801    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1802    pub privileged: Option<bool>,
1803    #[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
1804    pub privileged_reason: Option<String>,
1805}
1806
1807/// Result of revealing specific key linkage.
1808#[derive(Clone, Debug)]
1809#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1810#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1811pub struct RevealSpecificKeyLinkageResult {
1812    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1813    pub encrypted_linkage: Vec<u8>,
1814    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_array"))]
1815    pub encrypted_linkage_proof: Vec<u8>,
1816    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1817    pub prover: PublicKey,
1818    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1819    pub verifier: PublicKey,
1820    #[cfg_attr(feature = "network", serde(with = "serde_helpers::public_key_hex"))]
1821    pub counterparty: PublicKey,
1822    #[cfg_attr(feature = "network", serde(rename = "protocolID"))]
1823    pub protocol_id: Protocol,
1824    #[cfg_attr(feature = "network", serde(rename = "keyID"))]
1825    pub key_id: String,
1826    pub proof_type: u8,
1827}
1828
1829// ---------------------------------------------------------------------------
1830// Auth/Info types
1831// ---------------------------------------------------------------------------
1832
1833/// Whether the current session is authenticated.
1834#[derive(Clone, Debug)]
1835#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1836#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1837pub struct AuthenticatedResult {
1838    pub authenticated: bool,
1839}
1840
1841/// Current blockchain height.
1842#[derive(Clone, Debug)]
1843#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1844#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1845pub struct GetHeightResult {
1846    pub height: u32,
1847}
1848
1849/// Arguments for retrieving a blockchain header at a specific height.
1850#[derive(Clone, Debug)]
1851#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1852#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1853pub struct GetHeaderArgs {
1854    pub height: u32,
1855}
1856
1857/// Blockchain header data for the requested height.
1858#[derive(Clone, Debug)]
1859#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1860#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1861pub struct GetHeaderResult {
1862    #[cfg_attr(feature = "network", serde(with = "serde_helpers::bytes_as_hex"))]
1863    pub header: Vec<u8>,
1864}
1865
1866/// Current blockchain network.
1867#[derive(Clone, Debug)]
1868#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1869#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1870pub struct GetNetworkResult {
1871    pub network: Network,
1872}
1873
1874/// Version information about the wallet implementation.
1875#[derive(Clone, Debug)]
1876#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
1877#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
1878pub struct GetVersionResult {
1879    pub version: String,
1880}
1881
1882// ---------------------------------------------------------------------------
1883// WalletInterface trait
1884// ---------------------------------------------------------------------------
1885
1886/// The core wallet interface with all 28 async methods.
1887///
1888/// Uses `#[async_trait]` for object safety -- supports both static dispatch
1889/// (`W: WalletInterface`) and dynamic dispatch (`dyn WalletInterface`).
1890///
1891/// Every method takes `originator: Option<&str>` as the last parameter,
1892/// identifying the calling application domain.
1893#[async_trait]
1894pub trait WalletInterface: Send + Sync {
1895    // -- Action methods --
1896
1897    async fn create_action(
1898        &self,
1899        args: CreateActionArgs,
1900        originator: Option<&str>,
1901    ) -> Result<CreateActionResult, WalletError>;
1902
1903    async fn sign_action(
1904        &self,
1905        args: SignActionArgs,
1906        originator: Option<&str>,
1907    ) -> Result<SignActionResult, WalletError>;
1908
1909    async fn abort_action(
1910        &self,
1911        args: AbortActionArgs,
1912        originator: Option<&str>,
1913    ) -> Result<AbortActionResult, WalletError>;
1914
1915    async fn list_actions(
1916        &self,
1917        args: ListActionsArgs,
1918        originator: Option<&str>,
1919    ) -> Result<ListActionsResult, WalletError>;
1920
1921    async fn internalize_action(
1922        &self,
1923        args: InternalizeActionArgs,
1924        originator: Option<&str>,
1925    ) -> Result<InternalizeActionResult, WalletError>;
1926
1927    // -- Output methods --
1928
1929    async fn list_outputs(
1930        &self,
1931        args: ListOutputsArgs,
1932        originator: Option<&str>,
1933    ) -> Result<ListOutputsResult, WalletError>;
1934
1935    async fn relinquish_output(
1936        &self,
1937        args: RelinquishOutputArgs,
1938        originator: Option<&str>,
1939    ) -> Result<RelinquishOutputResult, WalletError>;
1940
1941    // -- Key/Crypto methods --
1942
1943    async fn get_public_key(
1944        &self,
1945        args: GetPublicKeyArgs,
1946        originator: Option<&str>,
1947    ) -> Result<GetPublicKeyResult, WalletError>;
1948
1949    async fn reveal_counterparty_key_linkage(
1950        &self,
1951        args: RevealCounterpartyKeyLinkageArgs,
1952        originator: Option<&str>,
1953    ) -> Result<RevealCounterpartyKeyLinkageResult, WalletError>;
1954
1955    async fn reveal_specific_key_linkage(
1956        &self,
1957        args: RevealSpecificKeyLinkageArgs,
1958        originator: Option<&str>,
1959    ) -> Result<RevealSpecificKeyLinkageResult, WalletError>;
1960
1961    async fn encrypt(
1962        &self,
1963        args: EncryptArgs,
1964        originator: Option<&str>,
1965    ) -> Result<EncryptResult, WalletError>;
1966
1967    async fn decrypt(
1968        &self,
1969        args: DecryptArgs,
1970        originator: Option<&str>,
1971    ) -> Result<DecryptResult, WalletError>;
1972
1973    async fn create_hmac(
1974        &self,
1975        args: CreateHmacArgs,
1976        originator: Option<&str>,
1977    ) -> Result<CreateHmacResult, WalletError>;
1978
1979    async fn verify_hmac(
1980        &self,
1981        args: VerifyHmacArgs,
1982        originator: Option<&str>,
1983    ) -> Result<VerifyHmacResult, WalletError>;
1984
1985    async fn create_signature(
1986        &self,
1987        args: CreateSignatureArgs,
1988        originator: Option<&str>,
1989    ) -> Result<CreateSignatureResult, WalletError>;
1990
1991    async fn verify_signature(
1992        &self,
1993        args: VerifySignatureArgs,
1994        originator: Option<&str>,
1995    ) -> Result<VerifySignatureResult, WalletError>;
1996
1997    // -- Certificate methods --
1998
1999    async fn acquire_certificate(
2000        &self,
2001        args: AcquireCertificateArgs,
2002        originator: Option<&str>,
2003    ) -> Result<Certificate, WalletError>;
2004
2005    async fn list_certificates(
2006        &self,
2007        args: ListCertificatesArgs,
2008        originator: Option<&str>,
2009    ) -> Result<ListCertificatesResult, WalletError>;
2010
2011    async fn prove_certificate(
2012        &self,
2013        args: ProveCertificateArgs,
2014        originator: Option<&str>,
2015    ) -> Result<ProveCertificateResult, WalletError>;
2016
2017    async fn relinquish_certificate(
2018        &self,
2019        args: RelinquishCertificateArgs,
2020        originator: Option<&str>,
2021    ) -> Result<RelinquishCertificateResult, WalletError>;
2022
2023    // -- Discovery methods --
2024
2025    async fn discover_by_identity_key(
2026        &self,
2027        args: DiscoverByIdentityKeyArgs,
2028        originator: Option<&str>,
2029    ) -> Result<DiscoverCertificatesResult, WalletError>;
2030
2031    async fn discover_by_attributes(
2032        &self,
2033        args: DiscoverByAttributesArgs,
2034        originator: Option<&str>,
2035    ) -> Result<DiscoverCertificatesResult, WalletError>;
2036
2037    // -- Auth/Info methods --
2038
2039    async fn is_authenticated(
2040        &self,
2041        originator: Option<&str>,
2042    ) -> Result<AuthenticatedResult, WalletError>;
2043
2044    async fn wait_for_authentication(
2045        &self,
2046        originator: Option<&str>,
2047    ) -> Result<AuthenticatedResult, WalletError>;
2048
2049    async fn get_height(&self, originator: Option<&str>) -> Result<GetHeightResult, WalletError>;
2050
2051    async fn get_header_for_height(
2052        &self,
2053        args: GetHeaderArgs,
2054        originator: Option<&str>,
2055    ) -> Result<GetHeaderResult, WalletError>;
2056
2057    async fn get_network(&self, originator: Option<&str>) -> Result<GetNetworkResult, WalletError>;
2058
2059    async fn get_version(&self, originator: Option<&str>) -> Result<GetVersionResult, WalletError>;
2060}
2061
2062#[cfg(test)]
2063mod tests {
2064    use super::*;
2065
2066    #[test]
2067    fn test_serial_number_from_string_hex_valid() {
2068        let hex = "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2";
2069        let sn = SerialNumber::from_string(hex).unwrap();
2070        assert_eq!(sn.0[0], 0xa1);
2071        assert_eq!(sn.0[31], 0xb2);
2072    }
2073
2074    #[test]
2075    fn test_serial_number_from_string_base64_valid() {
2076        // 32 bytes of zeros -> base64 is "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
2077        let b64 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
2078        let sn = SerialNumber::from_string(b64).unwrap();
2079        assert_eq!(sn.0, [0u8; 32]);
2080    }
2081
2082    #[test]
2083    fn test_serial_number_from_string_base64_nonzero() {
2084        // All 0xFF bytes: base64 = "//////////////////////////////////////////8="
2085        let b64 = "//////////////////////////////////////////8=";
2086        let sn = SerialNumber::from_string(b64).unwrap();
2087        assert_eq!(sn.0, [0xffu8; 32]);
2088    }
2089
2090    #[test]
2091    fn test_serial_number_from_string_invalid_length() {
2092        assert!(SerialNumber::from_string("abc").is_err());
2093        assert!(SerialNumber::from_string("").is_err());
2094        assert!(SerialNumber::from_string("a1b2c3").is_err());
2095    }
2096
2097    #[test]
2098    fn test_serial_number_from_string_invalid_chars() {
2099        // 64 chars but not valid hex
2100        let bad_hex = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
2101        assert!(SerialNumber::from_string(bad_hex).is_err());
2102    }
2103}