rustywallet_electrum/
types.rs

1//! Data types for Electrum protocol responses.
2
3use serde::{Deserialize, Serialize};
4
5/// Balance information for an address.
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct Balance {
8    /// Confirmed balance in satoshis
9    pub confirmed: u64,
10    /// Unconfirmed balance in satoshis (can be negative when spending)
11    pub unconfirmed: i64,
12}
13
14impl Balance {
15    /// Returns the total balance (confirmed + unconfirmed).
16    /// Note: This can be less than confirmed if there are unconfirmed spends.
17    #[inline]
18    pub fn total(&self) -> i64 {
19        self.confirmed as i64 + self.unconfirmed
20    }
21
22    /// Returns true if the address has any balance (confirmed or unconfirmed).
23    #[inline]
24    pub fn has_balance(&self) -> bool {
25        self.confirmed > 0 || self.unconfirmed != 0
26    }
27
28    /// Returns true if there are unconfirmed transactions.
29    #[inline]
30    pub fn has_unconfirmed(&self) -> bool {
31        self.unconfirmed != 0
32    }
33}
34
35/// Unspent transaction output (UTXO).
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37pub struct Utxo {
38    /// Transaction ID (hex)
39    #[serde(rename = "tx_hash")]
40    pub txid: String,
41    /// Output index
42    #[serde(rename = "tx_pos")]
43    pub vout: u32,
44    /// Value in satoshis
45    pub value: u64,
46    /// Block height (0 = unconfirmed)
47    pub height: u64,
48}
49
50impl Utxo {
51    /// Returns true if this UTXO is confirmed.
52    #[inline]
53    pub fn is_confirmed(&self) -> bool {
54        self.height > 0
55    }
56
57    /// Returns the outpoint string (txid:vout).
58    pub fn outpoint(&self) -> String {
59        format!("{}:{}", self.txid, self.vout)
60    }
61}
62
63/// Transaction history entry.
64#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
65pub struct TxHistory {
66    /// Transaction ID (hex)
67    #[serde(rename = "tx_hash")]
68    pub txid: String,
69    /// Block height (-1 = unconfirmed in mempool)
70    pub height: i64,
71    /// Transaction fee in satoshis (optional)
72    #[serde(default)]
73    pub fee: Option<u64>,
74}
75
76impl TxHistory {
77    /// Returns true if this transaction is confirmed.
78    #[inline]
79    pub fn is_confirmed(&self) -> bool {
80        self.height > 0
81    }
82}
83
84/// Server version information.
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct ServerVersion {
87    /// Server software name and version
88    pub server_software: String,
89    /// Protocol version supported
90    pub protocol_version: String,
91}
92
93/// Server features and capabilities.
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct ServerFeatures {
96    /// Server software identification
97    #[serde(default)]
98    pub server_version: String,
99    /// Protocol version
100    #[serde(default)]
101    pub protocol_max: String,
102    /// Genesis block hash
103    #[serde(default)]
104    pub genesis_hash: String,
105    /// Hash function used
106    #[serde(default)]
107    pub hash_function: String,
108}
109
110/// Configuration for Electrum client.
111#[derive(Debug, Clone)]
112pub struct ClientConfig {
113    /// Server hostname or IP
114    pub server: String,
115    /// Server port
116    pub port: u16,
117    /// Use TLS/SSL connection
118    pub use_tls: bool,
119    /// Connection timeout
120    pub timeout: std::time::Duration,
121    /// Number of retry attempts
122    pub retry_count: u32,
123    /// Delay between retries
124    pub retry_delay: std::time::Duration,
125    /// Skip TLS certificate validation (INSECURE - for testing only)
126    pub skip_tls_verify: bool,
127}
128
129impl ClientConfig {
130    /// Create config for TCP connection (port 50001).
131    pub fn tcp(server: impl Into<String>) -> Self {
132        Self {
133            server: server.into(),
134            port: 50001,
135            use_tls: false,
136            timeout: std::time::Duration::from_secs(30),
137            retry_count: 3,
138            retry_delay: std::time::Duration::from_secs(1),
139            skip_tls_verify: false,
140        }
141    }
142
143    /// Create config for SSL/TLS connection (port 50002).
144    pub fn ssl(server: impl Into<String>) -> Self {
145        Self {
146            server: server.into(),
147            port: 50002,
148            use_tls: true,
149            timeout: std::time::Duration::from_secs(30),
150            retry_count: 3,
151            retry_delay: std::time::Duration::from_secs(1),
152            skip_tls_verify: false,
153        }
154    }
155
156    /// Set custom port.
157    pub fn with_port(mut self, port: u16) -> Self {
158        self.port = port;
159        self
160    }
161
162    /// Set connection timeout.
163    pub fn with_timeout(mut self, timeout: std::time::Duration) -> Self {
164        self.timeout = timeout;
165        self
166    }
167
168    /// Set retry configuration.
169    pub fn with_retry(mut self, count: u32, delay: std::time::Duration) -> Self {
170        self.retry_count = count;
171        self.retry_delay = delay;
172        self
173    }
174
175    /// Skip TLS certificate validation (INSECURE - for testing only).
176    /// 
177    /// # Warning
178    /// This disables certificate validation and should only be used for testing
179    /// with self-signed certificates. Never use in production!
180    pub fn with_skip_tls_verify(mut self) -> Self {
181        self.skip_tls_verify = true;
182        self
183    }
184
185    /// Get the full server address (host:port).
186    pub fn address(&self) -> String {
187        format!("{}:{}", self.server, self.port)
188    }
189}
190
191impl Default for ClientConfig {
192    fn default() -> Self {
193        Self::ssl("electrum.blockstream.info")
194    }
195}
196
197/// Built-in list of public Electrum servers.
198pub const DEFAULT_SERVERS: &[(&str, u16, bool)] = &[
199    ("electrum.blockstream.info", 50002, true),
200    ("electrum.blockstream.info", 50001, false),
201    ("electrum1.bluewallet.io", 443, true),
202    ("electrum2.bluewallet.io", 443, true),
203    ("bitcoin.aranguren.org", 50002, true),
204    ("electrum.bitaroo.net", 50002, true),
205];