Skip to main content

bsv/wallet/
types.rs

1//! Semantic type aliases and core types for the wallet module.
2//!
3//! Mirrors the Go SDK wallet/wallet.go and wallet/interfaces.go type
4//! definitions, providing strongly-typed aliases for protocol parameters.
5
6use crate::primitives::private_key::PrivateKey;
7use crate::primitives::public_key::PublicKey;
8
9// ---------------------------------------------------------------------------
10// Semantic type aliases
11// ---------------------------------------------------------------------------
12
13/// Hex-encoded public key string.
14pub type PubKeyHex = String;
15
16/// Satoshi value (unsigned 64-bit integer).
17pub type SatoshiValue = u64;
18
19/// Outpoint string in "txid.index" format.
20pub type OutpointString = String;
21
22/// Transaction ID as a hex string.
23pub type TXIDHexString = String;
24
25/// Description string (5 to 50 bytes).
26pub type DescriptionString5to50Bytes = String;
27
28/// Basket name string (under 300 bytes).
29pub type BasketStringUnder300Bytes = String;
30
31/// Output tag string (under 300 bytes).
32pub type OutputTagStringUnder300Bytes = String;
33
34/// Label string (under 300 bytes).
35pub type LabelStringUnder300Bytes = String;
36
37/// Key ID string (under 800 bytes).
38pub type KeyIDStringUnder800Bytes = String;
39
40/// Originator domain name string (under 250 bytes).
41pub type OriginatorDomainNameStringUnder250Bytes = String;
42
43/// Certificate field name (under 50 bytes).
44pub type CertificateFieldNameUnder50Bytes = String;
45
46/// Base64-encoded string.
47pub type Base64String = String;
48
49/// Hex-encoded string.
50pub type HexString = String;
51
52/// Boolean that defaults to true when None.
53pub type BooleanDefaultTrue = Option<bool>;
54
55/// Boolean that defaults to false when None.
56pub type BooleanDefaultFalse = Option<bool>;
57
58/// Positive integer defaulting to 10, max 10000.
59pub type PositiveIntegerDefault10Max10000 = Option<u32>;
60
61/// Positive integer or zero.
62pub type PositiveIntegerOrZero = u32;
63
64// ---------------------------------------------------------------------------
65// Protocol
66// ---------------------------------------------------------------------------
67
68/// Defines a protocol with its security level and name.
69///
70/// The security level determines how strictly the wallet enforces
71/// user confirmation:
72/// - 0: Silent (no user interaction)
73/// - 1: Every app (user confirms per app)
74/// - 2: Every app and counterparty (user confirms per app + counterparty)
75///
76/// Serializes as a JSON array `[securityLevel, "protocolName"]` matching
77/// the Go SDK encoding.
78#[derive(Clone, Debug)]
79pub struct Protocol {
80    pub security_level: u8,
81    pub protocol: String,
82}
83
84#[cfg(feature = "network")]
85impl serde::Serialize for Protocol {
86    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
87        use serde::ser::SerializeSeq;
88        let mut seq = serializer.serialize_seq(Some(2))?;
89        seq.serialize_element(&self.security_level)?;
90        seq.serialize_element(&self.protocol)?;
91        seq.end()
92    }
93}
94
95#[cfg(feature = "network")]
96impl<'de> serde::Deserialize<'de> for Protocol {
97    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
98        use serde::de::{self, SeqAccess, Visitor};
99        use std::fmt;
100
101        struct ProtocolVisitor;
102
103        impl<'de> Visitor<'de> for ProtocolVisitor {
104            type Value = Protocol;
105
106            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
107                formatter.write_str("an array [securityLevel, protocolName]")
108            }
109
110            fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Protocol, A::Error> {
111                let security_level: u8 = seq
112                    .next_element()?
113                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
114                let protocol: String = seq
115                    .next_element()?
116                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
117                Ok(Protocol {
118                    security_level,
119                    protocol,
120                })
121            }
122        }
123
124        deserializer.deserialize_seq(ProtocolVisitor)
125    }
126}
127
128// ---------------------------------------------------------------------------
129// Counterparty
130// ---------------------------------------------------------------------------
131
132/// The type of counterparty in a cryptographic operation.
133#[derive(Clone, Debug, PartialEq)]
134pub enum CounterpartyType {
135    /// Uninitialized / unknown.
136    Uninitialized,
137    /// The wallet itself.
138    Self_,
139    /// The special "anyone" key (PrivateKey(1)).
140    Anyone,
141    /// A specific other party identified by public key.
142    Other,
143}
144
145/// Represents the other party in a cryptographic operation.
146///
147/// Can be a specific public key, or one of the special values
148/// "self" or "anyone".
149///
150/// Serializes as a JSON string: "anyone", "self", or DER hex public key,
151/// matching the Go SDK encoding.
152#[derive(Clone, Debug)]
153pub struct Counterparty {
154    pub counterparty_type: CounterpartyType,
155    pub public_key: Option<PublicKey>,
156}
157
158#[cfg(feature = "network")]
159impl serde::Serialize for Counterparty {
160    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
161        match self.counterparty_type {
162            CounterpartyType::Anyone => serializer.serialize_str("anyone"),
163            CounterpartyType::Self_ => serializer.serialize_str("self"),
164            CounterpartyType::Other => {
165                if let Some(ref pk) = self.public_key {
166                    serializer.serialize_str(&pk.to_der_hex())
167                } else {
168                    serializer.serialize_none()
169                }
170            }
171            CounterpartyType::Uninitialized => serializer.serialize_str(""),
172        }
173    }
174}
175
176#[cfg(feature = "network")]
177impl<'de> serde::Deserialize<'de> for Counterparty {
178    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
179        let s = String::deserialize(deserializer)?;
180        match s.as_str() {
181            "anyone" => Ok(Counterparty {
182                counterparty_type: CounterpartyType::Anyone,
183                public_key: None,
184            }),
185            "self" => Ok(Counterparty {
186                counterparty_type: CounterpartyType::Self_,
187                public_key: None,
188            }),
189            "" => Ok(Counterparty {
190                counterparty_type: CounterpartyType::Uninitialized,
191                public_key: None,
192            }),
193            hex_str => {
194                let pk = PublicKey::from_string(hex_str).map_err(serde::de::Error::custom)?;
195                Ok(Counterparty {
196                    counterparty_type: CounterpartyType::Other,
197                    public_key: Some(pk),
198                })
199            }
200        }
201    }
202}
203
204// ---------------------------------------------------------------------------
205// Anyone key helper
206// ---------------------------------------------------------------------------
207
208/// Returns the "anyone" public key: the public key corresponding to
209/// PrivateKey(1), which is the generator point G.
210///
211/// This is used when no specific counterparty is specified, making
212/// operations available to anyone who knows the protocol.
213pub fn anyone_pubkey() -> PublicKey {
214    let priv_key = PrivateKey::from_bytes(&{
215        let mut buf = [0u8; 32];
216        buf[31] = 1;
217        buf
218    })
219    // SAFETY: PrivateKey(1) is always valid -- 1 is within the secp256k1 scalar range.
220    .expect("PrivateKey(1) is always valid");
221    priv_key.to_public_key()
222}
223
224/// Returns the "anyone" private key: PrivateKey(1).
225pub fn anyone_private_key() -> PrivateKey {
226    PrivateKey::from_bytes(&{
227        let mut buf = [0u8; 32];
228        buf[31] = 1;
229        buf
230    })
231    // SAFETY: PrivateKey(1) is always valid -- 1 is within the secp256k1 scalar range.
232    .expect("PrivateKey(1) is always valid")
233}