shared.rs 8.4 KB

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