kaccy_bitcoin/
testnet4.rs1use crate::client::{BitcoinClient, BitcoinNetwork, ReconnectConfig};
12use crate::error::Result;
13use bitcoin::Network;
14
15#[derive(Debug, Clone)]
17pub struct Testnet4Config {
18 pub rpc_url: String,
20 pub rpc_user: String,
22 pub rpc_password: String,
24 pub reconnect_config: ReconnectConfig,
26}
27
28impl Testnet4Config {
29 pub fn new(rpc_url: String, rpc_user: String, rpc_password: String) -> Self {
31 Self {
32 rpc_url,
33 rpc_user,
34 rpc_password,
35 reconnect_config: ReconnectConfig::default(),
36 }
37 }
38
39 pub fn with_reconnect_config(mut self, reconnect_config: ReconnectConfig) -> Self {
41 self.reconnect_config = reconnect_config;
42 self
43 }
44}
45
46impl Default for Testnet4Config {
47 fn default() -> Self {
48 Self {
49 rpc_url: "http://localhost:48332".to_string(), rpc_user: "bitcoin".to_string(),
51 rpc_password: "".to_string(),
52 reconnect_config: ReconnectConfig::default(),
53 }
54 }
55}
56
57pub struct Testnet4Client {
59 client: BitcoinClient,
60}
61
62impl Testnet4Client {
63 pub fn new(config: Testnet4Config) -> Result<Self> {
65 let client = BitcoinClient::with_config(
66 &config.rpc_url,
67 &config.rpc_user,
68 &config.rpc_password,
69 BitcoinNetwork::Testnet4,
70 config.reconnect_config,
71 )?;
72
73 Ok(Self { client })
74 }
75
76 pub fn client(&self) -> &BitcoinClient {
78 &self.client
79 }
80
81 pub fn network(&self) -> Network {
83 BitcoinNetwork::Testnet4.into()
84 }
85
86 pub fn is_available(&self) -> Result<bool> {
88 match self.client.get_network_info() {
90 Ok(_) => Ok(true),
91 Err(_) => Ok(false),
92 }
93 }
94
95 pub fn get_faucet_info(&self) -> FaucetInfo {
97 FaucetInfo::default()
98 }
99}
100
101#[derive(Debug, Clone)]
103pub struct FaucetInfo {
104 pub urls: Vec<String>,
106 pub max_amount: u64,
108 pub rate_limit: String,
110}
111
112impl Default for FaucetInfo {
113 fn default() -> Self {
114 Self {
115 urls: vec![
116 "https://testnet4-faucet.mempool.space".to_string(),
118 "https://testnet4.coinfaucet.eu".to_string(),
119 ],
120 max_amount: 100_000_000, rate_limit: "Once per 24 hours per IP".to_string(),
122 }
123 }
124}
125
126#[derive(Debug, Clone)]
128pub struct Testnet4Params {
129 pub magic: [u8; 4],
131 pub port: u16,
133 pub rpc_port: u16,
135 pub genesis_hash: String,
137 pub bip44_coin_type: u32,
139}
140
141impl Default for Testnet4Params {
142 fn default() -> Self {
143 Self {
144 magic: [0x0b, 0x11, 0x09, 0x07], port: 48333, rpc_port: 48332, genesis_hash: "TBD".to_string(), bip44_coin_type: 1, }
151 }
152}
153
154impl Testnet4Params {
155 pub fn get() -> Self {
157 Self::default()
158 }
159
160 pub fn verify(&self) -> bool {
162 true
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_testnet4_config_default() {
173 let config = Testnet4Config::default();
174 assert_eq!(config.rpc_url, "http://localhost:48332");
175 assert_eq!(config.rpc_user, "bitcoin");
176 }
177
178 #[test]
179 fn test_testnet4_config_new() {
180 let config = Testnet4Config::new(
181 "http://example.com:48332".to_string(),
182 "user".to_string(),
183 "pass".to_string(),
184 );
185 assert_eq!(config.rpc_url, "http://example.com:48332");
186 assert_eq!(config.rpc_user, "user");
187 assert_eq!(config.rpc_password, "pass");
188 }
189
190 #[test]
191 fn test_testnet4_params() {
192 let params = Testnet4Params::get();
193 assert_eq!(params.port, 48333);
194 assert_eq!(params.rpc_port, 48332);
195 assert_eq!(params.bip44_coin_type, 1);
196 assert!(params.verify());
197 }
198
199 #[test]
200 fn test_faucet_info() {
201 let info = FaucetInfo::default();
202 assert!(!info.urls.is_empty());
203 assert!(info.max_amount > 0);
204 assert!(!info.rate_limit.is_empty());
205 }
206
207 #[test]
208 fn test_network_conversion() {
209 let network: Network = BitcoinNetwork::Testnet4.into();
210 assert_eq!(network, Network::Testnet);
212 }
213}