1use crate::{config_helpers::opt_path_from_toml, key_utils::Secp256k1PublicKey};
2use std::path::PathBuf;
3
4#[derive(Clone, Debug, serde::Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum BitcoinNetwork {
8 Mainnet,
9 Testnet4,
10 Signet,
11 Regtest,
12}
13
14impl BitcoinNetwork {
15 fn subdir(&self) -> Option<&'static str> {
18 match self {
19 BitcoinNetwork::Mainnet => None,
20 BitcoinNetwork::Testnet4 => Some("testnet4"),
21 BitcoinNetwork::Signet => Some("signet"),
22 BitcoinNetwork::Regtest => Some("regtest"),
23 }
24 }
25}
26
27fn default_bitcoin_data_dir() -> Option<PathBuf> {
29 #[cfg(target_os = "linux")]
30 {
31 dirs::home_dir().map(|h| h.join(".bitcoin"))
32 }
33 #[cfg(target_os = "macos")]
34 {
35 dirs::home_dir().map(|h| h.join("Library/Application Support/Bitcoin"))
36 }
37 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
38 {
39 None
40 }
41}
42
43pub fn resolve_ipc_socket_path(
48 network: &BitcoinNetwork,
49 data_dir: Option<PathBuf>,
50) -> Option<PathBuf> {
51 let base_dir = data_dir.or_else(default_bitcoin_data_dir)?;
52
53 Some(match network.subdir() {
54 Some(subdir) => base_dir.join(subdir).join("node.sock"),
55 None => base_dir.join("node.sock"),
56 })
57}
58
59#[derive(Clone, Debug, serde::Deserialize)]
62pub enum TemplateProviderType {
63 Sv2Tp {
64 address: String,
65 public_key: Option<Secp256k1PublicKey>,
66 },
67 BitcoinCoreIpc {
68 network: BitcoinNetwork,
70 #[serde(default, deserialize_with = "opt_path_from_toml")]
72 data_dir: Option<PathBuf>,
73 fee_threshold: u64,
74 min_interval: u8,
75 },
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn network_with_data_dir_mainnet() {
84 let result =
85 resolve_ipc_socket_path(&BitcoinNetwork::Mainnet, Some(PathBuf::from("/data")));
86 assert_eq!(result, Some(PathBuf::from("/data/node.sock")));
87 }
88
89 #[test]
90 fn network_with_data_dir_regtest() {
91 let result =
92 resolve_ipc_socket_path(&BitcoinNetwork::Regtest, Some(PathBuf::from("/data")));
93 assert_eq!(result, Some(PathBuf::from("/data/regtest/node.sock")));
94 }
95
96 #[test]
97 fn network_with_data_dir_signet() {
98 let result = resolve_ipc_socket_path(&BitcoinNetwork::Signet, Some(PathBuf::from("/data")));
99 assert_eq!(result, Some(PathBuf::from("/data/signet/node.sock")));
100 }
101
102 #[test]
103 fn network_with_data_dir_testnet4() {
104 let result =
105 resolve_ipc_socket_path(&BitcoinNetwork::Testnet4, Some(PathBuf::from("/data")));
106 assert_eq!(result, Some(PathBuf::from("/data/testnet4/node.sock")));
107 }
108
109 #[test]
110 fn missing_data_dir_uses_os_default() {
111 let result = resolve_ipc_socket_path(&BitcoinNetwork::Regtest, None);
114 #[cfg(any(target_os = "linux", target_os = "macos"))]
115 assert!(result.is_some());
116 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
117 assert!(result.is_none());
118 }
119}