Skip to main content

csv_adapter_bitcoin/
testnet_deploy.rs

1//! Testnet deployment helpers for the Bitcoin adapter
2//!
3//! Provides pre-configured testnet setups for Signet and Testnet3,
4//! including RPC endpoints, contract deployments, and validation tools.
5
6use crate::adapter::BitcoinAnchorLayer;
7use crate::config::{BitcoinConfig, Network};
8use crate::wallet::SealWallet;
9
10/// Testnet deployment configuration
11#[derive(Clone, Debug)]
12pub struct TestnetDeployConfig {
13    /// Bitcoin network (Signet or Testnet3)
14    pub network: Network,
15    /// RPC endpoint URL
16    pub rpc_url: &'static str,
17    /// Required confirmations for finality
18    pub finality_depth: u32,
19    /// Publication timeout in seconds
20    pub publication_timeout: u64,
21}
22
23impl TestnetDeployConfig {
24    /// Signet deployment configuration (recommended for development)
25    pub fn signet() -> Self {
26        Self {
27            network: Network::Signet,
28            rpc_url: "https://mempool.space/signet/api/",
29            finality_depth: 6,
30            publication_timeout: 3600,
31        }
32    }
33
34    /// Testnet3 deployment configuration
35    pub fn testnet3() -> Self {
36        Self {
37            network: Network::Testnet,
38            rpc_url: "https://blockstream.info/testnet/api/",
39            finality_depth: 6,
40            publication_timeout: 3600,
41        }
42    }
43
44    /// Convert to BitcoinConfig
45    pub fn to_config(&self) -> BitcoinConfig {
46        BitcoinConfig {
47            network: self.network,
48            finality_depth: self.finality_depth,
49            publication_timeout_seconds: self.publication_timeout,
50            rpc_url: self.rpc_url.to_string(),
51        }
52    }
53}
54
55/// Create a testnet-ready adapter with a random wallet
56pub fn create_testnet_adapter(
57    network: Network,
58) -> Result<BitcoinAnchorLayer, Box<dyn std::error::Error + Send + Sync>> {
59    let config = match network {
60        Network::Signet => TestnetDeployConfig::signet().to_config(),
61        Network::Testnet => TestnetDeployConfig::testnet3().to_config(),
62        _ => return Err("Only Signet and Testnet3 are supported for testnet deployment".into()),
63    };
64
65    let wallet = SealWallet::generate_random(network.to_bitcoin_network());
66    BitcoinAnchorLayer::with_wallet(config, wallet)
67        .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)
68}
69
70/// Validate testnet connectivity
71pub fn validate_testnet_connectivity(
72    adapter: &BitcoinAnchorLayer,
73) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
74    // Try to get current block height
75    let height = adapter.get_current_height_for_test();
76
77    if height > 0 {
78        Ok(())
79    } else {
80        Err("Failed to connect to testnet - could not retrieve block height".into())
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn test_signet_config_creation() {
90        let config = TestnetDeployConfig::signet().to_config();
91        assert_eq!(config.network, Network::Signet);
92        assert_eq!(config.finality_depth, 6);
93        assert!(!config.rpc_url.is_empty());
94    }
95
96    #[test]
97    fn test_testnet3_config_creation() {
98        let config = TestnetDeployConfig::testnet3().to_config();
99        assert_eq!(config.network, Network::Testnet);
100        assert_eq!(config.finality_depth, 6);
101    }
102
103    #[test]
104    fn test_create_testnet_adapter_signet() {
105        let adapter = create_testnet_adapter(Network::Signet);
106        assert!(adapter.is_ok());
107    }
108
109    #[test]
110    #[ignore] // Requires live network access
111    fn test_live_signet_connectivity() {
112        let adapter = create_testnet_adapter(Network::Signet).unwrap();
113        // This would actually connect to Signet
114        let result = validate_testnet_connectivity(&adapter);
115        // May fail in CI without network access
116        let _ = result;
117    }
118}