csv_adapter_bitcoin/
config.rs1#[derive(Clone, Debug)]
5pub struct BitcoinConfig {
6 pub network: Network,
8 pub finality_depth: u32,
10 pub publication_timeout_seconds: u64,
12 pub rpc_url: String,
14}
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum Network {
19 Mainnet,
21 Testnet,
23 Signet,
25 Regtest,
27}
28
29impl Network {
30 pub fn magic_bytes(&self) -> [u8; 4] {
32 match self {
33 Network::Mainnet => [0xf9, 0xbe, 0xb4, 0xd9],
34 Network::Testnet => [0x0b, 0x11, 0x09, 0x07],
35 Network::Signet => [0x0a, 0x03, 0xcf, 0x40],
36 Network::Regtest => [0xfa, 0xbf, 0xb5, 0xda],
37 }
38 }
39
40 pub fn to_bitcoin_network(&self) -> bitcoin::Network {
42 match self {
43 Network::Mainnet => bitcoin::Network::Bitcoin,
44 Network::Testnet => bitcoin::Network::Testnet,
45 Network::Signet => bitcoin::Network::Signet,
46 Network::Regtest => bitcoin::Network::Regtest,
47 }
48 }
49}
50
51impl BitcoinConfig {
52 pub fn validate(&self) -> Result<String, String> {
54 if self.rpc_url.is_empty() {
55 return Err("rpc_url cannot be empty".to_string());
56 }
57 if self.finality_depth == 0 {
58 return Err("finality_depth must be greater than 0".to_string());
59 }
60 if self.finality_depth > 1000 {
61 return Err("finality_depth must be <= 1000".to_string());
62 }
63 if self.publication_timeout_seconds == 0 {
64 return Err("publication_timeout_seconds must be greater than 0".to_string());
65 }
66 let expected_mainnet =
67 self.network == Network::Mainnet && self.rpc_url.contains("127.0.0.1");
68 if expected_mainnet {
69 return Err("mainnet config should not use localhost rpc_url".to_string());
70 }
71 Ok("Configuration is valid".to_string())
72 }
73}
74
75impl Default for BitcoinConfig {
76 fn default() -> Self {
77 Self {
78 network: Network::Signet,
79 finality_depth: 6,
80 publication_timeout_seconds: 3600, rpc_url: "http://127.0.0.1:8332".to_string(),
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_default_config() {
92 let config = BitcoinConfig::default();
93 assert_eq!(config.network, Network::Signet);
94 assert_eq!(config.finality_depth, 6);
95 assert!(config.validate().is_ok());
96 }
97
98 #[test]
99 fn test_config_validate_empty_rpc_url() {
100 let mut config = BitcoinConfig::default();
101 config.rpc_url = String::new();
102 assert!(config.validate().is_err());
103 }
104
105 #[test]
106 fn test_config_validate_zero_finality_depth() {
107 let mut config = BitcoinConfig::default();
108 config.finality_depth = 0;
109 assert!(config.validate().is_err());
110 }
111
112 #[test]
113 fn test_config_validate_excessive_finality_depth() {
114 let mut config = BitcoinConfig::default();
115 config.finality_depth = 1001;
116 assert!(config.validate().is_err());
117 }
118
119 #[test]
120 fn test_network_magic_bytes() {
121 assert_eq!(Network::Mainnet.magic_bytes(), [0xf9, 0xbe, 0xb4, 0xd9]);
122 assert_eq!(Network::Signet.magic_bytes(), [0x0a, 0x03, 0xcf, 0x40]);
123 }
124}