shared.rs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //! Shared utilities for mint integration tests
  2. //!
  3. //! This module provides common functionality used across different
  4. //! integration test binaries to reduce code duplication.
  5. use std::fs;
  6. use std::path::{Path, PathBuf};
  7. use std::str::FromStr;
  8. use std::sync::Arc;
  9. use std::time::Duration;
  10. use anyhow::Result;
  11. use cdk_axum::cache;
  12. use cdk_mintd::config::{Database, DatabaseEngine};
  13. use tokio::signal;
  14. use tokio::sync::Notify;
  15. use crate::cli::{init_logging, CommonArgs};
  16. /// Default minimum mint amount for test mints
  17. const DEFAULT_MIN_MINT: u64 = 1;
  18. /// Default maximum mint amount for test mints
  19. const DEFAULT_MAX_MINT: u64 = 500_000;
  20. /// Default minimum melt amount for test mints
  21. const DEFAULT_MIN_MELT: u64 = 1;
  22. /// Default maximum melt amount for test mints
  23. const DEFAULT_MAX_MELT: u64 = 500_000;
  24. /// Wait for mint to be ready by checking its info endpoint
  25. pub async fn wait_for_mint_ready(port: u16, timeout_secs: u64) -> Result<()> {
  26. let url = format!("http://127.0.0.1:{port}/v1/info");
  27. let start_time = std::time::Instant::now();
  28. println!("Waiting for mint on port {port} to be ready...");
  29. loop {
  30. // Check if timeout has been reached
  31. if start_time.elapsed().as_secs() > timeout_secs {
  32. return Err(anyhow::anyhow!("Timeout waiting for mint on port {}", port));
  33. }
  34. // Try to make a request to the mint info endpoint
  35. match reqwest::get(&url).await {
  36. Ok(response) => {
  37. if response.status().is_success() {
  38. println!("Mint on port {port} is ready");
  39. return Ok(());
  40. } else {
  41. println!(
  42. "Mint on port {} returned status: {}",
  43. port,
  44. response.status()
  45. );
  46. }
  47. }
  48. Err(e) => {
  49. println!("Error connecting to mint on port {port}: {e}");
  50. }
  51. }
  52. tokio::time::sleep(Duration::from_secs(2)).await;
  53. }
  54. }
  55. /// Initialize working directory
  56. pub fn init_working_directory(work_dir: &str) -> Result<PathBuf> {
  57. let temp_dir = PathBuf::from_str(work_dir)?;
  58. // Create the temp directory if it doesn't exist
  59. fs::create_dir_all(&temp_dir)?;
  60. Ok(temp_dir)
  61. }
  62. /// Write environment variables to .env file
  63. pub fn write_env_file(temp_dir: &Path, env_vars: &[(&str, &str)]) -> Result<()> {
  64. let mut env_content = String::new();
  65. for (key, value) in env_vars {
  66. env_content.push_str(&format!("{key}={value}\n"));
  67. }
  68. let env_file_path = temp_dir.join(".env");
  69. fs::write(&env_file_path, &env_content)
  70. .map(|_| {
  71. println!(
  72. "Environment variables written to: {}",
  73. env_file_path.display()
  74. );
  75. })
  76. .map_err(|e| anyhow::anyhow!("Could not write .env file: {}", e))
  77. }
  78. /// Wait for .env file to be created
  79. pub async fn wait_for_env_file(temp_dir: &Path, timeout_secs: u64) -> Result<()> {
  80. let env_file_path = temp_dir.join(".env");
  81. let start_time = std::time::Instant::now();
  82. println!(
  83. "Waiting for .env file to be created at: {}",
  84. env_file_path.display()
  85. );
  86. loop {
  87. // Check if timeout has been reached
  88. if start_time.elapsed().as_secs() > timeout_secs {
  89. return Err(anyhow::anyhow!(
  90. "Timeout waiting for .env file at {}",
  91. env_file_path.display()
  92. ));
  93. }
  94. // Check if the file exists
  95. if env_file_path.exists() {
  96. println!(".env file found at: {}", env_file_path.display());
  97. return Ok(());
  98. }
  99. tokio::time::sleep(Duration::from_secs(1)).await;
  100. }
  101. }
  102. /// Setup common logging based on CLI arguments
  103. pub fn setup_logging(common_args: &CommonArgs) {
  104. init_logging(common_args.enable_logging, common_args.log_level);
  105. }
  106. /// Create shutdown handler for graceful termination
  107. pub fn create_shutdown_handler() -> Arc<Notify> {
  108. Arc::new(Notify::new())
  109. }
  110. /// Wait for Ctrl+C signal
  111. pub async fn wait_for_shutdown_signal(shutdown: Arc<Notify>) {
  112. signal::ctrl_c()
  113. .await
  114. .expect("failed to install CTRL+C handler");
  115. println!("\nReceived Ctrl+C, shutting down...");
  116. shutdown.notify_waiters();
  117. }
  118. /// Common mint information display
  119. pub fn display_mint_info(port: u16, temp_dir: &Path, database_type: &str) {
  120. println!("Mint started successfully!");
  121. println!("Mint URL: http://127.0.0.1:{port}");
  122. println!("Temp directory: {temp_dir:?}");
  123. println!("Database type: {database_type}");
  124. }
  125. /// Create settings for a fake wallet mint
  126. pub fn create_fake_wallet_settings(
  127. port: u16,
  128. database: &str,
  129. mnemonic: Option<String>,
  130. signatory_config: Option<(String, String)>, // (url, certs_dir)
  131. fake_wallet_config: Option<cdk_mintd::config::FakeWallet>,
  132. ) -> cdk_mintd::config::Settings {
  133. cdk_mintd::config::Settings {
  134. info: cdk_mintd::config::Info {
  135. url: format!("http://127.0.0.1:{port}"),
  136. listen_host: "127.0.0.1".to_string(),
  137. listen_port: port,
  138. mnemonic,
  139. signatory_url: signatory_config.as_ref().map(|(url, _)| url.clone()),
  140. signatory_certs: signatory_config
  141. .as_ref()
  142. .map(|(_, certs_dir)| certs_dir.clone()),
  143. input_fee_ppk: None,
  144. http_cache: cache::Config::default(),
  145. logging: cdk_mintd::config::LoggingConfig {
  146. output: cdk_mintd::config::LoggingOutput::Both,
  147. console_level: Some("debug".to_string()),
  148. file_level: Some("debug".to_string()),
  149. },
  150. enable_swagger_ui: None,
  151. },
  152. mint_info: cdk_mintd::config::MintInfo::default(),
  153. ln: cdk_mintd::config::Ln {
  154. ln_backend: cdk_mintd::config::LnBackend::FakeWallet,
  155. invoice_description: None,
  156. min_mint: DEFAULT_MIN_MINT.into(),
  157. max_mint: DEFAULT_MAX_MINT.into(),
  158. min_melt: DEFAULT_MIN_MELT.into(),
  159. max_melt: DEFAULT_MAX_MELT.into(),
  160. },
  161. cln: None,
  162. lnbits: None,
  163. lnd: None,
  164. fake_wallet: fake_wallet_config,
  165. grpc_processor: None,
  166. database: Database {
  167. engine: DatabaseEngine::from_str(database).expect("valid database"),
  168. postgres: None,
  169. },
  170. mint_management_rpc: None,
  171. auth: None,
  172. }
  173. }
  174. /// Create settings for a CLN mint
  175. pub fn create_cln_settings(
  176. port: u16,
  177. _cln_rpc_path: PathBuf,
  178. mnemonic: String,
  179. cln_config: cdk_mintd::config::Cln,
  180. ) -> cdk_mintd::config::Settings {
  181. cdk_mintd::config::Settings {
  182. info: cdk_mintd::config::Info {
  183. url: format!("http://127.0.0.1:{port}"),
  184. listen_host: "127.0.0.1".to_string(),
  185. listen_port: port,
  186. mnemonic: Some(mnemonic),
  187. signatory_url: None,
  188. signatory_certs: None,
  189. input_fee_ppk: None,
  190. http_cache: cache::Config::default(),
  191. logging: cdk_mintd::config::LoggingConfig {
  192. output: cdk_mintd::config::LoggingOutput::Both,
  193. console_level: Some("debug".to_string()),
  194. file_level: Some("debug".to_string()),
  195. },
  196. enable_swagger_ui: None,
  197. },
  198. mint_info: cdk_mintd::config::MintInfo::default(),
  199. ln: cdk_mintd::config::Ln {
  200. ln_backend: cdk_mintd::config::LnBackend::Cln,
  201. invoice_description: None,
  202. min_mint: DEFAULT_MIN_MINT.into(),
  203. max_mint: DEFAULT_MAX_MINT.into(),
  204. min_melt: DEFAULT_MIN_MELT.into(),
  205. max_melt: DEFAULT_MAX_MELT.into(),
  206. },
  207. cln: Some(cln_config),
  208. lnbits: None,
  209. lnd: None,
  210. fake_wallet: None,
  211. grpc_processor: None,
  212. database: cdk_mintd::config::Database::default(),
  213. mint_management_rpc: None,
  214. auth: None,
  215. }
  216. }
  217. /// Create settings for an LND mint
  218. pub fn create_lnd_settings(
  219. port: u16,
  220. lnd_config: cdk_mintd::config::Lnd,
  221. mnemonic: String,
  222. ) -> cdk_mintd::config::Settings {
  223. cdk_mintd::config::Settings {
  224. info: cdk_mintd::config::Info {
  225. url: format!("http://127.0.0.1:{port}"),
  226. listen_host: "127.0.0.1".to_string(),
  227. listen_port: port,
  228. mnemonic: Some(mnemonic),
  229. signatory_url: None,
  230. signatory_certs: None,
  231. input_fee_ppk: None,
  232. http_cache: cache::Config::default(),
  233. logging: cdk_mintd::config::LoggingConfig {
  234. output: cdk_mintd::config::LoggingOutput::Both,
  235. console_level: Some("debug".to_string()),
  236. file_level: Some("debug".to_string()),
  237. },
  238. enable_swagger_ui: None,
  239. },
  240. mint_info: cdk_mintd::config::MintInfo::default(),
  241. ln: cdk_mintd::config::Ln {
  242. ln_backend: cdk_mintd::config::LnBackend::Lnd,
  243. invoice_description: None,
  244. min_mint: DEFAULT_MIN_MINT.into(),
  245. max_mint: DEFAULT_MAX_MINT.into(),
  246. min_melt: DEFAULT_MIN_MELT.into(),
  247. max_melt: DEFAULT_MAX_MELT.into(),
  248. },
  249. cln: None,
  250. lnbits: None,
  251. lnd: Some(lnd_config),
  252. fake_wallet: None,
  253. grpc_processor: None,
  254. database: cdk_mintd::config::Database::default(),
  255. mint_management_rpc: None,
  256. auth: None,
  257. }
  258. }